kdc: Use sname from request rather than user-to-user TGT client name
Assists Samba to address CVE-2020-25719 This may be contary to RFC4120 3.3.3 at https://datatracker.ietf.org/doc/html/rfc4120/#section-3.3.3 (clearer in the GSS mechanism here: https://datatracker.ietf.org/doc/html/draft-swift-win2k-krb-user2user-03 ) as server-name is decribed as optional, however Windows AD and Samba both require that the server-name exist and be a valid SPN matching the provided TGT. The lookup of SPN -> entry ensures that the SPN the client thought it was connecting to was held by the target server. it could be the typical user principal, or a service principal, but needs to be checked for the client not to be fooled into connecting to the wrong service. Samba BUG: https://bugzilla.samba.org/show_bug.cgi?id=14873 Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org> (Similar to Samba commit fd50fecbe99ae4fc63843c796d0a516731a1fe6a)
This commit is contained in:

committed by
Luke Howard

parent
b768c78fca
commit
4112f6fc79
147
kdc/krb5tgs.c
147
kdc/krb5tgs.c
@@ -1429,81 +1429,7 @@ tgs_build_reply(astgs_request_t priv,
|
||||
if (b->kdc_options.canonicalize)
|
||||
flags |= HDB_F_CANON;
|
||||
|
||||
if(b->kdc_options.enc_tkt_in_skey){
|
||||
Ticket *t;
|
||||
hdb_entry_ex *uu;
|
||||
krb5_principal p;
|
||||
Key *uukey;
|
||||
krb5uint32 second_kvno = 0;
|
||||
krb5uint32 *kvno_ptr = NULL;
|
||||
|
||||
if(b->additional_tickets == NULL ||
|
||||
b->additional_tickets->len == 0){
|
||||
ret = KRB5KDC_ERR_BADOPTION; /* ? */
|
||||
kdc_log(context, config, 4,
|
||||
"No second ticket present in user-to-user request");
|
||||
_kdc_audit_addreason((kdc_request_t)priv,
|
||||
"No second ticket present in user-to-user request");
|
||||
goto out;
|
||||
}
|
||||
t = &b->additional_tickets->val[0];
|
||||
if(!get_krbtgt_realm(&t->sname)){
|
||||
kdc_log(context, config, 4,
|
||||
"Additional ticket is not a ticket-granting ticket");
|
||||
_kdc_audit_addreason((kdc_request_t)priv,
|
||||
"Additional ticket is not a ticket-granting ticket");
|
||||
ret = KRB5KDC_ERR_POLICY;
|
||||
goto out;
|
||||
}
|
||||
ret = _krb5_principalname2krb5_principal(context, &p, t->sname, t->realm);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = krb5_unparse_name(context, p, &tpn);
|
||||
if (ret)
|
||||
goto out;
|
||||
if(t->enc_part.kvno){
|
||||
second_kvno = *t->enc_part.kvno;
|
||||
kvno_ptr = &second_kvno;
|
||||
}
|
||||
ret = _kdc_db_fetch(context, config, p,
|
||||
HDB_F_GET_KRBTGT, kvno_ptr,
|
||||
NULL, &uu);
|
||||
krb5_free_principal(context, p);
|
||||
if(ret){
|
||||
if (ret == HDB_ERR_NOENTRY)
|
||||
ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
|
||||
_kdc_audit_addreason((kdc_request_t)priv,
|
||||
"User-to-user service principal (TGS) unknown");
|
||||
goto out;
|
||||
}
|
||||
ret = hdb_enctype2key(context, &uu->entry, NULL,
|
||||
t->enc_part.etype, &uukey);
|
||||
if(ret){
|
||||
_kdc_free_ent(context, uu);
|
||||
ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
|
||||
_kdc_audit_addreason((kdc_request_t)priv,
|
||||
"User-to-user enctype not supported");
|
||||
goto out;
|
||||
}
|
||||
ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0);
|
||||
_kdc_free_ent(context, uu);
|
||||
if(ret) {
|
||||
_kdc_audit_addreason((kdc_request_t)priv,
|
||||
"User-to-user TGT decrypt failure");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = _kdc_verify_flags(context, config, &adtkt, tpn);
|
||||
if (ret) {
|
||||
_kdc_audit_addreason((kdc_request_t)priv,
|
||||
"User-to-user TGT expired or invalid");
|
||||
goto out;
|
||||
}
|
||||
|
||||
s = &adtkt.cname;
|
||||
r = adtkt.crealm;
|
||||
} else if (s == NULL) {
|
||||
if (s == NULL) {
|
||||
ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
|
||||
_kdc_set_e_text(priv, "No server in request");
|
||||
goto out;
|
||||
@@ -1713,7 +1639,78 @@ server_lookup:
|
||||
krb5_enctype etype;
|
||||
|
||||
if(b->kdc_options.enc_tkt_in_skey) {
|
||||
Ticket *t;
|
||||
hdb_entry_ex *uu;
|
||||
krb5_principal p;
|
||||
Key *uukey;
|
||||
krb5uint32 second_kvno = 0;
|
||||
krb5uint32 *kvno_ptr = NULL;
|
||||
size_t i;
|
||||
|
||||
if(b->additional_tickets == NULL ||
|
||||
b->additional_tickets->len == 0){
|
||||
ret = KRB5KDC_ERR_BADOPTION; /* ? */
|
||||
kdc_log(context, config, 4,
|
||||
"No second ticket present in user-to-user request");
|
||||
_kdc_audit_addreason((kdc_request_t)priv,
|
||||
"No second ticket present in user-to-user request");
|
||||
goto out;
|
||||
}
|
||||
t = &b->additional_tickets->val[0];
|
||||
if(!get_krbtgt_realm(&t->sname)){
|
||||
kdc_log(context, config, 4,
|
||||
"Additional ticket is not a ticket-granting ticket");
|
||||
_kdc_audit_addreason((kdc_request_t)priv,
|
||||
"Additional ticket is not a ticket-granting ticket");
|
||||
ret = KRB5KDC_ERR_POLICY;
|
||||
goto out;
|
||||
}
|
||||
ret = _krb5_principalname2krb5_principal(context, &p, t->sname, t->realm);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = krb5_unparse_name(context, p, &tpn);
|
||||
if (ret)
|
||||
goto out;
|
||||
if(t->enc_part.kvno){
|
||||
second_kvno = *t->enc_part.kvno;
|
||||
kvno_ptr = &second_kvno;
|
||||
}
|
||||
ret = _kdc_db_fetch(context, config, p,
|
||||
HDB_F_GET_KRBTGT, kvno_ptr,
|
||||
NULL, &uu);
|
||||
krb5_free_principal(context, p);
|
||||
if(ret){
|
||||
if (ret == HDB_ERR_NOENTRY)
|
||||
ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
|
||||
_kdc_audit_addreason((kdc_request_t)priv,
|
||||
"User-to-user service principal (TGS) unknown");
|
||||
goto out;
|
||||
}
|
||||
ret = hdb_enctype2key(context, &uu->entry, NULL,
|
||||
t->enc_part.etype, &uukey);
|
||||
if(ret){
|
||||
_kdc_free_ent(context, uu);
|
||||
ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
|
||||
_kdc_audit_addreason((kdc_request_t)priv,
|
||||
"User-to-user enctype not supported");
|
||||
goto out;
|
||||
}
|
||||
ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0);
|
||||
_kdc_free_ent(context, uu);
|
||||
if(ret) {
|
||||
_kdc_audit_addreason((kdc_request_t)priv,
|
||||
"User-to-user TGT decrypt failure");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = _kdc_verify_flags(context, config, &adtkt, tpn);
|
||||
if (ret) {
|
||||
_kdc_audit_addreason((kdc_request_t)priv,
|
||||
"User-to-user TGT expired or invalid");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ekey = &adtkt.key;
|
||||
for(i = 0; i < b->etype.len; i++)
|
||||
if (b->etype.val[i] == adtkt.key.keytype)
|
||||
|
Reference in New Issue
Block a user