From 14faec9cd9437ef116ae054412d25ec2e820e409 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Jul 19 2018 14:08:50 +0000 Subject: ipa provider: expand search base to cover trusted domain objects In case of a trust between FreeIPA and an Active Directory, domain controller would use a TDO object in the trusting domain to authenticate. Due to how trusted domain objects are used in Active Directory, a domain controller from the trusted domain either synthesize a Kerberos ticket without MS-PAC or would use NTLMSSP to authenticate. On IPA master smbd process will attempt to validate successfully authenticated TDO principal by looking at its MS-PAC structure, only to find it is missing. As result, smbd will revert to a direct getpwnam() to see if this user exists on the system. Because TDO objects are stored under cn=trusts,$SUFFIX in FreeIPA, they couldn't be found by SSSD which uses cn=accounts,$SUFFIX by default. Add a search base to look up cn=trusts,$SUFFX to allow TDO objects to be queried. On FreeIPA side access controls are put in place so that only AD trust agents are able to see a content of the cn=trusts,$SUFFIX subtree. Signed-of-by: Alexander Bokovoy Reviewed-by: Jakub Hrozek --- diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c index 0614019..c71eca8 100644 --- a/src/providers/ipa/ipa_common.c +++ b/src/providers/ipa/ipa_common.c @@ -180,6 +180,7 @@ int ipa_get_id_options(struct ipa_options *ipa_opts, char *value; int ret; int i; + bool server_mode; tmpctx = talloc_new(ipa_opts); if (!tmpctx) { @@ -293,6 +294,59 @@ int ipa_get_id_options(struct ipa_options *ipa_opts, &ipa_opts->id->sdom->user_search_bases); if (ret != EOK) goto done; + /* In server mode we need to search both cn=accounts,$SUFFIX and + * cn=trusts,$SUFFIX to allow trusted domain object accounts to be found. + * If cn=trusts,$SUFFIX is missing in the user search bases, add one + */ + server_mode = dp_opt_get_bool(ipa_opts->basic, IPA_SERVER_MODE); + if (server_mode != false) { + /* bases is not NULL at this point already */ + struct sdap_search_base **bases = ipa_opts->id->sdom->user_search_bases; + struct sdap_search_base *new_base = NULL; + + for (i = 0; bases[i] != NULL; i++) { + if (strcasestr(bases[i]->basedn, "cn=trusts,") != NULL) { + break; + } + } + if (NULL == bases[i]) { + /* no cn=trusts in the base, add a new one */ + char *new_dn = talloc_asprintf(bases, + "cn=trusts,%s", + basedn); + if (NULL == new_dn) { + ret = ENOMEM; + goto done; + } + + ret = sdap_create_search_base(bases, new_dn, + LDAP_SCOPE_SUBTREE, + "(objectClass=ipaIDObject)", + &new_base); + if (ret != EOK) { + goto done; + } + + bases = talloc_realloc(ipa_opts->id, + ipa_opts->id->sdom->user_search_bases, + struct sdap_search_base*, + i + 2); + + if (NULL == bases) { + ret = ENOMEM; + goto done; + } + + bases[i] = new_base; + bases[i+1] = NULL; + ipa_opts->id->sdom->user_search_bases = bases; + + DEBUG(SSSDBG_TRACE_FUNC, + "Option %s expanded to cover cn=trusts base\n", + ipa_opts->id->basic[SDAP_USER_SEARCH_BASE].opt_name); + } + } + if (NULL == dp_opt_get_string(ipa_opts->id->basic, SDAP_GROUP_SEARCH_BASE)) { ret = dp_opt_set_string(ipa_opts->id->basic, SDAP_GROUP_SEARCH_BASE,