kdc: salt FAST cookie key with client name
This commit is contained in:
109
kdc/fast.c
109
kdc/fast.c
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
|
Reference in New Issue
Block a user