diff --git a/0045-sdap_connect_send-fail-if-uri-or-sockaddr-is-NULL.patch b/0045-sdap_connect_send-fail-if-uri-or-sockaddr-is-NULL.patch new file mode 100644 index 0000000..a889617 --- /dev/null +++ b/0045-sdap_connect_send-fail-if-uri-or-sockaddr-is-NULL.patch @@ -0,0 +1,37 @@ +From 62ae069bc8c559f4814f64504335475edc522622 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Tue, 19 Jan 2016 13:30:58 +0100 +Subject: [PATCH 45/55] sdap_connect_send: fail if uri or sockaddr is NULL +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: +https://fedorahosted.org/sssd/ticket/2904 + +Reviewed-by: Michal Židek +(cherry picked from commit 8bd9ec3a8885b01a34863d22aa784e221fc422fb) +--- + src/providers/ldap/sdap_async_connection.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c +index 8f5227d263f995693f6e65bd238171538aa52af7..85b7aaa5bf5acedf3511ffe6f8636be007d5a136 100644 +--- a/src/providers/ldap/sdap_async_connection.c ++++ b/src/providers/ldap/sdap_async_connection.c +@@ -75,6 +75,12 @@ struct tevent_req *sdap_connect_send(TALLOC_CTX *memctx, + req = tevent_req_create(memctx, &state, struct sdap_connect_state); + if (!req) return NULL; + ++ if (uri == NULL || sockaddr == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid uri or sockaddr\n"); ++ ret = EINVAL; ++ goto fail; ++ } ++ + state->reply = talloc(state, struct sdap_msg); + if (!state->reply) { + talloc_zfree(req); +-- +2.5.0 + diff --git a/0046-SDAP-Make-it-possible-to-silence-errors-from-derefer.patch b/0046-SDAP-Make-it-possible-to-silence-errors-from-derefer.patch new file mode 100644 index 0000000..4ec8f06 --- /dev/null +++ b/0046-SDAP-Make-it-possible-to-silence-errors-from-derefer.patch @@ -0,0 +1,136 @@ +From 199a9d29c3e56c1c341fb331cfe790b35736a1f2 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Tue, 19 Jan 2016 14:54:45 +0100 +Subject: [PATCH 46/55] SDAP: Make it possible to silence errors from + dereference +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +https://fedorahosted.org/sssd/ticket/2791 + +When a modern IPA client is connected to an old (3.x) IPA server, the +attribute dereferenced during the ID views lookup does not exist, which +triggers an error during the dereference processing and also a confusing +syslog message. + +This patch suppresses the syslog message. + +Reviewed-by: Michal Židek +(cherry picked from commit 95c132e1a8c6bbab4be8b3a340333fadd8076122) +--- + src/providers/ipa/ipa_subdomains.c | 6 +++++- + src/providers/ldap/sdap_async.c | 25 +++++++++++++++++-------- + src/providers/ldap/sdap_async.h | 7 ++++++- + 3 files changed, 28 insertions(+), 10 deletions(-) + +diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c +index cd78506ffc59c392da4e834c764c9ca82dbc89b0..f13847f12a7eae42b13a51e3fe1d09b60878633b 100644 +--- a/src/providers/ipa/ipa_subdomains.c ++++ b/src/providers/ipa/ipa_subdomains.c +@@ -792,6 +792,9 @@ static errno_t ipa_get_view_name(struct ipa_subdomains_req_ctx *ctx) + return EOK; + } + ++ /* We add SDAP_DEREF_FLG_SILENT because old IPA servers don't have ++ * the attribute we dereference, causing the deref call to fail ++ */ + req = sdap_deref_search_with_filter_send(ctx, ctx->sd_ctx->be_ctx->ev, + ctx->sd_ctx->sdap_id_ctx->opts, + sdap_id_op_handle(ctx->sdap_op), +@@ -799,7 +802,8 @@ static errno_t ipa_get_view_name(struct ipa_subdomains_req_ctx *ctx) + ctx->current_filter, IPA_ASSIGNED_ID_VIEW, attrs, + 1, maps, + dp_opt_get_int(ctx->sd_ctx->sdap_id_ctx->opts->basic, +- SDAP_SEARCH_TIMEOUT)); ++ SDAP_SEARCH_TIMEOUT), ++ SDAP_DEREF_FLG_SILENT); + + if (req == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send failed.\n"); +diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c +index 5260aafebf7570291876b2433dbcf44ffb5b0011..6cc32323b4a4c43023a50e10a3a003bc4b2b8994 100644 +--- a/src/providers/ldap/sdap_async.c ++++ b/src/providers/ldap/sdap_async.c +@@ -2763,6 +2763,7 @@ struct sdap_deref_search_state { + size_t reply_count; + struct sdap_deref_attrs **reply; + enum sdap_deref_type deref_type; ++ unsigned flags; + }; + + static void sdap_deref_search_done(struct tevent_req *subreq); +@@ -2779,7 +2780,8 @@ sdap_deref_search_with_filter_send(TALLOC_CTX *memctx, + const char **attrs, + int num_maps, + struct sdap_attr_map_info *maps, +- int timeout) ++ int timeout, ++ unsigned flags) + { + struct tevent_req *req = NULL; + struct tevent_req *subreq = NULL; +@@ -2791,6 +2793,7 @@ sdap_deref_search_with_filter_send(TALLOC_CTX *memctx, + state->sh = sh; + state->reply_count = 0; + state->reply = NULL; ++ state->flags = flags; + + if (sdap_is_control_supported(sh, LDAP_CONTROL_X_DEREF)) { + DEBUG(SSSDBG_TRACE_INTERNAL, "Server supports OpenLDAP deref\n"); +@@ -2917,14 +2920,20 @@ static void sdap_deref_search_done(struct tevent_req *subreq) + DEBUG(SSSDBG_OP_FAILURE, + "dereference processing failed [%d]: %s\n", ret, strerror(ret)); + if (ret == ENOTSUP) { +- sss_log(SSS_LOG_WARNING, +- "LDAP server claims to support deref, but deref search failed. " +- "Disabling deref for further requests. You can permanently " +- "disable deref by setting ldap_deref_threshold to 0 in domain " +- "configuration."); + state->sh->disable_deref = true; +- } else { +- sss_log(SSS_LOG_WARNING, "dereference processing failed : %s", strerror(ret)); ++ } ++ ++ if (!(state->flags & SDAP_DEREF_FLG_SILENT)) { ++ if (ret == ENOTSUP) { ++ sss_log(SSS_LOG_WARNING, ++ "LDAP server claims to support deref, but deref search " ++ "failed. Disabling deref for further requests. You can " ++ "permanently disable deref by setting " ++ "ldap_deref_threshold to 0 in domain configuration."); ++ } else { ++ sss_log(SSS_LOG_WARNING, ++ "dereference processing failed : %s", strerror(ret)); ++ } + } + tevent_req_error(req, ret); + return; +diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h +index 09bc0d65407253f93514b30877850cc38009c625..f86f1890bc2971ede4fe70f42154d7bc39c43ac6 100644 +--- a/src/providers/ldap/sdap_async.h ++++ b/src/providers/ldap/sdap_async.h +@@ -227,6 +227,10 @@ int sdap_get_generic_recv(struct tevent_req *req, + + bool sdap_has_deref_support(struct sdap_handle *sh, struct sdap_options *opts); + ++enum sdap_deref_flags { ++ SDAP_DEREF_FLG_SILENT = 1 << 0, /* Do not warn if dereference fails */ ++}; ++ + struct tevent_req * + sdap_deref_search_with_filter_send(TALLOC_CTX *memctx, + struct tevent_context *ev, +@@ -238,7 +242,8 @@ sdap_deref_search_with_filter_send(TALLOC_CTX *memctx, + const char **attrs, + int num_maps, + struct sdap_attr_map_info *maps, +- int timeout); ++ int timeout, ++ unsigned flags); + int sdap_deref_search_with_filter_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + size_t *reply_count, +-- +2.5.0 + diff --git a/0047-p11-add-gnome-screensaver-to-list-of-allowed-service.patch b/0047-p11-add-gnome-screensaver-to-list-of-allowed-service.patch new file mode 100644 index 0000000..cff172a --- /dev/null +++ b/0047-p11-add-gnome-screensaver-to-list-of-allowed-service.patch @@ -0,0 +1,29 @@ +From 20623658d24b860b2d13ae2da4a22ce7151394d9 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Thu, 14 Jan 2016 11:42:26 +0100 +Subject: [PATCH 47/55] p11: add gnome-screensaver to list of allowed services + +Resolves https://fedorahosted.org/sssd/ticket/2925 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit e9c42ec738c213bd5f351567c20d404a280b32d0) +--- + src/responder/pam/pamsrv_p11.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/responder/pam/pamsrv_p11.c b/src/responder/pam/pamsrv_p11.c +index ea428a6a3dd41b1770b69ff0301ed98c1c08c01d..ad1670136dbf8efc41df6950af744ff8b06e6a11 100644 +--- a/src/responder/pam/pamsrv_p11.c ++++ b/src/responder/pam/pamsrv_p11.c +@@ -45,7 +45,7 @@ bool may_do_cert_auth(struct pam_ctx *pctx, struct pam_data *pd) + size_t c; + const char *sc_services[] = { "login", "su", "su-l", "gdm-smartcard", + "gdm-password", "kdm", "sudo", "sudo-i", +- NULL }; ++ "gnome-screensaver", NULL }; + if (!pctx->cert_auth) { + return false; + } +-- +2.5.0 + diff --git a/0048-IDMAP-Fix-computing-max-id-for-slice-range.patch b/0048-IDMAP-Fix-computing-max-id-for-slice-range.patch new file mode 100644 index 0000000..28210e4 --- /dev/null +++ b/0048-IDMAP-Fix-computing-max-id-for-slice-range.patch @@ -0,0 +1,50 @@ +From 2fe18a1614007d20ffaa74387e162b5af4dcafb0 Mon Sep 17 00:00:00 2001 +From: Pavel Reichl +Date: Wed, 13 Jan 2016 09:07:39 -0500 +Subject: [PATCH 48/55] IDMAP: Fix computing max id for slice range + +Max value of id mapping range was 1 unit too high. + +Resolves: +https://fedorahosted.org/sssd/ticket/2922 + +Reviewed-by: Sumit Bose +(cherry picked from commit 7db89d44b5582a0cb0a61a7aa42a2fac7ca9408f) +--- + src/lib/idmap/sss_idmap.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/lib/idmap/sss_idmap.c b/src/lib/idmap/sss_idmap.c +index 4c453120539a549807e9b6bb4db2dc396c1b3152..b5457f92dbb91ac5109ad17258920549e8808d26 100644 +--- a/src/lib/idmap/sss_idmap.c ++++ b/src/lib/idmap/sss_idmap.c +@@ -336,7 +336,7 @@ enum idmap_error_code sss_idmap_calculate_range(struct sss_idmap_ctx *ctx, + } + + min = (rangesize * new_slice) + idmap_lower; +- max = min + rangesize; ++ max = min + rangesize - 1; + /* Verify that this slice is not already in use */ + do { + for (dom = ctx->idmap_domain_info; dom != NULL; dom = dom->next) { +@@ -353,7 +353,7 @@ enum idmap_error_code sss_idmap_calculate_range(struct sss_idmap_ctx *ctx, + } + + min = (rangesize * new_slice) + idmap_lower; +- max = min + rangesize; ++ max = min + rangesize - 1; + break; + } + } +@@ -371,7 +371,7 @@ enum idmap_error_code sss_idmap_calculate_range(struct sss_idmap_ctx *ctx, + } + + _range->min = (rangesize * new_slice) + idmap_lower; +- _range->max = _range->min + rangesize; ++ _range->max = _range->min + rangesize - 1; + + if (slice_num) { + *slice_num = new_slice; +-- +2.5.0 + diff --git a/0049-IDMAP-New-structure-for-domain-range-params.patch b/0049-IDMAP-New-structure-for-domain-range-params.patch new file mode 100644 index 0000000..3e61fe0 --- /dev/null +++ b/0049-IDMAP-New-structure-for-domain-range-params.patch @@ -0,0 +1,238 @@ +From 3cc105df9f064a4380dc01010f470025217964e7 Mon Sep 17 00:00:00 2001 +From: Pavel Reichl +Date: Thu, 26 Nov 2015 10:46:34 -0500 +Subject: [PATCH 49/55] IDMAP: New structure for domain range params + +Create new internal structure idmap_range_params by merging ID mapping +range relevant fields from idmap_domain_info and remove corrsponding +fields. + +Resolves: +https://fedorahosted.org/sssd/ticket/2188 + +Reviewed-by: Sumit Bose +(cherry picked from commit c3cdd6a644a870531092e4378cbcd1a428ff514c) +--- + src/lib/idmap/sss_idmap.c | 117 ++++++++++++++++++++++++---------------------- + 1 file changed, 60 insertions(+), 57 deletions(-) + +diff --git a/src/lib/idmap/sss_idmap.c b/src/lib/idmap/sss_idmap.c +index b5457f92dbb91ac5109ad17258920549e8808d26..23ed46a583547a3f2f0bca5ab62824bd045e56b9 100644 +--- a/src/lib/idmap/sss_idmap.c ++++ b/src/lib/idmap/sss_idmap.c +@@ -33,13 +33,21 @@ + #define SID_FMT "%s-%d" + #define SID_STR_MAX_LEN 1024 + ++/* Hold all parameters for unix<->sid mapping relevant for ++ * given slice. */ ++struct idmap_range_params { ++ uint32_t min_id; ++ uint32_t max_id; ++ char *range_id; ++ ++ uint32_t first_rid; ++}; ++ + struct idmap_domain_info { + char *name; + char *sid; +- struct sss_idmap_range *range; ++ struct idmap_range_params range_params; + struct idmap_domain_info *next; +- uint32_t first_rid; +- char *range_id; + bool external_mapping; + }; + +@@ -72,37 +80,17 @@ static char *idmap_strdup(struct sss_idmap_ctx *ctx, const char *str) + return new; + } + +-static struct sss_idmap_range *idmap_range_dup(struct sss_idmap_ctx *ctx, +- struct sss_idmap_range *range) +-{ +- struct sss_idmap_range *new = NULL; +- +- CHECK_IDMAP_CTX(ctx, NULL); +- +- +- new = ctx->alloc_func(sizeof(struct sss_idmap_range), ctx->alloc_pvt); +- if (new == NULL) { +- return NULL; +- } +- +- memset(new, 0, sizeof(struct sss_idmap_range)); +- +- new->min = range->min; +- new->max = range->max; +- +- return new; +-} +- +-static bool id_is_in_range(uint32_t id, struct idmap_domain_info *dom, ++static bool id_is_in_range(uint32_t id, ++ struct idmap_range_params *rp, + uint32_t *rid) + { +- if (id == 0 || dom == NULL || dom->range == NULL) { ++ if (id == 0 || rp == NULL) { + return false; + } + +- if (id >= dom->range->min && id <= dom->range->max) { ++ if (id >= rp->min_id && id <= rp->max_id) { + if (rid != NULL) { +- *rid = dom->first_rid + (id - dom->range->min); ++ *rid = rp->first_rid + (id - rp->min_id); + } + + return true; +@@ -220,8 +208,7 @@ static void sss_idmap_free_domain(struct sss_idmap_ctx *ctx, + return; + } + +- ctx->free_func(dom->range_id, ctx->alloc_pvt); +- ctx->free_func(dom->range, ctx->alloc_pvt); ++ ctx->free_func(dom->range_params.range_id, ctx->alloc_pvt); + ctx->free_func(dom->name, ctx->alloc_pvt); + ctx->free_func(dom->sid, ctx->alloc_pvt); + ctx->free_func(dom, ctx->alloc_pvt); +@@ -340,9 +327,12 @@ enum idmap_error_code sss_idmap_calculate_range(struct sss_idmap_ctx *ctx, + /* Verify that this slice is not already in use */ + do { + for (dom = ctx->idmap_domain_info; dom != NULL; dom = dom->next) { +- if ((dom->range->min <= min && dom->range->max >= max) || +- (dom->range->min >= min && dom->range->min <= max) || +- (dom->range->max >= min && dom->range->max <= max)) { ++ uint32_t dmin = dom->range_params.min_id; ++ uint32_t dmax = dom->range_params.max_id; ++ ++ if ((dmin <= min && dmax >= max) || ++ (dmin >= min && dmin <= max) || ++ (dmax >= min && dmax <= max)) { + /* This range overlaps one already registered + * We'll try the next available slot + */ +@@ -445,10 +435,17 @@ enum idmap_error_code sss_idmap_check_collision(struct sss_idmap_ctx *ctx, + { + struct idmap_domain_info *dom; + enum idmap_error_code err; ++ struct sss_idmap_range range; + + for (dom = ctx->idmap_domain_info; dom != NULL; dom = dom->next) { +- err = sss_idmap_check_collision_ex(dom->name, dom->sid, dom->range, +- dom->first_rid, dom->range_id, ++ ++ range.min = dom->range_params.min_id; ++ range.max = dom->range_params.max_id; ++ ++ err = sss_idmap_check_collision_ex(dom->name, dom->sid, ++ &range, ++ dom->range_params.first_rid, ++ dom->range_params.range_id, + dom->external_mapping, + n_name, n_sid, n_range, n_first_rid, + n_range_id, n_external_mapping); +@@ -459,20 +456,29 @@ enum idmap_error_code sss_idmap_check_collision(struct sss_idmap_ctx *ctx, + return IDMAP_SUCCESS; + } + +-static enum idmap_error_code dom_check_collision( +- struct idmap_domain_info *dom_list, +- struct idmap_domain_info *new_dom) ++static enum ++idmap_error_code dom_check_collision(struct idmap_domain_info *dom_list, ++ struct idmap_domain_info *new_dom) + { + struct idmap_domain_info *dom; + enum idmap_error_code err; ++ struct sss_idmap_range range; ++ struct sss_idmap_range new_dom_range = { new_dom->range_params.min_id, ++ new_dom->range_params.max_id }; + + for (dom = dom_list; dom != NULL; dom = dom->next) { +- err = sss_idmap_check_collision_ex(dom->name, dom->sid, dom->range, +- dom->first_rid, dom->range_id, ++ range.min = dom->range_params.min_id; ++ range.max = dom->range_params.max_id; ++ ++ err = sss_idmap_check_collision_ex(dom->name, dom->sid, ++ &range, ++ dom->range_params.first_rid, ++ dom->range_params.range_id, + dom->external_mapping, + new_dom->name, new_dom->sid, +- new_dom->range, new_dom->first_rid, +- new_dom->range_id, ++ &new_dom_range, ++ new_dom->range_params.first_rid, ++ new_dom->range_params.range_id, + new_dom->external_mapping); + if (err != IDMAP_SUCCESS) { + return err; +@@ -531,21 +537,18 @@ enum idmap_error_code sss_idmap_add_domain_ex(struct sss_idmap_ctx *ctx, + } + } + +- dom->range = idmap_range_dup(ctx, range); +- if (dom->range == NULL) { +- err = IDMAP_OUT_OF_MEMORY; +- goto fail; +- } ++ dom->range_params.min_id = range->min; ++ dom->range_params.max_id = range->max; + + if (range_id != NULL) { +- dom->range_id = idmap_strdup(ctx, range_id); +- if (dom->range_id == NULL) { ++ dom->range_params.range_id = idmap_strdup(ctx, range_id); ++ if (dom->range_params.range_id == NULL) { + err = IDMAP_OUT_OF_MEMORY; + goto fail; + } + } + +- dom->first_rid = rid; ++ dom->range_params.first_rid = rid; + dom->external_mapping = external_mapping; + + err = dom_check_collision(ctx->idmap_domain_info, dom); +@@ -621,10 +624,10 @@ enum idmap_error_code sss_idmap_sid_to_unix(struct sss_idmap_ctx *ctx, + return IDMAP_SID_INVALID; + } + +- if (rid >= idmap_domain_info->first_rid) { +- id = idmap_domain_info->range->min +- + (rid - idmap_domain_info->first_rid); +- if (id <= idmap_domain_info->range->max) { ++ if (rid >= idmap_domain_info->range_params.first_rid) { ++ id = idmap_domain_info->range_params.min_id ++ + (rid - idmap_domain_info->range_params.first_rid); ++ if (id <= idmap_domain_info->range_params.max_id) { + *_id = id; + return IDMAP_SUCCESS; + } +@@ -670,8 +673,8 @@ enum idmap_error_code sss_idmap_check_sid_unix(struct sss_idmap_ctx *ctx, + if (strlen(sid) > dom_len && sid[dom_len] == '-' + && strncmp(sid, idmap_domain_info->sid, dom_len) == 0) { + +- if (id >= idmap_domain_info->range->min +- && id <= idmap_domain_info->range->max) { ++ if (id >= idmap_domain_info->range_params.min_id ++ && id <= idmap_domain_info->range_params.max_id) { + return IDMAP_SUCCESS; + } + +@@ -700,7 +703,7 @@ enum idmap_error_code sss_idmap_unix_to_sid(struct sss_idmap_ctx *ctx, + idmap_domain_info = ctx->idmap_domain_info; + + while (idmap_domain_info != NULL) { +- if (id_is_in_range(id, idmap_domain_info, &rid)) { ++ if (id_is_in_range(id, &idmap_domain_info->range_params, &rid)) { + + if (idmap_domain_info->external_mapping == true + || idmap_domain_info->sid == NULL) { +-- +2.5.0 + diff --git a/0050-IDMAP-Add-support-for-automatic-adding-of-ranges.patch b/0050-IDMAP-Add-support-for-automatic-adding-of-ranges.patch new file mode 100644 index 0000000..872d964 --- /dev/null +++ b/0050-IDMAP-Add-support-for-automatic-adding-of-ranges.patch @@ -0,0 +1,1537 @@ +From bb102c5afac8fef00487d5db4dc148927ab8e29d Mon Sep 17 00:00:00 2001 +From: Pavel Reichl +Date: Fri, 27 Nov 2015 04:15:00 -0500 +Subject: [PATCH 50/55] IDMAP: Add support for automatic adding of ranges + +Resolves: +https://fedorahosted.org/sssd/ticket/2188 + +Reviewed-by: Sumit Bose +(cherry picked from commit 8babbeee01e67893af4828ddfc922ecac0be4197) +--- + Makefile.am | 2 +- + src/config/SSSDConfig/__init__.py.in | 1 + + src/config/etc/sssd.api.d/sssd-ad.conf | 1 + + src/config/etc/sssd.api.d/sssd-ipa.conf | 1 + + src/config/etc/sssd.api.d/sssd-ldap.conf | 1 + + src/lib/idmap/sss_idmap.c | 526 ++++++++++++++++++++++++++++--- + src/lib/idmap/sss_idmap.exports | 10 + + src/lib/idmap/sss_idmap.h | 65 ++++ + src/lib/idmap/sss_idmap_private.h | 4 + + src/man/include/ldap_id_mapping.xml | 20 ++ + src/providers/ad/ad_opts.c | 1 + + src/providers/ipa/ipa_opts.c | 1 + + src/providers/ldap/ldap_opts.c | 1 + + src/providers/ldap/sdap.h | 1 + + src/providers/ldap/sdap_idmap.c | 16 +- + src/tests/cmocka/test_sss_idmap.c | 87 ++++- + src/tests/sss_idmap-tests.c | 332 +++++++++++++++++++ + 17 files changed, 1007 insertions(+), 63 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index a9099c07fcfe54a88bd56129364dde5262e901ed..22653cfe08ca1fa42f551bdd585868a7e56046ba 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -960,7 +960,7 @@ libsss_idmap_la_SOURCES = \ + src/util/murmurhash3.c + libsss_idmap_la_LDFLAGS = \ + -Wl,--version-script,$(srcdir)/src/lib/idmap/sss_idmap.exports \ +- -version-info 4:0:4 ++ -version-info 5:0:5 + + dist_noinst_DATA += src/lib/idmap/sss_idmap.exports + +diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in +index b4a6fcb0d37469e1dda85eda95fd80825697902c..6abdbc3a43cd4dbd74208efa8602b889f6e84d2b 100644 +--- a/src/config/SSSDConfig/__init__.py.in ++++ b/src/config/SSSDConfig/__init__.py.in +@@ -355,6 +355,7 @@ option_strings = { + 'ldap_idmap_autorid_compat' : _('Use autorid-compatible algorithm for ID-mapping'), + 'ldap_idmap_default_domain' : _('Name of the default domain for ID-mapping'), + 'ldap_idmap_default_domain_sid' : _('SID of the default domain for ID-mapping'), ++ 'ldap_idmap_helper_table_size' : _('Number of secondary slices'), + + 'ldap_groups_use_matching_rule_in_chain' : _('Use LDAP_MATCHING_RULE_IN_CHAIN for group lookups'), + 'ldap_initgroups_use_matching_rule_in_chain' : _('Use LDAP_MATCHING_RULE_IN_CHAIN for initgroup lookups'), +diff --git a/src/config/etc/sssd.api.d/sssd-ad.conf b/src/config/etc/sssd.api.d/sssd-ad.conf +index 0ea73d14112d1c7cf7a6d4cbda0d2b2e53a3a7be..149590f4f30de3438f2fc5534ae65c98ee0f10ad 100644 +--- a/src/config/etc/sssd.api.d/sssd-ad.conf ++++ b/src/config/etc/sssd.api.d/sssd-ad.conf +@@ -125,6 +125,7 @@ ldap_idmap_range_size = int, None, false + ldap_idmap_autorid_compat = bool, None, false + ldap_idmap_default_domain = str, None, false + ldap_idmap_default_domain_sid = str, None, false ++ldap_idmap_helper_table_size = int, None, false + ldap_groups_use_matching_rule_in_chain = bool, None, false + ldap_initgroups_use_matching_rule_in_chain = bool, None, false + ldap_use_tokengroups = bool, None, false +diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf b/src/config/etc/sssd.api.d/sssd-ipa.conf +index 13715ec34666f2dbc66df037565b495b9df42511..822599db6390ad2244a71db770c0b162345a3321 100644 +--- a/src/config/etc/sssd.api.d/sssd-ipa.conf ++++ b/src/config/etc/sssd.api.d/sssd-ipa.conf +@@ -131,6 +131,7 @@ ldap_idmap_range_size = int, None, false + ldap_idmap_autorid_compat = bool, None, false + ldap_idmap_default_domain = str, None, false + ldap_idmap_default_domain_sid = str, None, false ++ldap_idmap_helper_table_size = int, None, false + ldap_groups_use_matching_rule_in_chain = bool, None, false + ldap_initgroups_use_matching_rule_in_chain = bool, None, false + ldap_use_tokengroups = bool, None, false +diff --git a/src/config/etc/sssd.api.d/sssd-ldap.conf b/src/config/etc/sssd.api.d/sssd-ldap.conf +index 8fd45fd4093714f458161eb352157c845d926f06..fc9fcefce94891760a3f3ada4c044dbcaf156945 100644 +--- a/src/config/etc/sssd.api.d/sssd-ldap.conf ++++ b/src/config/etc/sssd.api.d/sssd-ldap.conf +@@ -118,6 +118,7 @@ ldap_idmap_range_size = int, None, false + ldap_idmap_autorid_compat = bool, None, false + ldap_idmap_default_domain = str, None, false + ldap_idmap_default_domain_sid = str, None, false ++ldap_idmap_helper_table_size = int, None, false + ldap_groups_use_matching_rule_in_chain = bool, None, false + ldap_initgroups_use_matching_rule_in_chain = bool, None, false + ldap_use_tokengroups = bool, None, false +diff --git a/src/lib/idmap/sss_idmap.c b/src/lib/idmap/sss_idmap.c +index 23ed46a583547a3f2f0bca5ab62824bd045e56b9..269ef0132ff3b9ffbfbe65006361fac6d4f88cf9 100644 +--- a/src/lib/idmap/sss_idmap.c ++++ b/src/lib/idmap/sss_idmap.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #include "lib/idmap/sss_idmap.h" + #include "lib/idmap/sss_idmap_private.h" +@@ -41,6 +42,7 @@ struct idmap_range_params { + char *range_id; + + uint32_t first_rid; ++ struct idmap_range_params *next; + }; + + struct idmap_domain_info { +@@ -49,6 +51,13 @@ struct idmap_domain_info { + struct idmap_range_params range_params; + struct idmap_domain_info *next; + bool external_mapping; ++ ++ struct idmap_range_params *helpers; ++ bool auto_add_ranges; ++ bool helpers_owner; ++ ++ idmap_store_cb cb; ++ void *pvt; + }; + + static void *default_alloc(size_t size, void *pvt) +@@ -195,12 +204,34 @@ enum idmap_error_code sss_idmap_init(idmap_alloc_func *alloc_func, + ctx->idmap_opts.idmap_lower = SSS_IDMAP_DEFAULT_LOWER; + ctx->idmap_opts.idmap_upper = SSS_IDMAP_DEFAULT_UPPER; + ctx->idmap_opts.rangesize = SSS_IDMAP_DEFAULT_RANGESIZE; ++ ctx->idmap_opts.extra_slice_init = SSS_IDMAP_DEFAULT_EXTRA_SLICE_INIT; + + *_ctx = ctx; + + return IDMAP_SUCCESS; + } + ++static void free_helpers(struct sss_idmap_ctx *ctx, ++ struct idmap_range_params *helpers, ++ bool helpers_owner) ++{ ++ struct idmap_range_params *it = helpers; ++ struct idmap_range_params *tmp; ++ ++ if (helpers_owner == false) { ++ return; ++ } ++ ++ while (it != NULL) { ++ tmp = it->next; ++ ++ ctx->free_func(it->range_id, ctx->alloc_pvt); ++ ctx->free_func(it, ctx->alloc_pvt); ++ ++ it = tmp; ++ } ++} ++ + static void sss_idmap_free_domain(struct sss_idmap_ctx *ctx, + struct idmap_domain_info *dom) + { +@@ -209,6 +240,9 @@ static void sss_idmap_free_domain(struct sss_idmap_ctx *ctx, + } + + ctx->free_func(dom->range_params.range_id, ctx->alloc_pvt); ++ ++ free_helpers(ctx, dom->helpers, dom->helpers_owner); ++ + ctx->free_func(dom->name, ctx->alloc_pvt); + ctx->free_func(dom->sid, ctx->alloc_pvt); + ctx->free_func(dom, ctx->alloc_pvt); +@@ -269,6 +303,22 @@ enum idmap_error_code sss_idmap_free_bin_sid(struct sss_idmap_ctx *ctx, + return sss_idmap_free_ptr(ctx, bin_sid); + } + ++static bool check_overlap(struct idmap_range_params *range, ++ id_t min, id_t max) ++{ ++ return ((range->min_id <= min && range->max_id >= max) ++ || (range->min_id >= min && range->min_id <= max) ++ || (range->max_id >= min && range->max_id <= max)); ++} ++ ++static bool check_dom_overlap(struct idmap_range_params *prim_range, ++ /* struct idmap_range_params *sec_ranges, */ ++ id_t min, ++ id_t max) ++{ ++ return check_overlap(prim_range, min, max); ++} ++ + enum idmap_error_code sss_idmap_calculate_range(struct sss_idmap_ctx *ctx, + const char *dom_sid, + id_t *slice_num, +@@ -327,12 +377,9 @@ enum idmap_error_code sss_idmap_calculate_range(struct sss_idmap_ctx *ctx, + /* Verify that this slice is not already in use */ + do { + for (dom = ctx->idmap_domain_info; dom != NULL; dom = dom->next) { +- uint32_t dmin = dom->range_params.min_id; +- uint32_t dmax = dom->range_params.max_id; + +- if ((dmin <= min && dmax >= max) || +- (dmin >= min && dmin <= max) || +- (dmax >= min && dmax <= max)) { ++ if (check_dom_overlap(&dom->range_params, ++ min, max)) { + /* This range overlaps one already registered + * We'll try the next available slot + */ +@@ -487,6 +534,105 @@ idmap_error_code dom_check_collision(struct idmap_domain_info *dom_list, + return IDMAP_SUCCESS; + } + ++static char* ++generate_sec_slice_name(struct sss_idmap_ctx *ctx, ++ const char *domain_name, uint32_t rid) ++{ ++ const char *SEC_SLICE_NAME_FMT = "%s-%"PRIu32; ++ char *slice_name; ++ int len, len2; ++ ++ len = snprintf(NULL, 0, SEC_SLICE_NAME_FMT, domain_name, rid); ++ if (len <= 0) { ++ return NULL; ++ } ++ ++ slice_name = ctx->alloc_func(len + 1, ctx->alloc_pvt); ++ if (slice_name == NULL) { ++ return NULL; ++ } ++ ++ len2 = snprintf(slice_name, len + 1, SEC_SLICE_NAME_FMT, domain_name, ++ rid); ++ if (len != len2) { ++ ctx->free_func(slice_name, ctx->alloc_pvt); ++ return NULL; ++ } ++ ++ return slice_name; ++} ++ ++static enum idmap_error_code ++generate_slice(struct sss_idmap_ctx *ctx, char *slice_name, uint32_t first_rid, ++ struct idmap_range_params **_slice) ++{ ++ struct idmap_range_params *slice; ++ struct sss_idmap_range tmp_range; ++ enum idmap_error_code err; ++ ++ slice = ctx->alloc_func(sizeof(struct idmap_range_params), ctx->alloc_pvt); ++ if (slice == NULL) { ++ return IDMAP_OUT_OF_MEMORY; ++ } ++ ++ slice->next = NULL; ++ ++ err = sss_idmap_calculate_range(ctx, slice_name, NULL, &tmp_range); ++ if (err != IDMAP_SUCCESS) { ++ ctx->free_func(slice, ctx->alloc_pvt); ++ return err; ++ } ++ ++ slice->min_id = tmp_range.min; ++ slice->max_id = tmp_range.max; ++ slice->range_id = slice_name; ++ slice->first_rid = first_rid; ++ ++ *_slice = slice; ++ return IDMAP_SUCCESS; ++} ++ ++static enum idmap_error_code ++get_helpers(struct sss_idmap_ctx *ctx, ++ const char *domain_sid, ++ uint32_t first_rid, ++ struct idmap_range_params **_sec_slices) ++{ ++ struct idmap_range_params *prev = NULL; ++ struct idmap_range_params *sec_slices = NULL; ++ static enum idmap_error_code err; ++ struct idmap_range_params *slice; ++ char *secondary_name; ++ ++ for (int i = 0; i < ctx->idmap_opts.extra_slice_init; i++) { ++ secondary_name = generate_sec_slice_name(ctx, domain_sid, first_rid); ++ if (secondary_name == NULL) { ++ return IDMAP_OUT_OF_MEMORY; ++ } ++ ++ err = generate_slice(ctx, secondary_name, first_rid, &slice); ++ if (err != IDMAP_SUCCESS) { ++ ctx->free_func(secondary_name, ctx->alloc_pvt); ++ return err; ++ } ++ ++ first_rid += ctx->idmap_opts.rangesize; ++ ++ if (prev != NULL) { ++ prev->next = slice; ++ } ++ ++ if (sec_slices == NULL) { ++ sec_slices = slice; ++ } ++ ++ prev = slice; ++ } ++ ++ *_sec_slices = sec_slices; ++ return IDMAP_SUCCESS; ++} ++ + enum idmap_error_code sss_idmap_add_domain_ex(struct sss_idmap_ctx *ctx, + const char *domain_name, + const char *domain_sid, +@@ -567,6 +713,67 @@ fail: + return err; + } + ++enum idmap_error_code ++sss_idmap_add_auto_domain_ex(struct sss_idmap_ctx *ctx, ++ const char *domain_name, ++ const char *domain_sid, ++ struct sss_idmap_range *range, ++ const char *range_id, ++ uint32_t rid, ++ bool external_mapping, ++ idmap_store_cb cb, ++ void *pvt) ++{ ++ enum idmap_error_code err; ++ ++ err = sss_idmap_add_domain_ex(ctx, domain_name, domain_sid, range, ++ range_id, rid, external_mapping); ++ if (err != IDMAP_SUCCESS) { ++ return err; ++ } ++ ++ if (external_mapping) { ++ /* There's no point in generating secondary ranges if external_mapping ++ is enabled. */ ++ ctx->idmap_domain_info->auto_add_ranges = false; ++ return IDMAP_SUCCESS; ++ } ++ ++ if ((range->max - range->min + 1) != ctx->idmap_opts.rangesize) { ++ /* Range of primary slice is not equal to the value of ++ ldap_idmap_range_size option. */ ++ return IDMAP_ERROR; ++ } ++ ++ /* No additional secondary ranges should be added if no sec ranges are ++ predeclared. */ ++ if (ctx->idmap_opts.extra_slice_init == 0) { ++ ctx->idmap_domain_info->auto_add_ranges = false; ++ return IDMAP_SUCCESS; ++ } ++ ++ /* Add size of primary slice for first_rid of secondary slices. */ ++ rid += ctx->idmap_opts.rangesize; ++ err = get_helpers(ctx, domain_sid, rid, ++ &ctx->idmap_domain_info->helpers); ++ if (err == IDMAP_SUCCESS) { ++ ctx->idmap_domain_info->auto_add_ranges = true; ++ ctx->idmap_domain_info->helpers_owner = true; ++ } else { ++ /* Running out of slices for secondary mapping is a non-fatal ++ * problem. */ ++ if (err == IDMAP_OUT_OF_SLICES) { ++ err = IDMAP_SUCCESS; ++ } ++ ctx->idmap_domain_info->auto_add_ranges = false; ++ } ++ ++ ctx->idmap_domain_info->cb = cb; ++ ctx->idmap_domain_info->pvt = pvt; ++ ++ return err; ++} ++ + enum idmap_error_code sss_idmap_add_domain(struct sss_idmap_ctx *ctx, + const char *domain_name, + const char *domain_sid, +@@ -585,16 +792,198 @@ static bool sss_idmap_sid_is_builtin(const char *sid) + return false; + } + ++static bool parse_rid(const char *sid, size_t dom_prefix_len, long long *_rid) ++{ ++ long long rid; ++ char *endptr; ++ ++ errno = 0; ++ /* Use suffix of sid - part after domain and following '-' */ ++ rid = strtoull(sid + dom_prefix_len + 1, &endptr, 10); ++ if (errno != 0 || rid > UINT32_MAX || *endptr != '\0') { ++ return false; ++ } ++ ++ *_rid = rid; ++ return true; ++} ++ ++static bool is_sid_from_dom(const char *dom_sid, const char *sid, ++ size_t *_dom_sid_len) ++{ ++ size_t dom_sid_len; ++ ++ if (dom_sid == NULL) { ++ return false; ++ } ++ ++ dom_sid_len = strlen(dom_sid); ++ *_dom_sid_len = dom_sid_len; ++ ++ if (strlen(sid) < dom_sid_len || sid[dom_sid_len] != '-') { ++ return false; ++ } ++ ++ return strncmp(sid, dom_sid, dom_sid_len) == 0; ++} ++ ++static bool comp_id(struct idmap_range_params *range_params, long long rid, ++ uint32_t *_id) ++{ ++ uint32_t id; ++ ++ if (rid >= range_params->first_rid ++ && ((UINT32_MAX - range_params->min_id) > ++ (rid - range_params->first_rid))) { ++ id = range_params->min_id + (rid - range_params->first_rid); ++ if (id <= range_params->max_id) { ++ *_id = id; ++ return true; ++ } ++ } ++ return false; ++} ++ ++static enum idmap_error_code ++get_range(struct sss_idmap_ctx *ctx, ++ const char *dom_sid, ++ long long rid, ++ struct idmap_range_params **_range) ++{ ++ char *secondary_name; ++ enum idmap_error_code err; ++ int first_rid; ++ struct idmap_range_params *range; ++ ++ first_rid = (rid / ctx->idmap_opts.rangesize) * ctx->idmap_opts.rangesize; ++ ++ secondary_name = generate_sec_slice_name(ctx, dom_sid, first_rid); ++ if (secondary_name == NULL) { ++ return IDMAP_OUT_OF_MEMORY; ++ } ++ ++ err = generate_slice(ctx, secondary_name, first_rid, &range); ++ if (err == IDMAP_OUT_OF_SLICES) { ++ ctx->free_func(secondary_name, ctx->alloc_pvt); ++ return err; ++ } ++ ++ *_range = range; ++ return IDMAP_SUCCESS; ++} ++ ++static enum idmap_error_code ++spawn_dom(struct sss_idmap_ctx *ctx, ++ struct idmap_domain_info *parent, ++ struct idmap_range_params *range) ++{ ++ struct sss_idmap_range tmp; ++ static enum idmap_error_code err; ++ struct idmap_domain_info *it; ++ ++ tmp.min = range->min_id; ++ tmp.max = range->max_id; ++ ++ err = sss_idmap_add_domain_ex(ctx, ++ parent->name, ++ parent->sid, ++ &tmp, range->range_id, ++ range->first_rid, false); ++ if (err != IDMAP_SUCCESS) { ++ return err; ++ } ++ ++ it = ctx->idmap_domain_info; ++ while (it != NULL) { ++ /* Find the newly added domain. */ ++ if (it->range_params.first_rid == range->first_rid ++ && it->range_params.min_id == range->min_id ++ && it->range_params.max_id == range->max_id) { ++ ++ /* Share helpers. */ ++ it->helpers = parent->helpers; ++ it->auto_add_ranges = parent->auto_add_ranges; ++ ++ /* Share call back for storing domains */ ++ it->cb = parent->cb; ++ it->pvt = parent->pvt; ++ break; ++ } ++ ++ it = it->next; ++ } ++ ++ if (it == NULL) { ++ /* Failed to find just added domain. */ ++ return IDMAP_ERROR; ++ } ++ ++ /* Store mapping for newly created domain. */ ++ if (it->cb != NULL) { ++ err = it->cb(it->name, ++ it->sid, ++ it->range_params.range_id, ++ it->range_params.min_id, ++ it->range_params.max_id, ++ it->range_params.first_rid, ++ it->pvt); ++ if (err != IDMAP_SUCCESS) { ++ return err; ++ } ++ } ++ ++ return IDMAP_SUCCESS; ++} ++ ++static enum idmap_error_code ++add_dom_for_sid(struct sss_idmap_ctx *ctx, ++ struct idmap_domain_info *matched_dom, ++ const char *sid, ++ uint32_t *_id) ++{ ++ enum idmap_error_code err; ++ long long rid; ++ struct idmap_range_params *range = NULL; ++ ++ if (parse_rid(sid, strlen(matched_dom->sid), &rid) == false) { ++ err = IDMAP_SID_INVALID; ++ goto done; ++ } ++ ++ /* todo optimize */ ++ err = get_range(ctx, matched_dom->sid, rid, &range); ++ if (err != IDMAP_SUCCESS) { ++ goto done; ++ } ++ ++ err = spawn_dom(ctx, matched_dom, range); ++ if (err != IDMAP_SUCCESS) { ++ goto done; ++ } ++ ++ if (!comp_id(range, rid, _id)) { ++ err = IDMAP_ERROR; ++ goto done; ++ } ++ ++ err = IDMAP_SUCCESS; ++ ++done: ++ if (range != NULL) { ++ ctx->free_func(range->range_id, ctx->alloc_pvt); ++ } ++ ctx->free_func(range, ctx->alloc_pvt); ++ return err; ++} ++ + enum idmap_error_code sss_idmap_sid_to_unix(struct sss_idmap_ctx *ctx, + const char *sid, + uint32_t *_id) + { + struct idmap_domain_info *idmap_domain_info; ++ struct idmap_domain_info *matched_dom = NULL; + size_t dom_len; + long long rid; +- char *endptr; +- uint32_t id; +- bool no_range = false; + + if (sid == NULL || _id == NULL) { + return IDMAP_ERROR; +@@ -608,39 +997,34 @@ enum idmap_error_code sss_idmap_sid_to_unix(struct sss_idmap_ctx *ctx, + return IDMAP_BUILTIN_SID; + } + ++ /* Try primary slices */ + while (idmap_domain_info != NULL) { +- if (idmap_domain_info->sid != NULL) { +- dom_len = strlen(idmap_domain_info->sid); +- if (strlen(sid) > dom_len && sid[dom_len] == '-' +- && strncmp(sid, idmap_domain_info->sid, dom_len) == 0) { + +- if (idmap_domain_info->external_mapping == true) { +- return IDMAP_EXTERNAL; +- } ++ if (is_sid_from_dom(idmap_domain_info->sid, sid, &dom_len)) { + +- errno = 0; +- rid = strtoull(sid + dom_len + 1, &endptr, 10); +- if (errno != 0 || rid > UINT32_MAX || *endptr != '\0') { +- return IDMAP_SID_INVALID; +- } ++ if (idmap_domain_info->external_mapping == true) { ++ return IDMAP_EXTERNAL; ++ } + +- if (rid >= idmap_domain_info->range_params.first_rid) { +- id = idmap_domain_info->range_params.min_id +- + (rid - idmap_domain_info->range_params.first_rid); +- if (id <= idmap_domain_info->range_params.max_id) { +- *_id = id; +- return IDMAP_SUCCESS; +- } +- } ++ if (parse_rid(sid, dom_len, &rid) == false) { ++ return IDMAP_SID_INVALID; ++ } + +- no_range = true; ++ if (comp_id(&idmap_domain_info->range_params, rid, _id)) { ++ return IDMAP_SUCCESS; + } ++ ++ matched_dom = idmap_domain_info; + } + + idmap_domain_info = idmap_domain_info->next; + } + +- return no_range ? IDMAP_NO_RANGE : IDMAP_NO_DOMAIN; ++ if (matched_dom != NULL && matched_dom->auto_add_ranges) { ++ return add_dom_for_sid(ctx, matched_dom, sid, _id); ++ } ++ ++ return matched_dom ? IDMAP_NO_RANGE : IDMAP_NO_DOMAIN; + } + + enum idmap_error_code sss_idmap_check_sid_unix(struct sss_idmap_ctx *ctx, +@@ -688,15 +1072,42 @@ enum idmap_error_code sss_idmap_check_sid_unix(struct sss_idmap_ctx *ctx, + return no_range ? IDMAP_NO_RANGE : IDMAP_SID_UNKNOWN; + } + ++static enum idmap_error_code generate_sid(struct sss_idmap_ctx *ctx, ++ const char *dom_sid, ++ uint32_t rid, ++ char **_sid) ++{ ++ char *sid; ++ int len; ++ int ret; ++ ++ len = snprintf(NULL, 0, SID_FMT, dom_sid, rid); ++ if (len <= 0 || len > SID_STR_MAX_LEN) { ++ return IDMAP_ERROR; ++ } ++ ++ sid = ctx->alloc_func(len + 1, ctx->alloc_pvt); ++ if (sid == NULL) { ++ return IDMAP_OUT_OF_MEMORY; ++ } ++ ++ ret = snprintf(sid, len + 1, SID_FMT, dom_sid, rid); ++ if (ret != len) { ++ ctx->free_func(sid, ctx->alloc_pvt); ++ return IDMAP_ERROR; ++ } ++ ++ *_sid = sid; ++ return IDMAP_SUCCESS; ++} ++ + enum idmap_error_code sss_idmap_unix_to_sid(struct sss_idmap_ctx *ctx, + uint32_t id, + char **_sid) + { + struct idmap_domain_info *idmap_domain_info; +- int len; +- int ret; + uint32_t rid; +- char *sid = NULL; ++ enum idmap_error_code err; + + CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); + +@@ -710,24 +1121,34 @@ enum idmap_error_code sss_idmap_unix_to_sid(struct sss_idmap_ctx *ctx, + return IDMAP_EXTERNAL; + } + +- len = snprintf(NULL, 0, SID_FMT, idmap_domain_info->sid, rid); +- if (len <= 0 || len > SID_STR_MAX_LEN) { +- return IDMAP_ERROR; +- } ++ return generate_sid(ctx, idmap_domain_info->sid, rid, _sid); ++ } + +- sid = ctx->alloc_func(len + 1, ctx->alloc_pvt); +- if (sid == NULL) { +- return IDMAP_OUT_OF_MEMORY; +- } ++ idmap_domain_info = idmap_domain_info->next; ++ } + +- ret = snprintf(sid, len + 1, SID_FMT, idmap_domain_info->sid, rid); +- if (ret != len) { +- ctx->free_func(sid, ctx->alloc_pvt); +- return IDMAP_ERROR; +- } ++ /* Check secondary ranges. */ ++ idmap_domain_info = ctx->idmap_domain_info; ++ while (idmap_domain_info != NULL) { ++ ++ for (struct idmap_range_params *it = idmap_domain_info->helpers; ++ it != NULL; ++ it = it->next) { + +- *_sid = sid; +- return IDMAP_SUCCESS; ++ if (id_is_in_range(id, it, &rid)) { ++ ++ if (idmap_domain_info->external_mapping == true ++ || idmap_domain_info->sid == NULL) { ++ return IDMAP_EXTERNAL; ++ } ++ ++ err = spawn_dom(ctx, idmap_domain_info, it); ++ if (err != IDMAP_SUCCESS) { ++ return err; ++ } ++ ++ return generate_sid(ctx, idmap_domain_info->sid, rid, _sid); ++ } + } + + idmap_domain_info = idmap_domain_info->next; +@@ -970,6 +1391,15 @@ sss_idmap_ctx_set_rangesize(struct sss_idmap_ctx *ctx, id_t rangesize) + } + + enum idmap_error_code ++sss_idmap_ctx_set_extra_slice_init(struct sss_idmap_ctx *ctx, ++ int extra_slice_init) ++{ ++ CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); ++ ctx->idmap_opts.extra_slice_init = extra_slice_init; ++ return IDMAP_SUCCESS; ++} ++ ++enum idmap_error_code + sss_idmap_ctx_get_autorid(struct sss_idmap_ctx *ctx, bool *_autorid) + { + CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); +diff --git a/src/lib/idmap/sss_idmap.exports b/src/lib/idmap/sss_idmap.exports +index 52115636d5a6b936f18b4392e9d12adc26c85f53..f10feea6f880a6e02fdc354dce2044bcfae9b05c 100644 +--- a/src/lib/idmap/sss_idmap.exports ++++ b/src/lib/idmap/sss_idmap.exports +@@ -54,3 +54,13 @@ SSS_IDMAP_0.4 { + local: + *; + }; ++ ++SSS_IDMAP_0.5 { ++ ++ # public functions ++ global: ++ ++ sss_idmap_ctx_set_extra_slice_init; ++ sss_idmap_add_auto_domain_ex; ++ ++} SSS_IDMAP_0.4; +\ No newline at end of file +diff --git a/src/lib/idmap/sss_idmap.h b/src/lib/idmap/sss_idmap.h +index 0797083293f7e010962828ddcd72709b290859b9..483241eeafda7ac5952bbae41c442ba676a09483 100644 +--- a/src/lib/idmap/sss_idmap.h ++++ b/src/lib/idmap/sss_idmap.h +@@ -94,6 +94,17 @@ typedef void *(idmap_alloc_func)(size_t size, void *pvt); + typedef void (idmap_free_func)(void *ptr, void *pvt); + + /** ++ * Typedef for storing mappings of dynamically created domains ++ */ ++typedef enum idmap_error_code (*idmap_store_cb)(const char *dom_name, ++ const char *dom_sid, ++ const char *range_id, ++ uint32_t min_id, ++ uint32_t max_id, ++ uint32_t first_rid, ++ void *pvt); ++ ++/** + * Structure for id ranges + * FIXME: this struct might change when it is clear how ranges are handled on + * the server side +@@ -175,6 +186,17 @@ enum idmap_error_code + sss_idmap_ctx_set_rangesize(struct sss_idmap_ctx *ctx, id_t rangesize); + + /** ++ * @brief Set the number of secondary slices available for domain ++ * ++ * @param[in] ctx idmap context ++ * @param[in] extra_slice_init number of secondary slices to be generated ++ * at startup ++ */ ++enum idmap_error_code ++sss_idmap_ctx_set_extra_slice_init(struct sss_idmap_ctx *ctx, ++ int extra_slice_init); ++ ++/** + * @brief Check if autorid compatibility mode is set + * + * @param[in] ctx idmap context +@@ -291,6 +313,49 @@ enum idmap_error_code sss_idmap_add_domain_ex(struct sss_idmap_ctx *ctx, + bool external_mapping); + + /** ++ * @brief Add a domain with the first mappable RID to the idmap context and ++ * generate automatically secondary slices ++ * ++ * @param[in] ctx Idmap context ++ * @param[in] domain_name Zero-terminated string with the domain name ++ * @param[in] domain_sid Zero-terminated string representation of the domain ++ * SID (S-1-15-.....) ++ * @param[in] range TBD Some information about the id ranges of this ++ * domain ++ * @param[in] range_id optional unique identifier of a range, it is needed ++ * to allow updates at runtime ++ * @param[in] rid The RID that should be mapped to the first ID of the ++ * given range. ++ * @param[in] external_mapping If set to true the ID will not be mapped ++ * algorithmically, but the *_to_unix and *_unix_to_* ++ * calls will return IDMAP_EXTERNAL to instruct the ++ * caller to check external sources. For a single ++ * domain all ranges must be of the same type. It is ++ * not possible to mix algorithmic and external ++ * mapping. ++ * @param[in] s_cv The callback for storing mapping of dynamically ++ * created domains. ++ * @param[in] pvt Private data for callback cb. ++ * ++ * @return ++ * - #IDMAP_OUT_OF_MEMORY: Insufficient memory to store the data in the idmap ++ * context ++ * - #IDMAP_SID_INVALID: Invalid SID provided ++ * - #IDMAP_NO_DOMAIN: No domain domain name given ++ * - #IDMAP_COLLISION: New domain collides with existing one ++ */ ++enum idmap_error_code ++sss_idmap_add_auto_domain_ex(struct sss_idmap_ctx *ctx, ++ const char *domain_name, ++ const char *domain_sid, ++ struct sss_idmap_range *range, ++ const char *range_id, ++ uint32_t rid, ++ bool external_mapping, ++ idmap_store_cb cb, ++ void *pvt); ++ ++/** + * @brief Check if a new range would collide with any existing one + * + * @param[in] ctx Idmap context +diff --git a/src/lib/idmap/sss_idmap_private.h b/src/lib/idmap/sss_idmap_private.h +index 1d3a36901781ae51ab79015d0b789559325c8de5..15300d11fc50a47c6d37149fdb79477069d931f4 100644 +--- a/src/lib/idmap/sss_idmap_private.h ++++ b/src/lib/idmap/sss_idmap_private.h +@@ -29,6 +29,7 @@ + #define SSS_IDMAP_DEFAULT_UPPER 2000200000 + #define SSS_IDMAP_DEFAULT_RANGESIZE 200000 + #define SSS_IDMAP_DEFAULT_AUTORID false ++#define SSS_IDMAP_DEFAULT_EXTRA_SLICE_INIT 10 + + #define CHECK_IDMAP_CTX(ctx, ret) do { \ + if (ctx == NULL || ctx->alloc_func == NULL || ctx->free_func == NULL) { \ +@@ -48,6 +49,9 @@ struct sss_idmap_opts { + + /* number of available UIDs (for single domain) */ + id_t rangesize; ++ ++ /* maximal number of secondary slices */ ++ int extra_slice_init; + }; + + struct sss_idmap_ctx { +diff --git a/src/man/include/ldap_id_mapping.xml b/src/man/include/ldap_id_mapping.xml +index 17ef803289d14fa52b725c90062ee4ba0379acd0..a088c4e81d81c5670edea8ae8081abe80927446a 100644 +--- a/src/man/include/ldap_id_mapping.xml ++++ b/src/man/include/ldap_id_mapping.xml +@@ -243,6 +243,26 @@ ldap_schema = ad + + + ++ ++ ldap_idmap_helper_table_size (integer) ++ ++ ++ Maximal number of secondary slices that is tried when ++ performing mapping from UNIX id to SID. ++ ++ ++ Note: Additional secondary slices might be generated ++ when SID is being mapped to UNIX id and RID part of ++ SID is out of range for secondary slices generated so ++ far. If value of ldap_idmap_helper_table_size is equal ++ to 0 then no additional secondary slices are ++ generated. ++ ++ ++ Default: 10 ++ ++ ++ + + + +diff --git a/src/providers/ad/ad_opts.c b/src/providers/ad/ad_opts.c +index 8b2841eadc0236b51f8c9c2c02b7c98837fbe416..28d4768b20bd035f7c1971c95f9b6b690844816e 100644 +--- a/src/providers/ad/ad_opts.c ++++ b/src/providers/ad/ad_opts.c +@@ -137,6 +137,7 @@ struct dp_option ad_def_ldap_opts[] = { + { "ldap_idmap_autorid_compat", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, + { "ldap_idmap_default_domain", DP_OPT_STRING, NULL_STRING, NULL_STRING }, + { "ldap_idmap_default_domain_sid", DP_OPT_STRING, NULL_STRING, NULL_STRING }, ++ { "ldap_idmap_helper_table_size", DP_OPT_NUMBER, { .number = 10 }, NULL_NUMBER }, + { "ldap_groups_use_matching_rule_in_chain", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, + { "ldap_initgroups_use_matching_rule_in_chain", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, + { "ldap_use_tokengroups", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE}, +diff --git a/src/providers/ipa/ipa_opts.c b/src/providers/ipa/ipa_opts.c +index cda10f89a60264ffd998da73ebadd09dff35ed79..cd87852e5891fd43d7ec728f76860f3050a54d2f 100644 +--- a/src/providers/ipa/ipa_opts.c ++++ b/src/providers/ipa/ipa_opts.c +@@ -147,6 +147,7 @@ struct dp_option ipa_def_ldap_opts[] = { + { "ldap_idmap_autorid_compat", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, + { "ldap_idmap_default_domain", DP_OPT_STRING, NULL_STRING, NULL_STRING }, + { "ldap_idmap_default_domain_sid", DP_OPT_STRING, NULL_STRING, NULL_STRING }, ++ { "ldap_idmap_helper_table_size", DP_OPT_NUMBER, { .number = 10 }, NULL_NUMBER }, + { "ldap_groups_use_matching_rule_in_chain", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, + { "ldap_initgroups_use_matching_rule_in_chain", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, + { "ldap_use_tokengroups", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE}, +diff --git a/src/providers/ldap/ldap_opts.c b/src/providers/ldap/ldap_opts.c +index 54926c6c31b1b6edfc1f07b22e79225c5fdddf5b..84ba2b54271bcb6650e0336131ace8bfc1a40fc8 100644 +--- a/src/providers/ldap/ldap_opts.c ++++ b/src/providers/ldap/ldap_opts.c +@@ -111,6 +111,7 @@ struct dp_option default_basic_opts[] = { + { "ldap_idmap_autorid_compat", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, + { "ldap_idmap_default_domain", DP_OPT_STRING, NULL_STRING, NULL_STRING }, + { "ldap_idmap_default_domain_sid", DP_OPT_STRING, NULL_STRING, NULL_STRING }, ++ { "ldap_idmap_helper_table_size", DP_OPT_NUMBER, { .number = 10 }, NULL_NUMBER }, + { "ldap_groups_use_matching_rule_in_chain", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, + { "ldap_initgroups_use_matching_rule_in_chain", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, + { "ldap_use_tokengroups", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE}, +diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h +index d7a299220414f2cf9d80de9921b6a5ec49e5793b..e06f2b6ac47990f21985fb86f8ad3f3ae5a74df3 100644 +--- a/src/providers/ldap/sdap.h ++++ b/src/providers/ldap/sdap.h +@@ -223,6 +223,7 @@ enum sdap_basic_opt { + SDAP_IDMAP_AUTORID_COMPAT, + SDAP_IDMAP_DEFAULT_DOMAIN, + SDAP_IDMAP_DEFAULT_DOMAIN_SID, ++ SDAP_IDMAP_EXTRA_SLICE_INIT, + SDAP_AD_MATCHING_RULE_GROUPS, + SDAP_AD_MATCHING_RULE_INITGROUPS, + SDAP_AD_USE_TOKENGROUPS, +diff --git a/src/providers/ldap/sdap_idmap.c b/src/providers/ldap/sdap_idmap.c +index fa79e66226e572c29cf371fffe3c149a2eda8895..53a98730954f6ba4321fb2a219c3bc85140c65cc 100644 +--- a/src/providers/ldap/sdap_idmap.c ++++ b/src/providers/ldap/sdap_idmap.c +@@ -94,9 +94,10 @@ sdap_idmap_add_configured_external_range(struct sdap_idmap_ctx *idmap_ctx) + + id_ctx = idmap_ctx->id_ctx; + +- err = sss_idmap_add_domain_ex(idmap_ctx->map, id_ctx->be->domain->name, +- id_ctx->be->domain->domain_id, &range, +- NULL, 0, true); ++ err = sss_idmap_add_auto_domain_ex(idmap_ctx->map, ++ id_ctx->be->domain->name, ++ id_ctx->be->domain->domain_id, &range, ++ NULL, 0, true, NULL, NULL); + if (err != IDMAP_SUCCESS) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Could not add domain [%s] to the map: [%d]\n", +@@ -142,6 +143,7 @@ sdap_idmap_init(TALLOC_CTX *mem_ctx, + id_t idmap_upper; + id_t rangesize; + bool autorid_mode; ++ int extra_slice_init; + struct sdap_idmap_ctx *idmap_ctx = NULL; + + tmp_ctx = talloc_new(NULL); +@@ -163,6 +165,8 @@ sdap_idmap_init(TALLOC_CTX *mem_ctx, + SDAP_IDMAP_RANGESIZE); + autorid_mode = dp_opt_get_bool(idmap_ctx->id_ctx->opts->basic, + SDAP_IDMAP_AUTORID_COMPAT); ++ extra_slice_init = dp_opt_get_int(idmap_ctx->id_ctx->opts->basic, ++ SDAP_IDMAP_EXTRA_SLICE_INIT); + + /* Validate that the values make sense */ + if (rangesize <= 0 +@@ -203,6 +207,7 @@ sdap_idmap_init(TALLOC_CTX *mem_ctx, + err |= sss_idmap_ctx_set_lower(idmap_ctx->map, idmap_lower); + err |= sss_idmap_ctx_set_upper(idmap_ctx->map, idmap_upper); + err |= sss_idmap_ctx_set_rangesize(idmap_ctx->map, rangesize); ++ err |= sss_idmap_ctx_set_extra_slice_init(idmap_ctx->map, extra_slice_init); + if (err != IDMAP_SUCCESS) { + /* This should never happen */ + DEBUG(SSSDBG_CRIT_FAILURE, "sss_idmap_ctx corrupted\n"); +@@ -376,8 +381,9 @@ sdap_idmap_add_domain(struct sdap_idmap_ctx *idmap_ctx, + } + + /* Add this domain to the map */ +- err = sss_idmap_add_domain_ex(idmap_ctx->map, dom_name, dom_sid, &range, +- NULL, 0, external_mapping); ++ err = sss_idmap_add_auto_domain_ex(idmap_ctx->map, dom_name, dom_sid, ++ &range, NULL, 0, external_mapping, ++ NULL, NULL); + if (err != IDMAP_SUCCESS) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Could not add domain [%s] to the map: [%d]\n", +diff --git a/src/tests/cmocka/test_sss_idmap.c b/src/tests/cmocka/test_sss_idmap.c +index 1e52c8507461ab3caa04eb2c0e63410c363ba723..00e03ffd9ab1532fb55795b9935b254c8a89ec16 100644 +--- a/src/tests/cmocka/test_sss_idmap.c ++++ b/src/tests/cmocka/test_sss_idmap.c +@@ -82,7 +82,7 @@ static int test_sss_idmap_setup(void **state) + } + + static int setup_ranges(struct test_ctx *test_ctx, bool external_mapping, +- bool second_domain) ++ bool second_domain, bool sec_slices) + { + struct sss_idmap_range range; + enum idmap_error_code err; +@@ -103,15 +103,27 @@ static int setup_ranges(struct test_ctx *test_ctx, bool external_mapping, + sid = TEST_DOM_SID; + } + +- err = sss_idmap_add_domain_ex(test_ctx->idmap_ctx, name, sid, &range, NULL, +- 0, external_mapping); ++ if (sec_slices) { ++ err = sss_idmap_add_auto_domain_ex(test_ctx->idmap_ctx, name, sid, ++ &range, NULL, 0, external_mapping, ++ NULL, NULL); ++ } else { ++ err = sss_idmap_add_domain_ex(test_ctx->idmap_ctx, name, sid, &range, ++ NULL, 0, external_mapping); ++ } + assert_int_equal(err, IDMAP_SUCCESS); + + range.min += TEST_OFFSET; + range.max += TEST_OFFSET; + +- err = sss_idmap_add_domain_ex(test_ctx->idmap_ctx, name, sid, &range, NULL, +- TEST_OFFSET, external_mapping); ++ if (sec_slices) { ++ err = sss_idmap_add_auto_domain_ex(test_ctx->idmap_ctx, name, sid, ++ &range, NULL, TEST_OFFSET, ++ external_mapping, NULL, NULL); ++ } else { ++ err = sss_idmap_add_domain_ex(test_ctx->idmap_ctx, name, sid, &range, ++ NULL, TEST_OFFSET, external_mapping); ++ } + assert_int_equal(err, IDMAP_SUCCESS); + return 0; + } +@@ -124,7 +136,19 @@ static int test_sss_idmap_setup_with_domains(void **state) { + test_ctx = talloc_get_type(*state, struct test_ctx); + assert_non_null(test_ctx); + +- setup_ranges(test_ctx, false, false); ++ setup_ranges(test_ctx, false, false, false); ++ return 0; ++} ++ ++static int test_sss_idmap_setup_with_domains_sec_slices(void **state) { ++ struct test_ctx *test_ctx; ++ ++ test_sss_idmap_setup(state); ++ ++ test_ctx = talloc_get_type(*state, struct test_ctx); ++ assert_non_null(test_ctx); ++ ++ setup_ranges(test_ctx, false, false, true); + return 0; + } + +@@ -136,7 +160,7 @@ static int test_sss_idmap_setup_with_external_mappings(void **state) { + test_ctx = talloc_get_type(*state, struct test_ctx); + assert_non_null(test_ctx); + +- setup_ranges(test_ctx, true, false); ++ setup_ranges(test_ctx, true, false, false); + return 0; + } + +@@ -148,8 +172,8 @@ static int test_sss_idmap_setup_with_both(void **state) { + test_ctx = talloc_get_type(*state, struct test_ctx); + assert_non_null(test_ctx); + +- setup_ranges(test_ctx, false, false); +- setup_ranges(test_ctx, true, true); ++ setup_ranges(test_ctx, false, false, false); ++ setup_ranges(test_ctx, true, true, false); + return 0; + } + +@@ -274,6 +298,48 @@ void test_map_id(void **state) + sss_idmap_free_sid(test_ctx->idmap_ctx, sid); + } + ++void test_map_id_sec_slices(void **state) ++{ ++ struct test_ctx *test_ctx; ++ enum idmap_error_code err; ++ uint32_t id; ++ char *sid = NULL; ++ ++ test_ctx = talloc_get_type(*state, struct test_ctx); ++ ++ assert_non_null(test_ctx); ++ ++ err = sss_idmap_sid_to_unix(test_ctx->idmap_ctx, TEST_DOM_SID"1-1", &id); ++ assert_int_equal(err, IDMAP_NO_DOMAIN); ++ ++ err = sss_idmap_sid_to_unix(test_ctx->idmap_ctx, TEST_DOM_SID"-4000000", ++ &id); ++ assert_int_equal(err, IDMAP_SUCCESS); ++ assert_int_equal(id, 575600000); ++ ++ err = sss_idmap_unix_to_sid(test_ctx->idmap_ctx, TEST_OFFSET - 1, &sid); ++ assert_int_equal(err, IDMAP_NO_DOMAIN); ++ ++ err = sss_idmap_sid_to_unix(test_ctx->idmap_ctx, TEST_DOM_SID"-0", &id); ++ assert_int_equal(err, IDMAP_SUCCESS); ++ assert_int_equal(id, TEST_RANGE_MIN); ++ ++ err = sss_idmap_unix_to_sid(test_ctx->idmap_ctx, id, &sid); ++ assert_int_equal(err, IDMAP_SUCCESS); ++ assert_string_equal(sid, TEST_DOM_SID"-0"); ++ sss_idmap_free_sid(test_ctx->idmap_ctx, sid); ++ ++ err = sss_idmap_sid_to_unix(test_ctx->idmap_ctx, ++ TEST_DOM_SID"-"TEST_OFFSET_STR, &id); ++ assert_int_equal(err, IDMAP_SUCCESS); ++ assert_int_equal(id, TEST_RANGE_MIN+TEST_OFFSET); ++ ++ err = sss_idmap_unix_to_sid(test_ctx->idmap_ctx, id, &sid); ++ assert_int_equal(err, IDMAP_SUCCESS); ++ assert_string_equal(sid, TEST_DOM_SID"-"TEST_OFFSET_STR); ++ sss_idmap_free_sid(test_ctx->idmap_ctx, sid); ++} ++ + void test_map_id_external(void **state) + { + struct test_ctx *test_ctx; +@@ -523,6 +589,9 @@ int main(int argc, const char *argv[]) + cmocka_unit_test_setup_teardown(test_map_id, + test_sss_idmap_setup_with_domains, + test_sss_idmap_teardown), ++ cmocka_unit_test_setup_teardown(test_map_id_sec_slices, ++ test_sss_idmap_setup_with_domains_sec_slices, ++ test_sss_idmap_teardown), + cmocka_unit_test_setup_teardown(test_map_id_external, + test_sss_idmap_setup_with_external_mappings, + test_sss_idmap_teardown), +diff --git a/src/tests/sss_idmap-tests.c b/src/tests/sss_idmap-tests.c +index f5ec68383679bfc685467bd625c86b8d6f474d48..900b7bff1cd4f3c6f9cdffc4b012864d05e72913 100644 +--- a/src/tests/sss_idmap-tests.c ++++ b/src/tests/sss_idmap-tests.c +@@ -68,6 +68,20 @@ void idmap_ctx_setup(void) + fail_unless(idmap_ctx != NULL, "sss_idmap_init returned NULL."); + } + ++void idmap_ctx_setup_additional_seconary_slices(void) ++{ ++ enum idmap_error_code err; ++ ++ err = sss_idmap_init(idmap_talloc, global_talloc_context, idmap_talloc_free, ++ &idmap_ctx); ++ ++ fail_unless(err == IDMAP_SUCCESS, "sss_idmap_init failed."); ++ fail_unless(idmap_ctx != NULL, "sss_idmap_init returned NULL."); ++ ++ idmap_ctx->idmap_opts.rangesize = 10; ++ idmap_ctx->idmap_opts.extra_slice_init = 5; ++} ++ + void idmap_ctx_teardown(void) + { + enum idmap_error_code err; +@@ -85,6 +99,86 @@ void idmap_add_domain_setup(void) + fail_unless(err == IDMAP_SUCCESS, "sss_idmap_add_domain failed."); + } + ++void idmap_add_domain_with_sec_slices_setup(void) ++{ ++ enum idmap_error_code err; ++ struct sss_idmap_range range = { ++ IDMAP_RANGE_MIN, ++ IDMAP_RANGE_MIN + idmap_ctx->idmap_opts.rangesize - 1, ++ }; ++ ++ err = sss_idmap_add_auto_domain_ex(idmap_ctx, "test.dom", "S-1-5-21-1-2-3", ++ &range, NULL, 0, false, NULL, NULL); ++ ++ fail_unless(err == IDMAP_SUCCESS, "sss_idmap_add_auto_domain_ex failed."); ++} ++ ++ ++enum idmap_error_code cb(const char *dom_name, ++ const char *dom_sid, ++ const char *range_id, ++ uint32_t min_id, ++ uint32_t max_id, ++ uint32_t first_rid, ++ void *pvt) ++{ ++ return IDMAP_ERROR; ++} ++ ++void idmap_add_domain_with_sec_slices_setup_cb_fail(void) ++{ ++ enum idmap_error_code err; ++ struct sss_idmap_range range = { ++ IDMAP_RANGE_MIN, ++ IDMAP_RANGE_MIN + idmap_ctx->idmap_opts.rangesize - 1, ++ }; ++ ++ err = sss_idmap_add_auto_domain_ex(idmap_ctx, "test.dom", "S-1-5-21-1-2-3", ++ &range, NULL, 0, false, cb, NULL); ++ ++ fail_unless(err == IDMAP_SUCCESS, "sss_idmap_add_auto_domain_ex failed."); ++} ++ ++ ++#define MAX 1000 ++char data[MAX]; ++ ++enum idmap_error_code cb2(const char *dom_name, ++ const char *dom_sid, ++ const char *range_id, ++ uint32_t min_id, ++ uint32_t max_id, ++ uint32_t first_rid, ++ void *pvt) ++{ ++ char *p = (char*)pvt; ++ size_t len; ++ ++ len = snprintf(p, MAX, "%s, %s %s, %"PRIu32", %"PRIu32", %" PRIu32, ++ dom_name, dom_sid, range_id, min_id, max_id, first_rid); ++ ++ if (len >= MAX) { ++ return IDMAP_OUT_OF_MEMORY; ++ } ++ return IDMAP_SUCCESS; ++} ++ ++void idmap_add_domain_with_sec_slices_setup_cb_ok(void) ++{ ++ enum idmap_error_code err; ++ struct sss_idmap_range range = { ++ IDMAP_RANGE_MIN, ++ IDMAP_RANGE_MIN + idmap_ctx->idmap_opts.rangesize - 1, ++ }; ++ ++ void *pvt = (void*) data; ++ ++ err = sss_idmap_add_auto_domain_ex(idmap_ctx, "test.dom", "S-1-5-21-1-2-3", ++ &range, NULL, 0, false, cb2, pvt); ++ ++ fail_unless(err == IDMAP_SUCCESS, "sss_idmap_add_auto_domain_ex failed."); ++} ++ + START_TEST(idmap_test_is_domain_sid) + { + size_t c; +@@ -225,6 +319,145 @@ START_TEST(idmap_test_sid2uid) + } + END_TEST + ++START_TEST(idmap_test_sid2uid_ss) ++{ ++ enum idmap_error_code err; ++ uint32_t id; ++ const uint32_t exp_id = 351800000; ++ const uint32_t exp_id2 = 832610000; ++ ++ err = sss_idmap_sid_to_unix(idmap_ctx, "S-1-5-21-1-2-3333-1000", &id); ++ fail_unless(err == IDMAP_NO_DOMAIN, "sss_idmap_sid_to_unix did not detect " ++ "unknown domain"); ++ ++ /* RID out of primary and secondary range */ ++ err = sss_idmap_sid_to_unix(idmap_ctx, "S-1-5-21-1-2-3-4000000", &id); ++ fail_unless(err == IDMAP_SUCCESS, "sss_idmap_sid_to_unix failed."); ++ fail_unless(id == exp_id, ++ "sss_idmap_sid_to_unix returned wrong id, " ++ "got [%d], expected [%d].", id, exp_id); ++ ++ err = sss_idmap_sid_to_unix(idmap_ctx, "S-1-5-21-1-2-3-1000", &id); ++ fail_unless(err == IDMAP_SUCCESS, "sss_idmap_sid_to_unix failed."); ++ fail_unless(id == (1000 + IDMAP_RANGE_MIN), ++ "sss_idmap_sid_to_unix returned wrong id, " ++ "got [%d], expected [%d].", id, 1000 + IDMAP_RANGE_MIN); ++ ++ err = sss_idmap_sid_to_unix(idmap_ctx, "S-1-5-21-1-2-3-210000", &id); ++ fail_unless(err == IDMAP_SUCCESS, "sss_idmap_sid_to_unix failed."); ++ fail_unless(id == exp_id2, ++ "sss_idmap_sid_to_unix returned wrong id, " ++ "got [%d], expected [%d].", id, exp_id2); ++} ++END_TEST ++ ++START_TEST(idmap_test_sid2uid_ext_sec_slices) ++{ ++ enum idmap_error_code err; ++ uint32_t id; ++ char *sid; ++ const uint32_t exp_id = 351800000; ++ ++ err = sss_idmap_unix_to_sid(idmap_ctx, exp_id, &sid); ++ fail_unless(err == IDMAP_NO_DOMAIN, "sss_idmap_unix_to_sid did not detect " ++ "id out of range"); ++ ++ /* RID out of primary and secondary range */ ++ err = sss_idmap_sid_to_unix(idmap_ctx, "S-1-5-21-1-2-3-4000000", &id); ++ fail_unless(err == IDMAP_SUCCESS, "sss_idmap_sid_to_unix failed."); ++ fail_unless(id == exp_id, ++ "sss_idmap_sid_to_unix returned wrong id, " ++ "got [%d], expected [%d].", id, exp_id); ++ ++ /* Secondary ranges were expanded by sid_to_unix call */ ++ err = sss_idmap_unix_to_sid(idmap_ctx, exp_id, &sid); ++ fail_unless(err == IDMAP_SUCCESS, "sss_idmap_unix_to_sid failed."); ++ fail_unless(strcmp(sid, "S-1-5-21-1-2-3-4000000") == 0, ++ "sss_idmap_unix_to_sid returned wrong SID, " ++ "expected [%s], got [%s].", "S-1-5-21-1-2-3-4000000", sid); ++ sss_idmap_free_sid(idmap_ctx, sid); ++} ++END_TEST ++ ++ ++START_TEST(idmap_test_dyn_dom_store_cb_fail) ++{ ++ enum idmap_error_code err; ++ uint32_t id; ++ char *sid; ++ const uint32_t exp_id = 351800000; ++ ++ err = sss_idmap_unix_to_sid(idmap_ctx, exp_id, &sid); ++ fail_unless(err == IDMAP_NO_DOMAIN, "sss_idmap_unix_to_sid did not detect " ++ "id out of range"); ++ ++ /* RID out of primary and secondary range */ ++ err = sss_idmap_sid_to_unix(idmap_ctx, "S-1-5-21-1-2-3-4000000", &id); ++ fail_unless(err == IDMAP_ERROR, "sss_idmap_sid_to_unix failed."); ++} ++END_TEST ++ ++START_TEST(idmap_test_dyn_dom_store_cb_ok) ++{ ++ enum idmap_error_code err; ++ uint32_t id; ++ char *sid; ++ const uint32_t exp_id = 351800000; ++ const char *exp_stored_data = "test.dom, S-1-5-21-1-2-3 S-1-5-21-1-2-3-4000000, 351800000, 351999999, 4000000"; ++ ++ err = sss_idmap_unix_to_sid(idmap_ctx, exp_id, &sid); ++ fail_unless(err == IDMAP_NO_DOMAIN, "sss_idmap_unix_to_sid did not detect " ++ "id out of range"); ++ ++ /* RID out of primary and secondary range */ ++ err = sss_idmap_sid_to_unix(idmap_ctx, "S-1-5-21-1-2-3-4000000", &id); ++ fail_unless(err == IDMAP_SUCCESS, "sss_idmap_sid_to_unix failed."); ++ ++ fail_unless(strcmp(data, ++ exp_stored_data) == 0, ++ "Storing dynamic domains idmapping failed: " ++ "expected [%s] but got [%s].", exp_stored_data, data); ++} ++END_TEST ++ ++ ++START_TEST(idmap_test_sid2uid_additional_secondary_slices) ++{ ++ enum idmap_error_code err; ++ struct TALLOC_CTX *tmp_ctx; ++ const char *dom_prefix = "S-1-5-21-1-2-3"; ++ const int max_rid = 80; ++ const char *sids[max_rid]; ++ unsigned int ids[max_rid]; ++ ++ tmp_ctx = talloc_new(NULL); ++ fail_unless(tmp_ctx != NULL, "Out of memory."); ++ ++ for (unsigned int i = 0; i < max_rid + 1; i++) { ++ sids[i] = talloc_asprintf(tmp_ctx, "%s-%u", dom_prefix, i); ++ ++ fail_unless(sids[i] != NULL, "Out of memory"); ++ ++ err = sss_idmap_sid_to_unix(idmap_ctx, sids[i], &ids[i]); ++ fail_unless(err == IDMAP_SUCCESS, "sss_idmap_sid_to_unix failed."); ++ } ++ ++ for (unsigned int i = 0; i < max_rid + 1; i++) { ++ char *sid; ++ ++ err = sss_idmap_unix_to_sid(idmap_ctx, ids[i], &sid); ++ fail_unless(err == IDMAP_SUCCESS, "sss_idmap_sid_to_unix failed."); ++ ++ fail_unless(strcmp(sid, sids[i]) == 0, ++ "sss_idmap_unix_to_sid returned wrong sid, " ++ "got [%s], expected [%s].", sid, sids[i]); ++ talloc_free(sid); ++ } ++ ++ talloc_free(tmp_ctx); ++} ++END_TEST ++ + START_TEST(idmap_test_bin_sid2uid) + { + enum idmap_error_code err; +@@ -284,6 +517,38 @@ START_TEST(idmap_test_uid2sid) + } + END_TEST + ++START_TEST(idmap_test_uid2sid_ss) ++{ ++ enum idmap_error_code err; ++ char *sid; ++ ++ err = sss_idmap_unix_to_sid(idmap_ctx, ++ IDMAP_RANGE_MIN + idmap_ctx->idmap_opts.rangesize + 1, ++ &sid); ++ fail_unless(err == IDMAP_NO_DOMAIN, "sss_idmap_unix_to_sid did not detect " ++ "id out of range"); ++ ++ err = sss_idmap_unix_to_sid(idmap_ctx, 2234, &sid); ++ fail_unless(err == IDMAP_SUCCESS, "sss_idmap_unix_to_sid failed."); ++ fail_unless(strcmp(sid, "S-1-5-21-1-2-3-1000") == 0, ++ "sss_idmap_unix_to_sid returned wrong SID, " ++ "expected [%s], got [%s].", "S-1-5-21-1-2-3-1000", sid); ++ ++ sss_idmap_free_sid(idmap_ctx, sid); ++ ++ /* Secondary ranges */ ++ err = sss_idmap_unix_to_sid(idmap_ctx, ++ 313800000, ++ &sid); ++ fail_unless(err == IDMAP_SUCCESS, "sss_idmap_unix_to_sid failed."); ++ fail_unless(strcmp(sid, "S-1-5-21-1-2-3-400000") == 0, ++ "sss_idmap_unix_to_sid returned wrong SID, " ++ "expected [%s], got [%s].", "S-1-5-21-1-2-3-400000", sid); ++ ++ sss_idmap_free_sid(idmap_ctx, sid); ++} ++END_TEST ++ + START_TEST(idmap_test_uid2dom_sid) + { + enum idmap_error_code err; +@@ -618,6 +883,73 @@ Suite *idmap_test_suite (void) + + suite_add_tcase(s, tc_map); + ++ /* Test secondary slices */ ++ TCase *tc_map_ss = tcase_create("IDMAP mapping tests"); ++ tcase_add_checked_fixture(tc_map_ss, ++ ck_leak_check_setup, ++ ck_leak_check_teardown); ++ tcase_add_checked_fixture(tc_map_ss, ++ idmap_ctx_setup, ++ idmap_ctx_teardown); ++ tcase_add_checked_fixture(tc_map_ss, ++ idmap_add_domain_with_sec_slices_setup, ++ NULL); ++ ++ tcase_add_test(tc_map_ss, idmap_test_sid2uid_ss); ++ tcase_add_test(tc_map_ss, idmap_test_uid2sid_ss); ++ tcase_add_test(tc_map_ss, idmap_test_sid2uid_ext_sec_slices); ++ ++ suite_add_tcase(s, tc_map_ss); ++ ++ /* Test secondary slices - callback to store failed. */ ++ TCase *tc_map_cb_fail = tcase_create("IDMAP mapping tests - store fail"); ++ tcase_add_checked_fixture(tc_map_cb_fail, ++ ck_leak_check_setup, ++ ck_leak_check_teardown); ++ tcase_add_checked_fixture(tc_map_cb_fail, ++ idmap_ctx_setup, ++ idmap_ctx_teardown); ++ tcase_add_checked_fixture(tc_map_cb_fail, ++ idmap_add_domain_with_sec_slices_setup_cb_fail, ++ NULL); ++ ++ tcase_add_test(tc_map_cb_fail, idmap_test_dyn_dom_store_cb_fail); ++ suite_add_tcase(s, tc_map_cb_fail); ++ ++ /* Test secondary slices - callback to store passed. */ ++ TCase *tc_map_cb_ok = tcase_create("IDMAP mapping tests"); ++ tcase_add_checked_fixture(tc_map_cb_ok, ++ ck_leak_check_setup, ++ ck_leak_check_teardown); ++ tcase_add_checked_fixture(tc_map_cb_ok, ++ idmap_ctx_setup, ++ idmap_ctx_teardown); ++ tcase_add_checked_fixture(tc_map_cb_ok, ++ idmap_add_domain_with_sec_slices_setup_cb_ok, ++ NULL); ++ ++ tcase_add_test(tc_map_cb_ok, idmap_test_dyn_dom_store_cb_ok); ++ suite_add_tcase(s, tc_map_cb_ok); ++ ++ /* Test additional secondary slices */ ++ TCase *tc_map_additional_secondary_slices = \ ++ tcase_create("IDMAP additional secondary slices"); ++ ++ tcase_add_checked_fixture(tc_map_additional_secondary_slices, ++ ck_leak_check_setup, ++ ck_leak_check_teardown); ++ tcase_add_checked_fixture(tc_map_additional_secondary_slices, ++ idmap_ctx_setup_additional_seconary_slices, ++ idmap_ctx_teardown); ++ tcase_add_checked_fixture(tc_map_additional_secondary_slices, ++ idmap_add_domain_with_sec_slices_setup, ++ NULL); ++ ++ tcase_add_test(tc_map_additional_secondary_slices, ++ idmap_test_sid2uid_additional_secondary_slices); ++ ++ suite_add_tcase(s, tc_map_additional_secondary_slices); ++ + return s; + } + int main(int argc, const char *argv[]) +-- +2.5.0 + diff --git a/sssd.spec b/sssd.spec index 8119eb0..b90090c 100644 --- a/sssd.spec +++ b/sssd.spec @@ -24,7 +24,7 @@ Name: sssd Version: 1.13.3 -Release: 2%{?dist} +Release: 3%{?dist} Group: Applications/System Summary: System Security Services Daemon License: GPLv3+ @@ -77,6 +77,12 @@ Patch0041: 0041-AD-add-task-to-renew-the-machine-account-password-if.patch Patch0042: 0042-FO-add-fo_get_active_server.patch Patch0043: 0043-FO-add-be_fo_get_active_server_name.patch Patch0044: 0044-AD-try-to-use-current-server-in-the-renewal-task.patch +Patch0045: 0045-sdap_connect_send-fail-if-uri-or-sockaddr-is-NULL.patch +Patch0046: 0046-SDAP-Make-it-possible-to-silence-errors-from-derefer.patch +Patch0047: 0047-p11-add-gnome-screensaver-to-list-of-allowed-service.patch +Patch0048: 0048-IDMAP-Fix-computing-max-id-for-slice-range.patch +Patch0049: 0049-IDMAP-New-structure-for-domain-range-params.patch +Patch0050: 0050-IDMAP-Add-support-for-automatic-adding-of-ranges.patch Patch0100: 0100-FO-Don-t-free-rc-allocated-structure.patch Patch0101: 0101-tests-Reduce-failover-code-duplication.patch Patch0102: 0102-FO-Use-refcount-to-keep-track-of-servers-returned-to.patch @@ -1063,6 +1069,9 @@ fi %{_libdir}/%{name}/modules/libwbclient.so %changelog +* Wed Jan 20 2016 Lukas Slebodnik - 1.13.3-3 +- Additional upstream fixes + * Tue Jan 19 2016 Lukas Slebodnik - 1.13.3-2 - Resolves: rhbz#1256849 - SUDO: Support the IPA schema