kdc: salt FAST cookie key with client name

This commit is contained in:
Luke Howard
2021-08-10 13:56:46 +10:00
parent 9b55215a2a
commit 2b95853df4
2 changed files with 100 additions and 12 deletions

View File

@@ -36,17 +36,85 @@
#include "kdc_locl.h" #include "kdc_locl.h"
static krb5_error_code static krb5_error_code
get_fastuser_crypto(astgs_request_t r, krb5_enctype enctype, salt_fastuser_crypto(astgs_request_t r,
krb5_const_principal salt_principal,
krb5_enctype enctype,
krb5_crypto fast_crypto,
krb5_crypto *salted_crypto)
{
krb5_error_code ret;
krb5_principal client_princ = NULL;
krb5_data salt;
krb5_keyblock dkey;
size_t size;
*salted_crypto = NULL;
krb5_data_zero(&salt);
krb5_keyblock_zero(&dkey);
if (salt_principal == NULL) {
if (r->req.req_body.cname == NULL) {
ret = KRB5KRB_ERR_GENERIC;
goto out;
}
ret = _krb5_principalname2krb5_principal(r->context, &client_princ,
*(r->req.req_body.cname),
r->req.req_body.realm);
if (ret)
goto out;
salt_principal = client_princ;
}
ret = krb5_unparse_name(r->context, salt_principal, (char **)&salt.data);
if (ret)
goto out;
salt.length = strlen(salt.data);
kdc_log(r->context, r->config, 10,
"salt_fastuser_crypto: salt principal is %s (%d)",
(char *)salt.data, enctype);
ret = krb5_enctype_keysize(r->context, enctype, &size);
if (ret)
goto out;
ret = krb5_crypto_prfplus(r->context, fast_crypto, &salt,
size, &dkey.keyvalue);
if (ret)
goto out;
dkey.keytype = enctype;
ret = krb5_crypto_init(r->context, &dkey, ENCTYPE_NULL, salted_crypto);
if (ret)
goto out;
out:
krb5_free_keyblock_contents(r->context, &dkey);
krb5_data_free(&salt);
krb5_free_principal(r->context, client_princ);
return ret;
}
static krb5_error_code
get_fastuser_crypto(astgs_request_t r,
krb5_const_principal ticket_client,
krb5_enctype enctype,
krb5_crypto *crypto) krb5_crypto *crypto)
{ {
krb5_principal fast_princ; krb5_principal fast_princ;
hdb_entry_ex *fast_user = NULL; hdb_entry_ex *fast_user = NULL;
Key *cookie_key = NULL; Key *cookie_key = NULL;
krb5_crypto fast_crypto = NULL;
krb5_error_code ret; krb5_error_code ret;
*crypto = NULL; *crypto = NULL;
/* TODO: salt cookie key with client name and realm */
ret = krb5_make_principal(r->context, &fast_princ, ret = krb5_make_principal(r->context, &fast_princ,
KRB5_WELLKNOWN_ORG_H5L_REALM, KRB5_WELLKNOWN_ORG_H5L_REALM,
KRB5_WELLKNOWN_NAME, "org.h5l.fast-cookie", NULL); KRB5_WELLKNOWN_NAME, "org.h5l.fast-cookie", NULL);
@@ -55,7 +123,6 @@ get_fastuser_crypto(astgs_request_t r, krb5_enctype enctype,
ret = _kdc_db_fetch(r->context, r->config, fast_princ, ret = _kdc_db_fetch(r->context, r->config, fast_princ,
HDB_F_GET_FAST_COOKIE, NULL, NULL, &fast_user); HDB_F_GET_FAST_COOKIE, NULL, NULL, &fast_user);
krb5_free_principal(r->context, fast_princ);
if (ret) if (ret)
goto out; goto out;
@@ -68,20 +135,32 @@ get_fastuser_crypto(astgs_request_t r, krb5_enctype enctype,
if (ret) if (ret)
goto out; goto out;
ret = krb5_crypto_init(r->context, &cookie_key->key, 0, crypto); ret = krb5_crypto_init(r->context, &cookie_key->key,
ENCTYPE_NULL, &fast_crypto);
if (ret)
goto out;
ret = salt_fastuser_crypto(r, ticket_client,
cookie_key->key.keytype,
fast_crypto, crypto);
if (ret) if (ret)
goto out; goto out;
out: out:
if (fast_user) if (fast_user)
_kdc_free_ent(r->context, fast_user); _kdc_free_ent(r->context, fast_user);
if (fast_crypto)
krb5_crypto_destroy(r->context, fast_crypto);
krb5_free_principal(r->context, fast_princ);
return ret; return ret;
} }
static krb5_error_code static krb5_error_code
fast_parse_cookie(astgs_request_t r, const PA_DATA *pa) fast_parse_cookie(astgs_request_t r,
krb5_const_principal ticket_client,
const PA_DATA *pa)
{ {
krb5_crypto crypto = NULL; krb5_crypto crypto = NULL;
krb5_error_code ret; krb5_error_code ret;
@@ -100,7 +179,7 @@ fast_parse_cookie(astgs_request_t r, const PA_DATA *pa)
return KRB5KDC_ERR_POLICY; return KRB5KDC_ERR_POLICY;
} }
ret = get_fastuser_crypto(r, data.cookie.etype, &crypto); ret = get_fastuser_crypto(r, ticket_client, data.cookie.etype, &crypto);
if (ret) if (ret)
goto out; goto out;
@@ -129,7 +208,9 @@ fast_parse_cookie(astgs_request_t r, const PA_DATA *pa)
} }
static krb5_error_code static krb5_error_code
fast_add_cookie(astgs_request_t r, METHOD_DATA *method_data) fast_add_cookie(astgs_request_t r,
krb5_const_principal ticket_client,
METHOD_DATA *method_data)
{ {
krb5_crypto crypto = NULL; krb5_crypto crypto = NULL;
KDCFastCookie shell; KDCFastCookie shell;
@@ -147,7 +228,7 @@ fast_add_cookie(astgs_request_t r, METHOD_DATA *method_data)
return ret; return ret;
heim_assert(size == data.length, "internal asn.1 encoder error"); heim_assert(size == data.length, "internal asn.1 encoder error");
ret = get_fastuser_crypto(r, KRB5_ENCTYPE_NULL, &crypto); ret = get_fastuser_crypto(r, ticket_client, KRB5_ENCTYPE_NULL, &crypto);
if (ret) { if (ret) {
kdc_log(r->context, r->config, 0, kdc_log(r->context, r->config, 0,
"Failed to find FAST principal for cookie encryption: %d", ret); "Failed to find FAST principal for cookie encryption: %d", ret);
@@ -266,7 +347,7 @@ _kdc_fast_mk_error(astgs_request_t r,
* FX-COOKIE can be used outside of FAST, e.g. SRP or GSS. * FX-COOKIE can be used outside of FAST, e.g. SRP or GSS.
*/ */
if (armor_crypto || r->fast.fast_state.len) { if (armor_crypto || r->fast.fast_state.len) {
ret = fast_add_cookie(r, error_method); ret = fast_add_cookie(r, error_client, error_method);
if (ret) { if (ret) {
kdc_log(r->context, r->config, 1, kdc_log(r->context, r->config, 1,
"Failed to add FAST cookie: %d", ret); "Failed to add FAST cookie: %d", ret);
@@ -625,8 +706,14 @@ _kdc_fast_unwrap_request(astgs_request_t r,
* FX-COOKIE can be used outside of FAST, e.g. SRP or GSS. * FX-COOKIE can be used outside of FAST, e.g. SRP or GSS.
*/ */
pa = _kdc_find_padata(&r->req, &i, KRB5_PADATA_FX_COOKIE); pa = _kdc_find_padata(&r->req, &i, KRB5_PADATA_FX_COOKIE);
if (pa) if (pa) {
ret = fast_parse_cookie(r, pa); krb5_const_principal ticket_client = NULL;
if (tgs_ticket)
ticket_client = tgs_ticket->client;
ret = fast_parse_cookie(r, ticket_client, pa);
}
return ret; return ret;
} }

View File

@@ -2417,7 +2417,8 @@ out:
r->armor_crypto, r->armor_crypto,
&req->req_body, &req->req_body,
ret, r->e_text, ret, r->e_text,
NULL, NULL, ticket != NULL ? ticket->client : NULL,
ticket != NULL ? ticket->server : NULL,
csec, cusec, csec, cusec,
data); data);
free_METHOD_DATA(&error_method); free_METHOD_DATA(&error_method);