diff options
Diffstat (limited to 'source4/heimdal/kdc/krb5tgs.c')
-rw-r--r-- | source4/heimdal/kdc/krb5tgs.c | 130 |
1 files changed, 78 insertions, 52 deletions
diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index 037934f2a6..66170cb29f 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) |