From 8dc8519dfe8b2cd2bcffa0bf67f29223815c6667 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Thu, 24 May 2012 12:39:56 +0200 Subject: [PATCH] sss_idmap: add support for samba struct dom_sid The samba ndr libraries use struct dom_sid to handle SIDs. Since there is no public samba library which offers conversion from other representations, e.g. as string, this is addded to libsss_idmap. There is only a compile-time dependency to the samba header files to check if struct dom_sid has the expected format. There is no run-time dependency to any samba library. --- Makefile.am | 3 + configure.ac | 1 + src/external/dom_sid.m4 | 65 ++++++++++++++ src/lib/idmap/sss_idmap.h | 107 +++++++++++++++++++++++ src/lib/idmap/sss_idmap_conv.c | 183 ++++++++++++++++++++++++++++++++++++++++ src/tests/sss_idmap-tests.c | 104 ++++++++++++++++++++++- 6 files changed, 461 insertions(+), 2 deletions(-) create mode 100644 src/external/dom_sid.m4 diff --git a/Makefile.am b/Makefile.am index a6c2f90..5092413 100644 --- a/Makefile.am +++ b/Makefile.am @@ -499,6 +499,8 @@ dist_pkgconfig_DATA += src/lib/idmap/sss_idmap.pc libsss_idmap_la_SOURCES = \ src/lib/idmap/sss_idmap.c \ src/lib/idmap/sss_idmap_conv.c +libsss_idmap_la_CFLAGS = \ + $(NDR_CFLAGS) libsss_idmap_la_LDFLAGS = \ -version-info 0:1:0 @@ -956,6 +958,7 @@ sss_idmap_tests_SOURCES = \ src/tests/sss_idmap-tests.c sss_idmap_tests_CFLAGS = \ $(AM_CFLAGS) \ + $(NDR_CFLAGS) \ $(CHECK_CFLAGS) sss_idmap_tests_LDADD = \ $(CHECK_LIBS) \ diff --git a/configure.ac b/configure.ac index d4647d8..1a432c4 100644 --- a/configure.ac +++ b/configure.ac @@ -124,6 +124,7 @@ m4_include([src/external/nsupdate.m4]) m4_include([src/external/libkeyutils.m4]) m4_include([src/external/libnl.m4]) m4_include([src/external/systemd.m4]) +m4_include([src/external/dom_sid.m4]) m4_include([src/util/signal.m4]) WITH_UNICODE_LIB diff --git a/src/external/dom_sid.m4 b/src/external/dom_sid.m4 new file mode 100644 index 0000000..0088008 --- /dev/null +++ b/src/external/dom_sid.m4 @@ -0,0 +1,65 @@ +AC_SUBST(NDR_CFLAGS) +AC_SUBST(NDR_LIBS) +PKG_CHECK_MODULES(NDR, ndr,, + AC_MSG_ERROR([Cannot check struct dom_sid without ndr header installed])) +SAVE_CFLAGS=$CFLAGS +CFLAGS="$CFLAGS $NDR_CFLAGS" +dnl Since the names of the checked components are used as parts of variable +dnl names by autoconf it is not possible to use the [] index notation directly. +dnl As a workaround I used the define apporach below +AC_CHECK_MEMBERS([struct dom_sid.sid_rev_num, + struct dom_sid.num_auths, + struct dom_sid.id_auth0, + struct dom_sid.id_auth1, + struct dom_sid.id_auth2, + struct dom_sid.id_auth3, + struct dom_sid.id_auth4, + struct dom_sid.id_auth5, + struct dom_sid.sub_auths0, + struct dom_sid.sub_auths1, + struct dom_sid.sub_auths2, + struct dom_sid.sub_auths3, + struct dom_sid.sub_auths4, + struct dom_sid.sub_auths5, + struct dom_sid.sub_auths6, + struct dom_sid.sub_auths7, + struct dom_sid.sub_auths8, + struct dom_sid.sub_auths9, + struct dom_sid.sub_auths10, + struct dom_sid.sub_auths11, + struct dom_sid.sub_auths12, + struct dom_sid.sub_auths13, + struct dom_sid.sub_auths14], + [AC_DEFINE([HAVE_VALID_DOM_SID], + [1], + [Define if struct dom_sid has all expected members.])], + [AC_MSG_ERROR([struct dom_sid does not has all expected members.])], + [[#include + #include + #include + #include + #define id_auth0 id_auth[0] + #define id_auth1 id_auth[1] + #define id_auth2 id_auth[2] + #define id_auth3 id_auth[3] + #define id_auth4 id_auth[4] + #define id_auth5 id_auth[5] + #define sub_auths0 sub_auths[0] + #define sub_auths1 sub_auths[1] + #define sub_auths2 sub_auths[2] + #define sub_auths3 sub_auths[3] + #define sub_auths4 sub_auths[4] + #define sub_auths5 sub_auths[5] + #define sub_auths6 sub_auths[6] + #define sub_auths7 sub_auths[7] + #define sub_auths8 sub_auths[8] + #define sub_auths9 sub_auths[9] + #define sub_auths10 sub_auths[10] + #define sub_auths11 sub_auths[11] + #define sub_auths12 sub_auths[12] + #define sub_auths13 sub_auths[13] + #define sub_auths14 sub_auths[14] + #define sub_auths15 sub_auths[15] + ]]) + +CFLAGS=$SAVE_CFLAGS diff --git a/src/lib/idmap/sss_idmap.h b/src/lib/idmap/sss_idmap.h index a3ec919..6b7cbe5 100644 --- a/src/lib/idmap/sss_idmap.h +++ b/src/lib/idmap/sss_idmap.h @@ -98,6 +98,13 @@ struct sss_dom_sid; struct sss_idmap_ctx; /** + * Placeholder for Samba's struct dom_sid. Consumers of libsss_idmap should + * include an appropriate Samba header file to define struct dom_sid. We use + * it here to avoid a hard dependency on Samba devel packages. + */ +struct dom_sid; + +/** * @brief Initialize idmap context * * @param[in] alloc_func Function to allocate memory for the context, if @@ -375,6 +382,106 @@ enum idmap_error_code sss_idmap_dom_sid_to_sid(struct sss_idmap_ctx *ctx, enum idmap_error_code sss_idmap_sid_to_dom_sid(struct sss_idmap_ctx *ctx, const char *sid, struct sss_dom_sid **dom_sid); + +/** + * @brief Convert SID string to Samba dom_sid structure + * + * @param[in] ctx Idmap context + * @param[in] sid Zero-terminated string representation of the SID + * @param[out] smb_sid Samba dom_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_smb_sid(struct sss_idmap_ctx *ctx, + const char *sid, + struct dom_sid **smb_sid); + +/** + * @brief Convert Samba dom_sid structure to SID string + * + * @param[in] ctx Idmap context + * @param[in] smb_sid Samba dom_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_smb_sid_to_sid(struct sss_idmap_ctx *ctx, + struct dom_sid *smb_sid, + char **sid); + +/** + * @brief Convert SID stucture to Samba dom_sid structure + * + * @param[in] ctx Idmap context + * @param[in] dom_sid SID structure + * @param[out] smb_sid Samba dom_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_dom_sid_to_smb_sid(struct sss_idmap_ctx *ctx, + struct sss_dom_sid *dom_sid, + struct dom_sid **smb_sid); + +/** + * @brief Convert Samba dom_sid structure to SID structure + * + * @param[in] ctx Idmap context + * @param[in] smb_sid Samba dom_sid structure + * @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_smb_sid_to_dom_sid(struct sss_idmap_ctx *ctx, + struct dom_sid *smb_sid, + struct sss_dom_sid **dom_sid); + +/** + * @brief Convert binary SID to Samba dom_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] smb_sid Samba dom_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_smb_sid(struct sss_idmap_ctx *ctx, + const uint8_t *bin_sid, + size_t length, + struct dom_sid **smb_sid); + +/** + * @brief Convert Samba dom_sid structure to binary SID + * + * @param[in] ctx Idmap context + * @param[in] smb_sid Samba dom_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_smb_sid_to_bin_sid(struct sss_idmap_ctx *ctx, + struct dom_sid *smb_sid, + uint8_t **bin_sid, + size_t *length); /** * @} */ diff --git a/src/lib/idmap/sss_idmap_conv.c b/src/lib/idmap/sss_idmap_conv.c index df96fcc..d74df8c 100644 --- a/src/lib/idmap/sss_idmap_conv.c +++ b/src/lib/idmap/sss_idmap_conv.c @@ -31,6 +31,10 @@ #include "lib/idmap/sss_idmap_private.h" #include "util/util.h" +#include +#include +#include + #define SID_ID_AUTHS 6 #define SID_SUB_AUTHS 15 struct sss_dom_sid { @@ -59,6 +63,7 @@ enum idmap_error_code sss_idmap_bin_sid_to_dom_sid(struct sss_idmap_ctx *ctx, if (dom_sid == NULL) { return IDMAP_OUT_OF_MEMORY; } + memset(dom_sid, 0, sizeof(struct sss_dom_sid)); /* Safely copy in the SID revision number */ dom_sid->sid_rev_num = (uint8_t) *(bin_sid + p); @@ -387,3 +392,181 @@ done: return err; } + +enum idmap_error_code sss_idmap_sid_to_smb_sid(struct sss_idmap_ctx *ctx, + const char *sid, + struct dom_sid **_smb_sid) +{ + enum idmap_error_code err; + struct sss_dom_sid *dom_sid = NULL; + struct dom_sid *smb_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_smb_sid(ctx, dom_sid, &smb_sid); + if (err != IDMAP_SUCCESS) { + goto done; + } + + *_smb_sid = smb_sid; + err = IDMAP_SUCCESS; + +done: + talloc_free(dom_sid); + if (err != IDMAP_SUCCESS) { + talloc_free(smb_sid); + } + + return err; +} + +enum idmap_error_code sss_idmap_smb_sid_to_sid(struct sss_idmap_ctx *ctx, + struct dom_sid *smb_sid, + char **_sid) +{ + enum idmap_error_code err; + struct sss_dom_sid *dom_sid = NULL; + char *sid = NULL; + + err = sss_idmap_smb_sid_to_dom_sid(ctx, smb_sid, &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: + talloc_free(dom_sid); + if (err != IDMAP_SUCCESS) { + talloc_free(sid); + } + + return err; +} + +enum idmap_error_code sss_idmap_dom_sid_to_smb_sid(struct sss_idmap_ctx *ctx, + struct sss_dom_sid *dom_sid, + struct dom_sid **_smb_sid) +{ + struct dom_sid *smb_sid; + size_t c; + + smb_sid = ctx->alloc_func(sizeof(struct dom_sid), ctx->alloc_pvt); + if (smb_sid == NULL) { + return IDMAP_OUT_OF_MEMORY; + } + memset(smb_sid, 0, sizeof(struct dom_sid)); + + smb_sid->sid_rev_num = dom_sid->sid_rev_num; + smb_sid->num_auths = dom_sid->num_auths; + for (c = 0; c < SID_ID_AUTHS; c++) { + smb_sid->id_auth[c] = dom_sid->id_auth[c]; + } + for (c = 0; c < SID_SUB_AUTHS; c++) { + smb_sid->sub_auths[c] = dom_sid->sub_auths[c]; + } + + *_smb_sid = smb_sid; + + return IDMAP_SUCCESS; +} + +enum idmap_error_code sss_idmap_smb_sid_to_dom_sid(struct sss_idmap_ctx *ctx, + struct dom_sid *smb_sid, + struct sss_dom_sid **_dom_sid) +{ + struct sss_dom_sid *dom_sid; + size_t c; + + dom_sid = ctx->alloc_func(sizeof(struct sss_dom_sid), ctx->alloc_pvt); + if (dom_sid == NULL) { + return IDMAP_OUT_OF_MEMORY; + } + memset(dom_sid, 0, sizeof(struct sss_dom_sid)); + + dom_sid->sid_rev_num = smb_sid->sid_rev_num; + dom_sid->num_auths = smb_sid->num_auths; + for (c = 0; c < SID_ID_AUTHS; c++) { + dom_sid->id_auth[c] = smb_sid->id_auth[c]; + } + for (c = 0; c < SID_SUB_AUTHS; c++) { + dom_sid->sub_auths[c] = smb_sid->sub_auths[c]; + } + + *_dom_sid = dom_sid; + + return IDMAP_SUCCESS; +} + +enum idmap_error_code sss_idmap_bin_sid_to_smb_sid(struct sss_idmap_ctx *ctx, + const uint8_t *bin_sid, + size_t length, + struct dom_sid **_smb_sid) +{ + enum idmap_error_code err; + struct sss_dom_sid *dom_sid = NULL; + struct dom_sid *smb_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_smb_sid(ctx, dom_sid, &smb_sid); + if (err != IDMAP_SUCCESS) { + goto done; + } + + *_smb_sid = smb_sid; + err = IDMAP_SUCCESS; + +done: + talloc_free(dom_sid); + if (err != IDMAP_SUCCESS) { + talloc_free(smb_sid); + } + + return err; +} + +enum idmap_error_code sss_idmap_smb_sid_to_bin_sid(struct sss_idmap_ctx *ctx, + struct dom_sid *smb_sid, + uint8_t **_bin_sid, + size_t *_length) +{ + enum idmap_error_code err; + struct sss_dom_sid *dom_sid = NULL; + uint8_t *bin_sid = NULL; + size_t length; + + err = sss_idmap_smb_sid_to_dom_sid(ctx, smb_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; + } + + *_bin_sid = bin_sid; + *_length = length; + err = IDMAP_SUCCESS; + +done: + talloc_free(dom_sid); + if (err != IDMAP_SUCCESS) { + talloc_free(bin_sid); + } + + return err; +} diff --git a/src/tests/sss_idmap-tests.c b/src/tests/sss_idmap-tests.c index b821dfc..a7d5f57 100644 --- a/src/tests/sss_idmap-tests.c +++ b/src/tests/sss_idmap-tests.c @@ -21,6 +21,9 @@ */ #include +#include +#include +#include #include "lib/idmap/sss_idmap.h" #include "tests/common.h" @@ -35,6 +38,8 @@ uint8_t test_bin_sid[] = {0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x15, 0x00}; size_t test_bin_sid_length = sizeof(test_bin_sid); +struct dom_sid test_smb_sid = {1, 5, {0, 0, 0, 0, 0, 5}, {21, 2127521184, 1604012920, 1887927527, 72713, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; + struct sss_idmap_ctx *idmap_ctx; static void *idmap_talloc(size_t size, void *pvt) @@ -267,7 +272,7 @@ START_TEST(idmap_test_uid2bin_sid) } END_TEST -START_TEST(idmap_test_sid_bin2dom_sid) +START_TEST(idmap_test_bin_sid2dom_sid) { struct sss_dom_sid *dom_sid = NULL; enum idmap_error_code err; @@ -357,6 +362,96 @@ START_TEST(idmap_test_bin_sid2sid) } END_TEST +START_TEST(idmap_test_smb_sid2dom_sid) +{ + struct sss_dom_sid *dom_sid = NULL; + enum idmap_error_code err; + struct dom_sid *new_smb_sid = NULL; + + err = sss_idmap_smb_sid_to_dom_sid(idmap_ctx, &test_smb_sid, &dom_sid); + fail_unless(err == IDMAP_SUCCESS, + "Failed to convert samba dom_sid to struct sss_dom_sid."); + + err = sss_idmap_dom_sid_to_smb_sid(idmap_ctx, dom_sid, &new_smb_sid); + fail_unless(err == IDMAP_SUCCESS, + "Failed to convert struct sss_dom_sid to samba dom_sid."); + + fail_unless(memcmp(&test_smb_sid, new_smb_sid, sizeof(struct dom_sid)) == 0, + "Samba dom_sid-s do not match."); + + talloc_free(dom_sid); + talloc_free(new_smb_sid); +} +END_TEST + +START_TEST(idmap_test_smb_sid2bin_sid) +{ + enum idmap_error_code err; + size_t length; + uint8_t *bin_sid = NULL; + + err = sss_idmap_smb_sid_to_bin_sid(idmap_ctx, &test_smb_sid, + &bin_sid, &length); + fail_unless(err == IDMAP_SUCCESS, + "Failed to convert samba dom_sid 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_sid2smb_sid) +{ + enum idmap_error_code err; + struct dom_sid *smb_sid = NULL; + + err = sss_idmap_bin_sid_to_smb_sid(idmap_ctx, test_bin_sid, + test_bin_sid_length, &smb_sid); + fail_unless(err == IDMAP_SUCCESS, + "Failed to convert binary sid to samba dom_sid."); + fail_unless(memcmp(&test_smb_sid, smb_sid, sizeof(struct dom_sid)) == 0, + "Samba dom_sid structs do not match."); + + talloc_free(smb_sid); +} +END_TEST + +START_TEST(idmap_test_smb_sid2sid) +{ + enum idmap_error_code err; + char *sid = NULL; + + err = sss_idmap_smb_sid_to_sid(idmap_ctx, &test_smb_sid, &sid); + fail_unless(err == IDMAP_SUCCESS, + "Failed to convert samba dom_sid to sid string."); + fail_unless(strcmp(sid, test_sid) == 0, "SID strings do not match, " + "expected [%s], get [%s]", + test_sid, sid); + + talloc_free(sid); +} +END_TEST + +START_TEST(idmap_test_sid2smb_sid) +{ + enum idmap_error_code err; + struct dom_sid *smb_sid = NULL; + + err = sss_idmap_sid_to_smb_sid(idmap_ctx, test_sid, &smb_sid); + fail_unless(err == IDMAP_SUCCESS, + "Failed to convert binary sid to samba dom_sid."); + fail_unless(memcmp(&test_smb_sid, smb_sid, sizeof(struct dom_sid)) == 0, + "Samba dom_sid structs do not match."); + + talloc_free(smb_sid); +} +END_TEST + + Suite *idmap_test_suite (void) { Suite *s = suite_create ("IDMAP"); @@ -392,10 +487,15 @@ Suite *idmap_test_suite (void) idmap_ctx_setup, idmap_ctx_teardown); - tcase_add_test(tc_conv, idmap_test_sid_bin2dom_sid); + tcase_add_test(tc_conv, idmap_test_bin_sid2dom_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); + tcase_add_test(tc_conv, idmap_test_smb_sid2dom_sid); + tcase_add_test(tc_conv, idmap_test_smb_sid2bin_sid); + tcase_add_test(tc_conv, idmap_test_bin_sid2smb_sid); + tcase_add_test(tc_conv, idmap_test_smb_sid2sid); + tcase_add_test(tc_conv, idmap_test_sid2smb_sid); suite_add_tcase(s, tc_conv); -- 1.7.7.6