From 033f3376a834c1078b377647069b7e30aef59667 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 21 Jun 2011 11:05:15 +0200 Subject: s4:auth/kerberos: protect kerberos_kinit_password_cc() against old KDCs If the KDC does not support S4U2Proxy, it might return a ticket for the TGT client principal. metze --- source4/auth/kerberos/kerberos.c | 49 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) (limited to 'source4') diff --git a/source4/auth/kerberos/kerberos.c b/source4/auth/kerberos/kerberos.c index d32559ed81..0fc9d143ab 100644 --- a/source4/auth/kerberos/kerberos.c +++ b/source4/auth/kerberos/kerberos.c @@ -109,6 +109,7 @@ krb5_ccache tmp_cc; const char *self_realm; krb5_principal blacklist_principal = NULL; + krb5_principal whitelist_principal = NULL; if (impersonate_principal && self_service == NULL) { return EINVAL; @@ -282,13 +283,23 @@ s4u2self_creds->ticket.length, &s4u2self_ticket, &s4u2self_ticketlen); - krb5_free_creds(ctx, s4u2self_creds); if (code != 0) { + krb5_free_creds(ctx, s4u2self_creds); krb5_free_principal(ctx, blacklist_principal); krb5_cc_destroy(ctx, tmp_cc); return code; } + /* + * we need to remember the client principal of the + * S4U2Self stage and as it needs to match the one we + * will get for the S4U2Proxy stage. We need this + * in order to detect KDCs which does not support S4U2Proxy. + */ + whitelist_principal = s4u2self_creds->client; + s4u2self_creds->client = NULL; + krb5_free_creds(ctx, s4u2self_creds); + /* * For S4U2Proxy we also got a target service principal, * which also belongs to our own realm (available on @@ -297,6 +308,7 @@ code = krb5_parse_name(ctx, target_service, &target_princ); if (code != 0) { free_Ticket(&s4u2self_ticket); + krb5_free_principal(ctx, whitelist_principal); krb5_free_principal(ctx, blacklist_principal); krb5_cc_destroy(ctx, tmp_cc); return code; @@ -306,6 +318,7 @@ if (code != 0) { free_Ticket(&s4u2self_ticket); krb5_free_principal(ctx, target_princ); + krb5_free_principal(ctx, whitelist_principal); krb5_free_principal(ctx, blacklist_principal); krb5_cc_destroy(ctx, tmp_cc); return code; @@ -315,6 +328,7 @@ if (code != 0) { free_Ticket(&s4u2self_ticket); krb5_free_principal(ctx, target_princ); + krb5_free_principal(ctx, whitelist_principal); krb5_free_principal(ctx, blacklist_principal); krb5_cc_destroy(ctx, tmp_cc); return code; @@ -328,6 +342,7 @@ if (code != 0) { krb5_get_creds_opt_free(ctx, options); krb5_free_principal(ctx, target_princ); + krb5_free_principal(ctx, whitelist_principal); krb5_free_principal(ctx, blacklist_principal); krb5_cc_destroy(ctx, tmp_cc); return code; @@ -339,6 +354,7 @@ krb5_free_principal(ctx, target_princ); krb5_cc_destroy(ctx, tmp_cc); if (code != 0) { + krb5_free_principal(ctx, whitelist_principal); krb5_free_principal(ctx, blacklist_principal); return code; } @@ -352,6 +368,7 @@ &store_creds); krb5_free_creds(ctx, s4u2proxy_creds); if (code != 0) { + krb5_free_principal(ctx, whitelist_principal); krb5_free_principal(ctx, blacklist_principal); return code; } @@ -385,6 +402,7 @@ SAFE_FREE(sp); SAFE_FREE(ip); + krb5_free_principal(ctx, whitelist_principal); krb5_free_principal(ctx, blacklist_principal); krb5_free_cred_contents(ctx, &store_creds); return KRB5_FWD_BAD_PRINCIPAL; @@ -393,6 +411,35 @@ krb5_free_principal(ctx, blacklist_principal); } + if (whitelist_principal && + !krb5_principal_compare(ctx, store_creds.client, whitelist_principal)) { + char *sp = NULL; + char *ep = NULL; + + code = krb5_unparse_name(ctx, store_creds.client, &sp); + if (code != 0) { + sp = NULL; + } + code = krb5_unparse_name(ctx, whitelist_principal, &ep); + if (code != 0) { + ep = NULL; + } + DEBUG(1, ("kerberos_kinit_password_cc: " + "KDC returned wrong principal[%s] we expected [%s]\n", + sp?sp:"", + ep?ep:"")); + + SAFE_FREE(sp); + SAFE_FREE(ep); + + krb5_free_principal(ctx, whitelist_principal); + krb5_free_cred_contents(ctx, &store_creds); + return KRB5_FWD_BAD_PRINCIPAL; + } + if (whitelist_principal) { + krb5_free_principal(ctx, whitelist_principal); + } + code = krb5_cc_initialize(ctx, store_cc, store_principal); if (code != 0) { krb5_free_cred_contents(ctx, &store_creds); -- cgit