client referral support for trusted domain principals

https://fedorahosted.org/freeipa/ticket/3559

Reviewed-By: Sumit Bose <sbose@redhat.com>
This commit is contained in:
Alexander Bokovoy
2015-08-20 15:06:12 +03:00
committed by Martin Basti
parent 4b381b1503
commit 766438aba0
3 changed files with 123 additions and 0 deletions

View File

@@ -274,6 +274,14 @@ krb5_error_code ipadb_check_transited_realms(krb5_context kcontext,
const krb5_data *tr_contents, const krb5_data *tr_contents,
const krb5_data *client_realm, const krb5_data *client_realm,
const krb5_data *server_realm); const krb5_data *server_realm);
/* Checks whether a principal's realm is one of trusted domains' realm or NetBIOS name
* and returns the realm of the matched trusted domain in 'trusted_domain'
* Returns 0 in case of success and KRB5_KDB_NOENTRY otherwise
* If DAL driver is not initialized, returns KRB5_KDB_DBNOTINITED */
krb5_error_code ipadb_is_princ_from_trusted_realm(krb5_context kcontext,
const char *test_realm, size_t size,
char **trusted_realm);
/* DELEGATION CHECKS */ /* DELEGATION CHECKS */
krb5_error_code ipadb_check_allowed_to_delegate(krb5_context kcontext, krb5_error_code ipadb_check_allowed_to_delegate(krb5_context kcontext,

View File

@@ -2790,3 +2790,63 @@ krb5_error_code ipadb_check_transited_realms(krb5_context kcontext,
} }
return ret; return ret;
} }
/* Checks whether a principal's realm is one of trusted domains' realm or NetBIOS name
* and returns the realm of the matched trusted domain in 'trusted_domain'
* Returns 0 in case of success and KRB5_KDB_NOENTRY otherwise
* If DAL driver is not initialized, returns KRB5_KDB_DBNOTINITED */
krb5_error_code ipadb_is_princ_from_trusted_realm(krb5_context kcontext,
const char *test_realm, size_t size,
char **trusted_realm)
{
struct ipadb_context *ipactx;
int i, j, length;
const char *name;
if (test_realm == NULL || test_realm[0] == '\0') {
return KRB5_KDB_NOENTRY;
}
ipactx = ipadb_get_context(kcontext);
if (!ipactx || !ipactx->mspac) {
return KRB5_KDB_DBNOTINITED;
}
/* First, compare realm with ours, it would not be from a trusted realm then */
if (strncasecmp(test_realm, ipactx->realm, size) == 0) {
return KRB5_KDB_NOENTRY;
}
if (!ipactx->mspac || !ipactx->mspac->trusts) {
return KRB5_KDB_NOENTRY;
}
/* 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)) {
/* return the realm if caller supplied a place for it */
if (trusted_realm != NULL) {
name = (ipactx->mspac->trusts[i].parent_name != NULL) ?
ipactx->mspac->trusts[i].parent_name :
ipactx->mspac->trusts[i].domain_name;
length = strlen(name) + 1;
*trusted_realm = calloc(1, length);
if (*trusted_realm != NULL) {
for (j = 0; j < length; j++) {
(*trusted_realm)[j] = toupper(name[j]);
}
} else {
return KRB5_KDB_NOENTRY;
}
}
return 0;
}
}
return KRB5_KDB_NOENTRY;
}

View File

@@ -1023,8 +1023,10 @@ krb5_error_code ipadb_get_principal(krb5_context kcontext,
struct ipadb_context *ipactx; struct ipadb_context *ipactx;
krb5_error_code kerr; krb5_error_code kerr;
char *principal = NULL; char *principal = NULL;
char *trusted_realm = NULL;
LDAPMessage *res = NULL; LDAPMessage *res = NULL;
LDAPMessage *lentry; LDAPMessage *lentry;
krb5_db_entry *kentry = NULL;
uint32_t pol; uint32_t pol;
ipactx = ipadb_get_context(kcontext); ipactx = ipadb_get_context(kcontext);
@@ -1044,6 +1046,55 @@ krb5_error_code ipadb_get_principal(krb5_context kcontext,
kerr = ipadb_find_principal(kcontext, flags, res, &principal, &lentry); kerr = ipadb_find_principal(kcontext, flags, res, &principal, &lentry);
if (kerr != 0) { if (kerr != 0) {
if ((kerr == KRB5_KDB_NOENTRY) &&
((flags & (KRB5_KDB_FLAG_CANONICALIZE |
KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY)) != 0)) {
/* First check if we got enterprise principal which looks like
* username\@enterprise_realm@REALM */
char *realm;
krb5_data *upn;
upn = krb5_princ_component(kcontext, search_for,
krb5_princ_size(kcontext, search_for) - 1);
if (upn == NULL) {
kerr = KRB5_KDB_NOENTRY;
goto done;
}
realm = memrchr(upn->data, '@', upn->length);
if (realm == NULL) {
kerr = KRB5_KDB_NOENTRY;
goto done;
}
/* skip '@' and use part after '@' as an enterprise realm for comparison */
realm++;
kerr = ipadb_is_princ_from_trusted_realm(kcontext,
realm,
upn->length - (realm - upn->data),
&trusted_realm);
if (kerr == 0) {
kentry = calloc(1, sizeof(krb5_db_entry));
if (!kentry) {
kerr = ENOMEM;
goto done;
}
kerr = krb5_parse_name(kcontext, principal,
&kentry->princ);
if (kerr != 0) {
goto done;
}
kerr = krb5_set_principal_realm(kcontext, kentry->princ, trusted_realm);
if (kerr != 0) {
goto done;
}
*entry = kentry;
}
}
goto done; goto done;
} }
@@ -1060,6 +1111,10 @@ krb5_error_code ipadb_get_principal(krb5_context kcontext,
} }
done: done:
free(trusted_realm);
if ((kerr != 0) && (kentry != NULL)) {
ipadb_free_principal(kcontext, kentry);
}
ldap_msgfree(res); ldap_msgfree(res);
krb5_free_unparsed_name(kcontext, principal); krb5_free_unparsed_name(kcontext, principal);
return kerr; return kerr;