s4-kdc Fix the realm handling again, this time pay attention to the flags
[samba.git] / source4 / kdc / db-glue.c
index 2cda04bca8fcc143f57ca48d44a53a92a4616b3b..b062282c289a449e223892a6fc4b85da3a70b19b 100644 (file)
@@ -30,7 +30,6 @@
 #include "auth/auth.h"
 #include "auth/credentials/credentials.h"
 #include "auth/auth_sam.h"
-#include "../lib/util/util_ldb.h"
 #include "dsdb/samdb/samdb.h"
 #include "dsdb/common/util.h"
 #include "librpc/ndr/libndr.h"
@@ -85,7 +84,7 @@ static KerberosTime ldb_msg_find_krb5time_ldap_time(struct ldb_message *msg, con
     return timegm(&tm);
 }
 
-static HDBFlags uf2HDBFlags(krb5_context context, int userAccountControl, enum samba_kdc_ent_type ent_type)
+static HDBFlags uf2HDBFlags(krb5_context context, uint32_t userAccountControl, enum samba_kdc_ent_type ent_type)
 {
        HDBFlags flags = int2HDBFlags(0);
 
@@ -193,10 +192,12 @@ static void samba_kdc_free_entry(krb5_context context, hdb_entry_ex *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,
                                                    struct ldb_message *msg,
                                                    uint32_t rid,
-                                                   unsigned int userAccountControl,
+                                                   bool is_rodc,
+                                                   uint32_t userAccountControl,
                                                    enum samba_kdc_ent_type ent_type,
                                                    hdb_entry_ex *entry_ex)
 {
@@ -213,25 +214,39 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context,
        uint16_t i;
        uint16_t allocated_keys = 0;
        int rodc_krbtgt_number = 0;
-       bool is_rodc = false;
-
-       /* Supported Enc for this entry */
-       uint32_t supported_enctypes = ENC_ALL_TYPES; /* by default, we support all enc types */
+       uint32_t supported_enctypes;
 
-       /* However, if this is a TGS-REQ, then lock it down to a
-        * reasonable guess as to what the server can decode.  The
-        * krbtgt is special - default to use what is stored for the KDC */
-       if (rid != DOMAIN_RID_KRBTGT && ent_type == SAMBA_KDC_ENT_TYPE_SERVER) {
-               /* This is the standard set for a server that has not declared a msDS-SupportedEncryptionTypes */
-               supported_enctypes = ENC_CRC32 | ENC_RSA_MD5 | ENC_RC4_HMAC_MD5;
+       if (rid == DOMAIN_RID_KRBTGT || is_rodc) {
+               /* KDCs (and KDCs on RODCs) use AES, but not DES */
+               supported_enctypes = ENC_ALL_TYPES;
+               supported_enctypes &= ~(ENC_CRC32|ENC_RSA_MD5);
+       } else if (userAccountControl & (UF_PARTIAL_SECRETS_ACCOUNT|UF_SERVER_TRUST_ACCOUNT)) {
+               /* DCs and RODCs comptuer accounts use AES */
+               supported_enctypes = ENC_ALL_TYPES;
+       } else if (ent_type == SAMBA_KDC_ENT_TYPE_CLIENT ||
+                  (ent_type == SAMBA_KDC_ENT_TYPE_ANY)) {
+               /* for AS-REQ the client chooses the enc types it
+                * supports, and this will vary between computers a
+                * user logs in from.  However, some accounts may be
+                * banned from using DES, so allow the default to be
+                * overridden
+                *
+                * likewise for 'any' return as much as is supported,
+                * to export into a keytab */
+               supported_enctypes = ldb_msg_find_attr_as_uint(msg, "msDS-SupportedEncryptionTypes",
+                                                              ENC_ALL_TYPES);
+       } else {
+               /* However, if this is a TGS-REQ, then lock it down to
+                * a reasonable guess as to what the server can decode
+                * - we must use whatever is in
+                * "msDS-SupportedEncryptionTypes", or the 'old' set
+                * of keys (ie, what Windows 2000 supported) */
+               supported_enctypes = ldb_msg_find_attr_as_uint(msg, "msDS-SupportedEncryptionTypes",
+                                                              ENC_CRC32 | ENC_RSA_MD5 | ENC_RC4_HMAC_MD5);
        }
-       supported_enctypes = ldb_msg_find_attr_as_uint(msg, "msDS-SupportedEncryptionTypes",
-                                                       supported_enctypes);
-       /* Is this the krbtgt or a RODC */
-
-       if (ldb_msg_find_element(msg, "msDS-SecondaryKrbTgtNumber")) {
-               is_rodc = true;
 
+       /* Is this the krbtgt or a RODC krbtgt */
+       if (is_rodc) {
                rodc_krbtgt_number = ldb_msg_find_attr_as_int(msg, "msDS-SecondaryKrbTgtNumber", -1);
 
                if (rodc_krbtgt_number == -1) {
@@ -239,26 +254,25 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context,
                }
        }
 
-       if (rid == DOMAIN_RID_KRBTGT || is_rodc) {
-               /* Be double-sure never to use DES here */
-               supported_enctypes &= ~(ENC_CRC32|ENC_RSA_MD5);
-       }
-
-       switch (ent_type) {
-       case SAMBA_KDC_ENT_TYPE_KRBTGT:
-       case SAMBA_KDC_ENT_TYPE_TRUST:
-               /* Disallow krbtgt and trust tickets to be DES encrypted, it's just too dangerous */
-               supported_enctypes &= ~(ENC_CRC32|ENC_RSA_MD5);
-               break;
-       default:
-               break;
-               /* No further restrictions */
-       }
 
        /* 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) {
-               /* However, don't allow use of DES, if we were told not to by msDS-SupportedEncTypes */
+               /* However, this still won't allow use of DES, if we
+                * were told not to by msDS-SupportedEncTypes */
                supported_enctypes &= ENC_CRC32|ENC_RSA_MD5;
+       } else {
+               switch (ent_type) {
+               case SAMBA_KDC_ENT_TYPE_KRBTGT:
+               case SAMBA_KDC_ENT_TYPE_TRUST:
+                       /* Unless a very special effort it made,
+                        * disallow trust tickets to be DES encrypted,
+                        * it's just too dangerous */
+                       supported_enctypes &= ~(ENC_CRC32|ENC_RSA_MD5);
+                       break;
+               default:
+                       break;
+                       /* No further restrictions */
+               }
        }
 
        entry_ex->entry.keys.val = NULL;
@@ -363,6 +377,11 @@ 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 */
+                       return HDB_ERR_NOT_FOUND_HERE;
+               }
+
                /* oh, no password.  Apparently (comment in
                 * hdb-ldap.c) this violates the ASN.1, but this
                 * allows an entry with no keys (yet). */
@@ -522,31 +541,36 @@ out:
  * Construct an hdb_entry from a directory entry.
  */
 static krb5_error_code samba_kdc_message2entry(krb5_context context,
-                                        struct samba_kdc_db_context *kdc_db_ctx,
-                                        TALLOC_CTX *mem_ctx, krb5_const_principal principal,
-                                        enum samba_kdc_ent_type ent_type,
-                                        struct ldb_dn *realm_dn,
-                                        struct ldb_message *msg,
-                                        hdb_entry_ex *entry_ex)
+                                              struct samba_kdc_db_context *kdc_db_ctx,
+                                              TALLOC_CTX *mem_ctx, krb5_const_principal principal,
+                                              enum samba_kdc_ent_type ent_type,
+                                              unsigned flags,
+                                              struct ldb_dn *realm_dn,
+                                              struct ldb_message *msg,
+                                              hdb_entry_ex *entry_ex)
 {
        struct loadparm_context *lp_ctx = kdc_db_ctx->lp_ctx;
-       unsigned int userAccountControl;
+       uint32_t userAccountControl;
        unsigned int i;
        krb5_error_code ret = 0;
        krb5_boolean is_computer = FALSE;
-       char *realm = strupper_talloc(mem_ctx, lpcfg_realm(lp_ctx));
 
        struct samba_kdc_entry *p;
        NTTIME acct_expiry;
        NTSTATUS status;
 
        uint32_t rid;
+       bool is_rodc = false;
        struct ldb_message_element *objectclasses;
        struct ldb_val computer_val;
        const char *samAccountName = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL);
        computer_val.data = discard_const_p(uint8_t,"computer");
        computer_val.length = strlen((const char *)computer_val.data);
 
+       if (ldb_msg_find_element(msg, "msDS-SecondaryKrbTgtNumber")) {
+               is_rodc = true;
+       }
+
        if (!samAccountName) {
                ret = ENOENT;
                krb5_set_error_message(context, ret, "samba_kdc_message2entry: no samAccountName present");
@@ -561,12 +585,6 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
 
        memset(entry_ex, 0, sizeof(*entry_ex));
 
-       if (!realm) {
-               ret = ENOMEM;
-               krb5_set_error_message(context, ret, "talloc_strdup: out of memory");
-               goto out;
-       }
-
        p = talloc(mem_ctx, struct samba_kdc_entry);
        if (!p) {
                ret = ENOMEM;
@@ -594,7 +612,7 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
 
        entry_ex->entry.principal = malloc(sizeof(*(entry_ex->entry.principal)));
        if (ent_type == SAMBA_KDC_ENT_TYPE_ANY && principal == NULL) {
-               krb5_make_principal(context, &entry_ex->entry.principal, realm, samAccountName, NULL);
+               krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL);
        } else {
                ret = copy_Principal(principal, entry_ex->entry.principal);
                if (ret) {
@@ -609,7 +627,7 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
                 * we determine from our records */
 
                /* this has to be with malloc() */
-               krb5_principal_set_realm(context, entry_ex->entry.principal, realm);
+               krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx));
        }
 
        /* First try and figure out the flags based on the userAccountControl */
@@ -627,7 +645,7 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
                }
        }
 
-       {
+       if (flags & HDB_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
@@ -638,7 +656,7 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
                /* use 'kadmin' for now (needed by mit_samba) */
                krb5_make_principal(context,
                                    &entry_ex->entry.created_by.principal,
-                                   realm, "kadmin", NULL);
+                                   lpcfg_realm(lp_ctx), "kadmin", NULL);
 
                entry_ex->entry.modified_by = (Event *) malloc(sizeof(Event));
                if (entry_ex->entry.modified_by == NULL) {
@@ -652,7 +670,7 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
                /* use 'kadmin' for now (needed by mit_samba) */
                krb5_make_principal(context,
                                    &entry_ex->entry.modified_by->principal,
-                                   realm, "kadmin", NULL);
+                                   lpcfg_realm(lp_ctx), "kadmin", NULL);
        }
 
 
@@ -686,6 +704,22 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
                entry_ex->entry.flags.client = 0;
                entry_ex->entry.flags.forwardable = 1;
                entry_ex->entry.flags.ok_as_delegate = 1;
+       } else if (is_rodc) {
+               /* The RODC krbtgt account is like the main krbtgt,
+                * but it does not have a changepw or kadmin
+                * service */
+
+               entry_ex->entry.valid_end = NULL;
+               entry_ex->entry.pw_end = NULL;
+
+               /* Also don't allow the RODC krbtgt to be a client (it should not be needed) */
+               entry_ex->entry.flags.client = 0;
+               entry_ex->entry.flags.invalid = 0;
+               entry_ex->entry.flags.server = 1;
+
+               entry_ex->entry.flags.client = 0;
+               entry_ex->entry.flags.forwardable = 1;
+               entry_ex->entry.flags.ok_as_delegate = 0;
        } else if (entry_ex->entry.flags.server && ent_type == SAMBA_KDC_ENT_TYPE_SERVER) {
                /* The account/password expiry only applies when the account is used as a
                 * client (ie password login), not when used as a server */
@@ -734,8 +768,8 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
        entry_ex->entry.generation = NULL;
 
        /* Get keys from the db */
-       ret = samba_kdc_message2entry_keys(context, p, msg, 
-                                          rid, userAccountControl,
+       ret = samba_kdc_message2entry_keys(context, kdc_db_ctx, p, msg,
+                                          rid, is_rodc, userAccountControl,
                                           ent_type, entry_ex);
        if (ret) {
                /* Could be bougus data in the entry, or out of memory */
@@ -786,7 +820,7 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context,
 {
        struct loadparm_context *lp_ctx = kdc_db_ctx->lp_ctx;
        const char *dnsdomain;
-       char *realm = strupper_talloc(mem_ctx, lpcfg_realm(lp_ctx));
+       const char *realm = lpcfg_realm(lp_ctx);
        DATA_BLOB password_utf16;
        struct samr_Password password_hash;
        const struct ldb_val *password_val;
@@ -832,7 +866,6 @@ static krb5_error_code samba_kdc_trust_message2entry(krb5_context context,
        } else { /* OUTBOUND */
                dnsdomain = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
                /* replace realm */
-               talloc_free(realm);
                realm = strupper_talloc(mem_ctx, dnsdomain);
                password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
        }
@@ -1030,6 +1063,7 @@ static krb5_error_code samba_kdc_fetch_client(krb5_context context,
                                               struct samba_kdc_db_context *kdc_db_ctx,
                                               TALLOC_CTX *mem_ctx,
                                               krb5_const_principal principal,
+                                              unsigned flags,
                                               hdb_entry_ex *entry_ex) {
        struct ldb_dn *realm_dn;
        krb5_error_code ret;
@@ -1043,16 +1077,19 @@ static krb5_error_code samba_kdc_fetch_client(krb5_context context,
        }
 
        ret = samba_kdc_message2entry(context, kdc_db_ctx, mem_ctx,
-                                      principal, SAMBA_KDC_ENT_TYPE_CLIENT,
-                                      realm_dn, msg, entry_ex);
+                                     principal, SAMBA_KDC_ENT_TYPE_CLIENT,
+                                     flags,
+                                     realm_dn, msg, entry_ex);
        return ret;
 }
 
 static krb5_error_code samba_kdc_fetch_krbtgt(krb5_context context,
-                                       struct samba_kdc_db_context *kdc_db_ctx,
-                                       TALLOC_CTX *mem_ctx,
-                                       krb5_const_principal principal,
-                                       hdb_entry_ex *entry_ex)
+                                             struct samba_kdc_db_context *kdc_db_ctx,
+                                             TALLOC_CTX *mem_ctx,
+                                             krb5_const_principal principal,
+                                             unsigned flags,
+                                             uint32_t krbtgt_number,
+                                             hdb_entry_ex *entry_ex)
 {
        struct loadparm_context *lp_ctx = kdc_db_ctx->lp_ctx;
        krb5_error_code ret;
@@ -1070,54 +1107,71 @@ static krb5_error_code samba_kdc_fetch_krbtgt(krb5_context context,
 
        if (lpcfg_is_my_domain_or_realm(lp_ctx, principal->realm)
            && lpcfg_is_my_domain_or_realm(lp_ctx, principal->name.name_string.val[1])) {
-               /* us */
+               /* us, or someone quite like us */
                /* Cludge, cludge cludge.  If the realm part of krbtgt/realm,
                 * is in our db, then direct the caller at our primary
                 * krbtgt */
 
                int lret;
-               char *realm_fixed;
 
-               lret = dsdb_search_one(kdc_db_ctx->samdb, mem_ctx,
-                                      &msg, realm_dn, LDB_SCOPE_SUBTREE,
-                                      krbtgt_attrs,
-                                      DSDB_SEARCH_SHOW_EXTENDED_DN,
-                                      "(&(objectClass=user)(samAccountName=krbtgt))");
+               if (krbtgt_number == kdc_db_ctx->my_krbtgt_number) {
+                       lret = dsdb_search_one(kdc_db_ctx->samdb, mem_ctx,
+                                              &msg, kdc_db_ctx->krbtgt_dn, LDB_SCOPE_BASE,
+                                              krbtgt_attrs, 0,
+                                              "(objectClass=user)");
+               } else {
+                       /* We need to look up an RODC krbtgt (perhaps
+                        * ours, if we are an RODC, perhaps another
+                        * RODC if we are a read-write DC */
+                       lret = dsdb_search_one(kdc_db_ctx->samdb, mem_ctx,
+                                              &msg, realm_dn, LDB_SCOPE_SUBTREE,
+                                              krbtgt_attrs,
+                                              DSDB_SEARCH_SHOW_EXTENDED_DN,
+                                              "(&(objectClass=user)(msDS-SecondaryKrbTgtNumber=%u))", (unsigned)(krbtgt_number));
+               }
+
                if (lret == LDB_ERR_NO_SUCH_OBJECT) {
-                       krb5_warnx(context, "samba_kdc_fetch: could not find own KRBTGT in DB!");
-                       krb5_set_error_message(context, HDB_ERR_NOENTRY, "samba_kdc_fetch: could not find own KRBTGT in DB!");
+                       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,
+                                              "samba_kdc_fetch: could not find KRBTGT number %u in DB!",
+                                              (unsigned)(krbtgt_number));
                        return HDB_ERR_NOENTRY;
                } else if (lret != LDB_SUCCESS) {
-                       krb5_warnx(context, "samba_kdc_fetch: could not find own KRBTGT in DB: %s", ldb_errstring(kdc_db_ctx->samdb));
-                       krb5_set_error_message(context, HDB_ERR_NOENTRY, "samba_kdc_fetch: could not find own KRBTGT in DB: %s", ldb_errstring(kdc_db_ctx->samdb));
+                       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,
+                                              "samba_kdc_fetch: could not find KRBTGT number %u in DB!",
+                                              (unsigned)(krbtgt_number));
                        return HDB_ERR_NOENTRY;
                }
 
-               realm_fixed = strupper_talloc(mem_ctx, lpcfg_realm(lp_ctx));
-               if (!realm_fixed) {
-                       ret = ENOMEM;
-                       krb5_set_error_message(context, ret, "strupper_talloc: out of memory");
-                       return ret;
-               }
-
-               ret = krb5_copy_principal(context, principal, &alloc_principal);
-               if (ret) {
-                       return ret;
-               }
-
-               free(alloc_principal->name.name_string.val[1]);
-               alloc_principal->name.name_string.val[1] = strdup(realm_fixed);
-               talloc_free(realm_fixed);
-               if (!alloc_principal->name.name_string.val[1]) {
-                       ret = ENOMEM;
-                       krb5_set_error_message(context, ret, "samba_kdc_fetch: strdup() failed!");
-                       return ret;
-               }
-               principal = alloc_principal;
+               if (flags & HDB_F_CANON) {
+                       ret = krb5_copy_principal(context, principal, &alloc_principal);
+                       if (ret) {
+                               return ret;
+                       }
+
+                       /* When requested to do so, ensure that the
+                        * both realm values in the principal are set
+                        * to the upper case, canonical realm */
+                       free(alloc_principal->name.name_string.val[1]);
+                       alloc_principal->name.name_string.val[1] = strdup(lpcfg_realm(lp_ctx));
+                       if (!alloc_principal->name.name_string.val[1]) {
+                               ret = ENOMEM;
+                               krb5_set_error_message(context, ret, "samba_kdc_fetch: strdup() failed!");
+                               return ret;
+                       }
+                       principal = alloc_principal;
+               }
 
                ret = samba_kdc_message2entry(context, kdc_db_ctx, mem_ctx,
-                                       principal, SAMBA_KDC_ENT_TYPE_KRBTGT,
-                                       realm_dn, msg, entry_ex);
+                                             principal, SAMBA_KDC_ENT_TYPE_KRBTGT,
+                                             flags, realm_dn, msg, entry_ex);
+               if (flags & HDB_F_CANON) {
+                       /* This is again copied in the message2entry call */
+                       krb5_free_principal(context, alloc_principal);
+               }
                if (ret != 0) {
                        krb5_warnx(context, "samba_kdc_fetch: self krbtgt message2entry failed");
                }
@@ -1177,7 +1231,6 @@ static krb5_error_code samba_kdc_lookup_server(krb5_context context,
                                                struct ldb_message **msg)
 {
        krb5_error_code ret;
-       const char *realm;
        if (principal->name.name_string.len >= 2) {
                /* 'normal server' case */
                int ldb_ret;
@@ -1216,6 +1269,7 @@ static krb5_error_code samba_kdc_lookup_server(krb5_context context,
                int lret;
                char *filter = NULL;
                char *short_princ;
+               const char *realm;
                /* server as client principal case, but we must not lookup userPrincipalNames */
                *realm_dn = ldb_get_default_basedn(kdc_db_ctx->samdb);
                realm = krb5_principal_get_realm(context, principal);
@@ -1252,10 +1306,11 @@ static krb5_error_code samba_kdc_lookup_server(krb5_context context,
 }
 
 static krb5_error_code samba_kdc_fetch_server(krb5_context context,
-                                              struct samba_kdc_db_context *kdc_db_ctx,
-                                              TALLOC_CTX *mem_ctx,
-                                              krb5_const_principal principal,
-                                              hdb_entry_ex *entry_ex)
+                                             struct samba_kdc_db_context *kdc_db_ctx,
+                                             TALLOC_CTX *mem_ctx,
+                                             krb5_const_principal principal,
+                                             unsigned flags,
+                                             hdb_entry_ex *entry_ex)
 {
        krb5_error_code ret;
        struct ldb_dn *realm_dn;
@@ -1268,8 +1323,9 @@ static krb5_error_code samba_kdc_fetch_server(krb5_context context,
        }
 
        ret = samba_kdc_message2entry(context, kdc_db_ctx, mem_ctx,
-                               principal, SAMBA_KDC_ENT_TYPE_SERVER,
-                               realm_dn, msg, entry_ex);
+                                     principal, SAMBA_KDC_ENT_TYPE_SERVER,
+                                     flags,
+                                     realm_dn, msg, entry_ex);
        if (ret != 0) {
                krb5_warnx(context, "samba_kdc_fetch: message2entry failed");
        }
@@ -1281,11 +1337,24 @@ krb5_error_code samba_kdc_fetch(krb5_context context,
                                struct samba_kdc_db_context *kdc_db_ctx,
                                krb5_const_principal principal,
                                unsigned flags,
+                               unsigned kvno,
                                hdb_entry_ex *entry_ex)
 {
        krb5_error_code ret = HDB_ERR_NOENTRY;
-       TALLOC_CTX *mem_ctx = talloc_named(kdc_db_ctx, 0, "samba_kdc_fetch context");
+       TALLOC_CTX *mem_ctx;
+       unsigned int krbtgt_number;
+       if (flags & HDB_F_KVNO_SPECIFIED) {
+               krbtgt_number = kvno >> 16;
+               if (kdc_db_ctx->rodc) {
+                       if (krbtgt_number != kdc_db_ctx->my_krbtgt_number) {
+                               return HDB_ERR_NOT_FOUND_HERE;
+                       }
+               }
+       } else {
+               krbtgt_number = kdc_db_ctx->my_krbtgt_number;
+       }
 
+       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!");
@@ -1293,20 +1362,20 @@ krb5_error_code samba_kdc_fetch(krb5_context context,
        }
 
        if (flags & HDB_F_GET_CLIENT) {
-               ret = samba_kdc_fetch_client(context, kdc_db_ctx, mem_ctx, principal, entry_ex);
+               ret = samba_kdc_fetch_client(context, kdc_db_ctx, mem_ctx, principal, flags, entry_ex);
                if (ret != HDB_ERR_NOENTRY) goto done;
        }
        if (flags & HDB_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, entry_ex);
+               ret = samba_kdc_fetch_krbtgt(context, kdc_db_ctx, mem_ctx, principal, flags, krbtgt_number, entry_ex);
                if (ret != HDB_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, entry_ex);
+               ret = samba_kdc_fetch_server(context, kdc_db_ctx, mem_ctx, principal, flags, entry_ex);
                if (ret != HDB_ERR_NOENTRY) goto done;
        }
        if (flags & HDB_F_GET_KRBTGT) {
-               ret = samba_kdc_fetch_krbtgt(context, kdc_db_ctx, mem_ctx, principal, entry_ex);
+               ret = samba_kdc_fetch_krbtgt(context, kdc_db_ctx, mem_ctx, principal, flags, krbtgt_number, entry_ex);
                if (ret != HDB_ERR_NOENTRY) goto done;
        }
 
@@ -1346,8 +1415,9 @@ static krb5_error_code samba_kdc_seq(krb5_context context,
 
        if (priv->index < priv->count) {
                ret = samba_kdc_message2entry(context, kdc_db_ctx, mem_ctx,
-                                       NULL, SAMBA_KDC_ENT_TYPE_ANY,
-                                       priv->realm_dn, priv->msgs[priv->index++], entry);
+                                             NULL, SAMBA_KDC_ENT_TYPE_ANY,
+                                             HDB_F_ADMIN_DATA|HDB_F_GET_ANY,
+                                             priv->realm_dn, priv->msgs[priv->index++], entry);
        } else {
                ret = HDB_ERR_NOENTRY;
        }
@@ -1568,7 +1638,6 @@ samba_kdc_check_pkinit_ms_upn_match(krb5_context context,
 NTSTATUS samba_kdc_setup_db_ctx(TALLOC_CTX *mem_ctx, struct samba_kdc_base_context *base_ctx,
                                struct samba_kdc_db_context **kdc_db_ctx_out)
 {
-       NTSTATUS nt_status;
        int ldb_ret;
        struct ldb_message *msg;
        struct auth_session_info *session_info;
@@ -1588,30 +1657,14 @@ 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;
 
-#if 1
-       /* we would prefer to use system_session(), as that would
-        * allow us to share the samdb backend context with other parts of the
-        * system. For now we can't as we need to override the
-        * credentials to set CRED_DONT_USE_KERBEROS, which would
-        * break other users of the system_session */
-       DEBUG(0,("FIXME: Using new system session for hdb\n"));
-       nt_status = auth_system_session_info(kdc_db_ctx, base_ctx->lp_ctx, &session_info);
-       if (!NT_STATUS_IS_OK(nt_status)) {
-              return nt_status;
-       }
-#else
        session_info = system_session(kdc_db_ctx->lp_ctx);
        if (session_info == NULL) {
                return NT_STATUS_INTERNAL_ERROR;
        }
-#endif
-
-       cli_credentials_set_kerberos_state(session_info->credentials,
-                                          CRED_DONT_USE_KERBEROS);
 
        /* Setup the link to LDB */
        kdc_db_ctx->samdb = samdb_connect(kdc_db_ctx, base_ctx->ev_ctx,
-                                         base_ctx->lp_ctx, session_info);
+                                         base_ctx->lp_ctx, session_info, 0);
        if (kdc_db_ctx->samdb == NULL) {
                DEBUG(1, ("hdb_samba4_create: Cannot open samdb for KDC backend!"));
                talloc_free(kdc_db_ctx);