Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kdc s4u2proxy fixes for Windows (Samba AD) clients #1156

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions kdc/kdc_locl.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ struct astgs_request_desc {
unsigned int rk_is_subkey : 1;
unsigned int fast_asserted : 1;
unsigned int explicit_armor_present : 1;
krb5_keyblock enc_ad_key;

krb5_crypto armor_crypto;
hdb_entry *armor_server;
Expand Down
1 change: 1 addition & 0 deletions kdc/kerberos5.c
Original file line number Diff line number Diff line change
Expand Up @@ -2800,6 +2800,7 @@ _kdc_as_rep(astgs_request_t r)
if (r->armor_server)
_kdc_free_ent(r->context, r->armor_serverdb, r->armor_server);
krb5_free_keyblock_contents(r->context, &r->reply_key);
krb5_free_keyblock_contents(r->context, &r->enc_ad_key);
krb5_free_keyblock_contents(r->context, &r->session_key);
krb5_free_keyblock_contents(r->context, &r->strengthen_key);
krb5_pac_free(r->context, r->pac);
Expand Down
127 changes: 71 additions & 56 deletions kdc/krb5tgs.c
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,8 @@ tgs_make_reply(astgs_request_t r,
rep->pvno = 5;
rep->msg_type = krb_tgs_rep;

et->authtime = tgt->authtime;
if (et->authtime == 0)
et->authtime = tgt->authtime;
_kdc_fix_time(&b->till);
et->endtime = min(tgt->endtime, *b->till);
ALLOC(et->starttime);
Expand Down Expand Up @@ -931,8 +932,7 @@ tgs_parse_request(astgs_request_t r,
const char *from,
const struct sockaddr *from_addr,
time_t **csec,
int **cusec,
AuthorizationData **auth_data)
int **cusec)
{
krb5_kdc_configuration *config = r->config;
KDC_REQ_BODY *b = &r->req.req_body;
Expand All @@ -943,16 +943,13 @@ tgs_parse_request(astgs_request_t r,
krb5_auth_context ac = NULL;
krb5_flags ap_req_options;
krb5_flags verify_ap_req_flags = 0;
krb5_crypto crypto;
krb5uint32 krbtgt_kvno; /* kvno used for the PA-TGS-REQ AP-REQ Ticket */
krb5uint32 krbtgt_kvno_try;
int kvno_search_tries = 4; /* number of kvnos to try when tkt_vno == 0 */
const Keys *krbtgt_keys;/* keyset for TGT tkt_vno */
Key *tkey;
krb5_keyblock *subkey = NULL;
unsigned usage;

*auth_data = NULL;
*csec = NULL;
*cusec = NULL;

Expand Down Expand Up @@ -1135,7 +1132,6 @@ tgs_parse_request(astgs_request_t r,
goto out;
}

usage = KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY;
r->rk_is_subkey = 1;

ret = krb5_auth_con_getremotesubkey(r->context, ac, &subkey);
Expand All @@ -1147,7 +1143,6 @@ tgs_parse_request(astgs_request_t r,
goto out;
}
if(subkey == NULL){
usage = KRB5_KU_TGS_REQ_AUTH_DAT_SESSION;
r->rk_is_subkey = 0;

ret = krb5_auth_con_getkey(r->context, ac, &subkey);
Expand All @@ -1173,45 +1168,13 @@ tgs_parse_request(astgs_request_t r,
if (ret)
goto out;

krb5_free_keyblock_contents(r->context, &r->enc_ad_key);
if (b->enc_authorization_data) {
krb5_data ad;

ret = krb5_crypto_init(r->context, &r->reply_key, 0, &crypto);
if (ret) {
const char *msg = krb5_get_error_message(r->context, ret);
krb5_auth_con_free(r->context, ac);
kdc_log(r->context, config, 4, "krb5_crypto_init failed: %s", msg);
krb5_free_error_message(r->context, msg);
goto out;
}
ret = krb5_decrypt_EncryptedData (r->context,
crypto,
usage,
b->enc_authorization_data,
&ad);
krb5_crypto_destroy(r->context, crypto);
if(ret){
krb5_auth_con_free(r->context, ac);
kdc_log(r->context, config, 4,
"Failed to decrypt enc-authorization-data");
ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
goto out;
}
ALLOC(*auth_data);
if (*auth_data == NULL) {
krb5_auth_con_free(r->context, ac);
ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
goto out;
}
ret = decode_AuthorizationData(ad.data, ad.length, *auth_data, NULL);
if(ret){
krb5_auth_con_free(r->context, ac);
free(*auth_data);
*auth_data = NULL;
kdc_log(r->context, config, 4, "Failed to decode authorization data");
ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
ret = krb5_copy_keyblock_contents(r->context,
&r->reply_key,
&r->enc_ad_key);
if (ret)
goto out;
}
}

ret = validate_fast_ad(r, r->ticket->ticket.authorization_data);
Expand Down Expand Up @@ -1370,7 +1333,6 @@ _kdc_db_fetch_client(krb5_context context,
static krb5_error_code
tgs_build_reply(astgs_request_t priv,
krb5_enctype krbtgt_etype,
AuthorizationData **auth_data,
const struct sockaddr *from_addr)
{
krb5_context context = priv->context;
Expand Down Expand Up @@ -1400,6 +1362,7 @@ tgs_build_reply(astgs_request_t priv,
krb5_principal_get_comp_string(context, priv->krbtgt->principal, 1);
char **capath = NULL;
size_t num_capath = 0;
AuthorizationData *auth_data = NULL;

HDB *krbtgt_outdb;
hdb_entry *krbtgt_out = NULL;
Expand Down Expand Up @@ -1931,6 +1894,60 @@ tgs_build_reply(astgs_request_t priv,
if (ret)
goto out;

if (b->enc_authorization_data) {
unsigned auth_data_usage;
krb5_crypto crypto;
krb5_data ad;

if (priv->rk_is_subkey != 0) {
auth_data_usage = KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY;
} else {
auth_data_usage = KRB5_KU_TGS_REQ_AUTH_DAT_SESSION;
}

ret = krb5_crypto_init(context, &priv->enc_ad_key, 0, &crypto);
if (ret) {
const char *msg = krb5_get_error_message(context, ret);
kdc_audit_addreason((kdc_request_t)priv,
"krb5_crypto_init() failed for "
"enc_authorization_data");
kdc_log(context, config, 4, "krb5_crypto_init failed: %s", msg);
krb5_free_error_message(context, msg);
goto out;
}
ret = krb5_decrypt_EncryptedData(context,
crypto,
auth_data_usage,
b->enc_authorization_data,
&ad);
krb5_crypto_destroy(context, crypto);
if(ret){
kdc_audit_addreason((kdc_request_t)priv,
"Failed to decrypt enc-authorization-data");
kdc_log(context, config, 4,
"Failed to decrypt enc-authorization-data");
ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
goto out;
}
ALLOC(auth_data);
if (auth_data == NULL) {
krb5_data_free(&ad);
ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
goto out;
}
ret = decode_AuthorizationData(ad.data, ad.length, auth_data, NULL);
krb5_data_free(&ad);
if(ret){
free(auth_data);
auth_data = NULL;
kdc_audit_addreason((kdc_request_t)priv,
"Failed to decode authorization data");
kdc_log(context, config, 4, "Failed to decode authorization data");
ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
goto out;
}
}

/*
* Check flags
*/
Expand Down Expand Up @@ -2042,7 +2059,7 @@ tgs_build_reply(astgs_request_t priv,
&tkey_sign->key,
&sessionkey,
kvno,
*auth_data,
auth_data,
tgt_realm,
rodc_id,
add_ticket_sig);
Expand All @@ -2062,6 +2079,11 @@ tgs_build_reply(astgs_request_t priv,
krb5_free_principal(context, krbtgt_out_principal);
free(ref_realm);

if (auth_data) {
free_AuthorizationData(auth_data);
free(auth_data);
}

free_EncTicketPart(&adtkt);

krb5_pac_free(context, user2user_pac);
Expand All @@ -2082,7 +2104,6 @@ _kdc_tgs_rep(astgs_request_t r)
const char *from = r->from;
struct sockaddr *from_addr = r->addr;
int datagram_reply = r->datagram_reply;
AuthorizationData *auth_data = NULL;
krb5_error_code ret;
int i = 0;
const PA_DATA *tgs_req, *pa;
Expand Down Expand Up @@ -2120,8 +2141,7 @@ _kdc_tgs_rep(astgs_request_t r)
ret = tgs_parse_request(r, tgs_req,
&krbtgt_etype,
from, from_addr,
&csec, &cusec,
&auth_data);
&csec, &cusec);
if (ret == HDB_ERR_NOT_FOUND_HERE) {
/* kdc_log() is called in tgs_parse_request() */
goto out;
Expand All @@ -2145,7 +2165,6 @@ _kdc_tgs_rep(astgs_request_t r)

ret = tgs_build_reply(r,
krbtgt_etype,
&auth_data,
from_addr);
if (ret) {
kdc_log(r->context, config, 4,
Expand Down Expand Up @@ -2225,6 +2244,7 @@ _kdc_tgs_rep(astgs_request_t r)
if (r->explicit_armor_pac)
krb5_pac_free(r->context, r->explicit_armor_pac);
krb5_free_keyblock_contents(r->context, &r->reply_key);
krb5_free_keyblock_contents(r->context, &r->enc_ad_key);
krb5_free_keyblock_contents(r->context, &r->strengthen_key);

if (r->ticket)
Expand All @@ -2241,10 +2261,5 @@ _kdc_tgs_rep(astgs_request_t r)
_kdc_free_fast_state(&r->fast);
krb5_pac_free(r->context, r->pac);

if (auth_data) {
free_AuthorizationData(auth_data);
free(auth_data);
}

return ret;
}
11 changes: 11 additions & 0 deletions kdc/mssfu.c
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,15 @@ validate_constrained_delegation(astgs_request_t r)
goto out;
}

if (b->enc_authorization_data && r->rk_is_subkey == 0) {
krb5_free_keyblock_contents(r->context, &r->enc_ad_key);
ret = krb5_copy_keyblock_contents(r->context,
&evidence_tkt.key,
&r->enc_ad_key);
if (ret)
goto out;
}

kdc_log(r->context, r->config, 4, "constrained delegation for %s "
"from %s (%s) to %s", s4ucname, r->cname, s4usname, r->sname);

Expand All @@ -535,6 +544,8 @@ validate_constrained_delegation(astgs_request_t r)

r->pac_attributes = s4u_pac_attributes;

r->et.authtime = evidence_tkt.authtime;

out:
if (s4u_client)
_kdc_free_ent(r->context, s4u_clientdb, s4u_client);
Expand Down
Loading