summaryrefslogtreecommitdiffstats
path: root/source4/heimdal/kdc/krb5tgs.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/heimdal/kdc/krb5tgs.c')
-rw-r--r--source4/heimdal/kdc/krb5tgs.c130
1 files changed, 78 insertions, 52 deletions
diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c
index 037934f2a65..66170cb29f1 100644
--- a/source4/heimdal/kdc/krb5tgs.c
+++ b/source4/heimdal/kdc/krb5tgs.c
@@ -282,8 +282,9 @@ check_PAC(krb5_context context,
hdb_entry_ex *client,
hdb_entry_ex *server,
hdb_entry_ex *krbtgt,
- const EncryptionKey *server_key,
+ const EncryptionKey *server_check_key,
const EncryptionKey *krbtgt_check_key,
+ const EncryptionKey *server_sign_key,
const EncryptionKey *krbtgt_sign_key,
EncTicketPart *tkt,
krb5_data *rspac,
@@ -328,7 +329,7 @@ check_PAC(krb5_context context,
ret = krb5_pac_verify(context, pac, tkt->authtime,
client_principal,
- krbtgt_check_key, NULL);
+ server_check_key, krbtgt_check_key);
if (ret) {
krb5_pac_free(context, pac);
return ret;
@@ -351,7 +352,7 @@ check_PAC(krb5_context context,
*signedpath = 1;
ret = _krb5_pac_sign(context, pac, tkt->authtime,
client_principal,
- server_key, krbtgt_sign_key, rspac);
+ server_sign_key, krbtgt_sign_key, rspac);
}
krb5_pac_free(context, pac);
@@ -1464,10 +1465,9 @@ tgs_build_reply(krb5_context context,
const struct sockaddr *from_addr)
{
krb5_error_code ret;
- krb5_principal cp = NULL, sp = NULL;
- krb5_principal client_principal = NULL;
+ krb5_principal cp = NULL, sp = NULL, tp = NULL;
krb5_principal krbtgt_principal = NULL;
- char *spn = NULL, *cpn = NULL;
+ char *spn = NULL, *cpn = NULL, *tpn = NULL;
hdb_entry_ex *server = NULL, *client = NULL, *s4u2self_impersonated_client = NULL;
HDB *clientdb, *s4u2self_impersonated_clientdb;
krb5_realm ref_realm = NULL;
@@ -1719,16 +1719,16 @@ server_lookup:
krb5_free_principal(context, krbtgt_principal);
if (ret) {
krb5_error_code ret2;
- char *tpn, *tpn2;
- ret = krb5_unparse_name(context, krbtgt->entry.principal, &tpn);
- ret2 = krb5_unparse_name(context, krbtgt->entry.principal, &tpn2);
+ char *ktpn, *ktpn2;
+ ret = krb5_unparse_name(context, krbtgt->entry.principal, &ktpn);
+ ret2 = krb5_unparse_name(context, krbtgt_principal, &ktpn2);
kdc_log(context, config, 0,
"Request with wrong krbtgt: %s, %s not found in our database",
- (ret == 0) ? tpn : "<unknown>", (ret2 == 0) ? tpn2 : "<unknown>");
+ (ret == 0) ? ktpn : "<unknown>", (ret2 == 0) ? ktpn2 : "<unknown>");
if(ret == 0)
- free(tpn);
+ free(ktpn);
if(ret2 == 0)
- free(tpn2);
+ free(ktpn2);
ret = KRB5KRB_AP_ERR_NOT_US;
goto out;
}
@@ -1740,13 +1740,13 @@ server_lookup:
* this) before the strcmp() */
if (strcmp(krb5_principal_get_realm(context, server->entry.principal),
krb5_principal_get_realm(context, krbtgt_out->entry.principal)) != 0) {
- char *tpn;
- ret = krb5_unparse_name(context, krbtgt_out->entry.principal, &tpn);
+ char *ktpn;
+ ret = krb5_unparse_name(context, krbtgt_out->entry.principal, &ktpn);
kdc_log(context, config, 0,
"Request with wrong krbtgt: %s",
- (ret == 0) ? tpn : "<unknown>");
+ (ret == 0) ? ktpn : "<unknown>");
if(ret == 0)
- free(tpn);
+ free(ktpn);
ret = KRB5KRB_AP_ERR_NOT_US;
}
@@ -1789,7 +1789,9 @@ server_lookup:
}
ret = check_PAC(context, config, cp,
- client, server, krbtgt, ekey, &tkey_check->key, &tkey_sign->key,
+ client, server, krbtgt,
+ &tkey_check->key, &tkey_check->key,
+ ekey, &tkey_sign->key,
tgt, &rspac, &signedpath);
if (ret) {
const char *msg = krb5_get_error_message(context, ret);
@@ -1821,7 +1823,9 @@ server_lookup:
* Process request
*/
- client_principal = cp;
+ /* by default the tgt principal matches the client principal */
+ tp = cp;
+ tpn = cpn;
if (client) {
const PA_DATA *sdata;
@@ -1832,7 +1836,6 @@ server_lookup:
krb5_crypto crypto;
krb5_data datack;
PA_S4U2Self self;
- char *selfcpn = NULL;
const char *str;
ret = decode_PA_S4U2Self(sdata->padata_value.data,
@@ -1875,14 +1878,14 @@ server_lookup:
}
ret = _krb5_principalname2krb5_principal(context,
- &client_principal,
+ &tp,
self.name,
self.realm);
free_PA_S4U2Self(&self);
if (ret)
goto out;
- ret = krb5_unparse_name(context, client_principal, &selfcpn);
+ ret = krb5_unparse_name(context, tp, &tpn);
if (ret)
goto out;
@@ -1890,7 +1893,7 @@ server_lookup:
if(rspac.data) {
krb5_pac p = NULL;
krb5_data_free(&rspac);
- ret = _kdc_db_fetch(context, config, client_principal, HDB_F_GET_CLIENT | HDB_F_CANON,
+ ret = _kdc_db_fetch(context, config, tp, HDB_F_GET_CLIENT | HDB_F_CANON,
NULL, &s4u2self_impersonated_clientdb, &s4u2self_impersonated_client);
if (ret) {
const char *msg;
@@ -1904,14 +1907,16 @@ server_lookup:
if (ret == HDB_ERR_NOENTRY)
ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
msg = krb5_get_error_message(context, ret);
- kdc_log(context, config, 1, "S2U4Self principal to impersonate %s not found in database: %s", cpn, msg);
+ kdc_log(context, config, 1,
+ "S2U4Self principal to impersonate %s not found in database: %s",
+ tpn, msg);
krb5_free_error_message(context, msg);
goto out;
}
ret = _kdc_pac_generate(context, s4u2self_impersonated_client, &p);
if (ret) {
kdc_log(context, config, 0, "PAC generation failed for -- %s",
- selfcpn);
+ tpn);
goto out;
}
if (p != NULL) {
@@ -1922,7 +1927,7 @@ server_lookup:
krb5_pac_free(context, p);
if (ret) {
kdc_log(context, config, 0, "PAC signing failed for -- %s",
- selfcpn);
+ tpn);
goto out;
}
}
@@ -1937,8 +1942,7 @@ server_lookup:
kdc_log(context, config, 0, "S4U2Self: %s is not allowed "
"to impersonate to service "
"(tried for user %s to service %s)",
- cpn, selfcpn, spn);
- free(selfcpn);
+ cpn, tpn, spn);
goto out;
}
@@ -1954,8 +1958,7 @@ server_lookup:
str = "";
}
kdc_log(context, config, 0, "s4u2self %s impersonating %s to "
- "service %s %s", cpn, selfcpn, spn, str);
- free(selfcpn);
+ "service %s %s", cpn, tpn, spn, str);
}
}
@@ -1971,7 +1974,6 @@ server_lookup:
int ad_signedpath = 0;
Key *clientkey;
Ticket *t;
- char *str;
/*
* Require that the KDC have issued the service's krbtgt (not
@@ -2002,11 +2004,23 @@ server_lookup:
goto out;
}
+ ret = _krb5_principalname2krb5_principal(context,
+ &tp,
+ adtkt.cname,
+ adtkt.crealm);
+ if (ret)
+ goto out;
+
+ ret = krb5_unparse_name(context, tp, &tpn);
+ if (ret)
+ goto out;
+
/* check that ticket is valid */
if (adtkt.flags.forwardable == 0) {
kdc_log(context, config, 0,
"Missing forwardable flag on ticket for "
- "constrained delegation from %s to %s ", cpn, spn);
+ "constrained delegation from %s as %s to %s ",
+ cpn, tpn, spn);
ret = KRB5KDC_ERR_BADOPTION;
goto out;
}
@@ -2015,25 +2029,37 @@ server_lookup:
client, sp);
if (ret) {
kdc_log(context, config, 0,
- "constrained delegation from %s to %s not allowed",
- cpn, spn);
+ "constrained delegation from %s as %s to %s not allowed",
+ cpn, tpn, spn);
goto out;
}
- ret = _krb5_principalname2krb5_principal(context,
- &client_principal,
- adtkt.cname,
- adtkt.crealm);
- if (ret)
- goto out;
-
- ret = krb5_unparse_name(context, client_principal, &str);
- if (ret)
+ ret = verify_flags(context, config, &adtkt, tpn);
+ if (ret) {
goto out;
+ }
- ret = verify_flags(context, config, &adtkt, str);
+ krb5_data_free(&rspac);
+ /*
+ * generate the PAC for the user.
+ *
+ * TODO: pass in t->sname and t->realm and build
+ * a S4U_DELEGATION_INFO blob to the PAC.
+ */
+ ret = check_PAC(context, config, tp,
+ client, server, krbtgt,
+ &clientkey->key, &tkey_check->key,
+ ekey, &tkey_sign->key,
+ &adtkt, &rspac, &ad_signedpath);
+ if (ret == 0 && !ad_signedpath)
+ ret = KRB5KDC_ERR_BADOPTION;
if (ret) {
- free(str);
+ const char *msg = krb5_get_error_message(context, ret);
+ kdc_log(context, config, 0,
+ "Verify delegated PAC failed to %s for client"
+ "%s as %s from %s with %s",
+ spn, cpn, tpn, from, msg);
+ krb5_free_error_message(context, msg);
goto out;
}
@@ -2043,7 +2069,7 @@ server_lookup:
ret = check_KRB5SignedPath(context,
config,
krbtgt,
- cp,
+ tp,
&adtkt,
NULL,
&ad_signedpath);
@@ -2055,15 +2081,13 @@ server_lookup:
"KRB5SignedPath check from service %s failed "
"for delegation to %s for client %s "
"from %s failed with %s",
- spn, str, cpn, from, msg);
+ spn, tpn, cpn, from, msg);
krb5_free_error_message(context, msg);
- free(str);
goto out;
}
kdc_log(context, config, 0, "constrained delegation for %s "
- "from %s to %s", str, cpn, spn);
- free(str);
+ "from %s to %s", tpn, cpn, spn);
}
/*
@@ -2134,7 +2158,7 @@ server_lookup:
ret = tgs_make_reply(context,
config,
b,
- client_principal,
+ tp,
tgt,
replykey,
rk_is_subkey,
@@ -2156,6 +2180,8 @@ server_lookup:
reply);
out:
+ if (tpn != cpn)
+ free(tpn);
free(spn);
free(cpn);
@@ -2170,8 +2196,8 @@ out:
if(s4u2self_impersonated_client)
_kdc_free_ent(context, s4u2self_impersonated_client);
- if (client_principal && client_principal != cp)
- krb5_free_principal(context, client_principal);
+ if (tp && tp != cp)
+ krb5_free_principal(context, tp);
if (cp)
krb5_free_principal(context, cp);
if (sp)