source4/smbd: Do not overstamp the process model with "single"
[amitay/samba.git] / source4 / kdc / db-glue.c
index a9ee42356274bb41e1e478b919082b29ba50f1f0..9ac5a1d38f06d227ad1eb4bc37f64a9656cb3d92 100644 (file)
 #include "../lib/crypto/md4.h"
 #include "system/kerberos.h"
 #include "auth/kerberos/kerberos.h"
-#include <hdb.h>
+#include "kdc/sdb.h"
 #include "kdc/samba_kdc.h"
 #include "kdc/db-glue.h"
+#include "librpc/gen_ndr/ndr_irpc_c.h"
+#include "lib/messaging/irpc.h"
+
 
 #define SAMBA_KVNO_GET_KRBTGT(kvno) \
        ((uint16_t)(((uint32_t)kvno) >> 16))
@@ -65,6 +68,52 @@ static const char *trust_attrs[] = {
        NULL
 };
 
+/*
+  send a message to the drepl server telling it to initiate a
+  REPL_SECRET getncchanges extended op to fetch the users secrets
+ */
+static void auth_sam_trigger_repl_secret(TALLOC_CTX *mem_ctx,
+                                  struct imessaging_context *msg_ctx,
+                                  struct tevent_context *event_ctx,
+                                  struct ldb_dn *user_dn)
+{
+        struct dcerpc_binding_handle *irpc_handle;
+        struct drepl_trigger_repl_secret r;
+        struct tevent_req *req;
+        TALLOC_CTX *tmp_ctx;
+
+        tmp_ctx = talloc_new(mem_ctx);
+        if (tmp_ctx == NULL) {
+                return;
+        }
+
+        irpc_handle = irpc_binding_handle_by_name(tmp_ctx, msg_ctx,
+                                                  "dreplsrv",
+                                                  &ndr_table_irpc);
+        if (irpc_handle == NULL) {
+                DEBUG(1,(__location__ ": Unable to get binding handle for dreplsrv\n"));
+                TALLOC_FREE(tmp_ctx);
+                return;
+        }
+
+        r.in.user_dn = ldb_dn_get_linearized(user_dn);
+
+        /*
+         * This seem to rely on the current IRPC implementation,
+         * which delivers the message in the _send function.
+         *
+         * TODO: we need a ONE_WAY IRPC handle and register
+         * a callback and wait for it to be triggered!
+         */
+        req = dcerpc_drepl_trigger_repl_secret_r_send(tmp_ctx,
+                                                      event_ctx,
+                                                      irpc_handle,
+                                                      &r);
+
+        /* we aren't interested in a reply */
+        talloc_free(req);
+        TALLOC_FREE(tmp_ctx);
+}
 
 static time_t ldb_msg_find_krb5time_ldap_time(struct ldb_message *msg, const char *attr, time_t default_val)
 {
@@ -84,9 +133,9 @@ static time_t ldb_msg_find_krb5time_ldap_time(struct ldb_message *msg, const cha
     return timegm(&tm);
 }
 
-static HDBFlags uf2HDBFlags(krb5_context context, uint32_t userAccountControl, enum samba_kdc_ent_type ent_type)
+static struct SDBFlags uf2SDBFlags(krb5_context context, uint32_t userAccountControl, enum samba_kdc_ent_type ent_type)
 {
-       HDBFlags flags = int2HDBFlags(0);
+       struct SDBFlags flags = int2SDBFlags(0);
 
        /* we don't allow kadmin deletes */
        flags.immutable = 1;
@@ -189,23 +238,74 @@ static HDBFlags uf2HDBFlags(krb5_context context, uint32_t userAccountControl, e
 static int samba_kdc_entry_destructor(struct samba_kdc_entry *p)
 {
        if (p->entry_ex != NULL) {
-               hdb_entry_ex *entry_ex = p->entry_ex;
-               free_hdb_entry(&entry_ex->entry);
+               struct sdb_entry_ex *entry_ex = p->entry_ex;
+               free_sdb_entry(&entry_ex->entry);
        }
 
        return 0;
 }
 
-static void samba_kdc_free_entry(krb5_context context, hdb_entry_ex *entry_ex)
+/*
+ * Sort keys in descending order of strength.
+ *
+ * Explanaton from Greg Hudson:
+ *
+ * To encrypt tickets only the first returned key is used by the MIT KDC.  The
+ * other keys just communicate support for session key enctypes, and aren't
+ * really used.  The encryption key for the ticket enc part doesn't have
+ * to be of a type requested by the client. The session key enctype is chosen
+ * based on the client preference order, limited by the set of enctypes present
+ * in the server keys (unless the string attribute is set on the server
+ * principal overriding that set).
+ */
+static int samba_kdc_sort_encryption_keys(struct sdb_entry_ex *entry_ex)
 {
-       /* this function is called only from hdb_free_entry().
-        * Make sure we neutralize the destructor or we will
-        * get a double free later when hdb_free_entry() will
-        * try to call free_hdb_entry() */
-       talloc_set_destructor(entry_ex->ctx, NULL);
-
-       /* now proceed to free the talloc part */
-       talloc_free(entry_ex->ctx);
+       unsigned int i, j, idx = 0;
+       static const krb5_enctype etype_list[] = {
+               ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+               ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+               ENCTYPE_DES3_CBC_SHA1,
+               ENCTYPE_ARCFOUR_HMAC,
+               ENCTYPE_DES_CBC_MD5,
+               ENCTYPE_DES_CBC_MD4,
+               ENCTYPE_DES_CBC_CRC,
+               ENCTYPE_NULL
+       };
+       size_t etype_len = ARRAY_SIZE(etype_list);
+       size_t keys_size = entry_ex->entry.keys.len;
+       struct sdb_key *keys = entry_ex->entry.keys.val;
+       struct sdb_key *sorted_keys;
+
+       sorted_keys = calloc(keys_size, sizeof(struct sdb_key));
+       if (sorted_keys == NULL) {
+               return -1;
+       }
+
+       for (i = 0; i < etype_len; i++) {
+               for (j = 0; j < keys_size; j++) {
+                       const struct sdb_key skey = keys[j];
+
+                       if (idx == keys_size) {
+                               break;
+                       }
+
+                       if (KRB5_KEY_TYPE(&skey.key) == etype_list[i]) {
+                               sorted_keys[idx] = skey;
+                               idx++;
+                       }
+               }
+       }
+
+       /* Paranoia: Something went wrong during data copy */
+       if (idx != keys_size) {
+               free(sorted_keys);
+               return -1;
+       }
+
+       free(entry_ex->entry.keys.val);
+       entry_ex->entry.keys.val = sorted_keys;
+
+       return 0;
 }
 
 static krb5_error_code samba_kdc_message2entry_keys(krb5_context context,
@@ -216,7 +316,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,
-                                                   hdb_entry_ex *entry_ex)
+                                                   struct sdb_entry_ex *entry_ex)
 {
        krb5_error_code ret = 0;
        enum ndr_err_code ndr_err;
@@ -273,6 +373,81 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context,
 
        entry_ex->entry.keys.val = NULL;
        entry_ex->entry.keys.len = 0;
+       entry_ex->entry.kvno = 0;
+
+       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;
+               goto out;
+       }
 
        kvno = ldb_msg_find_attr_as_int(msg, "msDS-KeyVersionNumber", 0);
        if (is_rodc) {
@@ -301,9 +476,11 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context,
                }
 
                if (scb.sub.signature != SUPPLEMENTAL_CREDENTIALS_SIGNATURE) {
-                       NDR_PRINT_DEBUG(supplementalCredentialsBlob, &scb);
-                       ret = EINVAL;
-                       goto out;
+                       if (scb.sub.num_packages != 0) {
+                               NDR_PRINT_DEBUG(supplementalCredentialsBlob, &scb);
+                               ret = EINVAL;
+                               goto out;
+                       }
                }
 
                for (i=0; i < scb.sub.num_packages; i++) {
@@ -376,8 +553,9 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context,
        if (allocated_keys == 0) {
                if (kdc_db_ctx->rodc) {
                        /* We are on an RODC, but don't have keys for this account.  Signal this to the caller */
-                       /* TODO:  We need to call a generalised version of auth_sam_trigger_repl_secret from here */
-                       return HDB_ERR_NOT_FOUND_HERE;
+                       auth_sam_trigger_repl_secret(kdc_db_ctx, kdc_db_ctx->msg_ctx,
+                                                    kdc_db_ctx->ev_ctx, msg->dn);
+                       return SDB_ERR_NOT_FOUND_HERE;
                }
 
                /* oh, no password.  Apparently (comment in
@@ -388,17 +566,14 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context,
 
        /* allocate space to decode into */
        entry_ex->entry.keys.len = 0;
-       entry_ex->entry.keys.val = calloc(allocated_keys, sizeof(Key));
+       entry_ex->entry.keys.val = calloc(allocated_keys, sizeof(struct sdb_key));
        if (entry_ex->entry.keys.val == NULL) {
                ret = ENOMEM;
                goto out;
        }
 
        if (hash && (supported_enctypes & ENC_RC4_HMAC_MD5)) {
-               Key key;
-
-               key.mkvno = 0;
-               key.salt = NULL; /* No salt for this enc type */
+               struct sdb_key key = {};
 
                ret = smb_krb5_keyblock_init_contents(context,
                                                      ENCTYPE_ARCFOUR_HMAC,
@@ -415,7 +590,7 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context,
 
        if (pkb4) {
                for (i=0; i < pkb4->num_keys; i++) {
-                       Key key;
+                       struct sdb_key key = {};
 
                        if (!pkb4->keys[i].value) continue;
 
@@ -423,9 +598,6 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context,
                                continue;
                        }
 
-                       key.mkvno = 0;
-                       key.salt = NULL;
-
                        if (pkb4->salt.string) {
                                DATA_BLOB salt;
 
@@ -439,9 +611,9 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context,
 
                                key.salt->type = KRB5_PW_SALT;
 
-                               ret = krb5_copy_data_contents(&key.salt->salt,
-                                                             salt.data,
-                                                             salt.length);
+                               ret = smb_krb5_copy_data_contents(&key.salt->salt,
+                                                                 salt.data,
+                                                                 salt.length);
                                if (ret) {
                                        free(key.salt);
                                        key.salt = NULL;
@@ -464,7 +636,7 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context,
                        }
                        if (ret) {
                                if (key.salt) {
-                                       free_Salt(key.salt);
+                                       smb_krb5_free_data_contents(context, &key.salt->salt);
                                        free(key.salt);
                                        key.salt = NULL;
                                }
@@ -476,7 +648,7 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context,
                }
        } else if (pkb3) {
                for (i=0; i < pkb3->num_keys; i++) {
-                       Key key;
+                       struct sdb_key key = {};
 
                        if (!pkb3->keys[i].value) continue;
 
@@ -484,9 +656,6 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context,
                                continue;
                        }
 
-                       key.mkvno = 0;
-                       key.salt = NULL;
-
                        if (pkb3->salt.string) {
                                DATA_BLOB salt;
 
@@ -500,9 +669,9 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context,
 
                                key.salt->type = KRB5_PW_SALT;
 
-                               ret = krb5_copy_data_contents(&key.salt->salt,
-                                                             salt.data,
-                                                             salt.length);
+                               ret = smb_krb5_copy_data_contents(&key.salt->salt,
+                                                                 salt.data,
+                                                                 salt.length);
                                if (ret) {
                                        free(key.salt);
                                        key.salt = NULL;
@@ -517,7 +686,7 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context,
                                                              &key.key);
                        if (ret) {
                                if (key.salt) {
-                                       free_Salt(key.salt);
+                                       smb_krb5_free_data_contents(context, &key.salt->salt);
                                        free(key.salt);
                                        key.salt = NULL;
                                }
@@ -532,6 +701,13 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context,
 out:
        if (ret != 0) {
                entry_ex->entry.keys.len = 0;
+       } else if (entry_ex->entry.keys.len > 0 &&
+                  entry_ex->entry.keys.val != NULL) {
+               ret = samba_kdc_sort_encryption_keys(entry_ex);
+               if (ret != 0) {
+                       entry_ex->entry.keys.len = 0;
+                       ret = ENOMEM;
+               }
        }
        if (entry_ex->entry.keys.len == 0 && entry_ex->entry.keys.val) {
                free(entry_ex->entry.keys.val);
@@ -605,12 +781,11 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
                                               unsigned flags,
                                               struct ldb_dn *realm_dn,
                                               struct ldb_message *msg,
-                                              hdb_entry_ex *entry_ex)
+                                              struct sdb_entry_ex *entry_ex)
 {
        struct loadparm_context *lp_ctx = kdc_db_ctx->lp_ctx;
        uint32_t userAccountControl;
        uint32_t msDS_User_Account_Control_Computed;
-       unsigned int i;
        krb5_error_code ret = 0;
        krb5_boolean is_computer = FALSE;
 
@@ -651,7 +826,6 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
        }
 
        p->kdc_db_ctx = kdc_db_ctx;
-       p->entry_ex = entry_ex;
        p->realm_dn = talloc_reference(p, realm_dn);
        if (!p->realm_dn) {
                ret = ENOMEM;
@@ -660,11 +834,7 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
 
        talloc_set_destructor(p, samba_kdc_entry_destructor);
 
-       /* make sure we do not have bogus data in there */
-       memset(&entry_ex->entry, 0, sizeof(hdb_entry));
-
        entry_ex->ctx = p;
-       entry_ex->free_entry = samba_kdc_free_entry;
 
        userAccountControl = ldb_msg_find_attr_as_uint(msg, "userAccountControl", 0);
 
@@ -701,7 +871,7 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
         */
 
        if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT) {
-               if (flags & (HDB_F_CANON)) {
+               if (flags & (SDB_F_CANON)) {
                        /*
                         * When requested to do so, ensure that the
                         * both realm values in the principal are set
@@ -738,9 +908,9 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
                        krb5_clear_error_message(context);
                        goto out;
                }
-       } else if (flags & HDB_F_CANON && flags & HDB_F_FOR_AS_REQ) {
+       } else if (flags & SDB_F_CANON && flags & SDB_F_FOR_AS_REQ) {
                /*
-                * HDB_F_CANON maps from the canonicalize flag in the
+                * SDB_F_CANON maps from the canonicalize flag in the
                 * packet, and has a different meaning between AS-REQ
                 * and TGS-REQ.  We only change the principal in the AS-REQ case
                 */
@@ -773,7 +943,7 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
        }
 
        /* First try and figure out the flags based on the userAccountControl */
-       entry_ex->entry.flags = uf2HDBFlags(context, userAccountControl, ent_type);
+       entry_ex->entry.flags = uf2SDBFlags(context, userAccountControl, ent_type);
 
        /* Windows 2008 seems to enforce this (very sensible) rule by
         * default - don't allow offline attacks on a user's password
@@ -794,11 +964,11 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
         * KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
         */
        if (ent_type == SAMBA_KDC_ENT_TYPE_SERVER && entry_ex->entry.flags.server == 0) {
-               ret = HDB_ERR_NOENTRY;
+               ret = SDB_ERR_NOENTRY;
                krb5_set_error_message(context, ret, "samba_kdc_message2entry: no servicePrincipalName present for this server, refusing with no-such-entry");
                goto out;
        }
-       if (flags & HDB_F_ADMIN_DATA) {
+       if (flags & SDB_F_ADMIN_DATA) {
                /* These (created_by, modified_by) parts of the entry are not relevant for Samba4's use
                 * of the Heimdal KDC.  They are stored in a the traditional
                 * DB for audit purposes, and still form part of the structure
@@ -816,7 +986,7 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
                        goto out;
                }
 
-               entry_ex->entry.modified_by = (Event *) malloc(sizeof(Event));
+               entry_ex->entry.modified_by = (struct sdb_event *) malloc(sizeof(struct sdb_event));
                if (entry_ex->entry.modified_by == NULL) {
                        ret = ENOMEM;
                        krb5_set_error_message(context, ret, "malloc: out of memory");
@@ -906,8 +1076,9 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
 
        } else {
                NTTIME must_change_time
-                       = samdb_result_force_password_change(kdc_db_ctx->samdb, mem_ctx,
-                                                            realm_dn, msg);
+                       = samdb_result_nttime(msg,
+                                       "msDS-UserPasswordExpiryTimeComputed",
+                                       0);
                if (must_change_time == 0x7FFFFFFFFFFFFFFFULL) {
                        entry_ex->entry.pw_end = NULL;
                } else {
@@ -962,34 +1133,16 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
                                           rid, is_rodc, userAccountControl,
                                           ent_type, entry_ex);
        if (ret) {
-               /* Could be bougus data in the entry, or out of memory */
-               goto out;
-       }
-
-       entry_ex->entry.etypes = malloc(sizeof(*(entry_ex->entry.etypes)));
-       if (entry_ex->entry.etypes == NULL) {
-               krb5_clear_error_message(context);
-               ret = ENOMEM;
+               /* Could be bogus data in the entry, or out of memory */
                goto out;
        }
-       entry_ex->entry.etypes->len = entry_ex->entry.keys.len;
-       entry_ex->entry.etypes->val = calloc(entry_ex->entry.etypes->len, sizeof(int));
-       if (entry_ex->entry.etypes->val == NULL) {
-               krb5_clear_error_message(context);
-               ret = ENOMEM;
-               goto out;
-       }
-       for (i=0; i < entry_ex->entry.etypes->len; i++) {
-               entry_ex->entry.etypes->val[i] = KRB5_KEY_TYPE(&entry_ex->entry.keys.val[i].key);
-       }
-
 
        p->msg = talloc_steal(p, msg);
 
 out:
        if (ret != 0) {
                /* This doesn't free ent itself, that is for the eventual caller to do */
-               hdb_free_entry(context, entry_ex);
+               sdb_free_entry(entry_ex);
                ZERO_STRUCTP(entry_ex);
        } else {
                talloc_steal(kdc_db_ctx, entry_ex->ctx);
@@ -1010,7 +1163,7 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context,
                                               unsigned flags,
                                               uint32_t kvno,
                                               struct ldb_message *msg,
-                                              hdb_entry_ex *entry_ex)
+                                              struct sdb_entry_ex *entry_ex)
 {
        struct loadparm_context *lp_ctx = kdc_db_ctx->lp_ctx;
        const char *our_realm = lpcfg_realm(lp_ctx);
@@ -1048,14 +1201,14 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context,
        trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
        if (!(trust_direction_flags & direction)) {
                krb5_clear_error_message(context);
-               ret = HDB_ERR_NOENTRY;
+               ret = SDB_ERR_NOENTRY;
                goto out;
        }
 
        dnsdomain = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
        if (dnsdomain == NULL) {
                krb5_clear_error_message(context);
-               ret = HDB_ERR_NOENTRY;
+               ret = SDB_ERR_NOENTRY;
                goto out;
        }
        partner_realm = strupper_talloc(mem_ctx, dnsdomain);
@@ -1079,7 +1232,7 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context,
 
        if (password_val == NULL) {
                krb5_clear_error_message(context);
-               ret = HDB_ERR_NOENTRY;
+               ret = SDB_ERR_NOENTRY;
                goto out;
        }
 
@@ -1098,16 +1251,14 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context,
        }
 
        p->kdc_db_ctx = kdc_db_ctx;
-       p->entry_ex = entry_ex;
        p->realm_dn = realm_dn;
 
        talloc_set_destructor(p, samba_kdc_entry_destructor);
 
        /* make sure we do not have bogus data in there */
-       memset(&entry_ex->entry, 0, sizeof(hdb_entry));
+       memset(&entry_ex->entry, 0, sizeof(struct sdb_entry));
 
        entry_ex->ctx = p;
-       entry_ex->free_entry = samba_kdc_free_entry;
 
        /* use 'whenCreated' */
        entry_ex->entry.created_by.time = ldb_msg_find_krb5time_ldap_time(msg, "whenCreated", 0);
@@ -1185,7 +1336,7 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context,
        if (password_blob.previous.count == 0) {
                /* there is no previous password */
                use_previous = false;
-       } else if (!(flags & HDB_F_KVNO_SPECIFIED)) {
+       } else if (!(flags & SDB_F_KVNO_SPECIFIED)) {
                /*
                 * If not specified we use the lowest kvno
                 * for the first hour after an update.
@@ -1223,7 +1374,7 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context,
        }
 
        /* use the kvno the client specified, if available */
-       if (flags & HDB_F_KVNO_SPECIFIED) {
+       if (flags & SDB_F_KVNO_SPECIFIED) {
                entry_ex->entry.kvno = kvno;
        } else {
                entry_ex->entry.kvno = *auth_kvno;
@@ -1282,11 +1433,11 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context,
        if (num_keys == 0) {
                DEBUG(1,(__location__ ": no usable key found\n"));
                krb5_clear_error_message(context);
-               ret = HDB_ERR_NOENTRY;
+               ret = SDB_ERR_NOENTRY;
                goto out;
        }
 
-       entry_ex->entry.keys.val = calloc(num_keys, sizeof(Key));
+       entry_ex->entry.keys.val = calloc(num_keys, sizeof(struct sdb_key));
        if (entry_ex->entry.keys.val == NULL) {
                krb5_clear_error_message(context);
                ret = ENOMEM;
@@ -1294,12 +1445,12 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context,
        }
 
        if (password_utf8.length != 0) {
-               Key key = {};
+               struct sdb_key key = {};
                krb5_const_principal salt_principal = entry_ex->entry.principal;
                krb5_data salt;
                krb5_data cleartext_data;
 
-               cleartext_data.data = password_utf8.data;
+               cleartext_data.data = discard_const_p(char, password_utf8.data);
                cleartext_data.length = password_utf8.length;
 
                ret = smb_krb5_get_pw_salt(context,
@@ -1317,7 +1468,7 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context,
                                                              ENCTYPE_AES256_CTS_HMAC_SHA1_96,
                                                              &key.key);
                        if (ret != 0) {
-                               kerberos_free_data_contents(context, &salt);
+                               smb_krb5_free_data_contents(context, &salt);
                                goto out;
                        }
 
@@ -1333,7 +1484,7 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context,
                                                              ENCTYPE_AES128_CTS_HMAC_SHA1_96,
                                                              &key.key);
                        if (ret != 0) {
-                               kerberos_free_data_contents(context, &salt);
+                               smb_krb5_free_data_contents(context, &salt);
                                goto out;
                        }
 
@@ -1341,11 +1492,11 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context,
                        entry_ex->entry.keys.len++;
                }
 
-               kerberos_free_data_contents(context, &salt);
+               smb_krb5_free_data_contents(context, &salt);
        }
 
        if (password_hash != NULL) {
-               Key key = {};
+               struct sdb_key key = {};
 
                ret = smb_krb5_keyblock_init_contents(context,
                                                      ENCTYPE_ARCFOUR_HMAC,
@@ -1360,7 +1511,7 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context,
                entry_ex->entry.keys.len++;
        }
 
-       entry_ex->entry.flags = int2HDBFlags(0);
+       entry_ex->entry.flags = int2SDBFlags(0);
        entry_ex->entry.flags.immutable = 1;
        entry_ex->entry.flags.invalid = 0;
        entry_ex->entry.flags.server = 1;
@@ -1372,22 +1523,12 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context,
 
        entry_ex->entry.max_renew = NULL;
 
-       entry_ex->entry.etypes = malloc(sizeof(*(entry_ex->entry.etypes)));
-       if (entry_ex->entry.etypes == NULL) {
-               krb5_clear_error_message(context);
-               ret = ENOMEM;
-               goto out;
-       }
-       entry_ex->entry.etypes->len = entry_ex->entry.keys.len;
-       entry_ex->entry.etypes->val = calloc(entry_ex->entry.etypes->len, sizeof(int));
-       if (entry_ex->entry.etypes->val == NULL) {
+       ret = samba_kdc_sort_encryption_keys(entry_ex);
+       if (ret != 0) {
                krb5_clear_error_message(context);
                ret = ENOMEM;
                goto out;
        }
-       for (i=0; i < entry_ex->entry.etypes->len; i++) {
-               entry_ex->entry.etypes->val[i] = KRB5_KEY_TYPE(&entry_ex->entry.keys.val[i].key);
-       }
 
        p->msg = talloc_steal(p, msg);
 
@@ -1396,7 +1537,7 @@ out:
 
        if (ret != 0) {
                /* This doesn't free ent itself, that is for the eventual caller to do */
-               hdb_free_entry(context, entry_ex);
+               sdb_free_entry(entry_ex);
        } else {
                talloc_steal(kdc_db_ctx, entry_ex->ctx);
        }
@@ -1414,13 +1555,12 @@ static krb5_error_code samba_kdc_lookup_trust(krb5_context context, struct ldb_c
        NTSTATUS status;
        const char * const *attrs = trust_attrs;
 
-       status = sam_get_results_trust(ldb_ctx,
-                                      mem_ctx, realm, realm, attrs,
-                                      pmsg);
+       status = dsdb_trust_search_tdo(ldb_ctx, realm, realm,
+                                      attrs, mem_ctx, pmsg);
        if (NT_STATUS_IS_OK(status)) {
                return 0;
-       } else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
-               return HDB_ERR_NOENTRY;
+       } else if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+               return SDB_ERR_NOENTRY;
        } else if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
                int ret = ENOMEM;
                krb5_set_error_message(context, ret, "get_sam_result_trust: out of memory");
@@ -1556,7 +1696,7 @@ static krb5_error_code samba_kdc_lookup_client(krb5_context context,
        TALLOC_FREE(principal_string);
 
        if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) {
-               return HDB_ERR_NOENTRY;
+               return SDB_ERR_NOENTRY;
        } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_MEMORY)) {
                return ENOMEM;
        } else if (!NT_STATUS_IS_OK(nt_status)) {
@@ -1571,7 +1711,7 @@ static krb5_error_code samba_kdc_fetch_client(krb5_context context,
                                               TALLOC_CTX *mem_ctx,
                                               krb5_const_principal principal,
                                               unsigned flags,
-                                              hdb_entry_ex *entry_ex) {
+                                              struct sdb_entry_ex *entry_ex) {
        struct ldb_dn *realm_dn;
        krb5_error_code ret;
        struct ldb_message *msg = NULL;
@@ -1596,7 +1736,7 @@ static krb5_error_code samba_kdc_fetch_krbtgt(krb5_context context,
                                              krb5_const_principal principal,
                                              unsigned flags,
                                              uint32_t kvno,
-                                             hdb_entry_ex *entry_ex)
+                                             struct sdb_entry_ex *entry_ex)
 {
        struct loadparm_context *lp_ctx = kdc_db_ctx->lp_ctx;
        krb5_error_code ret;
@@ -1608,18 +1748,18 @@ static krb5_error_code samba_kdc_fetch_krbtgt(krb5_context context,
        realm_from_princ_malloc = smb_krb5_principal_get_realm(context, principal);
        if (realm_from_princ_malloc == NULL) {
                /* can't happen */
-               return HDB_ERR_NOENTRY;
+               return SDB_ERR_NOENTRY;
        }
        realm_from_princ = talloc_strdup(mem_ctx, realm_from_princ_malloc);
        free(realm_from_princ_malloc);
        if (realm_from_princ == NULL) {
-               return HDB_ERR_NOENTRY;
+               return SDB_ERR_NOENTRY;
        }
 
        if (krb5_princ_size(context, principal) != 2
            || (principal_comp_strcmp(context, principal, 0, KRB5_TGS_NAME) != 0)) {
                /* Not a krbtgt */
-               return HDB_ERR_NOENTRY;
+               return SDB_ERR_NOENTRY;
        }
 
        /* krbtgt case.  Either us or a trusted realm */
@@ -1636,11 +1776,11 @@ static krb5_error_code samba_kdc_fetch_krbtgt(krb5_context context,
                /* w2k8r2 sometimes gives us a kvno of 255 for inter-domain
                   trust tickets. We don't yet know what this means, but we do
                   seem to need to treat it as unspecified */
-               if (flags & HDB_F_KVNO_SPECIFIED) {
+               if (flags & SDB_F_KVNO_SPECIFIED) {
                        krbtgt_number = SAMBA_KVNO_GET_KRBTGT(kvno);
                        if (kdc_db_ctx->rodc) {
                                if (krbtgt_number != kdc_db_ctx->my_krbtgt_number) {
-                                       return HDB_ERR_NOT_FOUND_HERE;
+                                       return SDB_ERR_NOT_FOUND_HERE;
                                }
                        }
                } else {
@@ -1666,17 +1806,17 @@ static krb5_error_code samba_kdc_fetch_krbtgt(krb5_context context,
                if (lret == LDB_ERR_NO_SUCH_OBJECT) {
                        krb5_warnx(context, "samba_kdc_fetch: could not find KRBTGT number %u in DB!",
                                   (unsigned)(krbtgt_number));
-                       krb5_set_error_message(context, HDB_ERR_NOENTRY,
+                       krb5_set_error_message(context, SDB_ERR_NOENTRY,
                                               "samba_kdc_fetch: could not find KRBTGT number %u in DB!",
                                               (unsigned)(krbtgt_number));
-                       return HDB_ERR_NOENTRY;
+                       return SDB_ERR_NOENTRY;
                } else if (lret != LDB_SUCCESS) {
                        krb5_warnx(context, "samba_kdc_fetch: could not find KRBTGT number %u in DB!",
                                   (unsigned)(krbtgt_number));
-                       krb5_set_error_message(context, HDB_ERR_NOENTRY,
+                       krb5_set_error_message(context, SDB_ERR_NOENTRY,
                                               "samba_kdc_fetch: could not find KRBTGT number %u in DB!",
                                               (unsigned)(krbtgt_number));
-                       return HDB_ERR_NOENTRY;
+                       return SDB_ERR_NOENTRY;
                }
 
                ret = samba_kdc_message2entry(context, kdc_db_ctx, mem_ctx,
@@ -1705,10 +1845,10 @@ static krb5_error_code samba_kdc_fetch_krbtgt(krb5_context context,
                        krb5_warnx(context, "samba_kdc_fetch: not our realm for trusts ('%s', '%s')",
                                   realm_from_princ,
                                   realm_princ_comp);
-                       krb5_set_error_message(context, HDB_ERR_NOENTRY, "samba_kdc_fetch: not our realm for trusts ('%s', '%s')",
+                       krb5_set_error_message(context, SDB_ERR_NOENTRY, "samba_kdc_fetch: not our realm for trusts ('%s', '%s')",
                                               realm_from_princ,
                                               realm_princ_comp);
-                       return HDB_ERR_NOENTRY;
+                       return SDB_ERR_NOENTRY;
                }
 
                /* Trusted domains are under CN=system */
@@ -1772,7 +1912,7 @@ static krb5_error_code samba_kdc_lookup_server(krb5_context context,
                free(principal_string);
 
                if (!NT_STATUS_IS_OK(nt_status)) {
-                       return HDB_ERR_NOENTRY;
+                       return SDB_ERR_NOENTRY;
                }
 
                ldb_ret = dsdb_search_one(kdc_db_ctx->samdb,
@@ -1782,10 +1922,10 @@ static krb5_error_code samba_kdc_lookup_server(krb5_context context,
                                          DSDB_SEARCH_SHOW_EXTENDED_DN | DSDB_SEARCH_NO_GLOBAL_CATALOG,
                                          "(objectClass=*)");
                if (ldb_ret != LDB_SUCCESS) {
-                       return HDB_ERR_NOENTRY;
+                       return SDB_ERR_NOENTRY;
                }
                return 0;
-       } else if (!(flags & HDB_F_FOR_AS_REQ)
+       } else if (!(flags & SDB_F_FOR_AS_REQ)
                   && smb_krb5_principal_get_type(context, principal) == KRB5_NT_ENTERPRISE_PRINCIPAL) {
                /*
                 * The behaviour of accepting an
@@ -1889,21 +2029,21 @@ static krb5_error_code samba_kdc_lookup_server(krb5_context context,
                if (lret == LDB_ERR_NO_SUCH_OBJECT) {
                        DEBUG(10, ("Failed to find an entry for %s filter:%s\n",
                                  name1, filter));
-                       return HDB_ERR_NOENTRY;
+                       return SDB_ERR_NOENTRY;
                }
                if (lret == LDB_ERR_CONSTRAINT_VIOLATION) {
                        DEBUG(10, ("Failed to find unique entry for %s filter:%s\n",
                                  name1, filter));
-                       return HDB_ERR_NOENTRY;
+                       return SDB_ERR_NOENTRY;
                }
                if (lret != LDB_SUCCESS) {
                        DEBUG(0, ("Failed single search for %s - %s\n",
                                  name1, ldb_errstring(kdc_db_ctx->samdb)));
-                       return HDB_ERR_NOENTRY;
+                       return SDB_ERR_NOENTRY;
                }
                return 0;
        }
-       return HDB_ERR_NOENTRY;
+       return SDB_ERR_NOENTRY;
 }
 
 
@@ -1913,7 +2053,7 @@ static krb5_error_code samba_kdc_fetch_server(krb5_context context,
                                              TALLOC_CTX *mem_ctx,
                                              krb5_const_principal principal,
                                              unsigned flags,
-                                             hdb_entry_ex *entry_ex)
+                                             struct sdb_entry_ex *entry_ex)
 {
        krb5_error_code ret;
        struct ldb_dn *realm_dn;
@@ -1936,14 +2076,223 @@ static krb5_error_code samba_kdc_fetch_server(krb5_context context,
        return ret;
 }
 
+static krb5_error_code samba_kdc_lookup_realm(krb5_context context,
+                                             struct samba_kdc_db_context *kdc_db_ctx,
+                                             TALLOC_CTX *mem_ctx,
+                                             krb5_const_principal principal,
+                                             unsigned flags,
+                                             struct sdb_entry_ex *entry_ex)
+{
+       TALLOC_CTX *frame = talloc_stackframe();
+       NTSTATUS status;
+       krb5_error_code ret;
+       char *_realm = NULL;
+       bool check_realm = false;
+       const char *realm = NULL;
+       struct dsdb_trust_routing_table *trt = NULL;
+       const struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
+       unsigned int num_comp;
+       bool ok;
+       char *upper = NULL;
+
+       num_comp = krb5_princ_size(context, principal);
+
+       if (flags & SDB_F_GET_CLIENT) {
+               if (flags & SDB_F_FOR_AS_REQ) {
+                       check_realm = true;
+               }
+       }
+       if (flags & SDB_F_GET_SERVER) {
+               if (flags & SDB_F_FOR_TGS_REQ) {
+                       check_realm = true;
+               }
+       }
+
+       if (!check_realm) {
+               TALLOC_FREE(frame);
+               return 0;
+       }
+
+       _realm = smb_krb5_principal_get_realm(context, principal);
+       if (_realm == NULL) {
+               TALLOC_FREE(frame);
+               return ENOMEM;
+       }
+
+       /*
+        * The requested realm needs to be our own
+        */
+       ok = lpcfg_is_my_domain_or_realm(kdc_db_ctx->lp_ctx, _realm);
+       if (!ok) {
+               /*
+                * The request is not for us...
+                */
+               SAFE_FREE(_realm);
+               TALLOC_FREE(frame);
+               return SDB_ERR_NOENTRY;
+       }
+
+       realm = talloc_strdup(frame, _realm);
+       SAFE_FREE(_realm);
+       if (realm == NULL) {
+               TALLOC_FREE(frame);
+               return ENOMEM;
+       }
+
+       if (smb_krb5_principal_get_type(context, principal) == KRB5_NT_ENTERPRISE_PRINCIPAL) {
+               char *principal_string = NULL;
+               krb5_principal enterprise_principal = NULL;
+               char *enterprise_realm = NULL;
+
+               if (num_comp != 1) {
+                       TALLOC_FREE(frame);
+                       return SDB_ERR_NOENTRY;
+               }
+
+               principal_string = smb_krb5_principal_get_comp_string(frame, context,
+                                                                     principal, 0);
+               if (principal_string == NULL) {
+                       TALLOC_FREE(frame);
+                       return ENOMEM;
+               }
+
+               ret = krb5_parse_name(context, principal_string,
+                                     &enterprise_principal);
+               TALLOC_FREE(principal_string);
+               if (ret) {
+                       TALLOC_FREE(frame);
+                       return ret;
+               }
+
+               enterprise_realm = smb_krb5_principal_get_realm(context,
+                                                       enterprise_principal);
+               krb5_free_principal(context, enterprise_principal);
+               if (enterprise_realm != NULL) {
+                       realm = talloc_strdup(frame, enterprise_realm);
+                       SAFE_FREE(enterprise_realm);
+                       if (realm == NULL) {
+                               TALLOC_FREE(frame);
+                               return ENOMEM;
+                       }
+               }
+       }
+
+       if (flags & SDB_F_GET_SERVER) {
+               char *service_realm = NULL;
+
+               ret = principal_comp_strcmp(context, principal, 0, KRB5_TGS_NAME);
+               if (ret == 0) {
+                       /*
+                        * we need to search krbtgt/ locally
+                        */
+                       TALLOC_FREE(frame);
+                       return 0;
+               }
+
+               /*
+                * We need to check the last component against the routing table.
+                *
+                * Note this works only with 2 or 3 component principals, e.g:
+                *
+                * servicePrincipalName: ldap/W2K8R2-219.bla.base
+                * servicePrincipalName: ldap/W2K8R2-219.bla.base/bla.base
+                * servicePrincipalName: ldap/W2K8R2-219.bla.base/ForestDnsZones.bla.base
+                * servicePrincipalName: ldap/W2K8R2-219.bla.base/DomainDnsZones.bla.base
+                */
+
+               if (num_comp == 2 || num_comp == 3) {
+                       service_realm = smb_krb5_principal_get_comp_string(frame,
+                                                                          context,
+                                                                          principal,
+                                                                          num_comp - 1);
+               }
+
+               if (service_realm != NULL) {
+                       realm = service_realm;
+               }
+       }
+
+       ok = lpcfg_is_my_domain_or_realm(kdc_db_ctx->lp_ctx, realm);
+       if (ok) {
+               /*
+                * skip the expensive routing lookup
+                */
+               TALLOC_FREE(frame);
+               return 0;
+       }
+
+       status = dsdb_trust_routing_table_load(kdc_db_ctx->samdb,
+                                              frame, &trt);
+       if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(frame);
+               return EINVAL;
+       }
+
+       tdo = dsdb_trust_routing_by_name(trt, realm);
+       if (tdo == NULL) {
+               /*
+                * This principal has to be local
+                */
+               TALLOC_FREE(frame);
+               return 0;
+       }
+
+       if (tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
+               /*
+                * TODO: handle the routing within the forest
+                *
+                * This should likely be handled in
+                * samba_kdc_message2entry() in case we're
+                * a global catalog. We'd need to check
+                * if realm_dn is our own domain and derive
+                * the dns domain name from realm_dn and check that
+                * against the routing table or fallback to
+                * the tdo we found here.
+                *
+                * But for now we don't support multiple domains
+                * in our forest correctly anyway.
+                *
+                * Just search in our local database.
+                */
+               TALLOC_FREE(frame);
+               return 0;
+       }
+
+       ZERO_STRUCT(entry_ex->entry);
+
+       ret = krb5_copy_principal(context, principal,
+                                 &entry_ex->entry.principal);
+       if (ret) {
+               TALLOC_FREE(frame);
+               return ret;
+       }
+
+       upper = strupper_talloc(frame, tdo->domain_name.string);
+       if (upper == NULL) {
+               TALLOC_FREE(frame);
+               return ENOMEM;
+       }
+
+       ret = smb_krb5_principal_set_realm(context,
+                                          entry_ex->entry.principal,
+                                          upper);
+       if (ret) {
+               TALLOC_FREE(frame);
+               return ret;
+       }
+
+       TALLOC_FREE(frame);
+       return SDB_ERR_WRONG_REALM;
+}
+
 krb5_error_code samba_kdc_fetch(krb5_context context,
                                struct samba_kdc_db_context *kdc_db_ctx,
                                krb5_const_principal principal,
                                unsigned flags,
                                krb5_kvno kvno,
-                               hdb_entry_ex *entry_ex)
+                               struct sdb_entry_ex *entry_ex)
 {
-       krb5_error_code ret = HDB_ERR_NOENTRY;
+       krb5_error_code ret = SDB_ERR_NOENTRY;
        TALLOC_CTX *mem_ctx;
 
        mem_ctx = talloc_named(kdc_db_ctx, 0, "samba_kdc_fetch context");
@@ -1953,22 +2302,30 @@ krb5_error_code samba_kdc_fetch(krb5_context context,
                return ret;
        }
 
-       if (flags & HDB_F_GET_CLIENT) {
+       ret = samba_kdc_lookup_realm(context, kdc_db_ctx, mem_ctx,
+                                    principal, flags, entry_ex);
+       if (ret != 0) {
+               goto done;
+       }
+
+       ret = SDB_ERR_NOENTRY;
+
+       if (flags & SDB_F_GET_CLIENT) {
                ret = samba_kdc_fetch_client(context, kdc_db_ctx, mem_ctx, principal, flags, entry_ex);
-               if (ret != HDB_ERR_NOENTRY) goto done;
+               if (ret != SDB_ERR_NOENTRY) goto done;
        }
-       if (flags & HDB_F_GET_SERVER) {
+       if (flags & SDB_F_GET_SERVER) {
                /* krbtgt fits into this situation for trusted realms, and for resolving different versions of our own realm name */
                ret = samba_kdc_fetch_krbtgt(context, kdc_db_ctx, mem_ctx, principal, flags, kvno, entry_ex);
-               if (ret != HDB_ERR_NOENTRY) goto done;
+               if (ret != SDB_ERR_NOENTRY) goto done;
 
                /* We return 'no entry' if it does not start with krbtgt/, so move to the common case quickly */
                ret = samba_kdc_fetch_server(context, kdc_db_ctx, mem_ctx, principal, flags, entry_ex);
-               if (ret != HDB_ERR_NOENTRY) goto done;
+               if (ret != SDB_ERR_NOENTRY) goto done;
        }
-       if (flags & HDB_F_GET_KRBTGT) {
+       if (flags & SDB_F_GET_KRBTGT) {
                ret = samba_kdc_fetch_krbtgt(context, kdc_db_ctx, mem_ctx, principal, flags, kvno, entry_ex);
-               if (ret != HDB_ERR_NOENTRY) goto done;
+               if (ret != SDB_ERR_NOENTRY) goto done;
        }
 
 done:
@@ -1985,7 +2342,7 @@ struct samba_kdc_seq {
 
 static krb5_error_code samba_kdc_seq(krb5_context context,
                                     struct samba_kdc_db_context *kdc_db_ctx,
-                                    hdb_entry_ex *entry)
+                                    struct sdb_entry_ex *entry)
 {
        krb5_error_code ret;
        struct samba_kdc_seq *priv = kdc_db_ctx->seq_ctx;
@@ -1996,7 +2353,7 @@ static krb5_error_code samba_kdc_seq(krb5_context context,
        TALLOC_CTX *mem_ctx;
 
        if (!priv) {
-               return HDB_ERR_NOENTRY;
+               return SDB_ERR_NOENTRY;
        }
 
        mem_ctx = talloc_named(priv, 0, "samba_kdc_seq context");
@@ -2017,7 +2374,7 @@ static krb5_error_code samba_kdc_seq(krb5_context context,
        }
 
        if (sAMAccountName == NULL) {
-               ret = HDB_ERR_NOENTRY;
+               ret = SDB_ERR_NOENTRY;
                goto out;
        }
 
@@ -2029,7 +2386,7 @@ static krb5_error_code samba_kdc_seq(krb5_context context,
 
        ret = samba_kdc_message2entry(context, kdc_db_ctx, mem_ctx,
                                      principal, SAMBA_KDC_ENT_TYPE_ANY,
-                                     HDB_F_ADMIN_DATA|HDB_F_GET_ANY,
+                                     SDB_F_ADMIN_DATA|SDB_F_GET_ANY,
                                      priv->realm_dn, msg, entry);
 
 out:
@@ -2049,7 +2406,7 @@ out:
 
 krb5_error_code samba_kdc_firstkey(krb5_context context,
                                   struct samba_kdc_db_context *kdc_db_ctx,
-                                  hdb_entry_ex *entry)
+                                  struct sdb_entry_ex *entry)
 {
        struct ldb_context *ldb_ctx = kdc_db_ctx->samdb;
        struct samba_kdc_seq *priv = kdc_db_ctx->seq_ctx;
@@ -2098,7 +2455,7 @@ krb5_error_code samba_kdc_firstkey(krb5_context context,
 
        if (lret != LDB_SUCCESS) {
                TALLOC_FREE(priv);
-               return HDB_ERR_NOENTRY;
+               return SDB_ERR_NOENTRY;
        }
 
        priv->count = res->count;
@@ -2120,7 +2477,7 @@ krb5_error_code samba_kdc_firstkey(krb5_context context,
 
 krb5_error_code samba_kdc_nextkey(krb5_context context,
                                  struct samba_kdc_db_context *kdc_db_ctx,
-                                 hdb_entry_ex *entry)
+                                 struct sdb_entry_ex *entry)
 {
        return samba_kdc_seq(context, kdc_db_ctx, entry);
 }
@@ -2153,7 +2510,7 @@ samba_kdc_check_s4u2self(krb5_context context,
        }
 
        ret = samba_kdc_lookup_server(context, kdc_db_ctx, mem_ctx, target_principal,
-                                     HDB_F_GET_CLIENT|HDB_F_GET_SERVER,
+                                     SDB_F_GET_CLIENT|SDB_F_GET_SERVER,
                                      delegation_check_attrs, &realm_dn, &msg);
 
        if (ret != 0) {
@@ -2370,6 +2727,7 @@ NTSTATUS samba_kdc_setup_db_ctx(TALLOC_CTX *mem_ctx, struct samba_kdc_base_conte
        }
        kdc_db_ctx->ev_ctx = base_ctx->ev_ctx;
        kdc_db_ctx->lp_ctx = base_ctx->lp_ctx;
+       kdc_db_ctx->msg_ctx = base_ctx->msg_ctx;
 
        /* get default kdc policy */
        lpcfg_default_kdc_policy(base_ctx->lp_ctx,