diff options
| author | Alexander Bokovoy <abokovoy@redhat.com> | 2016-06-06 11:41:46 +0300 |
|---|---|---|
| committer | Martin Basti <mbasti@redhat.com> | 2016-06-11 17:25:50 +0200 |
| commit | bb75f5a5836ea011b8920f8bb8d58c1f4cd9b4c8 (patch) | |
| tree | 108fedb3d09df8b2030e66702d3d3c2b4aaf701f /daemons | |
| parent | b506fd178edbf1553ca581c44ac6697f88ead125 (diff) | |
adtrust: support UPNs for trusted domain users
Add support for additional user name principal suffixes from
trusted Active Directory forests. UPN suffixes are property
of the forest and as such are associated with the forest root
domain.
FreeIPA stores UPN suffixes as ipaNTAdditionalSuffixes multi-valued
attribute of ipaNTTrustedDomain object class.
In order to look up UPN suffixes, netr_DsRGetForestTrustInformation
LSA RPC call is used instead of netr_DsrEnumerateDomainTrusts.
For more details on UPN and naming in Active Directory see
https://technet.microsoft.com/en-us/library/cc739093%28v=ws.10%29.aspx
https://fedorahosted.org/freeipa/ticket/5354
Reviewed-By: Martin Babinsky <mbabinsk@redhat.com>
Diffstat (limited to 'daemons')
| -rw-r--r-- | daemons/ipa-kdb/ipa_kdb_mspac.c | 60 | ||||
| -rw-r--r-- | daemons/ipa-kdb/ipa_kdb_mspac_private.h | 1 | ||||
| -rw-r--r-- | daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c | 9 |
3 files changed, 57 insertions, 13 deletions
diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c index d54ca7189..80e7055fd 100644 --- a/daemons/ipa-kdb/ipa_kdb_mspac.c +++ b/daemons/ipa-kdb/ipa_kdb_mspac.c @@ -2273,7 +2273,7 @@ static char *get_server_netbios_name(struct ipadb_context *ipactx) void ipadb_mspac_struct_free(struct ipadb_mspac **mspac) { - int i; + int i, j; if (!*mspac) return; @@ -2290,6 +2290,12 @@ void ipadb_mspac_struct_free(struct ipadb_mspac **mspac) free((*mspac)->trusts[i].sid_blacklist_outgoing); free((*mspac)->trusts[i].parent_name); (*mspac)->trusts[i].parent = NULL; + if ((*mspac)->trusts[i].upn_suffixes) { + for (j = 0; (*mspac)->trusts[i].upn_suffixes[j]; j++) { + free((*mspac)->trusts[i].upn_suffixes[j]); + } + free((*mspac)->trusts[i].upn_suffixes); + } } free((*mspac)->trusts); } @@ -2405,7 +2411,7 @@ krb5_error_code ipadb_mspac_get_trusted_domains(struct ipadb_context *ipactx) LDAP *lc = ipactx->lcontext; char *attrs[] = { "cn", "ipaNTTrustPartner", "ipaNTFlatName", "ipaNTTrustedDomainSID", "ipaNTSIDBlacklistIncoming", - "ipaNTSIDBlacklistOutgoing", NULL }; + "ipaNTSIDBlacklistOutgoing", "ipaNTAdditionalSuffixes", NULL }; char *filter = "(objectclass=ipaNTTrustedDomain)"; krb5_error_code kerr; LDAPMessage *res = NULL; @@ -2462,26 +2468,42 @@ krb5_error_code ipadb_mspac_get_trusted_domains(struct ipadb_context *ipactx) goto done; } + t[n].flat_name = NULL; ret = ipadb_ldap_attr_to_str(lc, le, "ipaNTFlatName", &t[n].flat_name); - if (ret) { + if (ret && ret != ENOENT) { ret = EINVAL; goto done; } + t[n].domain_sid = NULL; ret = ipadb_ldap_attr_to_str(lc, le, "ipaNTTrustedDomainSID", &t[n].domain_sid); - if (ret) { + if (ret && ret != ENOENT) { ret = EINVAL; goto done; } ret = string_to_sid(t[n].domain_sid, &t[n].domsid); - if (ret) { + if (ret && t[n].domain_sid != NULL) { ret = EINVAL; goto done; } + ret = ipadb_ldap_attr_to_strlist(lc, le, "ipaNTAdditionalSuffixes", + &t[n].upn_suffixes); + + if (ret) { + if (ret == ENOENT) { + /* This attribute is optional */ + ret = 0; + t[n].upn_suffixes = NULL; + } else { + ret = EINVAL; + goto done; + } + } + ret = ipadb_ldap_attr_to_strlist(lc, le, "ipaNTSIDBlacklistIncoming", &sid_blacklist_incoming); @@ -2808,6 +2830,7 @@ krb5_error_code ipadb_is_princ_from_trusted_realm(krb5_context kcontext, struct ipadb_context *ipactx; int i, j, length; const char *name; + bool result = false; if (test_realm == NULL || test_realm[0] == '\0') { return KRB5_KDB_NOENTRY; @@ -2829,12 +2852,27 @@ krb5_error_code ipadb_is_princ_from_trusted_realm(krb5_context kcontext, /* Iterate through list of trusts and check if input realm belongs to any of the trust */ for(i = 0 ; i < ipactx->mspac->num_trusts ; i++) { - if ((strncasecmp(test_realm, - ipactx->mspac->trusts[i].domain_name, - size) == 0) || - (strncasecmp(test_realm, - ipactx->mspac->trusts[i].flat_name, - size) == 0)) { + result = strncasecmp(test_realm, + ipactx->mspac->trusts[i].domain_name, + size) == 0; + + if (!result && (ipactx->mspac->trusts[i].flat_name != NULL)) { + result = strncasecmp(test_realm, + ipactx->mspac->trusts[i].flat_name, + size) == 0; + } + + if (!result && (ipactx->mspac->trusts[i].upn_suffixes != NULL)) { + for (j = 0; ipactx->mspac->trusts[i].upn_suffixes[j]; j++) { + result = strncasecmp(test_realm, + ipactx->mspac->trusts[i].upn_suffixes[j], + size) == 0; + if (result) + break; + } + } + + if (result) { /* return the realm if caller supplied a place for it */ if (trusted_realm != NULL) { name = (ipactx->mspac->trusts[i].parent_name != NULL) ? diff --git a/daemons/ipa-kdb/ipa_kdb_mspac_private.h b/daemons/ipa-kdb/ipa_kdb_mspac_private.h index 1052bb882..30382d2ee 100644 --- a/daemons/ipa-kdb/ipa_kdb_mspac_private.h +++ b/daemons/ipa-kdb/ipa_kdb_mspac_private.h @@ -47,6 +47,7 @@ struct ipadb_adtrusts { int len_sid_blacklist_outgoing; struct ipadb_adtrusts *parent; char *parent_name; + char **upn_suffixes; }; int string_to_sid(const char *str, struct dom_sid *sid); diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c index 84b1b9af4..e629247fd 100644 --- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c +++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c @@ -1023,8 +1023,13 @@ static int handle_name_request(struct ipa_extdom_ctx *ctx, char *buf = NULL; struct sss_nss_kv *kv_list = NULL; - ret = asprintf(&fq_name, "%s%c%s", name, SSSD_DOMAIN_SEPARATOR, - domain_name); + if (strchr(name, SSSD_DOMAIN_SEPARATOR) == NULL) { + ret = asprintf(&fq_name, "%s%c%s", name, SSSD_DOMAIN_SEPARATOR, + domain_name); + } else { + /* SSSD_DOMAIN_SEPARATOR already present, assume UPN */ + ret = asprintf(&fq_name, "%s", name); + } if (ret == -1) { ret = LDAP_OPERATIONS_ERROR; set_err_msg(req, "Failed to create fully qualified name"); |
