From 3274601d5fcb3992a519fb9f6252acce39c31aaf Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 8 Nov 2017 11:57:08 +0100 Subject: [PATCH 1/5] HEIMDAL:kdc: let _kdc_encode_reply() use the encryption type based on the server key Currently the value is the same anyway as the session key is always of the same type as server key up to now, but that will change shortly. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13135 Signed-off-by: Stefan Metzmacher --- source4/heimdal/kdc/kerberos5.c | 5 ++--- source4/heimdal/kdc/krb5tgs.c | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c index 27d38ad84b7b..4bc79444b98a 100644 --- a/source4/heimdal/kdc/kerberos5.c +++ b/source4/heimdal/kdc/kerberos5.c @@ -322,7 +322,6 @@ krb5_error_code _kdc_encode_reply(krb5_context context, krb5_kdc_configuration *config, KDC_REP *rep, const EncTicketPart *et, EncKDCRepPart *ek, - krb5_enctype etype, int skvno, const EncryptionKey *skey, int ckvno, const EncryptionKey *reply_key, int rk_is_subkey, @@ -349,7 +348,7 @@ _kdc_encode_reply(krb5_context context, return KRB5KRB_ERR_GENERIC; } - ret = krb5_crypto_init(context, skey, etype, &crypto); + ret = krb5_crypto_init(context, skey, 0, &crypto); if (ret) { const char *msg; free(buf); @@ -1759,7 +1758,7 @@ _kdc_as_rep(krb5_context context, log_as_req(context, config, reply_key->keytype, setype, b); ret = _kdc_encode_reply(context, config, - &rep, &et, &ek, setype, server->entry.kvno, + &rep, &et, &ek, server->entry.kvno, &skey->key, client->entry.kvno, reply_key, 0, &e_text, reply); free_EncTicketPart(&et); diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index 7aba64a285be..b65a480afe84 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -988,7 +988,7 @@ tgs_make_reply(krb5_context context, etype list, even if we don't want a session key with DES3? */ ret = _kdc_encode_reply(context, config, - &rep, &et, &ek, et.key.keytype, + &rep, &et, &ek, kvno, serverkey, 0, replykey, rk_is_subkey, e_text, reply); -- 2.17.1 From 81880a58bf6e07b4637dd2511a2d901c9286c0a1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 7 Nov 2017 15:47:25 +0100 Subject: [PATCH 2/5] HEIMDAL:hdb: export a hdb_enctype_supported() helper function BUG: https://bugzilla.samba.org/show_bug.cgi?id=13135 Signed-off-by: Stefan Metzmacher --- source4/heimdal/kdc/kerberos5.c | 15 +++++++---- source4/heimdal/kdc/krb5tgs.c | 3 +-- source4/heimdal/lib/hdb/hdb.c | 30 +++++++++++++++++++--- source4/heimdal/lib/hdb/version-script.map | 1 + 4 files changed, 39 insertions(+), 10 deletions(-) diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c index 4bc79444b98a..4ce020454d0f 100644 --- a/source4/heimdal/kdc/kerberos5.c +++ b/source4/heimdal/kdc/kerberos5.c @@ -131,7 +131,7 @@ _kdc_find_etype(krb5_context context, krb5_boolean use_strongest_session_key, krb5_error_code ret; krb5_salt def_salt; krb5_enctype enctype = ETYPE_NULL; - Key *key; + Key *key = NULL; int i; /* We'll want to avoid keys with v4 salted keys in the pre-auth case... */ @@ -159,29 +159,34 @@ _kdc_find_etype(krb5_context context, krb5_boolean use_strongest_session_key, /* drive the search with local supported enctypes list */ p = krb5_kerberos_enctypes(context); - for (i = 0; p[i] != ETYPE_NULL && enctype == ETYPE_NULL; i++) { + for (i = 0; p[i] != ETYPE_NULL && key == NULL; i++) { if (krb5_enctype_valid(context, p[i]) != 0) continue; /* check that the client supports it too */ - for (j = 0; j < len && enctype == ETYPE_NULL; j++) { + for (j = 0; j < len && key == NULL; j++) { if (p[i] != etypes[j]) continue; /* save best of union of { client, crypto system } */ if (clientbest == ETYPE_NULL) clientbest = p[i]; + if (enctype == ETYPE_NULL) { + ret = hdb_enctype_supported(context, &princ->entry, p[i]); + if (ret == 0) { + enctype = p[i]; + } + } /* check target princ support */ ret = hdb_enctype2key(context, &princ->entry, p[i], &key); if (ret) continue; if (is_preauth && !is_default_salt_p(&def_salt, key)) continue; - enctype = p[i]; } } if (clientbest != ETYPE_NULL && enctype == ETYPE_NULL) enctype = clientbest; - else if (enctype == ETYPE_NULL) + else if (key == NULL) ret = KRB5KDC_ERR_ETYPE_NOSUPP; if (ret == 0 && ret_enctype != NULL) *ret_enctype = enctype; diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index b65a480afe84..11ec2e9909f6 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -1705,7 +1705,7 @@ server_lookup: ret = _kdc_find_etype(context, config->tgs_use_strongest_session_key, FALSE, - server, b->etype.val, b->etype.len, NULL, + server, b->etype.val, b->etype.len, &etype, &skey); if(ret) { kdc_log(context, config, 0, @@ -1713,7 +1713,6 @@ server_lookup: goto out; } ekey = &skey->key; - etype = skey->key.keytype; kvno = server->entry.kvno; } diff --git a/source4/heimdal/lib/hdb/hdb.c b/source4/heimdal/lib/hdb/hdb.c index 5dc5a0957e08..4c8df930b0ce 100644 --- a/source4/heimdal/lib/hdb/hdb.c +++ b/source4/heimdal/lib/hdb/hdb.c @@ -93,11 +93,12 @@ static struct hdb_method dbmetod = #endif -krb5_error_code -hdb_next_enctype2key(krb5_context context, +static krb5_error_code +_hdb_next_enctype2key(krb5_context context, const hdb_entry *e, krb5_enctype enctype, - Key **key) + Key **key, + bool require_key) { Key *k; @@ -105,6 +106,10 @@ hdb_next_enctype2key(krb5_context context, k < e->keys.val + e->keys.len; k++) { + if (require_key && k->key.keyvalue.length == 0) { + continue; + } + if(k->key.keytype == enctype){ *key = k; return 0; @@ -116,6 +121,16 @@ hdb_next_enctype2key(krb5_context context, return KRB5_PROG_ETYPE_NOSUPP; /* XXX */ } + +krb5_error_code +hdb_next_enctype2key(krb5_context context, + const hdb_entry *e, + krb5_enctype enctype, + Key **key) +{ + return _hdb_next_enctype2key(context, e, enctype, key, true); +} + krb5_error_code hdb_enctype2key(krb5_context context, hdb_entry *e, @@ -126,6 +141,15 @@ hdb_enctype2key(krb5_context context, return hdb_next_enctype2key(context, e, enctype, key); } +krb5_error_code +hdb_enctype_supported(krb5_context context, + hdb_entry *e, + krb5_enctype enctype) +{ + Key *key = NULL; + return _hdb_next_enctype2key(context, e, enctype, &key, false); +} + void hdb_free_key(Key *key) { diff --git a/source4/heimdal/lib/hdb/version-script.map b/source4/heimdal/lib/hdb/version-script.map index f80fb78a654c..c4bd8f4cd447 100644 --- a/source4/heimdal/lib/hdb/version-script.map +++ b/source4/heimdal/lib/hdb/version-script.map @@ -20,6 +20,7 @@ HEIMDAL_HDB_1.0 { hdb_dbinfo_get_realm; hdb_default_db; hdb_enctype2key; + hdb_enctype_supported; hdb_entry2string; hdb_entry2value; hdb_entry_alias2value; -- 2.17.1 From 293c3a94aa8337993f023bf155f81308d0e57221 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 7 Nov 2017 18:03:45 +0100 Subject: [PATCH 3/5] s4:kdc: use the strongest possible tgs session key BUG: https://bugzilla.samba.org/show_bug.cgi?id=13135 Signed-off-by: Stefan Metzmacher --- source4/kdc/kdc-heimdal.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source4/kdc/kdc-heimdal.c b/source4/kdc/kdc-heimdal.c index ee4e1387def3..221edccefcc1 100644 --- a/source4/kdc/kdc-heimdal.c +++ b/source4/kdc/kdc-heimdal.c @@ -401,10 +401,14 @@ static void kdc_post_fork(struct task_server *task, struct process_details *pd) * * The old behavior in the _kdc_get_preferred_key() * function is use_strongest_server_key=TRUE. + * + * We actually want the behavior of + * tgs_use_strongest_session_key=TRUE, + * see https://bugzilla.samba.org/show_bug.cgi?id=13135 */ kdc_config->as_use_strongest_session_key = false; kdc_config->preauth_use_strongest_session_key = false; - kdc_config->tgs_use_strongest_session_key = false; + kdc_config->tgs_use_strongest_session_key = true; kdc_config->use_strongest_server_key = true; kdc_config->autodetect_referrals = false; -- 2.17.1 From b4b9ed875fd3feb310f0f73e63319df804bae595 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 7 Nov 2017 12:23:31 +0100 Subject: [PATCH 4/5] TODO s4:kdc: msDS-SupportedEncryptionTypes only on computers BUG: https://bugzilla.samba.org/show_bug.cgi?id=13135 WAS commit 466e634b4d6a170e4ba0082c2b0077e5bfa4e4bd in metze-wip/v4-7-s4u2proxy --- source4/kdc/db-glue.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c index 023ae7b580d6..00635a450c10 100644 --- a/source4/kdc/db-glue.c +++ b/source4/kdc/db-glue.c @@ -340,6 +340,14 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context, "msDS-SupportedEncryptionTypes", 0); + if (userAccountControl & UF_NORMAL_ACCOUNT) { + supported_enctypes = 0; + } + if (supported_enctypes == 0) { + /* Otherwise, add in the default enc types */ + supported_enctypes |= ENC_RC4_HMAC_MD5; + } + if (rid == DOMAIN_RID_KRBTGT || is_rodc) { /* KDCs (and KDCs on RODCs) use AES */ supported_enctypes |= ENC_HMAC_SHA1_96_AES128 | ENC_HMAC_SHA1_96_AES256; @@ -360,7 +368,7 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context, /* If UF_USE_DES_KEY_ONLY has been set, then don't allow use of the newer enc types */ if (userAccountControl & UF_USE_DES_KEY_ONLY) { supported_enctypes = 0; - } else { + } else if (supported_enctypes == 0) { /* Otherwise, add in the default enc types */ supported_enctypes |= ENC_RC4_HMAC_MD5; } -- 2.17.1 From d9fe182779d272a4d520068c16696e7be7d62cb9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 7 Nov 2017 12:23:31 +0100 Subject: [PATCH 5/5] TODO s4:kdc: indicate support for new encryption types by adding empty keys BUG: https://bugzilla.samba.org/show_bug.cgi?id=13135 --- source4/kdc/db-glue.c | 63 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c index 00635a450c10..f1315b8d9742 100644 --- a/source4/kdc/db-glue.c +++ b/source4/kdc/db-glue.c @@ -319,6 +319,7 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context, bool is_rodc, uint32_t userAccountControl, enum samba_kdc_ent_type ent_type, + unsigned flags, struct sdb_entry_ex *entry_ex) { krb5_error_code ret = 0; @@ -339,6 +340,30 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context, = ldb_msg_find_attr_as_uint(msg, "msDS-SupportedEncryptionTypes", 0); + uint32_t new_session_enctypes = 0; + const krb5_enctype newer_enctypes[] = { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + }; + + switch (ent_type) { + case SAMBA_KDC_ENT_TYPE_CLIENT: + case SAMBA_KDC_ENT_TYPE_ANY: + break; + case SAMBA_KDC_ENT_TYPE_SERVER: + case SAMBA_KDC_ENT_TYPE_KRBTGT: + case SAMBA_KDC_ENT_TYPE_TRUST: + if (flags & (SDB_F_FOR_AS_REQ|SDB_F_FOR_TGS_REQ)) { + /* + * We should indicate support for new encryption + * types (for session keys) via empty keyvalues, + * in case we don't have stored keys for such encryption + * types. + */ + new_session_enctypes = supported_enctypes; + } + break; + } if (userAccountControl & UF_NORMAL_ACCOUNT) { supported_enctypes = 0; @@ -575,6 +600,8 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context, return 0; } + allocated_keys += ARRAY_SIZE(newer_enctypes); + /* allocate space to decode into */ entry_ex->entry.keys.len = 0; entry_ex->entry.keys.val = calloc(allocated_keys, sizeof(struct sdb_key)); @@ -602,12 +629,15 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context, if (pkb4) { for (i=0; i < pkb4->num_keys; i++) { struct sdb_key key = {}; + uint32_t enctype; if (!pkb4->keys[i].value) continue; - if (!(kerberos_enctype_to_bitmap(pkb4->keys[i].keytype) & supported_enctypes)) { + enctype = kerberos_enctype_to_bitmap(pkb4->keys[i].keytype); + if (!(enctype & supported_enctypes)) { continue; } + new_session_enctypes &= ~enctype; if (pkb4->salt.string) { DATA_BLOB salt; @@ -660,12 +690,15 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context, } else if (pkb3) { for (i=0; i < pkb3->num_keys; i++) { struct sdb_key key = {}; + uint32_t enctype; if (!pkb3->keys[i].value) continue; - if (!(kerberos_enctype_to_bitmap(pkb3->keys[i].keytype) & supported_enctypes)) { + enctype = kerberos_enctype_to_bitmap(pkb3->keys[i].keytype); + if (!(enctype & supported_enctypes)) { continue; } + new_session_enctypes &= ~enctype; if (pkb3->salt.string) { DATA_BLOB salt; @@ -709,6 +742,30 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context, } } + /* + * Check if we should announce support for newer encryption + * types, which can be used as session keys, while the + * last password change only stored older keys. + * + * We do that by providing entries with empty key values. + */ + for (i = 0; i < ARRAY_SIZE(newer_enctypes); i++) { + struct sdb_key key = { + .key = { + .keytype = newer_enctypes[i], + }, + }; + uint32_t enctype; + + enctype = kerberos_enctype_to_bitmap(key.key.keytype); + if (!(enctype & new_session_enctypes)) { + continue; + } + + entry_ex->entry.keys.val[entry_ex->entry.keys.len] = key; + entry_ex->entry.keys.len++; + } + out: if (ret != 0) { entry_ex->entry.keys.len = 0; @@ -1146,7 +1203,7 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, /* Get keys from the db */ ret = samba_kdc_message2entry_keys(context, kdc_db_ctx, p, msg, rid, is_rodc, userAccountControl, - ent_type, entry_ex); + ent_type, flags, entry_ex); if (ret) { /* Could be bogus data in the entry, or out of memory */ goto out; -- 2.17.1