diff options
Diffstat (limited to 'src/providers')
-rw-r--r-- | src/providers/ad/ad_id.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c index 20f9c23fa..87b69c668 100644 --- a/src/providers/ad/ad_id.c +++ b/src/providers/ad/ad_id.c @@ -20,10 +20,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "util/util.h" +#include "util/strtonum.h" #include "providers/ad/ad_common.h" #include "providers/ad/ad_id.h" #include "providers/ad/ad_domain_info.h" #include "providers/ldap/sdap_async_enum.h" +#include "providers/ldap/sdap_idmap.h" struct ad_handle_acct_info_state { struct be_req *breq; @@ -222,6 +224,84 @@ get_conn_list(struct be_req *breq, struct ad_id_ctx *ad_ctx, return clist; } +static errno_t ad_account_can_shortcut(struct be_ctx *be_ctx, + struct sdap_idmap_ctx *idmap_ctx, + int filter_type, + const char *filter_value, + const char *filter_domain, + bool *_shortcut) +{ + struct sss_domain_info *domain = be_ctx->domain; + struct sss_domain_info *req_dom = NULL; + enum idmap_error_code err; + char *sid = NULL; + const char *csid = NULL; + uint32_t id; + bool shortcut = false; + errno_t ret; + + if (!sdap_idmap_domain_has_algorithmic_mapping(idmap_ctx, domain->name, + domain->domain_id)) { + shortcut = false; + ret = EOK; + goto done; + } + + switch (filter_type) { + case BE_FILTER_IDNUM: + /* convert value to ID */ + errno = 0; + id = strtouint32(filter_value, NULL, 10); + if (errno != 0) { + ret = errno; + goto done; + } + + /* convert the ID to its SID equivalent */ + err = sss_idmap_unix_to_sid(idmap_ctx->map, id, &sid); + if (err != IDMAP_SUCCESS) { + DEBUG(SSSDBG_MINOR_FAILURE, ("Mapping ID [%s] to SID failed: " + "[%s]\n", filter_value, idmap_error_string(err))); + ret = EIO; + goto done; + } + /* fall through */ + case BE_FILTER_SECID: + csid = sid == NULL ? filter_value : sid; + + req_dom = find_subdomain_by_sid(domain, csid); + if (req_dom == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("Invalid domain\n")); + ret = ERR_DOMAIN_NOT_FOUND; + goto done; + } + + if (strcasecmp(req_dom->name, filter_domain) != 0) { + shortcut = true; + } else { + shortcut = false; + } + break; + default: + shortcut = false; + break; + } + + ret = EOK; + +done: + if (sid != NULL) { + /* FIXME: use library function when #2133 is fixed */ + talloc_free(sid); + } + + if (ret == EOK) { + *_shortcut = shortcut; + } + + return ret; +} + static void ad_account_info_complete(struct tevent_req *req); void @@ -235,6 +315,7 @@ ad_account_info_handler(struct be_req *be_req) struct sss_domain_info *dom; struct sdap_domain *sdom; struct sdap_id_conn_ctx **clist; + bool shortcut; errno_t ret; ad_ctx = talloc_get_type(be_ctx->bet_info[BET_ID].pvt_bet_data, @@ -246,6 +327,21 @@ ad_account_info_handler(struct be_req *be_req) return be_req_terminate(be_req, DP_ERR_OFFLINE, EAGAIN, "Offline"); } + /* Try to shortcut if this is ID or SID search and it belongs to + * other domain range than is in ar->domain. */ + ret = ad_account_can_shortcut(be_ctx, sdap_id_ctx->opts->idmap_ctx, + ar->filter_type, ar->filter_value, + ar->domain, &shortcut); + if (ret != EOK) { + goto fail; + } + + if (shortcut) { + DEBUG(SSSDBG_TRACE_FUNC, ("This ID is from different domain\n")); + be_req_terminate(be_req, DP_ERR_OK, EOK, NULL); + return; + } + dom = be_ctx->domain; if (strcasecmp(ar->domain, be_ctx->domain->name) != 0) { /* Subdomain request, verify subdomain */ |