diff options
author | Sumit Bose <sbose@redhat.com> | 2012-04-25 09:16:41 +0200 |
---|---|---|
committer | Stephen Gallagher <sgallagh@redhat.com> | 2012-05-01 14:22:51 -0400 |
commit | b6dfbf81c61d4431aaa81687ec53e892f8b71edb (patch) | |
tree | 783f2e567335b2a57f8a21ee99847bfb05add78d /src/lib/idmap/sss_idmap_conv.c | |
parent | c8a124ac1b03d83016bda02cad5a369ce6fb1cd7 (diff) | |
download | sssd-b6dfbf81c61d4431aaa81687ec53e892f8b71edb.tar.gz sssd-b6dfbf81c61d4431aaa81687ec53e892f8b71edb.tar.xz sssd-b6dfbf81c61d4431aaa81687ec53e892f8b71edb.zip |
Allow different SID representations in libidmap
Besides as strings it is now possible to use binary SIDs or a struct
containing all SID information. Functions to convert between these
formats are added as well.
Diffstat (limited to 'src/lib/idmap/sss_idmap_conv.c')
-rw-r--r-- | src/lib/idmap/sss_idmap_conv.c | 385 |
1 files changed, 385 insertions, 0 deletions
diff --git a/src/lib/idmap/sss_idmap_conv.c b/src/lib/idmap/sss_idmap_conv.c new file mode 100644 index 000000000..83041efee --- /dev/null +++ b/src/lib/idmap/sss_idmap_conv.c @@ -0,0 +1,385 @@ +/* + SSSD + + ID-mapping library - conversion utilities + + Authors: + Sumit Bose <sbose@redhat.com> + + Copyright (C) 2012 Red Hat + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include <ctype.h> + +#include "lib/idmap/sss_idmap.h" +#include "lib/idmap/sss_idmap_private.h" +#include "util/util.h" + +#define SID_ID_AUTHS 6 +#define SID_SUB_AUTHS 15 +struct dom_sid { + uint8_t sid_rev_num; + int8_t num_auths;/* [range(0,15)] */ + uint8_t id_auth[SID_ID_AUTHS]; + uint32_t sub_auths[SID_SUB_AUTHS]; +}; + +enum idmap_error_code sss_idmap_bin_sid_to_dom_sid(struct sss_idmap_ctx *ctx, + const uint8_t *bin_sid, + size_t length, + struct dom_sid **_dom_sid) +{ + enum idmap_error_code err; + struct dom_sid *dom_sid; + size_t i = 0; + size_t p = 0; + + CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); + + if (length > sizeof(struct dom_sid)) return IDMAP_SID_INVALID; + + dom_sid = ctx->alloc_func(sizeof(struct dom_sid), ctx->alloc_pvt); + if (dom_sid == NULL) { + return IDMAP_OUT_OF_MEMORY; + } + + /* Safely copy in the SID revision number */ + dom_sid->sid_rev_num = (uint8_t) *(bin_sid + p); + p++; + + /* Safely copy in the number of sub auth values */ + dom_sid->num_auths = (uint8_t) *(bin_sid + p); + p++; + + /* Make sure we aren't being told to read more bin_sid + * than can fit in the structure + */ + if (dom_sid->num_auths > SID_SUB_AUTHS) { + err = IDMAP_SID_INVALID; + goto done; + } + + /* Safely copy in the id_auth values */ + for (i = 0; i < SID_ID_AUTHS; i++) { + dom_sid->id_auth[i] = (uint8_t) *(bin_sid + p); + p++; + } + + /* Safely copy in the sub_auths values */ + for (i = 0; i < dom_sid->num_auths; i++) { + SAFEALIGN_COPY_UINT32(&dom_sid->sub_auths[i], bin_sid + p, &p); + } + + *_dom_sid = dom_sid; + err = IDMAP_SUCCESS; + +done: + if (err != IDMAP_SUCCESS) { + ctx->free_func(dom_sid, ctx->alloc_pvt); + } + return err; +} + +enum idmap_error_code sss_idmap_dom_sid_to_bin_sid(struct sss_idmap_ctx *ctx, + struct dom_sid *dom_sid, + uint8_t **_bin_sid, + size_t *_length) +{ + enum idmap_error_code err; + uint8_t *bin_sid; + size_t length; + size_t i = 0; + size_t p = 0; + + CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); + + if (dom_sid->num_auths > SID_SUB_AUTHS) { + return IDMAP_SID_INVALID; + } + + length = 2 + SID_ID_AUTHS + dom_sid->num_auths * 4; + + bin_sid = ctx->alloc_func(length, ctx->alloc_pvt); + if (bin_sid == NULL) { + return IDMAP_OUT_OF_MEMORY; + } + + bin_sid[p] = dom_sid->sid_rev_num; + p++; + + bin_sid[p] = dom_sid->num_auths; + p++; + + for (i = 0; i < SID_ID_AUTHS; i++) { + bin_sid[p] = dom_sid->id_auth[i]; + p++; + } + + for (i = 0; i < dom_sid->num_auths; i++) { + if (p + sizeof(uint32_t) > length) { + err = IDMAP_SID_INVALID; + goto done; + } + SAFEALIGN_COPY_UINT32(bin_sid + p, &dom_sid->sub_auths[i], &p); + } + + *_bin_sid = bin_sid; + *_length = length; + + err = IDMAP_SUCCESS; +done: + if (err != IDMAP_SUCCESS) { + ctx->free_func(bin_sid, ctx->alloc_pvt); + } + return err; +} + +enum idmap_error_code sss_idmap_dom_sid_to_sid(struct sss_idmap_ctx *ctx, + struct dom_sid *dom_sid, + char **_sid) +{ + enum idmap_error_code err; + char *sid_buf; + size_t sid_buf_len; + char *p; + int nc; + int8_t i; + uint32_t id_auth_val = 0; + uint32_t sub_auth_val; + + if (dom_sid->num_auths > SID_SUB_AUTHS) { + return IDMAP_SID_INVALID; + } + + sid_buf_len = 25 + dom_sid->num_auths * 11; + sid_buf = ctx->alloc_func(sid_buf_len, ctx->alloc_pvt); + if (sid_buf == NULL) { + return IDMAP_OUT_OF_MEMORY; + } + memset(sid_buf, 0, sid_buf_len); + + /* Only 32bits are used for the string representation */ + id_auth_val = (dom_sid->id_auth[2] << 24) + + (dom_sid->id_auth[3] << 16) + + (dom_sid->id_auth[4] << 8) + + (dom_sid->id_auth[5]); + + nc = snprintf(sid_buf, sid_buf_len, "S-%u-%lu", dom_sid->sid_rev_num, + (unsigned long) id_auth_val); + if (nc < 0 || nc >= sid_buf_len) { + err = IDMAP_SID_INVALID; + goto done; + } + + + /* Loop through the sub-auths, if any, prepending a hyphen + * for each one. + */ + p = sid_buf; + for (i = 0; i < dom_sid->num_auths ; i++) { + p += nc; + sid_buf_len -= nc; + /* SID values in Active Directory are stored little-endian */ + sub_auth_val = le32toh(dom_sid->sub_auths[i]); + + nc = snprintf(p, sid_buf_len, "-%lu", (unsigned long) sub_auth_val); + if (nc < 0 || nc >= sid_buf_len) { + err = IDMAP_SID_INVALID; + goto done; + } + } + + *_sid = sid_buf; + err = IDMAP_SUCCESS; + +done: + if (err != IDMAP_SUCCESS) { + ctx->free_func(sid_buf, ctx->alloc_pvt); + } + + return err; +} + +enum idmap_error_code sss_idmap_sid_to_dom_sid(struct sss_idmap_ctx *ctx, + const char *sid, + struct dom_sid **_dom_sid) +{ + enum idmap_error_code err; + unsigned long ul; + char *r; + char *end; + struct dom_sid *dom_sid; + + CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); + + if (sid == NULL || (sid[0] != 'S' && sid[0] != 's') || sid[1] != '-') { + return IDMAP_SID_INVALID; + } + + dom_sid = ctx->alloc_func(sizeof(struct dom_sid), ctx->alloc_pvt); + if (dom_sid == NULL) { + return IDMAP_OUT_OF_MEMORY; + } + memset(dom_sid, 0, sizeof(struct dom_sid)); + + + if (!isdigit(sid[2])) { + err = IDMAP_SID_INVALID; + goto done; + } + errno = 0; + ul = strtoul(sid + 2, &r, 10); + if (errno != 0 || r == NULL || *r != '-' || ul > UINT8_MAX) { + err = IDMAP_SID_INVALID; + goto done; + } + dom_sid->sid_rev_num = (uint8_t) ul; + r++; + + if (!isdigit(*r)) { + err = IDMAP_SID_INVALID; + goto done; + } + errno = 0; + ul = strtoul(r, &r, 10); + if (errno != 0 || r == NULL) { + err = IDMAP_SID_INVALID; + goto done; + } + + /* id_auth in the string should always be <2^32 in decimal */ + /* store values in the same order as the binary representation */ + dom_sid->id_auth[0] = 0; + dom_sid->id_auth[1] = 0; + dom_sid->id_auth[2] = (ul & 0xff000000) >> 24; + dom_sid->id_auth[3] = (ul & 0x00ff0000) >> 16; + dom_sid->id_auth[4] = (ul & 0x0000ff00) >> 8; + dom_sid->id_auth[5] = (ul & 0x000000ff); + + if (*r == '\0') { + /* no sub auths given */ + err = IDMAP_SUCCESS; + goto done; + } + + if (*r != '-') { + err = IDMAP_SID_INVALID; + goto done; + } + + do { + if (dom_sid->num_auths > SID_SUB_AUTHS) { + err = IDMAP_SID_INVALID; + goto done; + } + + r++; + if (!isdigit(*r)) { + err = IDMAP_SID_INVALID; + goto done; + } + + errno = 0; + ul = strtol(r, &end, 10); + if (errno != 0 || end == NULL || + (*end != '\0' && *end != '-')) { + err = IDMAP_SID_INVALID; + goto done; + } + + dom_sid->sub_auths[dom_sid->num_auths++] = ul; + + r = end; + } while (*r != '\0'); + + err = IDMAP_SUCCESS; + +done: + if (err != IDMAP_SUCCESS) { + ctx->free_func(dom_sid, ctx->alloc_pvt); + } else { + *_dom_sid = dom_sid; + } + + return err; +} + +enum idmap_error_code sss_idmap_sid_to_bin_sid(struct sss_idmap_ctx *ctx, + const char *sid, + uint8_t **_bin_sid, + size_t *_length) +{ + enum idmap_error_code err; + struct dom_sid *dom_sid = NULL; + size_t length; + uint8_t *bin_sid = NULL; + + err = sss_idmap_sid_to_dom_sid(ctx, sid, &dom_sid); + if (err != IDMAP_SUCCESS) { + goto done; + } + + err = sss_idmap_dom_sid_to_bin_sid(ctx, dom_sid, &bin_sid, &length); + if (err != IDMAP_SUCCESS) { + goto done; + } + + *_length = length; + *_bin_sid = bin_sid; + err = IDMAP_SUCCESS; + +done: + ctx->free_func(dom_sid, ctx->alloc_pvt); + if (err != IDMAP_SUCCESS) { + ctx->free_func(bin_sid, ctx->alloc_pvt); + } + + return err; +} + +enum idmap_error_code sss_idmap_bin_sid_to_sid(struct sss_idmap_ctx *ctx, + const uint8_t *bin_sid, + size_t length, + char **_sid) +{ + enum idmap_error_code err; + struct dom_sid *dom_sid = NULL; + char *sid = NULL; + + err = sss_idmap_bin_sid_to_dom_sid(ctx, bin_sid, length, &dom_sid); + if (err != IDMAP_SUCCESS) { + goto done; + } + + err = sss_idmap_dom_sid_to_sid(ctx, dom_sid, &sid); + if (err != IDMAP_SUCCESS) { + goto done; + } + + *_sid = sid; + err = IDMAP_SUCCESS; + +done: + ctx->free_func(dom_sid, ctx->alloc_pvt); + if (err != IDMAP_SUCCESS) { + ctx->free_func(sid, ctx->alloc_pvt); + } + + return err; +} |