From 1a396db5661f1eeafddcde1ab303f730ecf807cd Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Wed, 25 Apr 2012 09:16:41 +0200 Subject: [PATCH] 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. --- Makefile.am | 6 +- src/lib/idmap/sss_idmap.c | 127 +++++++++++-- src/lib/idmap/sss_idmap.h | 179 +++++++++++++++++ src/lib/idmap/sss_idmap_conv.c | 385 +++++++++++++++++++++++++++++++++++++ src/lib/idmap/sss_idmap_private.h | 41 ++++ src/tests/sss_idmap-tests.c | 206 ++++++++++++++++++++ 6 files changed, 929 insertions(+), 15 deletions(-) create mode 100644 src/lib/idmap/sss_idmap_conv.c create mode 100644 src/lib/idmap/sss_idmap_private.h diff --git a/Makefile.am b/Makefile.am index 812d1ac..985e948 100644 --- a/Makefile.am +++ b/Makefile.am @@ -407,7 +407,8 @@ dist_noinst_HEADERS = \ src/resolv/ares/ares_parse_txt_reply.h \ src/resolv/ares/ares_data.h \ src/tests/common.h \ - src/sss_client/ssh/sss_ssh_client.h + src/sss_client/ssh/sss_ssh_client.h \ + src/lib/idmap/sss_idmap_private.h if HAVE_NSS @@ -494,7 +495,8 @@ libipa_hbac_la_LDFLAGS = \ dist_pkgconfig_DATA += src/lib/idmap/sss_idmap.pc libsss_idmap_la_SOURCES = \ - src/lib/idmap/sss_idmap.c + src/lib/idmap/sss_idmap.c \ + src/lib/idmap/sss_idmap_conv.c libsss_idmap_la_LDFLAGS = \ -version 1:0:1 diff --git a/src/lib/idmap/sss_idmap.c b/src/lib/idmap/sss_idmap.c index 11f934b..b00d615 100644 --- a/src/lib/idmap/sss_idmap.c +++ b/src/lib/idmap/sss_idmap.c @@ -27,18 +27,13 @@ #include #include "lib/idmap/sss_idmap.h" +#include "lib/idmap/sss_idmap_private.h" #define DOM_SID_PREFIX "S-1-5-21-" #define DOM_SID_PREFIX_LEN (sizeof(DOM_SID_PREFIX) - 1) #define SID_FMT "%s-%d" #define SID_STR_MAX_LEN 1024 -#define CHECK_IDMAP_CTX(ctx, ret) do { \ - if (ctx == NULL || ctx->alloc_func == NULL || ctx->free_func == NULL) { \ - return ret; \ - } \ -} while(0) - struct idmap_domain_info { char *name; char *sid; @@ -46,13 +41,6 @@ struct idmap_domain_info { struct idmap_domain_info *next; }; -struct sss_idmap_ctx { - idmap_alloc_func *alloc_func; - void *alloc_pvt; - idmap_free_func *free_func; - struct idmap_domain_info *idmap_domain_info; -}; - static void *default_alloc(size_t size, void *pvt) { return malloc(size); @@ -373,3 +361,116 @@ enum idmap_error_code sss_idmap_unix_to_sid(struct sss_idmap_ctx *ctx, return IDMAP_NO_DOMAIN; } + +enum idmap_error_code sss_idmap_dom_sid_to_unix(struct sss_idmap_ctx *ctx, + struct dom_sid *dom_sid, + uint32_t *id) +{ + enum idmap_error_code err; + char *sid; + + CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); + + err = sss_idmap_dom_sid_to_sid(ctx, dom_sid, &sid); + if (err != IDMAP_SUCCESS) { + goto done; + } + + err = sss_idmap_sid_to_unix(ctx, sid, id); + +done: + ctx->free_func(sid, ctx->alloc_pvt); + + return err; +} + +enum idmap_error_code sss_idmap_bin_sid_to_unix(struct sss_idmap_ctx *ctx, + uint8_t *bin_sid, + size_t length, + uint32_t *id) +{ + enum idmap_error_code err; + char *sid; + + CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); + + err = sss_idmap_bin_sid_to_sid(ctx, bin_sid, length, &sid); + if (err != IDMAP_SUCCESS) { + goto done; + } + + err = sss_idmap_sid_to_unix(ctx, sid, id); + +done: + ctx->free_func(sid, ctx->alloc_pvt); + + return err; +} + +enum idmap_error_code sss_idmap_unix_to_dom_sid(struct sss_idmap_ctx *ctx, + uint32_t id, + struct dom_sid **_dom_sid) +{ + enum idmap_error_code err; + char *sid = NULL; + struct dom_sid *dom_sid = NULL; + + CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); + + err = sss_idmap_unix_to_sid(ctx, id, &sid); + if (err != IDMAP_SUCCESS) { + goto done; + } + + err = sss_idmap_sid_to_dom_sid(ctx, sid, &dom_sid); + if (err != IDMAP_SUCCESS) { + goto done; + } + + *_dom_sid = dom_sid; + err = IDMAP_SUCCESS; + +done: + ctx->free_func(sid, ctx->alloc_pvt); + if (err != IDMAP_SUCCESS) { + ctx->free_func(dom_sid, ctx->alloc_pvt); + } + + return err; +} + +enum idmap_error_code sss_idmap_unix_to_bin_sid(struct sss_idmap_ctx *ctx, + uint32_t id, + uint8_t **_bin_sid, + size_t *_length) +{ + enum idmap_error_code err; + char *sid = NULL; + uint8_t *bin_sid = NULL; + size_t length; + + CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); + + err = sss_idmap_unix_to_sid(ctx, id, &sid); + if (err != IDMAP_SUCCESS) { + goto done; + } + + err = sss_idmap_sid_to_bin_sid(ctx, sid, &bin_sid, &length); + if (err != IDMAP_SUCCESS) { + goto done; + } + + *_bin_sid = bin_sid; + *_length = length; + err = IDMAP_SUCCESS; + +done: + ctx->free_func(sid, ctx->alloc_pvt); + if (err != IDMAP_SUCCESS) { + ctx->free_func(bin_sid, ctx->alloc_pvt); + } + + return err; + +} diff --git a/src/lib/idmap/sss_idmap.h b/src/lib/idmap/sss_idmap.h index dbb2700..146f831 100644 --- a/src/lib/idmap/sss_idmap.h +++ b/src/lib/idmap/sss_idmap.h @@ -85,6 +85,11 @@ struct sss_idmap_range { }; /** + * Opaque type for SIDs + */ +struct dom_sid; + +/** * Opaque type for the idmap context */ struct sss_idmap_ctx; @@ -146,6 +151,42 @@ enum idmap_error_code sss_idmap_sid_to_unix(struct sss_idmap_ctx *ctx, uint32_t *id); /** + * @brief Translate a SID stucture to a unix UID or GID + * + * @param[in] ctx Idmap context + * @param[in] dom_sid SID structure + * @param[out] id Returned unix UID or GID + * + * @return + * - #IDMAP_NO_DOMAIN: No domains are added to the idmap context + * - #IDMAP_SID_INVALID: Invalid SID provided + * - #IDMAP_SID_UNKNOWN: SID cannot be found in the domains added to the + * idmap context + */ +enum idmap_error_code sss_idmap_dom_sid_to_unix(struct sss_idmap_ctx *ctx, + struct dom_sid *dom_sid, + uint32_t *id); + +/** + * @brief Translate a binary SID to a unix UID or GID + * + * @param[in] ctx Idmap context + * @param[in] bin_sid Array with the binary SID + * @param[in] length Size of the array containing the binary SID + * @param[out] id Returned unix UID or GID + * + * @return + * - #IDMAP_NO_DOMAIN: No domains are added to the idmap context + * - #IDMAP_SID_INVALID: Invalid SID provided + * - #IDMAP_SID_UNKNOWN: SID cannot be found in the domains added to the + * idmap context + */ +enum idmap_error_code sss_idmap_bin_sid_to_unix(struct sss_idmap_ctx *ctx, + uint8_t *bin_sid, + size_t length, + uint32_t *id); + +/** * @brief Translate unix UID or GID to a SID * * @param[in] ctx Idmap context @@ -163,6 +204,41 @@ enum idmap_error_code sss_idmap_unix_to_sid(struct sss_idmap_ctx *ctx, char **sid); /** + * @brief Translate unix UID or GID to a SID structure + * + * @param[in] ctx Idmap context + * @param[in] id unix UID or GID + * @param[out] dom_sid SID structure, must be freed if not needed anymore + * + * @return + * - #IDMAP_NO_DOMAIN: No domains are added to the idmap context + * - #IDMAP_NO_RANGE: The provided ID cannot be found in the domains added + * to the idmap context + */ +enum idmap_error_code sss_idmap_unix_to_dom_sid(struct sss_idmap_ctx *ctx, + uint32_t id, + struct dom_sid **dom_sid); + +/** + * @brief Translate unix UID or GID to a binary SID + * + * @param[in] ctx Idmap context + * @param[in] id unix UID or GID + * @param[out] bin_sid Array with the binary SID, + * must be freed if not needed anymore + * @param[out] length size of the array containing the binary SID + * + * @return + * - #IDMAP_NO_DOMAIN: No domains are added to the idmap context + * - #IDMAP_NO_RANGE: The provided ID cannot be found in the domains added + * to the idmap context + */ +enum idmap_error_code sss_idmap_unix_to_bin_sid(struct sss_idmap_ctx *ctx, + uint32_t id, + uint8_t **bin_sid, + size_t *length); + +/** * @brief Free all the allocated memory of the idmap context * * @param[in] ctx Idmap context @@ -194,6 +270,109 @@ const char *idmap_error_string(enum idmap_error_code err); bool is_domain_sid(const char *str); /** + * @brief Convert binary SID to SID structure + * + * @param[in] ctx Idmap context + * @param[in] bin_sid Array with the binary SID + * @param[in] length Size of the array containing the binary SID + * @param[out] dom_sid SID structure, + * must be freed if not needed anymore + * + * @return + * - #IDMAP_SID_INVALID: Given SID is invalid + * - #IDMAP_OUT_OF_MEMORY: Failed to allocate memory for the result + */ +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); + +/** + * @brief Convert binary SID to SID string + * + * @param[in] ctx Idmap context + * @param[in] bin_sid Array with the binary SID + * @param[in] length Size of the array containing the binary SID + * @param[out] sid Zero-terminated string representation of the SID, + * must be freed if not needed anymore + * + * @return + * - #IDMAP_SID_INVALID: Given SID is invalid + * - #IDMAP_OUT_OF_MEMORY: Failed to allocate memory for the result + */ +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); + +/** + * @brief Convert SID structure to binary SID + * + * @param[in] ctx Idmap context + * @param[in] dom_sid SID structure + * @param[out] bin_sid Array with the binary SID, + * must be freed if not needed anymore + * @param[out] length Size of the array containing the binary SID + * + * @return + * - #IDMAP_SID_INVALID: Given SID is invalid + * - #IDMAP_OUT_OF_MEMORY: Failed to allocate memory for the result + */ +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); + +/** + * @brief Convert SID string to binary SID + * + * @param[in] ctx Idmap context + * @param[in] sid Zero-terminated string representation of the SID + * @param[out] bin_sid Array with the binary SID, + * must be freed if not needed anymore + * @param[out] length Size of the array containing the binary SID + * + * @return + * - #IDMAP_SID_INVALID: Given SID is invalid + * - #IDMAP_OUT_OF_MEMORY: Failed to allocate memory for the result + */ +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); + +/** + * @brief Convert SID structure to SID string + * + * @param[in] ctx Idmap context + * @param[in] dom_sid SID structure + * @param[out] sid Zero-terminated string representation of the SID, + * must be freed if not needed anymore + * + * @return + * - #IDMAP_SID_INVALID: Given SID is invalid + * - #IDMAP_OUT_OF_MEMORY: Failed to allocate memory for the result + */ +enum idmap_error_code sss_idmap_dom_sid_to_sid(struct sss_idmap_ctx *ctx, + struct dom_sid *dom_sid, + char **sid); + +/** + * @brief Convert SID string to SID structure + * + * @param[in] ctx Idmap context + * @param[in] sid Zero-terminated string representation of the SID + * @param[out] dom_sid SID structure, + * must be freed if not needed anymore + * + * @return + * - #IDMAP_SID_INVALID: Given SID is invalid + * - #IDMAP_OUT_OF_MEMORY: Failed to allocate memory for the result + */ +enum idmap_error_code sss_idmap_sid_to_dom_sid(struct sss_idmap_ctx *ctx, + const char *sid, + struct dom_sid **dom_sid); +/** * @} */ #endif /* SSS_IDMAP_H_ */ diff --git a/src/lib/idmap/sss_idmap_conv.c b/src/lib/idmap/sss_idmap_conv.c new file mode 100644 index 0000000..83041ef --- /dev/null +++ b/src/lib/idmap/sss_idmap_conv.c @@ -0,0 +1,385 @@ +/* + SSSD + + ID-mapping library - conversion utilities + + Authors: + Sumit Bose + + 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 . +*/ + +#include +#include +#include +#include + +#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; +} diff --git a/src/lib/idmap/sss_idmap_private.h b/src/lib/idmap/sss_idmap_private.h new file mode 100644 index 0000000..776c56a --- /dev/null +++ b/src/lib/idmap/sss_idmap_private.h @@ -0,0 +1,41 @@ +/* + SSSD + + ID-mapping library - private headers + + Authors: + Sumit Bose + + 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 . +*/ + +#ifndef SSS_IDMAP_PRIVATE_H_ +#define SSS_IDMAP_PRIVATE_H_ + +#define CHECK_IDMAP_CTX(ctx, ret) do { \ + if (ctx == NULL || ctx->alloc_func == NULL || ctx->free_func == NULL) { \ + return ret; \ + } \ +} while(0) + +struct sss_idmap_ctx { + idmap_alloc_func *alloc_func; + void *alloc_pvt; + idmap_free_func *free_func; + struct idmap_domain_info *idmap_domain_info; +}; + +#endif /* SSS_IDMAP_PRIVATE_H_ */ diff --git a/src/tests/sss_idmap-tests.c b/src/tests/sss_idmap-tests.c index 101970e..5be7a5f 100644 --- a/src/tests/sss_idmap-tests.c +++ b/src/tests/sss_idmap-tests.c @@ -28,6 +28,13 @@ #define IDMAP_RANGE_MIN 1234 #define IDMAP_RANGE_MAX 9876 +const char test_sid[] = "S-1-5-21-2127521184-1604012920-1887927527-72713"; +uint8_t test_bin_sid[] = {0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x15, + 0x00, 0x00, 0x00, 0xA0, 0x65, 0xCF, 0x7E, 0x78, 0x4B, + 0x9B, 0x5F, 0xE7, 0x7C, 0x87, 0x70, 0x09, 0x1C, 0x01, + 0x00}; +size_t test_bin_sid_length = sizeof(test_bin_sid); + struct sss_idmap_ctx *idmap_ctx; static void *idmap_talloc(size_t size, void *pvt) @@ -150,6 +157,46 @@ START_TEST(idmap_test_sid2uid) } END_TEST +START_TEST(idmap_test_bin_sid2uid) +{ + enum idmap_error_code err; + uint32_t id; + uint8_t *bin_sid = NULL; + size_t length; + + err = sss_idmap_sid_to_bin_sid(idmap_ctx, "S-1-5-21-1-2-3-1000", + &bin_sid, &length); + fail_unless(err == IDMAP_SUCCESS, "Failed to convert SID to binary SID"); + + err = sss_idmap_bin_sid_to_unix(idmap_ctx, bin_sid, length , &id); + fail_unless(err == IDMAP_SUCCESS, "sss_idmap_bin_sid_to_unix failed."); + fail_unless(id == (1000 + IDMAP_RANGE_MIN), + "sss_idmap_bin_sid_to_unix returned wrong id, " + "got [%d], expected [%d].", id, 1000 + IDMAP_RANGE_MIN); + + talloc_free(bin_sid); +} +END_TEST + +START_TEST(idmap_test_dom_sid2uid) +{ + enum idmap_error_code err; + uint32_t id; + struct dom_sid *dom_sid = NULL; + + err = sss_idmap_sid_to_dom_sid(idmap_ctx, "S-1-5-21-1-2-3-1000", &dom_sid); + fail_unless(err == IDMAP_SUCCESS, "Failed to convert SID to SID structure"); + + err = sss_idmap_dom_sid_to_unix(idmap_ctx, dom_sid, &id); + fail_unless(err == IDMAP_SUCCESS, "sss_idmap_dom_sid_to_unix failed."); + fail_unless(id == (1000 + IDMAP_RANGE_MIN), + "sss_idmap_dom_sid_to_unix returned wrong id, " + "got [%d], expected [%d].", id, 1000 + IDMAP_RANGE_MIN); + + talloc_free(dom_sid); +} +END_TEST + START_TEST(idmap_test_uid2sid) { enum idmap_error_code err; @@ -169,6 +216,145 @@ START_TEST(idmap_test_uid2sid) } END_TEST +START_TEST(idmap_test_uid2dom_sid) +{ + enum idmap_error_code err; + struct dom_sid *dom_sid = NULL; + char *sid = NULL; + + err = sss_idmap_unix_to_dom_sid(idmap_ctx, 10000, &dom_sid); + fail_unless(err == IDMAP_NO_DOMAIN, "sss_idmap_unix_to_dom_sid did not detect " + "id out of range"); + + err = sss_idmap_unix_to_dom_sid(idmap_ctx, 2234, &dom_sid); + fail_unless(err == IDMAP_SUCCESS, "sss_idmap_unix_to_dom_sid failed."); + + err = sss_idmap_dom_sid_to_sid(idmap_ctx, dom_sid, &sid); + fail_unless(err == IDMAP_SUCCESS, "sss_idmap_dom_sid_to_sid failed."); + + fail_unless(strcmp(sid, "S-1-5-21-1-2-3-1000") == 0, + "sss_idmap_unix_to_dom_sid returned wrong SID, " + "expected [%s], got [%s].", "S-1-5-21-1-2-3-1000", sid); + + talloc_free(sid); + talloc_free(dom_sid); +} +END_TEST + +START_TEST(idmap_test_uid2bin_sid) +{ + enum idmap_error_code err; + uint8_t *bin_sid = NULL; + size_t length; + char *sid = NULL; + + err = sss_idmap_unix_to_bin_sid(idmap_ctx, 10000, &bin_sid, &length); + fail_unless(err == IDMAP_NO_DOMAIN, "sss_idmap_unix_to_bin_sid did not detect " + "id out of range"); + + err = sss_idmap_unix_to_bin_sid(idmap_ctx, 2234, &bin_sid, &length); + fail_unless(err == IDMAP_SUCCESS, "sss_idmap_unix_to_bin_sid failed."); + + err = sss_idmap_bin_sid_to_sid(idmap_ctx, bin_sid, length, &sid); + fail_unless(err == IDMAP_SUCCESS, "sss_idmap_bin_sid_to_sid failed."); + + fail_unless(strcmp(sid, "S-1-5-21-1-2-3-1000") == 0, + "sss_idmap_unix_to_bin_sid returned wrong SID, " + "expected [%s], got [%s].", "S-1-5-21-1-2-3-1000", sid); + + talloc_free(sid); + talloc_free(bin_sid); +} +END_TEST + +START_TEST(idmap_test_sid_bin2dom_sid) +{ + struct dom_sid *dom_sid = NULL; + enum idmap_error_code err; + uint8_t *new_bin_sid = NULL; + size_t new_bin_sid_length; + + err = sss_idmap_bin_sid_to_dom_sid(idmap_ctx, test_bin_sid, + test_bin_sid_length, &dom_sid); + + fail_unless(err == IDMAP_SUCCESS, + "Failed to convert binary SID to struct dom_sid."); + + err = sss_idmap_dom_sid_to_bin_sid(idmap_ctx, dom_sid, &new_bin_sid, + &new_bin_sid_length); + fail_unless(err == IDMAP_SUCCESS, + "Failed to convert struct dom_sid to binary SID."); + + fail_unless(new_bin_sid_length == test_bin_sid_length, + "Length of binary SIDs do not match."); + fail_unless(memcmp(test_bin_sid, new_bin_sid, test_bin_sid_length) == 0, + "Binary SIDs do not match."); + + talloc_free(dom_sid); + talloc_free(new_bin_sid); +} +END_TEST + +START_TEST(idmap_test_sid2dom_sid) +{ + struct dom_sid *dom_sid = NULL; + enum idmap_error_code err; + char *new_sid = NULL; + + err = sss_idmap_sid_to_dom_sid(idmap_ctx, "S-1-5-21-1-2-3-1000", &dom_sid); + + fail_unless(err == IDMAP_SUCCESS, + "Failed to convert SID string to struct dom_sid."); + + err = sss_idmap_dom_sid_to_sid(idmap_ctx, dom_sid, &new_sid); + fail_unless(err == IDMAP_SUCCESS, + "Failed to convert struct dom_sid to SID string."); + + fail_unless(new_sid != NULL, "SID string not set"); + fail_unless(strlen("S-1-5-21-1-2-3-1000") == strlen(new_sid), + "Length of SID strings do not match."); + fail_unless(strcmp("S-1-5-21-1-2-3-1000", new_sid) == 0, + "SID strings do not match."); + + talloc_free(dom_sid); + talloc_free(new_sid); +} +END_TEST + +START_TEST(idmap_test_sid2bin_sid) +{ + enum idmap_error_code err; + size_t length; + uint8_t *bin_sid = NULL; + + err = sss_idmap_sid_to_bin_sid(idmap_ctx, test_sid, &bin_sid, &length); + fail_unless(err == IDMAP_SUCCESS, + "Failed to convert SID string to binary sid."); + fail_unless(length == test_bin_sid_length, + "Size of binary SIDs do not match, got [%d], expected [%d]", + length, test_bin_sid_length); + fail_unless(memcmp(bin_sid, test_bin_sid, test_bin_sid_length) == 0, + "Binary SIDs do not match"); + + talloc_free(bin_sid); +} +END_TEST + +START_TEST(idmap_test_bin_sid2sid) +{ + enum idmap_error_code err; + char *sid = NULL; + + err = sss_idmap_bin_sid_to_sid(idmap_ctx, test_bin_sid, test_bin_sid_length, + &sid); + fail_unless(err == IDMAP_SUCCESS, + "Failed to convert binary SID to SID string."); + fail_unless(strcmp(sid, test_sid) == 0, "SID strings do not match"); + + talloc_free(sid); +} +END_TEST + Suite *idmap_test_suite (void) { Suite *s = suite_create ("IDMAP"); @@ -196,6 +382,21 @@ Suite *idmap_test_suite (void) suite_add_tcase(s, tc_dom); + TCase *tc_conv = tcase_create("IDMAP SID conversion tests"); + tcase_add_checked_fixture(tc_conv, + leak_check_setup, + leak_check_teardown); + tcase_add_checked_fixture(tc_conv, + idmap_ctx_setup, + idmap_ctx_teardown); + + tcase_add_test(tc_conv, idmap_test_sid_bin2dom_sid); + tcase_add_test(tc_conv, idmap_test_sid2dom_sid); + tcase_add_test(tc_conv, idmap_test_sid2bin_sid); + tcase_add_test(tc_conv, idmap_test_bin_sid2sid); + + suite_add_tcase(s, tc_conv); + TCase *tc_map = tcase_create("IDMAP mapping tests"); tcase_add_checked_fixture(tc_map, leak_check_setup, @@ -208,9 +409,14 @@ Suite *idmap_test_suite (void) NULL); tcase_add_test(tc_map, idmap_test_sid2uid); + tcase_add_test(tc_map, idmap_test_bin_sid2uid); + tcase_add_test(tc_map, idmap_test_dom_sid2uid); tcase_add_test(tc_map, idmap_test_uid2sid); + tcase_add_test(tc_map, idmap_test_uid2dom_sid); + tcase_add_test(tc_map, idmap_test_uid2bin_sid); suite_add_tcase(s, tc_map); + return s; } int main(int argc, const char *argv[]) -- 1.7.7.6