diff options
author | Andrew Bartlett <abartlet@samba.org> | 2009-07-28 14:05:19 +1000 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2009-07-28 14:10:47 +1000 |
commit | 8ff1f50b0c47f7ff92d557ef4caf64a44b387ab4 (patch) | |
tree | 98f832f301c2e5c92a1391f1ae2bb9a6a1590e52 /source4/kdc | |
parent | 47a7a2e442c7e006eca8188c6a01707d85c4e61c (diff) | |
download | samba-8ff1f50b0c47f7ff92d557ef4caf64a44b387ab4.tar.gz samba-8ff1f50b0c47f7ff92d557ef4caf64a44b387ab4.tar.bz2 samba-8ff1f50b0c47f7ff92d557ef4caf64a44b387ab4.zip |
s4:kerberos Add support for user principal names in certificates
This extends the PKINIT code in Heimdal to ask the HDB layer if the
User Principal Name name in the certificate is an alias (perhaps just
by case change) of the name given in the AS-REQ. (This was a TODO in
the Heimdal KDC)
The testsuite is extended to test this behaviour, and the other PKINIT
certficate (using the standard method to specify a principal name in a
certificate) is updated to use a Administrator (not administrator).
(This fixes the kinit test).
Andrew Bartlett
Diffstat (limited to 'source4/kdc')
-rw-r--r-- | source4/kdc/hdb-samba4.c | 103 |
1 files changed, 91 insertions, 12 deletions
diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c index 1a0e93f7ce..e39366c407 100644 --- a/source4/kdc/hdb-samba4.c +++ b/source4/kdc/hdb-samba4.c @@ -978,17 +978,16 @@ static krb5_error_code hdb_samba4_rename(krb5_context context, HDB *db, const ch return HDB_ERR_DB_INUSE; } -static krb5_error_code hdb_samba4_fetch_client(krb5_context context, HDB *db, - struct loadparm_context *lp_ctx, - TALLOC_CTX *mem_ctx, - krb5_const_principal principal, - unsigned flags, - hdb_entry_ex *entry_ex) { +static krb5_error_code hdb_samba4_lookup_client(krb5_context context, HDB *db, + struct loadparm_context *lp_ctx, + TALLOC_CTX *mem_ctx, + krb5_const_principal principal, + const char **attrs, + struct ldb_dn **realm_dn, + struct ldb_message **msg) { NTSTATUS nt_status; char *principal_string; - struct ldb_dn *realm_dn; krb5_error_code ret; - struct ldb_message *msg = NULL; ret = krb5_unparse_name(context, principal, &principal_string); @@ -997,8 +996,8 @@ static krb5_error_code hdb_samba4_fetch_client(krb5_context context, HDB *db, } nt_status = sam_get_results_principal((struct ldb_context *)db->hdb_db, - mem_ctx, principal_string, - &realm_dn, &msg); + mem_ctx, principal_string, attrs, + realm_dn, msg); free(principal_string); if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) { return HDB_ERR_NOENTRY; @@ -1008,9 +1007,29 @@ static krb5_error_code hdb_samba4_fetch_client(krb5_context context, HDB *db, return EINVAL; } + return ret; +} + +static krb5_error_code hdb_samba4_fetch_client(krb5_context context, HDB *db, + struct loadparm_context *lp_ctx, + TALLOC_CTX *mem_ctx, + krb5_const_principal principal, + unsigned flags, + hdb_entry_ex *entry_ex) { + struct ldb_dn *realm_dn; + krb5_error_code ret; + struct ldb_message *msg = NULL; + + ret = hdb_samba4_lookup_client(context, db, lp_ctx, + mem_ctx, principal, user_attrs, + &realm_dn, &msg); + if (ret != 0) { + return ret; + } + ret = hdb_samba4_message2entry(context, db, lp_ctx, mem_ctx, - principal, HDB_SAMBA4_ENT_TYPE_CLIENT, - realm_dn, msg, entry_ex); + principal, HDB_SAMBA4_ENT_TYPE_CLIENT, + realm_dn, msg, entry_ex); return ret; } @@ -1422,6 +1441,11 @@ static krb5_error_code hdb_samba4_destroy(krb5_context context, HDB *db) return 0; } + +/* Check if a given entry may delegate to this target principal + * + * This is currently a very nasty hack - allowing only delegation to itself. + */ krb5_error_code hdb_samba4_check_constrained_delegation(krb5_context context, HDB *db, hdb_entry_ex *entry, krb5_const_principal target_principal) @@ -1491,6 +1515,60 @@ krb5_error_code hdb_samba4_check_constrained_delegation(krb5_context context, HD return ret; } +/* Certificates printed by a the Certificate Authority might have a + * slightly different form of the user principal name to that in the + * database. Allow a mismatch where they both refer to the same + * SID */ + +krb5_error_code hdb_samba4_check_pkinit_ms_upn_match(krb5_context context, HDB *db, + hdb_entry_ex *entry, + krb5_const_principal certificate_principal) +{ + struct ldb_context *ldb_ctx = (struct ldb_context *)db->hdb_db; + struct loadparm_context *lp_ctx = talloc_get_type(ldb_get_opaque(ldb_ctx, "loadparm"), + struct loadparm_context); + krb5_error_code ret; + struct ldb_dn *realm_dn; + struct ldb_message *msg; + struct dom_sid *orig_sid; + struct dom_sid *target_sid; + struct hdb_samba4_private *p = talloc_get_type(entry->ctx, struct hdb_samba4_private); + const char *ms_upn_check_attrs[] = { + "objectSid", NULL + }; + + TALLOC_CTX *mem_ctx = talloc_named(db, 0, "hdb_samba4_check_constrained_delegation"); + + if (!mem_ctx) { + ret = ENOMEM; + krb5_set_error_message(context, ret, "hdb_samba4_fetch: talloc_named() failed!"); + return ret; + } + + ret = hdb_samba4_lookup_client(context, db, lp_ctx, + mem_ctx, certificate_principal, + ms_upn_check_attrs, &realm_dn, &msg); + + if (ret != 0) { + talloc_free(mem_ctx); + return ret; + } + + orig_sid = samdb_result_dom_sid(mem_ctx, p->msg, "objectSid"); + target_sid = samdb_result_dom_sid(mem_ctx, msg, "objectSid"); + + /* Consider these to be the same principal, even if by a different + * name. The easy and safe way to prove this is by SID + * comparison */ + if (!(orig_sid && target_sid && dom_sid_equal(orig_sid, target_sid))) { + talloc_free(mem_ctx); + return KRB5_KDC_ERR_CLIENT_NAME_MISMATCH; + } + + talloc_free(mem_ctx); + return ret; +} + /* This interface is to be called by the KDC and libnet_keytab_dump, which is expecting Samba * calling conventions. It is also called by a wrapper * (hdb_samba4_create) from the kpasswdd -> krb5 -> keytab_hdb -> hdb @@ -1556,6 +1634,7 @@ NTSTATUS hdb_samba4_create_kdc(TALLOC_CTX *mem_ctx, (*db)->hdb_auth_status = NULL; (*db)->hdb_check_constrained_delegation = hdb_samba4_check_constrained_delegation; + (*db)->hdb_check_pkinit_ms_upn_match = hdb_samba4_check_pkinit_ms_upn_match; return NT_STATUS_OK; } |