mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
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>
This commit is contained in:
parent
8329e8d469
commit
8d7e9366f9
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user