diff options
author | Andrew Bartlett <abartlet@samba.org> | 2018-09-19 19:24:11 -0700 |
---|---|---|
committer | Joseph Sutton <jsutton@samba.org> | 2022-01-19 20:50:35 +0000 |
commit | 8d7e9366f90a549cd191c271fddfd03b4d00e4bb (patch) | |
tree | 17912cd26b99239ea5f83110ba324c13656c210a /source4 | |
parent | 8329e8d46917d67f0cb51c3a004e323a87fa1499 (diff) | |
download | samba-8d7e9366f90a549cd191c271fddfd03b4d00e4bb.tar.gz |
s4:kdc/hdb: Store and retrieve a FX-COOKIE value
Note Windows uses the string "MICROSOFT" as cookie,
so it's wrong to have a per DC cookie, but we need to
adjust the Heimdal logic to support that.
NOTE: THIS COMMIT WON'T COMPILE/WORK ON ITS OWN!
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
Diffstat (limited to 'source4')
-rw-r--r-- | source4/kdc/db-glue.c | 186 | ||||
-rw-r--r-- | source4/kdc/db-glue.h | 6 | ||||
-rw-r--r-- | source4/kdc/hdb-samba4.c | 129 | ||||
-rw-r--r-- | source4/kdc/samba_kdc.h | 2 |
4 files changed, 253 insertions, 70 deletions
diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c index b059d8c7e61..bef8bd4f454 100644 --- a/source4/kdc/db-glue.c +++ b/source4/kdc/db-glue.c @@ -29,6 +29,7 @@ #include "dsdb/common/util.h" #include "librpc/gen_ndr/ndr_drsblobs.h" #include "param/param.h" +#include "param/secrets.h" #include "../lib/crypto/md4.h" #include "system/kerberos.h" #include "auth/kerberos/kerberos.h" @@ -317,6 +318,104 @@ static int samba_kdc_sort_encryption_keys(struct sdb_entry_ex *entry_ex) return 0; } +int samba_kdc_set_fixed_keys(krb5_context context, + struct samba_kdc_db_context *kdc_db_ctx, + const struct ldb_val *secretbuffer, + struct sdb_entry_ex *entry_ex) +{ + const uint32_t supported_enctypes = ENC_ALL_TYPES; + uint16_t allocated_keys = 0; + int ret; + + allocated_keys = 3; + entry_ex->entry.keys.len = 0; + entry_ex->entry.keys.val = calloc(allocated_keys, sizeof(struct sdb_key)); + if (entry_ex->entry.keys.val == NULL) { + memset(secretbuffer->data, 0, secretbuffer->length); + ret = ENOMEM; + goto out; + } + + if (supported_enctypes & ENC_HMAC_SHA1_96_AES256) { + struct sdb_key key = {}; + + ret = smb_krb5_keyblock_init_contents(context, + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + secretbuffer->data, + MIN(secretbuffer->length, 32), + &key.key); + if (ret) { + memset(secretbuffer->data, 0, secretbuffer->length); + goto out; + } + + entry_ex->entry.keys.val[entry_ex->entry.keys.len] = key; + entry_ex->entry.keys.len++; + } + + if (supported_enctypes & ENC_HMAC_SHA1_96_AES128) { + struct sdb_key key = {}; + + ret = smb_krb5_keyblock_init_contents(context, + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + secretbuffer->data, + MIN(secretbuffer->length, 16), + &key.key); + if (ret) { + memset(secretbuffer->data, 0, secretbuffer->length); + goto out; + } + + entry_ex->entry.keys.val[entry_ex->entry.keys.len] = key; + entry_ex->entry.keys.len++; + } + + if (supported_enctypes & ENC_RC4_HMAC_MD5) { + struct sdb_key key = {}; + + ret = smb_krb5_keyblock_init_contents(context, + ENCTYPE_ARCFOUR_HMAC, + secretbuffer->data, + MIN(secretbuffer->length, 16), + &key.key); + if (ret) { + memset(secretbuffer->data, 0, secretbuffer->length); + goto out; + } + + entry_ex->entry.keys.val[entry_ex->entry.keys.len] = key; + entry_ex->entry.keys.len++; + } + ret = 0; +out: + return ret; +} + + +static int samba_kdc_set_random_keys(krb5_context context, + struct samba_kdc_db_context *kdc_db_ctx, + struct sdb_entry_ex *entry_ex) +{ + struct ldb_val secret_val; + uint8_t secretbuffer[32]; + + /* + * Fake keys until we have a better way to reject + * non-pkinit requests. + * + * We just need to indicate which encryption types are + * supported. + */ + generate_secret_buffer(secretbuffer, sizeof(secretbuffer)); + + secret_val = data_blob_const(secretbuffer, + sizeof(secretbuffer)); + return samba_kdc_set_fixed_keys(context, kdc_db_ctx, + &secret_val, + entry_ex); +} + + static krb5_error_code samba_kdc_message2entry_keys(krb5_context context, struct samba_kdc_db_context *kdc_db_ctx, TALLOC_CTX *mem_ctx, @@ -386,75 +485,9 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context, if ((ent_type == SAMBA_KDC_ENT_TYPE_CLIENT) && (userAccountControl & UF_SMARTCARD_REQUIRED)) { - uint8_t secretbuffer[32]; - - /* - * Fake keys until we have a better way to reject - * non-pkinit requests. - * - * We just need to indicate which encryption types are - * supported. - */ - generate_secret_buffer(secretbuffer, sizeof(secretbuffer)); - - allocated_keys = 3; - entry_ex->entry.keys.len = 0; - entry_ex->entry.keys.val = calloc(allocated_keys, sizeof(struct sdb_key)); - if (entry_ex->entry.keys.val == NULL) { - ZERO_STRUCT(secretbuffer); - ret = ENOMEM; - goto out; - } - - if (supported_enctypes & ENC_HMAC_SHA1_96_AES256) { - struct sdb_key key = {}; - - ret = smb_krb5_keyblock_init_contents(context, - ENCTYPE_AES256_CTS_HMAC_SHA1_96, - secretbuffer, 32, - &key.key); - if (ret) { - ZERO_STRUCT(secretbuffer); - goto out; - } - - entry_ex->entry.keys.val[entry_ex->entry.keys.len] = key; - entry_ex->entry.keys.len++; - } - - if (supported_enctypes & ENC_HMAC_SHA1_96_AES128) { - struct sdb_key key = {}; - - ret = smb_krb5_keyblock_init_contents(context, - ENCTYPE_AES128_CTS_HMAC_SHA1_96, - secretbuffer, 16, - &key.key); - if (ret) { - ZERO_STRUCT(secretbuffer); - goto out; - } - - entry_ex->entry.keys.val[entry_ex->entry.keys.len] = key; - entry_ex->entry.keys.len++; - } - - if (supported_enctypes & ENC_RC4_HMAC_MD5) { - struct sdb_key key = {}; - - ret = smb_krb5_keyblock_init_contents(context, - ENCTYPE_ARCFOUR_HMAC, - secretbuffer, 16, - &key.key); - if (ret) { - ZERO_STRUCT(secretbuffer); - goto out; - } - - entry_ex->entry.keys.val[entry_ex->entry.keys.len] = key; - entry_ex->entry.keys.len++; - } - - ret = 0; + ret = samba_kdc_set_random_keys(context, + kdc_db_ctx, + entry_ex); goto out; } @@ -2788,6 +2821,21 @@ NTSTATUS samba_kdc_setup_db_ctx(TALLOC_CTX *mem_ctx, struct samba_kdc_base_conte return NT_STATUS_INTERNAL_ERROR; } + /* Setup the link to secrets.ldb */ + + kdc_db_ctx->secrets_db = secrets_db_connect(kdc_db_ctx, + base_ctx->lp_ctx); + if (kdc_db_ctx->secrets_db == NULL) { + DEBUG(1, ("samba_kdc_setup_db_ctx: " + "Cannot open secrets.ldb for KDC backend!")); + talloc_free(kdc_db_ctx); + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + + kdc_db_ctx->fx_cookie_dn = ldb_dn_new(kdc_db_ctx, + kdc_db_ctx->secrets_db, + "CN=FX Cookie"); + /* Setup the link to LDB */ kdc_db_ctx->samdb = samdb_connect(kdc_db_ctx, base_ctx->ev_ctx, diff --git a/source4/kdc/db-glue.h b/source4/kdc/db-glue.h index 4defca2320c..218bd3cfae2 100644 --- a/source4/kdc/db-glue.h +++ b/source4/kdc/db-glue.h @@ -23,6 +23,12 @@ struct sdb_entry_ex; + +int samba_kdc_set_fixed_keys(krb5_context context, + struct samba_kdc_db_context *kdc_db_ctx, + const struct ldb_val *secretbuffer, + struct sdb_entry_ex *entry_ex); + krb5_error_code samba_kdc_fetch(krb5_context context, struct samba_kdc_db_context *kdc_db_ctx, krb5_const_principal principal, diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c index 9132bb46212..c0ec4bd3cd8 100644 --- a/source4/kdc/hdb-samba4.c +++ b/source4/kdc/hdb-samba4.c @@ -92,6 +92,128 @@ static krb5_error_code hdb_samba4_set_sync(krb5_context context, struct HDB *db, return 0; } +static int hdb_samba4_fill_fast_cookie(krb5_context context, + struct samba_kdc_db_context *kdc_db_ctx) +{ + struct ldb_message *msg = ldb_msg_new(kdc_db_ctx); + int ldb_ret; + + uint8_t secretbuffer[32]; + struct ldb_val val = data_blob_const(secretbuffer, + sizeof(secretbuffer)); + + if (msg == NULL) { + DBG_ERR("Failed to allocate msg for new fast cookie\n"); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Fill in all the keys with the same secret */ + generate_secret_buffer(secretbuffer, + sizeof(secretbuffer)); + + msg->dn = kdc_db_ctx->fx_cookie_dn; + + ldb_ret = ldb_msg_add_value(msg, "secret", &val, NULL); + + if (ldb_ret != LDB_SUCCESS) { + return ldb_ret; + } + + ldb_ret = ldb_add(kdc_db_ctx->secrets_db, + msg); + if (ldb_ret != LDB_SUCCESS) { + DBG_ERR("Failed to add fast cookie to ldb: %s\n", + ldb_errstring(kdc_db_ctx->secrets_db)); + } + return ldb_ret; +} + +static krb5_error_code hdb_samba4_fetch_fast_cookie(krb5_context context, + struct samba_kdc_db_context *kdc_db_ctx, + hdb_entry_ex *entry_ex) +{ + krb5_error_code ret = SDB_ERR_NOENTRY; + TALLOC_CTX *mem_ctx; + struct ldb_result *res; + int ldb_ret; + struct sdb_entry_ex sdb_entry_ex = {}; + const char *attrs[] = { + "secret", + NULL + }; + const struct ldb_val *val; + + mem_ctx = talloc_named(kdc_db_ctx, 0, "samba_kdc_fetch context"); + if (!mem_ctx) { + ret = ENOMEM; + krb5_set_error_message(context, ret, "samba_kdc_fetch: talloc_named() failed!"); + return ret; + } + + /* search for CN=FX-COOKIE */ + ldb_ret = ldb_search(kdc_db_ctx->secrets_db, + mem_ctx, + &res, + kdc_db_ctx->fx_cookie_dn, + LDB_SCOPE_BASE, + attrs, NULL); + + if (ldb_ret == LDB_ERR_NO_SUCH_OBJECT || res->count == 0) { + + ldb_ret = hdb_samba4_fill_fast_cookie(context, + kdc_db_ctx); + + if (ldb_ret != LDB_SUCCESS) { + TALLOC_FREE(mem_ctx); + return HDB_ERR_NO_WRITE_SUPPORT; + } + + /* search for CN=FX-COOKIE */ + ldb_ret = ldb_search(kdc_db_ctx->secrets_db, + mem_ctx, + &res, + kdc_db_ctx->fx_cookie_dn, + LDB_SCOPE_BASE, + attrs, NULL); + + if (ldb_ret != LDB_SUCCESS || res->count != 1) { + TALLOC_FREE(mem_ctx); + return HDB_ERR_NOENTRY; + } + } + + val = ldb_msg_find_ldb_val(res->msgs[0], + "secret"); + if (val == NULL || val->length != 32) { + TALLOC_FREE(mem_ctx); + return HDB_ERR_NOENTRY; + } + + + ret = krb5_make_principal(context, + &sdb_entry_ex.entry.principal, + KRB5_WELLKNOWN_ORG_H5L_REALM, + KRB5_WELLKNOWN_NAME, "org.h5l.fast-cookie", + NULL); + if (ret) { + TALLOC_FREE(mem_ctx); + return ret; + } + + ret = samba_kdc_set_fixed_keys(context, kdc_db_ctx, + val, &sdb_entry_ex); + if (ret != 0) { + return ret; + } + + ret = sdb_entry_ex_to_hdb_entry_ex(context, + &sdb_entry_ex, + entry_ex); + TALLOC_FREE(mem_ctx); + + return ret; +} + static krb5_error_code hdb_samba4_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal, unsigned flags, @@ -101,10 +223,15 @@ static krb5_error_code hdb_samba4_fetch_kvno(krb5_context context, HDB *db, struct samba_kdc_db_context *kdc_db_ctx; struct sdb_entry_ex sdb_entry_ex = {}; krb5_error_code code, ret; - kdc_db_ctx = talloc_get_type_abort(db->hdb_db, struct samba_kdc_db_context); + if (flags & HDB_F_GET_FAST_COOKIE) { + return hdb_samba4_fetch_fast_cookie(context, + kdc_db_ctx, + entry_ex); + } + ret = samba_kdc_fetch(context, kdc_db_ctx, principal, diff --git a/source4/kdc/samba_kdc.h b/source4/kdc/samba_kdc.h index e228a82ce6a..150729a01f3 100644 --- a/source4/kdc/samba_kdc.h +++ b/source4/kdc/samba_kdc.h @@ -48,6 +48,8 @@ struct samba_kdc_db_context { unsigned int my_krbtgt_number; struct ldb_dn *krbtgt_dn; struct samba_kdc_policy policy; + struct ldb_dn *fx_cookie_dn; + struct ldb_context *secrets_db; }; struct samba_kdc_entry { |