diff options
author | Stefan Metzmacher <metze@samba.org> | 2015-02-10 14:37:29 +0100 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2015-07-08 18:38:20 +0200 |
commit | 2d98800219e1bc434cccc09322b4b509879d2a7d (patch) | |
tree | 2571c63cea743263ddaa012caede38b74a7d4b05 /source4/heimdal | |
parent | c63f3607881154e1bf86bdd1009f9cdec4a47576 (diff) | |
download | samba-2d98800219e1bc434cccc09322b4b509879d2a7d.tar.gz |
heimdal:kdc: add support for HDB_ERR_WRONG_REALM
A backend can return this if asked with HDB_F_GET_CLIENT|HDB_F_FOR_AS_REQ
for a KRB5_NT_ENTERPRISE_PRINCIPAL record or for HDB_F_GET_SERVER | HDB_F_FOR_TGS_REQ.
entry_ex->entry.principal->realm needs to return the real realm of the principal
(or at least a the realm of the next cross-realm trust hop).
This is needed to route enterprise principals between AD domain trusts.
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Diffstat (limited to 'source4/heimdal')
-rw-r--r-- | source4/heimdal/kdc/kerberos5.c | 26 | ||||
-rw-r--r-- | source4/heimdal/kdc/krb5tgs.c | 26 | ||||
-rw-r--r-- | source4/heimdal/kdc/misc.c | 7 | ||||
-rw-r--r-- | source4/heimdal/lib/hdb/hdb_err.et | 1 |
4 files changed, 59 insertions, 1 deletions
diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c index cb97390d3e3..7e7aefd21e5 100644 --- a/source4/heimdal/kdc/kerberos5.c +++ b/source4/heimdal/kdc/kerberos5.c @@ -1060,6 +1060,30 @@ _kdc_as_rep(krb5_context context, if(ret == HDB_ERR_NOT_FOUND_HERE) { kdc_log(context, config, 5, "client %s does not have secrets at this KDC, need to proxy", client_name); goto out; + } else if (ret == HDB_ERR_WRONG_REALM) { + char *fixed_client_name = NULL; + + ret = krb5_unparse_name(context, client->entry.principal, + &fixed_client_name); + if (ret) { + goto out; + } + + kdc_log(context, config, 0, "WRONG_REALM - %s -> %s", + client_name, fixed_client_name); + free(fixed_client_name); + + ret = krb5_mk_error_ext(context, + KRB5_KDC_ERR_WRONG_REALM, + NULL, /* e_text */ + NULL, /* e_data */ + server_princ, + NULL, /* client_name */ + &client->entry.principal->realm, + NULL, /* client_time */ + NULL, /* client_usec */ + reply); + goto out; } else if(ret){ const char *msg = krb5_get_error_message(context, ret); kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name, msg); @@ -1779,7 +1803,7 @@ _kdc_as_rep(krb5_context context, out: free_AS_REP(&rep); - if(ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE){ + if(ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE && reply->length == 0) { krb5_mk_error(context, ret, e_text, diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index ca589e87fa0..1d0d1ddc3fa 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -1616,6 +1616,32 @@ server_lookup: if(ret == HDB_ERR_NOT_FOUND_HERE) { kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", sp); goto out; + } else if (ret == HDB_ERR_WRONG_REALM) { + if (ref_realm) + free(ref_realm); + ref_realm = strdup(server->entry.principal->realm); + if (ref_realm == NULL) { + ret = ENOMEM; + goto out; + } + + kdc_log(context, config, 5, + "Returning a referral to realm %s for " + "server %s.", + ref_realm, spn); + krb5_free_principal(context, sp); + sp = NULL; + free(spn); + spn = NULL; + ret = krb5_make_principal(context, &sp, r, KRB5_TGS_NAME, + ref_realm, NULL); + if (ret) + goto out; + ret = krb5_unparse_name(context, sp, &spn); + if (ret) + goto out; + + goto server_lookup; } else if(ret){ const char *new_rlm, *msg; Realm req_rlm; diff --git a/source4/heimdal/kdc/misc.c b/source4/heimdal/kdc/misc.c index 4ef5439cf14..b0bc38a2b6f 100644 --- a/source4/heimdal/kdc/misc.c +++ b/source4/heimdal/kdc/misc.c @@ -99,6 +99,13 @@ _kdc_db_fetch(krb5_context context, config->db[i]->hdb_close(context, config->db[i]); switch (ret) { + case HDB_ERR_WRONG_REALM: + /* + * the ent->entry.principal just contains hints for the client + * to retry. This is important for enterprise principal routing + * between trusts. + */ + /* fall through */ case 0: if (db) *db = config->db[i]; diff --git a/source4/heimdal/lib/hdb/hdb_err.et b/source4/heimdal/lib/hdb/hdb_err.et index 0bdcb385f6b..135747b0564 100644 --- a/source4/heimdal/lib/hdb/hdb_err.et +++ b/source4/heimdal/lib/hdb/hdb_err.et @@ -27,5 +27,6 @@ error_code MANDATORY_OPTION, "Entry contains unknown mandatory extension" error_code NO_WRITE_SUPPORT, "HDB backend doesn't contain write support" error_code NOT_FOUND_HERE, "The secret for this entry is not replicated to this database" error_code MISUSE, "Incorrect use of the API" +error_code WRONG_REALM, "The principal exists in another realm." end |