LCOV - code coverage report
Current view: top level - source4/kdc - db-glue.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 1409 1929 73.0 %
Date: 2024-05-31 13:13:24 Functions: 37 37 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Database Glue between Samba and the KDC
       5             : 
       6             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2009
       7             :    Copyright (C) Simo Sorce <idra@samba.org> 2010
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             : 
      20             :    You should have received a copy of the GNU General Public License
      21             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : #include "includes.h"
      25             : #include "libcli/security/security.h"
      26             : #include "librpc/gen_ndr/ndr_security.h"
      27             : #include "auth/auth.h"
      28             : #include "auth/auth_sam.h"
      29             : #include "dsdb/gmsa/util.h"
      30             : #include "dsdb/samdb/samdb.h"
      31             : #include "dsdb/common/util.h"
      32             : #include "librpc/gen_ndr/ndr_drsblobs.h"
      33             : #include "param/param.h"
      34             : #include "param/secrets.h"
      35             : #include "lib/crypto/gkdi.h"
      36             : #include "../lib/crypto/md4.h"
      37             : #include "lib/util/memory.h"
      38             : #include "system/kerberos.h"
      39             : #include "auth/kerberos/kerberos.h"
      40             : #include "kdc/authn_policy_util.h"
      41             : #include "kdc/sdb.h"
      42             : #include "kdc/samba_kdc.h"
      43             : #include "kdc/db-glue.h"
      44             : #include "kdc/pac-glue.h"
      45             : #include "librpc/gen_ndr/ndr_irpc_c.h"
      46             : #include "lib/messaging/irpc.h"
      47             : 
      48             : #undef DBGC_CLASS
      49             : #define DBGC_CLASS DBGC_KERBEROS
      50             : 
      51             : #undef strcasecmp
      52             : #undef strncasecmp
      53             : 
      54             : #define SAMBA_KVNO_GET_KRBTGT(kvno) \
      55             :         ((uint16_t)(((uint32_t)kvno) >> 16))
      56             : 
      57             : #define SAMBA_KVNO_GET_VALUE(kvno) \
      58             :         ((uint16_t)(((uint32_t)kvno) & 0xFFFF))
      59             : 
      60             : #define SAMBA_KVNO_AND_KRBTGT(kvno, krbtgt) \
      61             :         ((krb5_kvno)((((uint32_t)kvno) & 0xFFFF) | \
      62             :          ((((uint32_t)krbtgt) << 16) & 0xFFFF0000)))
      63             : 
      64             : enum trust_direction {
      65             :         UNKNOWN = 0,
      66             :         INBOUND = LSA_TRUST_DIRECTION_INBOUND,
      67             :         OUTBOUND = LSA_TRUST_DIRECTION_OUTBOUND
      68             : };
      69             : 
      70             : static const char *trust_attrs[] = {
      71             :         "securityIdentifier",
      72             :         "flatName",
      73             :         "trustPartner",
      74             :         "trustAttributes",
      75             :         "trustDirection",
      76             :         "trustType",
      77             :         "msDS-TrustForestTrustInfo",
      78             :         "trustAuthIncoming",
      79             :         "trustAuthOutgoing",
      80             :         "whenCreated",
      81             :         "msDS-SupportedEncryptionTypes",
      82             :         NULL
      83             : };
      84             : 
      85             : /*
      86             :   send a message to the drepl server telling it to initiate a
      87             :   REPL_SECRET getncchanges extended op to fetch the users secrets
      88             :  */
      89        1670 : static void auth_sam_trigger_repl_secret(TALLOC_CTX *mem_ctx,
      90             :                                   struct imessaging_context *msg_ctx,
      91             :                                   struct tevent_context *event_ctx,
      92             :                                   struct ldb_dn *user_dn)
      93             : {
      94           0 :         struct dcerpc_binding_handle *irpc_handle;
      95           0 :         struct drepl_trigger_repl_secret r;
      96           0 :         struct tevent_req *req;
      97           0 :         TALLOC_CTX *tmp_ctx;
      98             : 
      99        1670 :         tmp_ctx = talloc_new(mem_ctx);
     100        1670 :         if (tmp_ctx == NULL) {
     101           0 :                 return;
     102             :         }
     103             : 
     104        1670 :         irpc_handle = irpc_binding_handle_by_name(tmp_ctx, msg_ctx,
     105             :                                                   "dreplsrv",
     106             :                                                   &ndr_table_irpc);
     107        1670 :         if (irpc_handle == NULL) {
     108           0 :                 DBG_WARNING("Unable to get binding handle for dreplsrv\n");
     109           0 :                 TALLOC_FREE(tmp_ctx);
     110           0 :                 return;
     111             :         }
     112             : 
     113        1670 :         r.in.user_dn = ldb_dn_get_linearized(user_dn);
     114        1670 :         if (r.in.user_dn == NULL) {
     115           0 :                 DBG_WARNING("Unable to get user DN\n");
     116           0 :                 TALLOC_FREE(tmp_ctx);
     117           0 :                 return;
     118             :         }
     119             : 
     120             :         /*
     121             :          * This seem to rely on the current IRPC implementation,
     122             :          * which delivers the message in the _send function.
     123             :          *
     124             :          * TODO: we need a ONE_WAY IRPC handle and register
     125             :          * a callback and wait for it to be triggered!
     126             :          */
     127        1670 :         req = dcerpc_drepl_trigger_repl_secret_r_send(tmp_ctx,
     128             :                                                       event_ctx,
     129             :                                                       irpc_handle,
     130             :                                                       &r);
     131             : 
     132             :         /* we aren't interested in a reply */
     133        1670 :         talloc_free(req);
     134        1670 :         TALLOC_FREE(tmp_ctx);
     135             : }
     136             : 
     137        2633 : static time_t ldb_msg_find_krb5time_ldap_time(struct ldb_message *msg, const char *attr, time_t default_val)
     138             : {
     139        2633 :     const struct ldb_val *gentime = NULL;
     140           0 :     time_t t;
     141           0 :     int ret;
     142             : 
     143        2633 :     gentime = ldb_msg_find_ldb_val(msg, attr);
     144        2633 :     ret = ldb_val_to_time(gentime, &t);
     145        2633 :     if (ret) {
     146         264 :             return default_val;
     147             :     }
     148             : 
     149        2369 :     return t;
     150             : }
     151             : 
     152      306249 : static struct SDBFlags uf2SDBFlags(krb5_context context, uint32_t userAccountControl, enum samba_kdc_ent_type ent_type)
     153             : {
     154      306249 :         struct SDBFlags flags = {};
     155             : 
     156             :         /* we don't allow kadmin deletes */
     157      306249 :         flags.immutable = 1;
     158             : 
     159             :         /* mark the principal as invalid to start with */
     160      306249 :         flags.invalid = 1;
     161             : 
     162      306249 :         flags.renewable = 1;
     163             : 
     164             :         /* All accounts are servers, but this may be disabled again in the caller */
     165      306249 :         flags.server = 1;
     166             : 
     167             :         /* Account types - clear the invalid bit if it turns out to be valid */
     168      306249 :         if (userAccountControl & UF_NORMAL_ACCOUNT) {
     169      263114 :                 if (ent_type == SAMBA_KDC_ENT_TYPE_CLIENT || ent_type == SAMBA_KDC_ENT_TYPE_ANY) {
     170       84016 :                         flags.client = 1;
     171             :                 }
     172      254107 :                 flags.invalid = 0;
     173             :         }
     174             : 
     175      306249 :         if (userAccountControl & UF_INTERDOMAIN_TRUST_ACCOUNT) {
     176        3059 :                 if (ent_type == SAMBA_KDC_ENT_TYPE_CLIENT || ent_type == SAMBA_KDC_ENT_TYPE_ANY) {
     177        3059 :                         flags.client = 1;
     178             :                 }
     179        3059 :                 flags.invalid = 0;
     180             :         }
     181      306249 :         if (userAccountControl & UF_WORKSTATION_TRUST_ACCOUNT) {
     182       13230 :                 if (ent_type == SAMBA_KDC_ENT_TYPE_CLIENT || ent_type == SAMBA_KDC_ENT_TYPE_ANY) {
     183        6708 :                         flags.client = 1;
     184             :                 }
     185       12956 :                 flags.invalid = 0;
     186             :         }
     187      306249 :         if (userAccountControl & UF_SERVER_TRUST_ACCOUNT) {
     188       26846 :                 if (ent_type == SAMBA_KDC_ENT_TYPE_CLIENT || ent_type == SAMBA_KDC_ENT_TYPE_ANY) {
     189        7831 :                         flags.client = 1;
     190             :                 }
     191       25887 :                 flags.invalid = 0;
     192             :         }
     193             : 
     194             :         /* Not permitted to act as a client if disabled */
     195      306249 :         if (userAccountControl & UF_ACCOUNTDISABLE) {
     196      176668 :                 flags.client = 0;
     197             :         }
     198      306249 :         if (userAccountControl & UF_LOCKOUT) {
     199          26 :                 flags.locked_out = 1;
     200             :         }
     201             : /*
     202             :         if (userAccountControl & UF_PASSWD_NOTREQD) {
     203             :                 flags.invalid = 1;
     204             :         }
     205             : */
     206             : /*
     207             :         UF_PASSWD_CANT_CHANGE and UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED are irrelevant
     208             : */
     209      306249 :         if (userAccountControl & UF_TEMP_DUPLICATE_ACCOUNT) {
     210           0 :                 flags.invalid = 1;
     211             :         }
     212             : 
     213             : /* UF_DONT_EXPIRE_PASSWD and UF_USE_DES_KEY_ONLY handled in samba_kdc_message2entry() */
     214             : 
     215             : /*
     216             :         if (userAccountControl & UF_MNS_LOGON_ACCOUNT) {
     217             :                 flags.invalid = 1;
     218             :         }
     219             : */
     220      306249 :         if (userAccountControl & UF_SMARTCARD_REQUIRED) {
     221          57 :                 flags.require_hwauth = 1;
     222             :         }
     223      306249 :         if (userAccountControl & UF_TRUSTED_FOR_DELEGATION) {
     224       21549 :                 flags.ok_as_delegate = 1;
     225             :         }
     226      306249 :         if (userAccountControl & UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION) {
     227             :                 /*
     228             :                  * this is confusing...
     229             :                  *
     230             :                  * UF_TRUSTED_FOR_DELEGATION
     231             :                  * => ok_as_delegate
     232             :                  *
     233             :                  * and
     234             :                  *
     235             :                  * UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION
     236             :                  * => trusted_for_delegation
     237             :                  */
     238        3608 :                 flags.trusted_for_delegation = 1;
     239             :         }
     240      306249 :         if (!(userAccountControl & UF_NOT_DELEGATED)) {
     241      306241 :                 flags.forwardable = 1;
     242      306241 :                 flags.proxiable = 1;
     243             :         }
     244             : 
     245      306249 :         if (userAccountControl & UF_DONT_REQUIRE_PREAUTH) {
     246           0 :                 flags.require_preauth = 0;
     247             :         } else {
     248      306249 :                 flags.require_preauth = 1;
     249             :         }
     250             : 
     251      306249 :         if (userAccountControl & UF_NO_AUTH_DATA_REQUIRED) {
     252          30 :                 flags.no_auth_data_reqd = 1;
     253             :         }
     254             : 
     255      306249 :         return flags;
     256             : }
     257             : 
     258      616447 : static int samba_kdc_entry_destructor(struct samba_kdc_entry *p)
     259             : {
     260      616447 :         if (p->db_entry != NULL) {
     261             :                 /*
     262             :                  * A sdb_entry still has a reference
     263             :                  */
     264           0 :                 return -1;
     265             :         }
     266             : 
     267      616447 :         if (p->kdc_entry != NULL) {
     268             :                 /*
     269             :                  * hdb_entry or krb5_db_entry still
     270             :                  * have a reference...
     271             :                  */
     272      308557 :                 return -1;
     273             :         }
     274             : 
     275      297650 :         return 0;
     276             : }
     277             : 
     278             : /*
     279             :  * Sort keys in descending order of strength.
     280             :  *
     281             :  * Explanation from Greg Hudson:
     282             :  *
     283             :  * To encrypt tickets only the first returned key is used by the MIT KDC.  The
     284             :  * other keys just communicate support for session key enctypes, and aren't
     285             :  * really used.  The encryption key for the ticket enc part doesn't have
     286             :  * to be of a type requested by the client. The session key enctype is chosen
     287             :  * based on the client preference order, limited by the set of enctypes present
     288             :  * in the server keys (unless the string attribute is set on the server
     289             :  * principal overriding that set).
     290             :  */
     291             : 
     292     1103378 : static int sdb_key_strength_priority(krb5_enctype etype)
     293             : {
     294       20442 :         static const krb5_enctype etype_list[] = {
     295             :                 ENCTYPE_AES256_CTS_HMAC_SHA1_96,
     296             :                 ENCTYPE_AES128_CTS_HMAC_SHA1_96,
     297             :                 ENCTYPE_DES3_CBC_SHA1,
     298             :                 ENCTYPE_ARCFOUR_HMAC,
     299             :                 ENCTYPE_DES_CBC_MD5,
     300             :                 ENCTYPE_DES_CBC_MD4,
     301             :                 ENCTYPE_DES_CBC_CRC,
     302             :                 ENCTYPE_NULL
     303             :         };
     304       20442 :         int i;
     305             : 
     306     2472540 :         for (i = 0; i < ARRAY_SIZE(etype_list); i++) {
     307     2472540 :                 if (etype == etype_list[i]) {
     308     1062494 :                         break;
     309             :                 }
     310             :         }
     311             : 
     312     1103378 :         return ARRAY_SIZE(etype_list) - i;
     313             : }
     314             : 
     315      551689 : static int sdb_key_strength_cmp(const struct sdb_key *k1, const struct sdb_key *k2)
     316             : {
     317      551689 :         int p1 = sdb_key_strength_priority(KRB5_KEY_TYPE(&k1->key));
     318      551689 :         int p2 = sdb_key_strength_priority(KRB5_KEY_TYPE(&k2->key));
     319             : 
     320      551689 :         if (p1 == p2) {
     321           0 :                 return 0;
     322             :         }
     323             : 
     324      551689 :         if (p1 > p2) {
     325             :                 /*
     326             :                  * Higher priority comes first
     327             :                  */
     328      531247 :                 return -1;
     329             :         } else {
     330           0 :                 return 1;
     331             :         }
     332             : }
     333             : 
     334      335562 : static void samba_kdc_sort_keys(struct sdb_keys *keys)
     335             : {
     336      335562 :         if (keys == NULL) {
     337           0 :                 return;
     338             :         }
     339             : 
     340      335562 :         TYPESAFE_QSORT(keys->val, keys->len, sdb_key_strength_cmp);
     341             : }
     342             : 
     343          96 : int samba_kdc_set_fixed_keys(krb5_context context,
     344             :                              const struct ldb_val *secretbuffer,
     345             :                              uint32_t supported_enctypes,
     346             :                              struct sdb_keys *keys)
     347             : {
     348          96 :         uint16_t allocated_keys = 0;
     349           0 :         int ret;
     350             : 
     351          96 :         allocated_keys = 3;
     352          96 :         keys->len = 0;
     353          96 :         keys->val = calloc(allocated_keys, sizeof(struct sdb_key));
     354          96 :         if (keys->val == NULL) {
     355           0 :                 memset(secretbuffer->data, 0, secretbuffer->length);
     356           0 :                 ret = ENOMEM;
     357           0 :                 goto out;
     358             :         }
     359             : 
     360          96 :         if (supported_enctypes & ENC_HMAC_SHA1_96_AES256) {
     361          58 :                 struct sdb_key key = {};
     362             : 
     363          58 :                 ret = smb_krb5_keyblock_init_contents(context,
     364             :                                                       ENCTYPE_AES256_CTS_HMAC_SHA1_96,
     365          58 :                                                       secretbuffer->data,
     366          58 :                                                       MIN(secretbuffer->length, 32),
     367             :                                                       &key.key);
     368          58 :                 if (ret) {
     369           0 :                         memset(secretbuffer->data, 0, secretbuffer->length);
     370           0 :                         goto out;
     371             :                 }
     372             : 
     373          58 :                 keys->val[keys->len] = key;
     374          58 :                 keys->len++;
     375             :         }
     376             : 
     377          96 :         if (supported_enctypes & ENC_HMAC_SHA1_96_AES128) {
     378          58 :                 struct sdb_key key = {};
     379             : 
     380          58 :                 ret = smb_krb5_keyblock_init_contents(context,
     381             :                                                       ENCTYPE_AES128_CTS_HMAC_SHA1_96,
     382          58 :                                                       secretbuffer->data,
     383          58 :                                                       MIN(secretbuffer->length, 16),
     384             :                                                       &key.key);
     385          58 :                 if (ret) {
     386           0 :                         memset(secretbuffer->data, 0, secretbuffer->length);
     387           0 :                         goto out;
     388             :                 }
     389             : 
     390          58 :                 keys->val[keys->len] = key;
     391          58 :                 keys->len++;
     392             :         }
     393             : 
     394          96 :         if (supported_enctypes & ENC_RC4_HMAC_MD5) {
     395          96 :                 struct sdb_key key = {};
     396             : 
     397          96 :                 ret = smb_krb5_keyblock_init_contents(context,
     398             :                                                       ENCTYPE_ARCFOUR_HMAC,
     399          96 :                                                       secretbuffer->data,
     400          96 :                                                       MIN(secretbuffer->length, 16),
     401             :                                                       &key.key);
     402          96 :                 if (ret) {
     403           0 :                         memset(secretbuffer->data, 0, secretbuffer->length);
     404           0 :                         goto out;
     405             :                 }
     406             : 
     407          96 :                 keys->val[keys->len] = key;
     408          96 :                 keys->len++;
     409             :         }
     410          96 :         ret = 0;
     411          96 : out:
     412          96 :         return ret;
     413             : }
     414             : 
     415             : 
     416          96 : static int samba_kdc_set_random_keys(krb5_context context,
     417             :                                      uint32_t supported_enctypes,
     418             :                                      struct sdb_keys *keys)
     419             : {
     420           0 :         struct ldb_val secret_val;
     421           0 :         uint8_t secretbuffer[32];
     422             : 
     423             :         /*
     424             :          * Fake keys until we have a better way to reject
     425             :          * non-pkinit requests.
     426             :          *
     427             :          * We just need to indicate which encryption types are
     428             :          * supported.
     429             :          */
     430          96 :         generate_secret_buffer(secretbuffer, sizeof(secretbuffer));
     431             : 
     432          96 :         secret_val = data_blob_const(secretbuffer,
     433             :                                      sizeof(secretbuffer));
     434          96 :         return samba_kdc_set_fixed_keys(context,
     435             :                                         &secret_val,
     436             :                                         supported_enctypes,
     437             :                                         keys);
     438             : }
     439             : 
     440             : struct samba_kdc_user_keys {
     441             :         struct sdb_keys *skeys;
     442             :         uint32_t kvno;
     443             :         uint32_t *returned_kvno;
     444             :         uint32_t supported_enctypes;
     445             :         uint32_t *available_enctypes;
     446             :         const struct samr_Password *nthash;
     447             :         const char *salt_string;
     448             :         uint16_t num_pkeys;
     449             :         const struct package_PrimaryKerberosKey4 *pkeys;
     450             : };
     451             : 
     452      333457 : static krb5_error_code samba_kdc_fill_user_keys(krb5_context context,
     453             :                                                 struct samba_kdc_user_keys *p)
     454             : {
     455             :         /*
     456             :          * Make sure we'll never reveal DES keys
     457             :          */
     458      333457 :         uint32_t supported_enctypes = p->supported_enctypes &= ~(ENC_CRC32 | ENC_RSA_MD5);
     459      333457 :         uint32_t _available_enctypes = 0;
     460      333457 :         uint32_t *available_enctypes = p->available_enctypes;
     461      333457 :         uint32_t _returned_kvno = 0;
     462      333457 :         uint32_t *returned_kvno = p->returned_kvno;
     463      333457 :         uint32_t num_pkeys = p->num_pkeys;
     464      333457 :         uint32_t allocated_keys = num_pkeys;
     465       10646 :         uint32_t i;
     466       10646 :         int ret;
     467             : 
     468      333457 :         if (available_enctypes == NULL) {
     469        8564 :                 available_enctypes = &_available_enctypes;
     470             :         }
     471             : 
     472      333457 :         *available_enctypes = 0;
     473             : 
     474      333457 :         if (returned_kvno == NULL) {
     475        8564 :                 returned_kvno = &_returned_kvno;
     476             :         }
     477             : 
     478      333457 :         *returned_kvno = p->kvno;
     479             : 
     480      333457 :         if (p->nthash != NULL) {
     481      303574 :                 allocated_keys += 1;
     482             :         }
     483             : 
     484      333457 :         allocated_keys = MAX(1, allocated_keys);
     485             : 
     486             :         /* allocate space to decode into */
     487      333457 :         p->skeys->len = 0;
     488      333457 :         p->skeys->val = calloc(allocated_keys, sizeof(struct sdb_key));
     489      333457 :         if (p->skeys->val == NULL) {
     490           0 :                 return ENOMEM;
     491             :         }
     492             : 
     493     1479681 :         for (i=0; i < num_pkeys; i++) {
     494     1146224 :                 struct sdb_key key = {};
     495       41032 :                 uint32_t enctype_bit;
     496             : 
     497     1146224 :                 if (p->pkeys[i].value == NULL) {
     498     1146224 :                         continue;
     499             :                 }
     500             : 
     501     1146224 :                 enctype_bit = kerberos_enctype_to_bitmap(p->pkeys[i].keytype);
     502     1146224 :                 if (!(enctype_bit & supported_enctypes)) {
     503      584287 :                         continue;
     504             :                 }
     505             : 
     506      561937 :                 if (p->salt_string != NULL) {
     507       20479 :                         DATA_BLOB salt;
     508             : 
     509      561937 :                         salt = data_blob_string_const(p->salt_string);
     510             : 
     511      561937 :                         key.salt = calloc(1, sizeof(*key.salt));
     512      561937 :                         if (key.salt == NULL) {
     513           0 :                                 ret = ENOMEM;
     514           0 :                                 goto fail;
     515             :                         }
     516             : 
     517      561937 :                         key.salt->type = KRB5_PW_SALT;
     518             : 
     519      582416 :                         ret = smb_krb5_copy_data_contents(&key.salt->salt,
     520      561937 :                                                           salt.data,
     521             :                                                           salt.length);
     522      561937 :                         if (ret) {
     523           0 :                                 *key.salt = (struct sdb_salt) {};
     524           0 :                                 sdb_key_free(&key);
     525           0 :                                 goto fail;
     526             :                         }
     527             :                 }
     528             : 
     529      582416 :                 ret = smb_krb5_keyblock_init_contents(context,
     530      561937 :                                                       p->pkeys[i].keytype,
     531      561937 :                                                       p->pkeys[i].value->data,
     532      561937 :                                                       p->pkeys[i].value->length,
     533             :                                                       &key.key);
     534      561937 :                 if (ret == 0) {
     535      561937 :                         p->skeys->val[p->skeys->len++] = key;
     536      561937 :                         *available_enctypes |= enctype_bit;
     537      561937 :                         continue;
     538             :                 }
     539           0 :                 ZERO_STRUCT(key.key);
     540           0 :                 sdb_key_free(&key);
     541           0 :                 if (ret == KRB5_PROG_ETYPE_NOSUPP) {
     542           0 :                         DEBUG(2,("Unsupported keytype ignored - type %u\n",
     543             :                                  p->pkeys[i].keytype));
     544           0 :                         ret = 0;
     545           0 :                         continue;
     546             :                 }
     547             : 
     548           0 :                 goto fail;
     549             :         }
     550             : 
     551      333457 :         if (p->nthash != NULL && (supported_enctypes & ENC_RC4_HMAC_MD5)) {
     552      298678 :                 struct sdb_key key = {};
     553             : 
     554      308954 :                 ret = smb_krb5_keyblock_init_contents(context,
     555             :                                                       ENCTYPE_ARCFOUR_HMAC,
     556      298678 :                                                       p->nthash->hash,
     557             :                                                       sizeof(p->nthash->hash),
     558             :                                                       &key.key);
     559      298678 :                 if (ret == 0) {
     560      298678 :                         p->skeys->val[p->skeys->len++] = key;
     561             : 
     562      298678 :                         *available_enctypes |= ENC_RC4_HMAC_MD5;
     563           0 :                 } else if (ret == KRB5_PROG_ETYPE_NOSUPP) {
     564           0 :                         DEBUG(2,("Unsupported keytype ignored - type %u\n",
     565             :                                  ENCTYPE_ARCFOUR_HMAC));
     566           0 :                         ret = 0;
     567             :                 }
     568      298678 :                 if (ret != 0) {
     569           0 :                         goto fail;
     570             :                 }
     571             :         }
     572             : 
     573      333457 :         samba_kdc_sort_keys(p->skeys);
     574             : 
     575      333457 :         return 0;
     576           0 : fail:
     577           0 :         sdb_keys_free(p->skeys);
     578           0 :         return ret;
     579             : }
     580             : 
     581           2 : static krb5_error_code samba_kdc_merge_keys(struct sdb_keys *keys,
     582             :                                             struct sdb_keys *old_keys)
     583             : {
     584           0 :         unsigned num_keys;
     585           0 :         unsigned num_old_keys;
     586           0 :         unsigned total_keys;
     587           0 :         unsigned j;
     588           2 :         struct sdb_key *skeys = NULL;
     589             : 
     590           2 :         if (keys == NULL || old_keys == NULL) {
     591           0 :                 return EINVAL;
     592             :         }
     593             : 
     594           2 :         num_keys = keys->len;
     595           2 :         num_old_keys = old_keys->len;
     596           2 :         total_keys = num_keys + num_old_keys;
     597             : 
     598           2 :         skeys = realloc(keys->val, total_keys * sizeof keys->val[0]);
     599           2 :         if (skeys == NULL) {
     600           0 :                 return ENOMEM;
     601             :         }
     602           2 :         keys->val = skeys;
     603             : 
     604           8 :         for (j = 0; j < num_old_keys; ++j) {
     605           6 :                 keys->val[num_keys + j] = old_keys->val[j];
     606             :         }
     607           2 :         keys->len = total_keys;
     608             : 
     609           2 :         old_keys->len = 0;
     610           2 :         SAFE_FREE(old_keys->val);
     611             : 
     612           2 :         return 0;
     613             : }
     614             : 
     615      325041 : krb5_error_code samba_kdc_message2entry_keys(krb5_context context,
     616             :                                              TALLOC_CTX *mem_ctx,
     617             :                                              struct ldb_context *ldb,
     618             :                                              const struct ldb_message *msg,
     619             :                                              bool is_krbtgt,
     620             :                                              bool is_rodc,
     621             :                                              uint32_t userAccountControl,
     622             :                                              enum samba_kdc_ent_type ent_type,
     623             :                                              unsigned flags,
     624             :                                              krb5_kvno requested_kvno,
     625             :                                              struct sdb_entry *entry,
     626             :                                              const uint32_t supported_enctypes_in,
     627             :                                              uint32_t *supported_enctypes_out)
     628             : {
     629      325041 :         krb5_error_code ret = 0;
     630       10379 :         enum ndr_err_code ndr_err;
     631       10379 :         struct samr_Password *hash;
     632      325041 :         unsigned int num_ntPwdHistory = 0;
     633      325041 :         struct samr_Password *ntPwdHistory = NULL;
     634      325041 :         struct samr_Password *old_hash = NULL;
     635      325041 :         struct samr_Password *older_hash = NULL;
     636       10379 :         const struct ldb_val *sc_val;
     637       10379 :         struct supplementalCredentialsBlob scb;
     638      325041 :         struct supplementalCredentialsPackage *scpk = NULL;
     639       10379 :         struct package_PrimaryKerberosBlob _pkb;
     640      325041 :         struct package_PrimaryKerberosCtr4 *pkb4 = NULL;
     641      325041 :         int krbtgt_number = 0;
     642       10379 :         uint32_t current_kvno;
     643      325041 :         uint32_t old_kvno = 0;
     644      325041 :         uint32_t older_kvno = 0;
     645      325041 :         uint32_t returned_kvno = 0;
     646       10379 :         uint16_t i;
     647      325041 :         struct samba_kdc_user_keys keys = { .num_pkeys = 0, };
     648      325041 :         struct samba_kdc_user_keys old_keys = { .num_pkeys = 0, };
     649      325041 :         struct samba_kdc_user_keys older_keys = { .num_pkeys = 0, };
     650      325041 :         uint32_t available_enctypes = 0;
     651      325041 :         uint32_t supported_enctypes = supported_enctypes_in;
     652      325041 :         const bool exporting_keytab = flags & SDB_F_ADMIN_DATA;
     653             : 
     654      325041 :         *supported_enctypes_out = 0;
     655             : 
     656             :         /* Is this the krbtgt or a RODC krbtgt */
     657      325041 :         if (is_rodc) {
     658        7026 :                 krbtgt_number = ldb_msg_find_attr_as_int(msg, "msDS-SecondaryKrbTgtNumber", -1);
     659             : 
     660        7026 :                 if (krbtgt_number == -1) {
     661           0 :                         return EINVAL;
     662             :                 }
     663        7026 :                 if (krbtgt_number == 0) {
     664           0 :                         return EINVAL;
     665             :                 }
     666             :         }
     667             : 
     668      325041 :         if (flags & SDB_F_USER2USER_PRINCIPAL) {
     669             :                 /*
     670             :                  * User2User uses the session key
     671             :                  * from the additional ticket,
     672             :                  * so we just provide random keys
     673             :                  * here in order to make sure
     674             :                  * we never expose the user password
     675             :                  * keys.
     676             :                  */
     677          39 :                 ret = samba_kdc_set_random_keys(context,
     678             :                                                 supported_enctypes,
     679             :                                                 &entry->keys);
     680             : 
     681          39 :                 *supported_enctypes_out = supported_enctypes & ENC_ALL_TYPES;
     682             : 
     683          39 :                 goto out;
     684             :         }
     685             : 
     686      325002 :         if ((ent_type == SAMBA_KDC_ENT_TYPE_CLIENT)
     687      120331 :             && (userAccountControl & UF_SMARTCARD_REQUIRED)) {
     688          57 :                 ret = samba_kdc_set_random_keys(context,
     689             :                                                 supported_enctypes,
     690             :                                                 &entry->keys);
     691             : 
     692          57 :                 *supported_enctypes_out = supported_enctypes & ENC_ALL_TYPES;
     693             : 
     694          57 :                 goto out;
     695             :         }
     696             : 
     697      324945 :         current_kvno = ldb_msg_find_attr_as_int(msg, "msDS-KeyVersionNumber", 0);
     698      324945 :         if (current_kvno > 1) {
     699       40076 :                 old_kvno = current_kvno - 1;
     700             :         }
     701      324945 :         if (current_kvno > 2) {
     702       17791 :                 older_kvno = current_kvno - 2;
     703             :         }
     704      324945 :         if (is_krbtgt) {
     705             :                 /*
     706             :                  * Even for the main krbtgt account
     707             :                  * we have to strictly split the kvno into
     708             :                  * two 16-bit parts and the upper 16-bit
     709             :                  * need to be all zero, even if
     710             :                  * the msDS-KeyVersionNumber has a value
     711             :                  * larger than 65535.
     712             :                  *
     713             :                  * See https://bugzilla.samba.org/show_bug.cgi?id=14951
     714             :                  */
     715      176649 :                 current_kvno = SAMBA_KVNO_GET_VALUE(current_kvno);
     716      176649 :                 old_kvno = SAMBA_KVNO_GET_VALUE(old_kvno);
     717      176649 :                 older_kvno = SAMBA_KVNO_GET_VALUE(older_kvno);
     718      176649 :                 requested_kvno = SAMBA_KVNO_GET_VALUE(requested_kvno);
     719             :         }
     720             : 
     721             :         /* Get keys from the db */
     722             : 
     723      324945 :         hash = samdb_result_hash(mem_ctx, msg, "unicodePwd");
     724      324945 :         num_ntPwdHistory = samdb_result_hashes(mem_ctx, msg,
     725             :                                                "ntPwdHistory",
     726             :                                                &ntPwdHistory);
     727      324945 :         if (num_ntPwdHistory > 1) {
     728        7507 :                 old_hash = &ntPwdHistory[1];
     729             :         }
     730      324945 :         if (num_ntPwdHistory > 2) {
     731        3903 :                 older_hash = &ntPwdHistory[2];
     732             :         }
     733      324945 :         sc_val = ldb_msg_find_ldb_val(msg, "supplementalCredentials");
     734             : 
     735             :         /* supplementalCredentials if present */
     736      324945 :         if (sc_val) {
     737      303418 :                 ndr_err = ndr_pull_struct_blob_all(sc_val, mem_ctx, &scb,
     738             :                                                    (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob);
     739      303418 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     740           0 :                         ret = EINVAL;
     741           0 :                         goto out;
     742             :                 }
     743             : 
     744      303418 :                 if (scb.sub.signature != SUPPLEMENTAL_CREDENTIALS_SIGNATURE) {
     745           0 :                         if (scb.sub.num_packages != 0) {
     746           0 :                                 NDR_PRINT_DEBUG(supplementalCredentialsBlob, &scb);
     747           0 :                                 ret = EINVAL;
     748           0 :                                 goto out;
     749             :                         }
     750             :                 }
     751             : 
     752      360289 :                 for (i=0; i < scb.sub.num_packages; i++) {
     753      341332 :                         if (scb.sub.packages[i].name != NULL &&
     754      341332 :                             strcmp("Primary:Kerberos-Newer-Keys", scb.sub.packages[i].name) == 0)
     755             :                         {
     756      284461 :                                 scpk = &scb.sub.packages[i];
     757      284461 :                                 if (!scpk->data || !scpk->data[0]) {
     758           0 :                                         scpk = NULL;
     759           0 :                                         continue;
     760             :                                 }
     761      274221 :                                 break;
     762             :                         }
     763             :                 }
     764             :         }
     765             :         /*
     766             :          * Primary:Kerberos-Newer-Keys element
     767             :          * of supplementalCredentials
     768             :          *
     769             :          * The legacy Primary:Kerberos only contains
     770             :          * single DES keys, which are completely ignored
     771             :          * now.
     772             :          */
     773      324806 :         if (scpk) {
     774       10240 :                 DATA_BLOB blob;
     775             : 
     776      284461 :                 blob = strhex_to_data_blob(mem_ctx, scpk->data);
     777      284461 :                 if (!blob.data) {
     778           0 :                         ret = ENOMEM;
     779           0 :                         goto out;
     780             :                 }
     781             : 
     782             :                 /* we cannot use ndr_pull_struct_blob_all() here, as w2k and w2k3 add padding bytes */
     783      284461 :                 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &_pkb,
     784             :                                                (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
     785      284461 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     786           0 :                         ret = EINVAL;
     787           0 :                         krb5_set_error_message(context, ret, "samba_kdc_message2entry_keys: could not parse package_PrimaryKerberosBlob");
     788           0 :                         krb5_warnx(context, "samba_kdc_message2entry_keys: could not parse package_PrimaryKerberosBlob");
     789           0 :                         goto out;
     790             :                 }
     791             : 
     792      284461 :                 if (_pkb.version != 4) {
     793           0 :                         ret = EINVAL;
     794           0 :                         krb5_set_error_message(context, ret, "samba_kdc_message2entry_keys: Primary:Kerberos-Newer-Keys not version 4");
     795           0 :                         krb5_warnx(context, "samba_kdc_message2entry_keys: Primary:Kerberos-Newer-Keys not version 4");
     796           0 :                         goto out;
     797             :                 }
     798             : 
     799      284461 :                 pkb4 = &_pkb.ctr.ctr4;
     800             :         }
     801             : 
     802      324945 :         keys = (struct samba_kdc_user_keys) {
     803             :                 .kvno = current_kvno,
     804             :                 .supported_enctypes = supported_enctypes,
     805             :                 .nthash = hash,
     806      324945 :                 .salt_string = pkb4 != NULL ? pkb4->salt.string : NULL,
     807             :                 .num_pkeys = pkb4 != NULL ? pkb4->num_keys : 0,
     808      324945 :                 .pkeys = pkb4 != NULL ? pkb4->keys : NULL,
     809             :         };
     810             : 
     811      324945 :         old_keys = (struct samba_kdc_user_keys) {
     812             :                 .kvno = old_kvno,
     813             :                 .supported_enctypes = supported_enctypes,
     814             :                 .nthash = old_hash,
     815      324945 :                 .salt_string = pkb4 != NULL ? pkb4->salt.string : NULL,
     816             :                 .num_pkeys = pkb4 != NULL ? pkb4->num_old_keys : 0,
     817      324945 :                 .pkeys = pkb4 != NULL ? pkb4->old_keys : NULL,
     818             :         };
     819      324945 :         older_keys = (struct samba_kdc_user_keys) {
     820             :                 .kvno = older_kvno,
     821             :                 .supported_enctypes = supported_enctypes,
     822             :                 .nthash = older_hash,
     823      314566 :                 .salt_string = pkb4 != NULL ? pkb4->salt.string : NULL,
     824             :                 .num_pkeys = pkb4 != NULL ? pkb4->num_older_keys : 0,
     825      324945 :                 .pkeys = pkb4 != NULL ? pkb4->older_keys : NULL,
     826             :         };
     827             : 
     828      324945 :         if (flags & SDB_F_KVNO_SPECIFIED) {
     829       52551 :                 if (requested_kvno == keys.kvno) {
     830             :                         /*
     831             :                          * The current kvno was requested,
     832             :                          * so we return it.
     833             :                          */
     834       51893 :                         keys.skeys = &entry->keys;
     835       51893 :                         keys.available_enctypes = &available_enctypes;
     836       51893 :                         keys.returned_kvno = &returned_kvno;
     837         658 :                 } else if (requested_kvno == 0) {
     838             :                         /*
     839             :                          * don't return any keys
     840             :                          */
     841         606 :                 } else if (requested_kvno == old_keys.kvno) {
     842             :                         /*
     843             :                          * return the old keys as default keys
     844             :                          * with the requested kvno.
     845             :                          */
     846         416 :                         old_keys.skeys = &entry->keys;
     847         416 :                         old_keys.available_enctypes = &available_enctypes;
     848         416 :                         old_keys.returned_kvno = &returned_kvno;
     849         190 :                 } else if (requested_kvno == older_keys.kvno) {
     850             :                         /*
     851             :                          * return the older keys as default keys
     852             :                          * with the requested kvno.
     853             :                          */
     854         190 :                         older_keys.skeys = &entry->keys;
     855         190 :                         older_keys.available_enctypes = &available_enctypes;
     856         190 :                         older_keys.returned_kvno = &returned_kvno;
     857             :                 } else {
     858             :                         /*
     859             :                          * don't return any keys
     860             :                          */
     861             :                 }
     862             :         } else {
     863      272394 :                 bool include_history = false;
     864             : 
     865      272394 :                 if ((flags & SDB_F_GET_CLIENT) && (flags & SDB_F_FOR_AS_REQ)) {
     866       48864 :                         include_history = true;
     867      221754 :                 } else if (exporting_keytab) {
     868         264 :                         include_history = true;
     869             :                 }
     870             : 
     871      272394 :                 keys.skeys = &entry->keys;
     872      272394 :                 keys.available_enctypes = &available_enctypes;
     873      272394 :                 keys.returned_kvno = &returned_kvno;
     874             : 
     875      272394 :                 if (include_history && old_keys.kvno != 0) {
     876        6981 :                         old_keys.skeys = &entry->old_keys;
     877             :                 }
     878      272394 :                 if (include_history && older_keys.kvno != 0) {
     879        1583 :                         older_keys.skeys = &entry->older_keys;
     880             :                 }
     881             :         }
     882             : 
     883      324945 :         if (keys.skeys != NULL) {
     884      324287 :                 ret = samba_kdc_fill_user_keys(context, &keys);
     885      324287 :                 if (ret != 0) {
     886           0 :                         goto out;
     887             :                 }
     888             :         }
     889             : 
     890      324945 :         if (old_keys.skeys != NULL) {
     891        7397 :                 ret = samba_kdc_fill_user_keys(context, &old_keys);
     892        7397 :                 if (ret != 0) {
     893           0 :                         goto out;
     894             :                 }
     895             : 
     896        7397 :                 if (keys.skeys != NULL && !exporting_keytab) {
     897         249 :                         bool is_gmsa;
     898             : 
     899        6863 :                         is_gmsa = dsdb_account_is_gmsa(ldb, msg);
     900        6863 :                         if (is_gmsa) {
     901           0 :                                 NTTIME current_time;
     902           0 :                                 bool gmsa_key_is_recent;
     903           0 :                                 bool ok;
     904             : 
     905           5 :                                 ok = dsdb_gmsa_current_time(ldb, &current_time);
     906           5 :                                 if (!ok) {
     907           0 :                                         ret = EINVAL;
     908           0 :                                         goto out;
     909             :                                 }
     910             : 
     911           5 :                                 gmsa_key_is_recent = samdb_gmsa_key_is_recent(
     912             :                                         msg, current_time);
     913           5 :                                 if (gmsa_key_is_recent) {
     914             :                                         /*
     915             :                                          * As the current gMSA keys are less
     916             :                                          * than five minutes old, the previous
     917             :                                          * set of keys remains valid. The
     918             :                                          * Heimdal KDC will try each of the
     919             :                                          * current keys when decrypting a
     920             :                                          * client’s PA‐DATA, so by merging the
     921             :                                          * old set into the current set we can
     922             :                                          * cause both sets to be considered for
     923             :                                          * decryption.
     924             :                                          */
     925           2 :                                         ret = samba_kdc_merge_keys(
     926             :                                                 keys.skeys, old_keys.skeys);
     927           2 :                                         if (ret) {
     928           0 :                                                 goto out;
     929             :                                         }
     930             :                                 }
     931             :                         }
     932             :                 }
     933             :         }
     934             : 
     935      324945 :         if (older_keys.skeys != NULL) {
     936        1773 :                 ret = samba_kdc_fill_user_keys(context, &older_keys);
     937        1773 :                 if (ret != 0) {
     938           0 :                         goto out;
     939             :                 }
     940             :         }
     941             : 
     942      324945 :         *supported_enctypes_out |= available_enctypes;
     943             : 
     944      324945 :         if (is_krbtgt) {
     945             :                 /*
     946             :                  * Even for the main krbtgt account
     947             :                  * we have to strictly split the kvno into
     948             :                  * two 16-bit parts and the upper 16-bit
     949             :                  * need to be all zero, even if
     950             :                  * the msDS-KeyVersionNumber has a value
     951             :                  * larger than 65535.
     952             :                  *
     953             :                  * See https://bugzilla.samba.org/show_bug.cgi?id=14951
     954             :                  */
     955      176649 :                 returned_kvno = SAMBA_KVNO_AND_KRBTGT(returned_kvno, krbtgt_number);
     956             :         }
     957      324945 :         entry->kvno = returned_kvno;
     958             : 
     959      314662 : out:
     960      314662 :         return ret;
     961             : }
     962             : 
     963       53305 : static krb5_error_code is_principal_component_equal_impl(krb5_context context,
     964             :                                                          krb5_const_principal principal,
     965             :                                                          unsigned int component,
     966             :                                                          const char *string,
     967             :                                                          bool do_strcasecmp,
     968             :                                                          bool *eq)
     969             : {
     970        1672 :         const char *p;
     971             : 
     972             : #if defined(HAVE_KRB5_PRINCIPAL_GET_COMP_STRING)
     973       53027 :         if (component >= krb5_princ_size(context, principal)) {
     974             :                 /* A non‐existent component compares equal to no string. */
     975           0 :                 *eq = false;
     976           0 :                 return 0;
     977             :         }
     978       53027 :         p = krb5_principal_get_comp_string(context, principal, component);
     979       53027 :         if (p == NULL) {
     980           0 :                 return ENOENT;
     981             :         }
     982       53027 :         if (do_strcasecmp) {
     983         119 :                 *eq = strcasecmp(p, string) == 0;
     984             :         } else {
     985       52908 :                 *eq = strcmp(p, string) == 0;
     986             :         }
     987       51355 :         return 0;
     988             : #else
     989             :         size_t len;
     990             :         krb5_data d;
     991         278 :         krb5_error_code ret = 0;
     992             : 
     993         278 :         if (component > INT_MAX) {
     994           0 :                 return EINVAL;
     995             :         }
     996             : 
     997         278 :         if (component >= krb5_princ_size(context, principal)) {
     998             :                 /* A non‐existent component compares equal to no string. */
     999           0 :                 *eq = false;
    1000           0 :                 return 0;
    1001             :         }
    1002             : 
    1003         278 :         ret = smb_krb5_princ_component(context, principal, component, &d);
    1004         278 :         if (ret) {
    1005           0 :                 return ret;
    1006             :         }
    1007             : 
    1008         278 :         p = d.data;
    1009             : 
    1010         278 :         len = strlen(string);
    1011         278 :         if (d.length != len) {
    1012           2 :                 *eq = false;
    1013           2 :                 return 0;
    1014             :         }
    1015             : 
    1016         276 :         if (do_strcasecmp) {
    1017           0 :                 *eq = strncasecmp(p, string, len) == 0;
    1018             :         } else {
    1019         276 :                 *eq = memcmp(p, string, len) == 0;
    1020             :         }
    1021         276 :         return 0;
    1022             : #endif
    1023             : }
    1024             : 
    1025         119 : static krb5_error_code is_principal_component_equal_ignoring_case(krb5_context context,
    1026             :                                                                   krb5_const_principal principal,
    1027             :                                                                   unsigned int component,
    1028             :                                                                   const char *string,
    1029             :                                                                   bool *eq)
    1030             : {
    1031         119 :         return is_principal_component_equal_impl(context,
    1032             :                                                  principal,
    1033             :                                                  component,
    1034             :                                                  string,
    1035             :                                                  true /* do_strcasecmp */,
    1036             :                                                  eq);
    1037             : }
    1038             : 
    1039       53186 : static krb5_error_code is_principal_component_equal(krb5_context context,
    1040             :                                                     krb5_const_principal principal,
    1041             :                                                     unsigned int component,
    1042             :                                                     const char *string,
    1043             :                                                     bool *eq)
    1044             : {
    1045       53186 :         return is_principal_component_equal_impl(context,
    1046             :                                                  principal,
    1047             :                                                  component,
    1048             :                                                  string,
    1049             :                                                  false /* do_strcasecmp */,
    1050             :                                                  eq);
    1051             : }
    1052             : 
    1053         257 : static krb5_error_code is_kadmin_changepw(krb5_context context,
    1054             :                                           krb5_const_principal principal,
    1055             :                                           bool *is_changepw)
    1056             : {
    1057         257 :         krb5_error_code ret = 0;
    1058         257 :         bool eq = false;
    1059             : 
    1060         257 :         if (krb5_princ_size(context, principal) != 2) {
    1061           0 :                 *is_changepw = false;
    1062           0 :                 return 0;
    1063             :         }
    1064             : 
    1065         257 :         ret = is_principal_component_equal(context, principal, 0, "kadmin", &eq);
    1066         257 :         if (ret) {
    1067           0 :                 return ret;
    1068             :         }
    1069             : 
    1070         257 :         if (!eq) {
    1071           0 :                 *is_changepw = false;
    1072           0 :                 return 0;
    1073             :         }
    1074             : 
    1075         257 :         ret = is_principal_component_equal(context, principal, 1, "changepw", &eq);
    1076         257 :         if (ret) {
    1077           0 :                 return ret;
    1078             :         }
    1079             : 
    1080         257 :         *is_changepw = eq;
    1081         257 :         return 0;
    1082             : }
    1083             : 
    1084      305574 : static krb5_error_code samba_kdc_get_entry_principal(
    1085             :                 krb5_context context,
    1086             :                 struct samba_kdc_db_context *kdc_db_ctx,
    1087             :                 const char *samAccountName,
    1088             :                 enum samba_kdc_ent_type ent_type,
    1089             :                 unsigned flags,
    1090             :                 bool is_kadmin_changepw,
    1091             :                 krb5_const_principal in_princ,
    1092             :                 krb5_principal *out_princ)
    1093             : {
    1094      305574 :         struct loadparm_context *lp_ctx = kdc_db_ctx->lp_ctx;
    1095      305574 :         krb5_error_code code = 0;
    1096      305574 :         bool canon = flags & (SDB_F_CANON|SDB_F_FORCE_CANON);
    1097             : 
    1098             :         /*
    1099             :          * If we are set to canonicalize, we get back the fixed UPPER
    1100             :          * case realm, and the real username (ie matching LDAP
    1101             :          * samAccountName)
    1102             :          *
    1103             :          * Otherwise, if we are set to enterprise, we
    1104             :          * get back the whole principal as-sent
    1105             :          *
    1106             :          * Finally, if we are not set to canonicalize, we get back the
    1107             :          * fixed UPPER case realm, but the as-sent username
    1108             :          */
    1109             : 
    1110             :         /*
    1111             :          * We need to ensure that the kadmin/changepw principal isn't able to
    1112             :          * issue krbtgt tickets, even if canonicalization is turned on.
    1113             :          */
    1114      305574 :         if (!is_kadmin_changepw) {
    1115      305317 :                 if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT && canon) {
    1116             :                         /*
    1117             :                          * When requested to do so, ensure that both
    1118             :                          * the realm values in the principal are set
    1119             :                          * to the upper case, canonical realm
    1120             :                          */
    1121       42622 :                         code = smb_krb5_make_principal(context,
    1122             :                                                        out_princ,
    1123             :                                                        lpcfg_realm(lp_ctx),
    1124             :                                                        "krbtgt",
    1125             :                                                        lpcfg_realm(lp_ctx),
    1126             :                                                        NULL);
    1127       42622 :                         if (code != 0) {
    1128           0 :                                 return code;
    1129             :                         }
    1130       42622 :                         smb_krb5_principal_set_type(context,
    1131             :                                                     *out_princ,
    1132             :                                                     KRB5_NT_SRV_INST);
    1133             : 
    1134       42622 :                         return 0;
    1135             :                 }
    1136             : 
    1137      262695 :                 if ((canon && flags & (SDB_F_FORCE_CANON|SDB_F_FOR_AS_REQ)) ||
    1138        6814 :                     (ent_type == SAMBA_KDC_ENT_TYPE_ANY && in_princ == NULL)) {
    1139             :                         /*
    1140             :                          * SDB_F_CANON maps from the canonicalize flag in the
    1141             :                          * packet, and has a different meaning between AS-REQ
    1142             :                          * and TGS-REQ.  We only change the principal in the
    1143             :                          * AS-REQ case.
    1144             :                          *
    1145             :                          * The SDB_F_FORCE_CANON if for new MIT KDC code that
    1146             :                          * wants the canonical name in all lookups, and takes
    1147             :                          * care to canonicalize only when appropriate.
    1148             :                          */
    1149       51569 :                         code = smb_krb5_make_principal(context,
    1150             :                                                       out_princ,
    1151             :                                                       lpcfg_realm(lp_ctx),
    1152             :                                                       samAccountName,
    1153             :                                                       NULL);
    1154       51569 :                         return code;
    1155             :                 }
    1156             :         }
    1157             : 
    1158             :         /*
    1159             :          * For a krbtgt entry, this appears to be required regardless of the
    1160             :          * canonicalize flag from the client.
    1161             :          */
    1162      211383 :         code = krb5_copy_principal(context, in_princ, out_princ);
    1163      211383 :         if (code != 0) {
    1164           0 :                 return code;
    1165             :         }
    1166             : 
    1167             :         /*
    1168             :          * While we have copied the client principal, tests show that Win2k3
    1169             :          * returns the 'corrected' realm, not the client-specified realm.  This
    1170             :          * code attempts to replace the client principal's realm with the one
    1171             :          * we determine from our records
    1172             :          */
    1173      211383 :         code = smb_krb5_principal_set_realm(context,
    1174             :                                             *out_princ,
    1175             :                                             lpcfg_realm(lp_ctx));
    1176             : 
    1177      211383 :         return code;
    1178             : }
    1179             : 
    1180             : /*
    1181             :  * Construct an hdb_entry from a directory entry.
    1182             :  */
    1183      306249 : static krb5_error_code samba_kdc_message2entry(krb5_context context,
    1184             :                                                struct samba_kdc_db_context *kdc_db_ctx,
    1185             :                                                TALLOC_CTX *mem_ctx,
    1186             :                                                krb5_const_principal principal,
    1187             :                                                enum samba_kdc_ent_type ent_type,
    1188             :                                                unsigned flags,
    1189             :                                                krb5_kvno kvno,
    1190             :                                                struct ldb_dn *realm_dn,
    1191             :                                                struct ldb_message *msg,
    1192             :                                                struct sdb_entry *entry)
    1193             : {
    1194      306249 :         TALLOC_CTX *tmp_ctx = NULL;
    1195      306249 :         struct loadparm_context *lp_ctx = kdc_db_ctx->lp_ctx;
    1196       10240 :         uint32_t userAccountControl;
    1197       10240 :         uint32_t msDS_User_Account_Control_Computed;
    1198      306249 :         krb5_error_code ret = 0;
    1199      306249 :         krb5_boolean is_computer = FALSE;
    1200       10240 :         struct samba_kdc_entry *p;
    1201       10240 :         NTTIME acct_expiry;
    1202       10240 :         NTSTATUS status;
    1203      306249 :         bool protected_user = false;
    1204       10240 :         struct dom_sid sid;
    1205       10240 :         uint32_t rid;
    1206      306249 :         bool is_krbtgt = false;
    1207      306249 :         bool is_rodc = false;
    1208      306249 :         bool force_rc4 = lpcfg_kdc_force_enable_rc4_weak_session_keys(lp_ctx);
    1209       10240 :         struct ldb_message_element *objectclasses;
    1210      306249 :         struct ldb_val computer_val = data_blob_string_const("computer");
    1211      306249 :         struct ldb_val gmsa_oc_val = data_blob_string_const("msDS-GroupManagedServiceAccount");
    1212      306249 :         uint32_t config_default_supported_enctypes = lpcfg_kdc_default_domain_supported_enctypes(lp_ctx);
    1213      316489 :         uint32_t default_supported_enctypes =
    1214             :                 config_default_supported_enctypes != 0 ?
    1215      306249 :                 config_default_supported_enctypes :
    1216             :                 ENC_RC4_HMAC_MD5 | ENC_HMAC_SHA1_96_AES256_SK;
    1217       10240 :         uint32_t supported_enctypes
    1218      306249 :                 = ldb_msg_find_attr_as_uint(msg,
    1219             :                                             "msDS-SupportedEncryptionTypes",
    1220             :                                             default_supported_enctypes);
    1221       10240 :         uint32_t pa_supported_enctypes;
    1222       10240 :         uint32_t supported_session_etypes;
    1223      306249 :         uint32_t available_enctypes = 0;
    1224             :         /*
    1225             :          * also legacy enctypes are announced,
    1226             :          * but effectively restricted by kdc_enctypes
    1227             :          */
    1228      306249 :         uint32_t domain_enctypes = ENC_RC4_HMAC_MD5 | ENC_RSA_MD5 | ENC_CRC32;
    1229      306249 :         uint32_t config_kdc_enctypes = lpcfg_kdc_supported_enctypes(lp_ctx);
    1230      316489 :         uint32_t kdc_enctypes =
    1231             :                 config_kdc_enctypes != 0 ?
    1232      306249 :                 config_kdc_enctypes :
    1233             :                 ENC_ALL_TYPES;
    1234      306249 :         const char *samAccountName = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL);
    1235             : 
    1236      306249 :         const struct authn_kerberos_client_policy *authn_client_policy = NULL;
    1237      306249 :         const struct authn_server_policy *authn_server_policy = NULL;
    1238       10240 :         int64_t enforced_tgt_lifetime_raw;
    1239      306249 :         const bool user2user = (flags & SDB_F_USER2USER_PRINCIPAL);
    1240             : 
    1241      306249 :         *entry = (struct sdb_entry) {};
    1242             : 
    1243      306249 :         tmp_ctx = talloc_new(mem_ctx);
    1244      306249 :         if (tmp_ctx == NULL) {
    1245           0 :                 return ENOMEM;
    1246             :         }
    1247             : 
    1248      306249 :         if (supported_enctypes == 0) {
    1249           0 :                 supported_enctypes = default_supported_enctypes;
    1250             :         }
    1251             : 
    1252      306249 :         if (dsdb_functional_level(kdc_db_ctx->samdb) >= DS_DOMAIN_FUNCTION_2008) {
    1253      287390 :                 domain_enctypes |= ENC_HMAC_SHA1_96_AES128 | ENC_HMAC_SHA1_96_AES256;
    1254             :         }
    1255             : 
    1256      306249 :         if (ldb_msg_find_element(msg, "msDS-SecondaryKrbTgtNumber")) {
    1257        7026 :                 is_rodc = true;
    1258             :         }
    1259             : 
    1260      306249 :         if (!samAccountName) {
    1261           0 :                 ret = ENOENT;
    1262           0 :                 krb5_set_error_message(context, ret, "samba_kdc_message2entry: no samAccountName present");
    1263           0 :                 goto out;
    1264             :         }
    1265             : 
    1266      306249 :         objectclasses = ldb_msg_find_element(msg, "objectClass");
    1267             : 
    1268      306249 :         if (objectclasses && ldb_msg_find_val(objectclasses, &computer_val)) {
    1269       40076 :                 is_computer = TRUE;
    1270             :         }
    1271             : 
    1272      306249 :         p = talloc_zero(tmp_ctx, struct samba_kdc_entry);
    1273      306249 :         if (!p) {
    1274           0 :                 ret = ENOMEM;
    1275           0 :                 goto out;
    1276             :         }
    1277             : 
    1278      306249 :         if (objectclasses && ldb_msg_find_val(objectclasses, &gmsa_oc_val)) {
    1279          37 :                 p->group_managed_service_account = true;
    1280             :         }
    1281             : 
    1282      306249 :         p->is_rodc = is_rodc;
    1283      306249 :         p->kdc_db_ctx = kdc_db_ctx;
    1284      306249 :         p->realm_dn = talloc_reference(p, realm_dn);
    1285      306249 :         if (!p->realm_dn) {
    1286           0 :                 ret = ENOMEM;
    1287           0 :                 goto out;
    1288             :         }
    1289             : 
    1290      306249 :         talloc_set_destructor(p, samba_kdc_entry_destructor);
    1291             : 
    1292      306249 :         entry->skdc_entry = p;
    1293             : 
    1294      306249 :         userAccountControl = ldb_msg_find_attr_as_uint(msg, "userAccountControl", 0);
    1295             : 
    1296       10240 :         msDS_User_Account_Control_Computed
    1297      306249 :                 = ldb_msg_find_attr_as_uint(msg,
    1298             :                                             "msDS-User-Account-Control-Computed",
    1299             :                                             UF_ACCOUNTDISABLE);
    1300             : 
    1301             :         /*
    1302             :          * This brings in the lockout flag, block the account if not
    1303             :          * found.  We need the weird UF_ACCOUNTDISABLE check because
    1304             :          * we do not want to fail open if the value is not returned,
    1305             :          * but 0 is a valid value (all OK)
    1306             :          */
    1307      306249 :         if (msDS_User_Account_Control_Computed == UF_ACCOUNTDISABLE) {
    1308           0 :                 ret = EINVAL;
    1309           0 :                 krb5_set_error_message(context, ret, "samba_kdc_message2entry: "
    1310             :                                 "no msDS-User-Account-Control-Computed present");
    1311           0 :                 goto out;
    1312             :         } else {
    1313      306249 :                 userAccountControl |= msDS_User_Account_Control_Computed;
    1314             :         }
    1315             : 
    1316      306249 :         if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT) {
    1317      176383 :                 p->is_krbtgt = true;
    1318             :         }
    1319             : 
    1320             :         /* First try and figure out the flags based on the userAccountControl */
    1321      306249 :         entry->flags = uf2SDBFlags(context, userAccountControl, ent_type);
    1322             : 
    1323             :         /*
    1324             :          * Take control of the returned principal here, rather than
    1325             :          * allowing the Heimdal code to do it as we have specific
    1326             :          * behaviour around the forced realm to honour
    1327             :          */
    1328      306249 :         entry->flags.force_canonicalize = true;
    1329             : 
    1330             :         /*
    1331             :          * Windows 2008 seems to enforce this (very sensible) rule by
    1332             :          * default - don't allow offline attacks on a user's password
    1333             :          * by asking for a ticket to them as a service (encrypted with
    1334             :          * their probably pathetically insecure password)
    1335             :          *
    1336             :          * But user2user avoids using the keys based on the password,
    1337             :          * so we can allow it.
    1338             :          */
    1339             : 
    1340      306249 :         if (entry->flags.server && !user2user
    1341      306210 :             && lpcfg_parm_bool(lp_ctx, NULL, "kdc", "require spn for service", true)) {
    1342      306210 :                 if (!is_computer && !ldb_msg_find_attr_as_string(msg, "servicePrincipalName", NULL)) {
    1343       90722 :                         entry->flags.server = 0;
    1344             :                 }
    1345             :         }
    1346             : 
    1347             :         /*
    1348             :          * We restrict a 3-part SPN ending in my domain/realm to full
    1349             :          * domain controllers.
    1350             :          *
    1351             :          * This avoids any cases where (eg) a demoted DC still has
    1352             :          * these more restricted SPNs.
    1353             :          */
    1354      306249 :         if (krb5_princ_size(context, principal) > 2) {
    1355          28 :                 char *third_part = NULL;
    1356           0 :                 bool is_our_realm;
    1357           0 :                 bool is_dc;
    1358             : 
    1359          28 :                 ret = smb_krb5_principal_get_comp_string(tmp_ctx,
    1360             :                                                          context,
    1361             :                                                          principal,
    1362             :                                                          2,
    1363             :                                                          &third_part);
    1364          28 :                 if (ret) {
    1365           0 :                         krb5_set_error_message(context, ret, "smb_krb5_principal_get_comp_string: out of memory");
    1366           0 :                         goto out;
    1367             :                 }
    1368             : 
    1369          28 :                 is_our_realm = lpcfg_is_my_domain_or_realm(lp_ctx,
    1370             :                                                      third_part);
    1371          28 :                 is_dc = userAccountControl &
    1372             :                         (UF_SERVER_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT);
    1373          28 :                 if (is_our_realm && !is_dc) {
    1374           3 :                         entry->flags.server = 0;
    1375             :                 }
    1376             :         }
    1377             :         /*
    1378             :          * To give the correct type of error to the client, we must
    1379             :          * not just return the entry without .server set, we must
    1380             :          * pretend the principal does not exist.  Otherwise we may
    1381             :          * return ERR_POLICY instead of
    1382             :          * KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
    1383             :          */
    1384      306249 :         if (ent_type == SAMBA_KDC_ENT_TYPE_SERVER && entry->flags.server == 0) {
    1385         675 :                 ret = SDB_ERR_NOENTRY;
    1386         675 :                 krb5_set_error_message(context, ret, "samba_kdc_message2entry: no servicePrincipalName present for this server, refusing with no-such-entry");
    1387         675 :                 goto out;
    1388             :         }
    1389      305574 :         if (flags & SDB_F_ADMIN_DATA) {
    1390             :                 /* These (created_by, modified_by) parts of the entry are not relevant for Samba4's use
    1391             :                  * of the Heimdal KDC.  They are stored in the traditional
    1392             :                  * DB for audit purposes, and still form part of the structure
    1393             :                  * we must return */
    1394             : 
    1395             :                 /* use 'whenCreated' */
    1396         264 :                 entry->created_by.time = ldb_msg_find_krb5time_ldap_time(msg, "whenCreated", 0);
    1397             :                 /* use 'kadmin' for now (needed by mit_samba) */
    1398             : 
    1399         264 :                 ret = smb_krb5_make_principal(context,
    1400             :                                               &entry->created_by.principal,
    1401             :                                               lpcfg_realm(lp_ctx), "kadmin", NULL);
    1402         264 :                 if (ret) {
    1403           0 :                         krb5_clear_error_message(context);
    1404           0 :                         goto out;
    1405             :                 }
    1406             : 
    1407         264 :                 entry->modified_by = calloc(1, sizeof(struct sdb_event));
    1408         264 :                 if (entry->modified_by == NULL) {
    1409           0 :                         ret = ENOMEM;
    1410           0 :                         krb5_set_error_message(context, ret, "calloc: out of memory");
    1411           0 :                         goto out;
    1412             :                 }
    1413             : 
    1414             :                 /* use 'whenChanged' */
    1415         264 :                 entry->modified_by->time = ldb_msg_find_krb5time_ldap_time(msg, "whenChanged", 0);
    1416             :                 /* use 'kadmin' for now (needed by mit_samba) */
    1417         264 :                 ret = smb_krb5_make_principal(context,
    1418         264 :                                               &entry->modified_by->principal,
    1419             :                                               lpcfg_realm(lp_ctx), "kadmin", NULL);
    1420         264 :                 if (ret) {
    1421           0 :                         krb5_clear_error_message(context);
    1422           0 :                         goto out;
    1423             :                 }
    1424             :         }
    1425             : 
    1426             : 
    1427             :         /* The lack of password controls etc applies to krbtgt by
    1428             :          * virtue of being that particular RID */
    1429      305574 :         ret = samdb_result_dom_sid_buf(msg, "objectSid", &sid);
    1430      305574 :         if (ret) {
    1431           0 :                 goto out;
    1432             :         }
    1433      305574 :         status = dom_sid_split_rid(NULL, &sid, NULL, &rid);
    1434      305574 :         if (!NT_STATUS_IS_OK(status)) {
    1435           0 :                 ret = EINVAL;
    1436           0 :                 goto out;
    1437             :         }
    1438             : 
    1439      305574 :         if (rid == DOMAIN_RID_KRBTGT) {
    1440      169624 :                 char *realm = NULL;
    1441             : 
    1442      169624 :                 entry->valid_end = NULL;
    1443      169624 :                 entry->pw_end = NULL;
    1444             : 
    1445      169624 :                 entry->flags.invalid = 0;
    1446      169624 :                 entry->flags.server = 1;
    1447             : 
    1448      169624 :                 realm = smb_krb5_principal_get_realm(
    1449             :                         tmp_ctx, context, principal);
    1450      169624 :                 if (realm == NULL) {
    1451           0 :                         ret = ENOMEM;
    1452           0 :                         goto out;
    1453             :                 }
    1454             : 
    1455             :                 /* Don't mark all requests for the krbtgt/realm as
    1456             :                  * 'change password', as otherwise we could get into
    1457             :                  * trouble, and not enforce the password expiry.
    1458             :                  * Instead, only do it when request is for the kpasswd service */
    1459      169624 :                 if (ent_type == SAMBA_KDC_ENT_TYPE_SERVER) {
    1460         257 :                         bool is_changepw = false;
    1461             : 
    1462         257 :                         ret = is_kadmin_changepw(context, principal, &is_changepw);
    1463         257 :                         if (ret) {
    1464           0 :                                 goto out;
    1465             :                         }
    1466             : 
    1467         257 :                         if (is_changepw && lpcfg_is_my_domain_or_realm(lp_ctx, realm)) {
    1468         257 :                                 entry->flags.change_pw = 1;
    1469             :                         }
    1470             :                 }
    1471             : 
    1472      169624 :                 TALLOC_FREE(realm);
    1473             : 
    1474      169624 :                 entry->flags.client = 0;
    1475      169624 :                 entry->flags.forwardable = 1;
    1476      169624 :                 entry->flags.ok_as_delegate = 1;
    1477      135950 :         } else if (is_rodc) {
    1478             :                 /* The RODC krbtgt account is like the main krbtgt,
    1479             :                  * but it does not have a changepw or kadmin
    1480             :                  * service */
    1481             : 
    1482        7026 :                 entry->valid_end = NULL;
    1483        7026 :                 entry->pw_end = NULL;
    1484             : 
    1485             :                 /* Also don't allow the RODC krbtgt to be a client (it should not be needed) */
    1486        7026 :                 entry->flags.client = 0;
    1487        7026 :                 entry->flags.invalid = 0;
    1488        7026 :                 entry->flags.server = 1;
    1489             : 
    1490        7026 :                 entry->flags.client = 0;
    1491        7026 :                 entry->flags.forwardable = 1;
    1492        7026 :                 entry->flags.ok_as_delegate = 0;
    1493      128924 :         } else if (entry->flags.server && ent_type == SAMBA_KDC_ENT_TYPE_SERVER) {
    1494             :                 /* The account/password expiry only applies when the account is used as a
    1495             :                  * client (ie password login), not when used as a server */
    1496             : 
    1497             :                 /* Make very well sure we don't use this for a client,
    1498             :                  * it could bypass the password restrictions */
    1499       27320 :                 entry->flags.client = 0;
    1500             : 
    1501       27320 :                 entry->valid_end = NULL;
    1502       27320 :                 entry->pw_end = NULL;
    1503             : 
    1504             :         } else {
    1505        3448 :                 NTTIME must_change_time
    1506      101604 :                         = samdb_result_nttime(msg,
    1507             :                                         "msDS-UserPasswordExpiryTimeComputed",
    1508             :                                         0);
    1509      101604 :                 if (must_change_time == 0x7FFFFFFFFFFFFFFFULL) {
    1510       17675 :                         entry->pw_end = NULL;
    1511             :                 } else {
    1512       83929 :                         entry->pw_end = malloc(sizeof(*entry->pw_end));
    1513       83929 :                         if (entry->pw_end == NULL) {
    1514           0 :                                 ret = ENOMEM;
    1515           0 :                                 goto out;
    1516             :                         }
    1517       83929 :                         *entry->pw_end = nt_time_to_unix(must_change_time);
    1518             :                 }
    1519             : 
    1520      101604 :                 acct_expiry = samdb_result_account_expires(msg);
    1521      101604 :                 if (acct_expiry == 0x7FFFFFFFFFFFFFFFULL) {
    1522      101604 :                         entry->valid_end = NULL;
    1523             :                 } else {
    1524           0 :                         entry->valid_end = malloc(sizeof(*entry->valid_end));
    1525           0 :                         if (entry->valid_end == NULL) {
    1526           0 :                                 ret = ENOMEM;
    1527           0 :                                 goto out;
    1528             :                         }
    1529           0 :                         *entry->valid_end = nt_time_to_unix(acct_expiry);
    1530             :                 }
    1531             :         }
    1532             : 
    1533      315814 :         ret = samba_kdc_get_entry_principal(context,
    1534             :                                             kdc_db_ctx,
    1535             :                                             samAccountName,
    1536             :                                             ent_type,
    1537             :                                             flags,
    1538      305574 :                                             entry->flags.change_pw,
    1539             :                                             principal,
    1540             :                                             &entry->principal);
    1541      305574 :         if (ret != 0) {
    1542           0 :                 krb5_clear_error_message(context);
    1543           0 :                 goto out;
    1544             :         }
    1545             : 
    1546      305574 :         entry->valid_start = NULL;
    1547             : 
    1548      305574 :         entry->max_life = malloc(sizeof(*entry->max_life));
    1549      305574 :         if (entry->max_life == NULL) {
    1550           0 :                 ret = ENOMEM;
    1551           0 :                 goto out;
    1552             :         }
    1553             : 
    1554      305574 :         if (ent_type == SAMBA_KDC_ENT_TYPE_SERVER) {
    1555       27577 :                 *entry->max_life = kdc_db_ctx->policy.svc_tkt_lifetime;
    1556      277997 :         } else if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT || ent_type == SAMBA_KDC_ENT_TYPE_CLIENT) {
    1557      277871 :                 *entry->max_life = kdc_db_ctx->policy.usr_tkt_lifetime;
    1558             :         } else {
    1559         126 :                 *entry->max_life = MIN(kdc_db_ctx->policy.svc_tkt_lifetime,
    1560             :                                                 kdc_db_ctx->policy.usr_tkt_lifetime);
    1561             :         }
    1562             : 
    1563      305574 :         if (entry->flags.change_pw) {
    1564             :                 /* Limit lifetime of kpasswd tickets to two minutes or less. */
    1565         257 :                 *entry->max_life = MIN(*entry->max_life, CHANGEPW_LIFETIME);
    1566             :         }
    1567             : 
    1568      305574 :         entry->max_renew = malloc(sizeof(*entry->max_renew));
    1569      305574 :         if (entry->max_renew == NULL) {
    1570           0 :                 ret = ENOMEM;
    1571           0 :                 goto out;
    1572             :         }
    1573             : 
    1574      305574 :         *entry->max_renew = kdc_db_ctx->policy.renewal_lifetime;
    1575             : 
    1576             :         /*
    1577             :          * A principal acting as a client that is not being looked up as the
    1578             :          * principal of an armor ticket may have an authentication policy apply
    1579             :          * to it.
    1580             :          *
    1581             :          * We won’t get an authentication policy for the client of an S4U2Self
    1582             :          * or S4U2Proxy request. Those clients are looked up with
    1583             :          * SDB_F_FOR_TGS_REQ instead of with SDB_F_FOR_AS_REQ.
    1584             :          */
    1585      305574 :         if (ent_type == SAMBA_KDC_ENT_TYPE_CLIENT &&
    1586      101488 :             (flags & SDB_F_FOR_AS_REQ) &&
    1587       48894 :             !(flags & SDB_F_ARMOR_PRINCIPAL))
    1588             :         {
    1589       50202 :                 ret = authn_policy_kerberos_client(kdc_db_ctx->samdb, tmp_ctx, msg,
    1590             :                                                    &authn_client_policy);
    1591       50202 :                 if (ret) {
    1592           0 :                         goto out;
    1593             :                 }
    1594             :         }
    1595             : 
    1596             :         /*
    1597             :          * A principal acting as a server may have an authentication policy
    1598             :          * apply to it.
    1599             :          */
    1600      305574 :         if (ent_type == SAMBA_KDC_ENT_TYPE_SERVER) {
    1601       27577 :                 ret = authn_policy_server(kdc_db_ctx->samdb, tmp_ctx, msg,
    1602             :                                           &authn_server_policy);
    1603       27577 :                 if (ret) {
    1604           0 :                         goto out;
    1605             :                 }
    1606             :         }
    1607             : 
    1608      305574 :         enforced_tgt_lifetime_raw = authn_policy_enforced_tgt_lifetime_raw(authn_client_policy);
    1609      305574 :         if (enforced_tgt_lifetime_raw != 0) {
    1610          30 :                 int64_t lifetime_secs = enforced_tgt_lifetime_raw;
    1611             : 
    1612          30 :                 lifetime_secs /= INT64_C(1000) * 1000 * 10;
    1613          30 :                 lifetime_secs = MIN(lifetime_secs, INT_MAX);
    1614          30 :                 lifetime_secs = MAX(lifetime_secs, INT_MIN);
    1615             : 
    1616             :                 /*
    1617             :                  * Set both lifetime and renewal time based only on the
    1618             :                  * configured maximum lifetime — not on the configured renewal
    1619             :                  * time. Yes, this is what Windows does.
    1620             :                  */
    1621          30 :                 lifetime_secs = MIN(*entry->max_life, lifetime_secs);
    1622          30 :                 *entry->max_life = lifetime_secs;
    1623          30 :                 *entry->max_renew = lifetime_secs;
    1624             :         }
    1625             : 
    1626      305574 :         if (ent_type == SAMBA_KDC_ENT_TYPE_CLIENT && (flags & SDB_F_FOR_AS_REQ)) {
    1627        1776 :                 int result;
    1628       50670 :                 const struct auth_user_info_dc *user_info_dc = NULL;
    1629             :                 /*
    1630             :                  * These protections only apply to clients, so servers in the
    1631             :                  * Protected Users group may still have service tickets to them
    1632             :                  * encrypted with RC4. For accounts looked up as servers, note
    1633             :                  * that 'msg' does not contain the 'memberOf' attribute for
    1634             :                  * determining whether the account is a member of Protected
    1635             :                  * Users.
    1636             :                  *
    1637             :                  * Additionally, Microsoft advises that accounts for services
    1638             :                  * and computers should never be members of Protected Users, or
    1639             :                  * they may fail to authenticate.
    1640             :                  */
    1641       50670 :                 ret = samba_kdc_get_user_info_from_db(tmp_ctx,
    1642             :                                                       kdc_db_ctx->samdb,
    1643             :                                                       p,
    1644             :                                                       msg,
    1645             :                                                       &user_info_dc);
    1646       50670 :                 if (ret) {
    1647           0 :                         goto out;
    1648             :                 }
    1649             : 
    1650       52446 :                 result = dsdb_is_protected_user(kdc_db_ctx->samdb,
    1651       50670 :                                                 user_info_dc->sids,
    1652       50670 :                                                 user_info_dc->num_sids);
    1653       50670 :                 if (result == -1) {
    1654           0 :                         ret = EINVAL;
    1655           0 :                         goto out;
    1656             :                 }
    1657             : 
    1658       50670 :                 protected_user = result;
    1659             : 
    1660       50670 :                 if (protected_user) {
    1661          57 :                         entry->flags.forwardable = 0;
    1662          57 :                         entry->flags.proxiable = 0;
    1663             : 
    1664          57 :                         if (enforced_tgt_lifetime_raw == 0) {
    1665             :                                 /*
    1666             :                                  * If a TGT lifetime hasn’t been set, Protected
    1667             :                                  * Users enforces a four hour TGT lifetime.
    1668             :                                  */
    1669          52 :                                 *entry->max_life = MIN(*entry->max_life, 4 * 60 * 60);
    1670          52 :                                 *entry->max_renew = MIN(*entry->max_renew, 4 * 60 * 60);
    1671             :                         }
    1672             :                 }
    1673             :         }
    1674             : 
    1675      305574 :         if (rid == DOMAIN_RID_KRBTGT || is_rodc) {
    1676        6162 :                 bool enable_fast;
    1677             : 
    1678      176650 :                 is_krbtgt = true;
    1679             : 
    1680             :                 /*
    1681             :                  * KDCs (and KDCs on RODCs)
    1682             :                  * ignore msDS-SupportedEncryptionTypes completely
    1683             :                  * but support all supported enctypes by the domain.
    1684             :                  */
    1685      176650 :                 supported_enctypes = domain_enctypes;
    1686             : 
    1687      176650 :                 enable_fast = lpcfg_kdc_enable_fast(kdc_db_ctx->lp_ctx);
    1688      176650 :                 if (enable_fast) {
    1689      164908 :                         supported_enctypes |= ENC_FAST_SUPPORTED;
    1690             :                 }
    1691             : 
    1692      176650 :                 supported_enctypes |= ENC_CLAIMS_SUPPORTED;
    1693      176650 :                 supported_enctypes |= ENC_COMPOUND_IDENTITY_SUPPORTED;
    1694             : 
    1695             :                 /*
    1696             :                  * Resource SID compression is enabled implicitly, unless
    1697             :                  * disabled in msDS-SupportedEncryptionTypes.
    1698             :                  */
    1699             : 
    1700      128924 :         } else if (userAccountControl & (UF_PARTIAL_SECRETS_ACCOUNT|UF_SERVER_TRUST_ACCOUNT)) {
    1701             :                 /*
    1702             :                  * DCs and RODCs computer accounts take
    1703             :                  * msDS-SupportedEncryptionTypes unmodified, but
    1704             :                  * force all enctypes supported by the domain.
    1705             :                  */
    1706       29950 :                 supported_enctypes |= domain_enctypes;
    1707             : 
    1708       98974 :         } else if (ent_type == SAMBA_KDC_ENT_TYPE_CLIENT ||
    1709        3119 :                    (ent_type == SAMBA_KDC_ENT_TYPE_ANY)) {
    1710             :                 /*
    1711             :                  * for AS-REQ the client chooses the enc types it
    1712             :                  * supports, and this will vary between computers a
    1713             :                  * user logs in from. Therefore, so that we accept any
    1714             :                  * of the client's keys for decrypting padata,
    1715             :                  * supported_enctypes should not restrict etype usage.
    1716             :                  *
    1717             :                  * likewise for 'any' return as much as is supported,
    1718             :                  * to export into a keytab.
    1719             :                  */
    1720       91829 :                 supported_enctypes |= ENC_ALL_TYPES;
    1721             :         }
    1722             : 
    1723             :         /* If UF_USE_DES_KEY_ONLY has been set, then don't allow use of the newer enc types */
    1724      305574 :         if (userAccountControl & UF_USE_DES_KEY_ONLY) {
    1725           0 :                 supported_enctypes &= ~ENC_ALL_TYPES;
    1726             :         }
    1727             : 
    1728      305574 :         if (protected_user) {
    1729          57 :                 supported_enctypes &= ~ENC_RC4_HMAC_MD5;
    1730             :         }
    1731             : 
    1732      305574 :         pa_supported_enctypes = supported_enctypes;
    1733      305574 :         supported_session_etypes = supported_enctypes;
    1734      305574 :         if (supported_session_etypes & ENC_HMAC_SHA1_96_AES256_SK) {
    1735       96775 :                 supported_session_etypes |= ENC_HMAC_SHA1_96_AES256;
    1736       96775 :                 supported_session_etypes |= ENC_HMAC_SHA1_96_AES128;
    1737             :         }
    1738      305574 :         if (force_rc4) {
    1739       26531 :                 supported_session_etypes |= ENC_RC4_HMAC_MD5;
    1740             :         }
    1741             :         /*
    1742             :          * now that we remembered what to announce in pa_supported_enctypes
    1743             :          * and normalized ENC_HMAC_SHA1_96_AES256_SK, we restrict the
    1744             :          * rest to the enc types the local kdc supports.
    1745             :          */
    1746      305574 :         supported_enctypes &= kdc_enctypes;
    1747      305574 :         supported_session_etypes &= kdc_enctypes;
    1748             : 
    1749             :         /* Get keys from the db */
    1750      305574 :         ret = samba_kdc_message2entry_keys(context, p,
    1751             :                                            kdc_db_ctx->samdb, msg,
    1752             :                                            is_krbtgt, is_rodc,
    1753             :                                            userAccountControl,
    1754             :                                            ent_type, flags, kvno, entry,
    1755             :                                            supported_enctypes,
    1756             :                                            &available_enctypes);
    1757      305574 :         if (ret) {
    1758             :                 /* Could be bogus data in the entry, or out of memory */
    1759           0 :                 goto out;
    1760             :         }
    1761             : 
    1762             :         /*
    1763             :          * If we only have a nthash stored,
    1764             :          * but a better session key would be
    1765             :          * available, we fallback to fetching the
    1766             :          * RC4_HMAC_MD5, which implicitly also
    1767             :          * would allow an RC4_HMAC_MD5 session key.
    1768             :          * But only if the kdc actually supports
    1769             :          * RC4_HMAC_MD5.
    1770             :          */
    1771      305574 :         if (available_enctypes == 0 &&
    1772        2666 :             (supported_enctypes & ENC_RC4_HMAC_MD5) == 0 &&
    1773         984 :             (supported_enctypes & ~ENC_RC4_HMAC_MD5) != 0 &&
    1774         624 :             (kdc_enctypes & ENC_RC4_HMAC_MD5) != 0)
    1775             :         {
    1776         624 :                 supported_enctypes = ENC_RC4_HMAC_MD5;
    1777         624 :                 ret = samba_kdc_message2entry_keys(context, p,
    1778             :                                                    kdc_db_ctx->samdb, msg,
    1779             :                                                    is_krbtgt, is_rodc,
    1780             :                                                    userAccountControl,
    1781             :                                                    ent_type, flags, kvno, entry,
    1782             :                                                    supported_enctypes,
    1783             :                                                    &available_enctypes);
    1784         624 :                 if (ret) {
    1785             :                         /* Could be bogus data in the entry, or out of memory */
    1786           0 :                         goto out;
    1787             :                 }
    1788             :         }
    1789             : 
    1790             :         /*
    1791             :          * We need to support all session keys enctypes for
    1792             :          * all keys we provide
    1793             :          */
    1794      305574 :         supported_session_etypes |= available_enctypes;
    1795             : 
    1796      305574 :         ret = sdb_entry_set_etypes(entry);
    1797      305574 :         if (ret) {
    1798           0 :                 goto out;
    1799             :         }
    1800             : 
    1801      305574 :         if (entry->flags.server) {
    1802      222550 :                 bool add_aes256 =
    1803      222550 :                         supported_session_etypes & KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96;
    1804      222550 :                 bool add_aes128 =
    1805      222550 :                         supported_session_etypes & KERB_ENCTYPE_AES128_CTS_HMAC_SHA1_96;
    1806      222550 :                 bool add_rc4 =
    1807      222550 :                         supported_session_etypes & ENC_RC4_HMAC_MD5;
    1808      222550 :                 ret = sdb_entry_set_session_etypes(entry,
    1809             :                                                    add_aes256,
    1810             :                                                    add_aes128,
    1811             :                                                    add_rc4);
    1812      222550 :                 if (ret) {
    1813           0 :                         goto out;
    1814             :                 }
    1815             :         }
    1816             : 
    1817      305574 :         if (entry->keys.len != 0) {
    1818             :                 /*
    1819             :                  * FIXME: Currently limited to Heimdal so as not to
    1820             :                  * break MIT KDCs, for which no fix is available.
    1821             :                  */
    1822             : #ifdef SAMBA4_USES_HEIMDAL
    1823      303298 :                 if (is_krbtgt) {
    1824             :                         /*
    1825             :                          * The krbtgt account, having no reason to
    1826             :                          * issue tickets encrypted in weaker keys,
    1827             :                          * shall only make available its strongest
    1828             :                          * key. All weaker keys are stripped out. This
    1829             :                          * makes it impossible for an RC4-encrypted
    1830             :                          * TGT to be accepted when AES KDC keys exist.
    1831             :                          *
    1832             :                          * This controls the ticket key and so the PAC
    1833             :                          * signature algorithms indirectly, preventing
    1834             :                          * a weak KDC checksum from being accepted
    1835             :                          * when we verify the signatures for an
    1836             :                          * S4U2Proxy evidence ticket. As such, this is
    1837             :                          * indispensable for addressing
    1838             :                          * CVE-2022-37966.
    1839             :                          *
    1840             :                          * Being strict here also provides protection
    1841             :                          * against possible future attacks on weak
    1842             :                          * keys.
    1843             :                          */
    1844             : 
    1845             :                         /*
    1846             :                          * The krbtgt account is never a Group Managed Service
    1847             :                          * Account, but a similar system might well be
    1848             :                          * implemented as a means of having the krbtgt’s keys
    1849             :                          * roll over automatically. In that case, thought might
    1850             :                          * be given as to how this security measure — of
    1851             :                          * stripping out weaker keys — would interact with key
    1852             :                          * management.
    1853             :                          */
    1854             : 
    1855      176493 :                         entry->keys.len = 1;
    1856      176493 :                         if (entry->etypes != NULL) {
    1857      176493 :                                 entry->etypes->len = MIN(entry->etypes->len, 1);
    1858             :                         }
    1859      176493 :                         entry->old_keys.len = MIN(entry->old_keys.len, 1);
    1860      176493 :                         entry->older_keys.len = MIN(entry->older_keys.len, 1);
    1861             :                 }
    1862             : #endif
    1863        2042 :         } else if (kdc_db_ctx->rodc) {
    1864             :                 /*
    1865             :                  * We are on an RODC, but don't have keys for this
    1866             :                  * account.  Signal this to the caller
    1867             :                  */
    1868        1670 :                 auth_sam_trigger_repl_secret(kdc_db_ctx,
    1869             :                                              kdc_db_ctx->msg_ctx,
    1870             :                                              kdc_db_ctx->ev_ctx,
    1871             :                                              msg->dn);
    1872        1670 :                 ret = SDB_ERR_NOT_FOUND_HERE;
    1873        1670 :                 goto out;
    1874             :         } else {
    1875             :                 /*
    1876             :                  * oh, no password.  Apparently (comment in
    1877             :                  * hdb-ldap.c) this violates the ASN.1, but this
    1878             :                  * allows an entry with no keys (yet).
    1879             :                  */
    1880       10240 :         }
    1881             : 
    1882      303904 :         p->msg = talloc_steal(p, msg);
    1883      303904 :         p->supported_enctypes = pa_supported_enctypes;
    1884             : 
    1885      303904 :         p->client_policy = talloc_steal(p, authn_client_policy);
    1886      303904 :         p->server_policy = talloc_steal(p, authn_server_policy);
    1887             : 
    1888      303904 :         talloc_steal(kdc_db_ctx, p);
    1889             : 
    1890      306249 : out:
    1891      306249 :         if (ret != 0) {
    1892             :                 /* This doesn't free ent itself, that is for the eventual caller to do */
    1893        2345 :                 sdb_entry_free(entry);
    1894             :         }
    1895             : 
    1896      306249 :         talloc_free(tmp_ctx);
    1897      306249 :         return ret;
    1898             : }
    1899             : 
    1900             : struct samba_kdc_trust_keys {
    1901             :         struct sdb_keys *skeys;
    1902             :         uint32_t kvno;
    1903             :         uint32_t *returned_kvno;
    1904             :         uint32_t supported_enctypes;
    1905             :         uint32_t *available_enctypes;
    1906             :         krb5_const_principal salt_principal;
    1907             :         const struct AuthenticationInformationArray *auth_array;
    1908             : };
    1909             : 
    1910        2105 : static krb5_error_code samba_kdc_fill_trust_keys(krb5_context context,
    1911             :                                                  struct samba_kdc_trust_keys *p)
    1912             : {
    1913             :         /*
    1914             :          * Make sure we'll never reveal DES keys
    1915             :          */
    1916        2105 :         uint32_t supported_enctypes = p->supported_enctypes &= ~(ENC_CRC32 | ENC_RSA_MD5);
    1917        2105 :         uint32_t _available_enctypes = 0;
    1918        2105 :         uint32_t *available_enctypes = p->available_enctypes;
    1919        2105 :         uint32_t _returned_kvno = 0;
    1920        2105 :         uint32_t *returned_kvno = p->returned_kvno;
    1921        2105 :         TALLOC_CTX *frame = talloc_stackframe();
    1922        2105 :         const struct AuthenticationInformationArray *aa = p->auth_array;
    1923        2105 :         DATA_BLOB password_utf16 = { .length = 0, };
    1924        2105 :         DATA_BLOB password_utf8 = { .length = 0, };
    1925        2105 :         struct samr_Password _password_hash = { .hash = { 0,}, };
    1926        2105 :         const struct samr_Password *password_hash = NULL;
    1927        2105 :         uint32_t allocated_keys = 0;
    1928           0 :         uint32_t i;
    1929           0 :         int ret;
    1930             : 
    1931        2105 :         if (available_enctypes == NULL) {
    1932           0 :                 available_enctypes = &_available_enctypes;
    1933             :         }
    1934             : 
    1935        2105 :         *available_enctypes = 0;
    1936             : 
    1937        2105 :         if (returned_kvno == NULL) {
    1938           0 :                 returned_kvno = &_returned_kvno;
    1939             :         }
    1940             : 
    1941        2105 :         *returned_kvno = p->kvno;
    1942             : 
    1943        2105 :         for (i=0; i < aa->count; i++) {
    1944        2105 :                 if (aa->array[i].AuthType == TRUST_AUTH_TYPE_CLEAR) {
    1945        2105 :                         const struct AuthInfoClear *clear =
    1946        2105 :                                 &aa->array[i].AuthInfo.clear;
    1947           0 :                         bool ok;
    1948             : 
    1949        2105 :                         password_utf16 = data_blob_const(clear->password,
    1950        2105 :                                                          clear->size);
    1951        2105 :                         if (password_utf16.length == 0) {
    1952           0 :                                 break;
    1953             :                         }
    1954             : 
    1955        2105 :                         if (supported_enctypes & ENC_RC4_HMAC_MD5) {
    1956         102 :                                 mdfour(_password_hash.hash,
    1957         102 :                                        password_utf16.data,
    1958         102 :                                        password_utf16.length);
    1959         102 :                                 if (password_hash == NULL) {
    1960         102 :                                         allocated_keys += 1;
    1961             :                                 }
    1962         102 :                                 password_hash = &_password_hash;
    1963             :                         }
    1964             : 
    1965        2105 :                         if (!(supported_enctypes & (ENC_HMAC_SHA1_96_AES128|ENC_HMAC_SHA1_96_AES256))) {
    1966         102 :                                 break;
    1967             :                         }
    1968             : 
    1969        2003 :                         ok = convert_string_talloc(frame,
    1970             :                                                    CH_UTF16MUNGED, CH_UTF8,
    1971        2003 :                                                    password_utf16.data,
    1972             :                                                    password_utf16.length,
    1973             :                                                    &password_utf8.data,
    1974             :                                                    &password_utf8.length);
    1975        2003 :                         if (!ok) {
    1976           0 :                                 krb5_clear_error_message(context);
    1977           0 :                                 ret = ENOMEM;
    1978           0 :                                 goto fail;
    1979             :                         }
    1980             : 
    1981        2003 :                         if (supported_enctypes & ENC_HMAC_SHA1_96_AES128) {
    1982         131 :                                 allocated_keys += 1;
    1983             :                         }
    1984        2003 :                         if (supported_enctypes & ENC_HMAC_SHA1_96_AES256) {
    1985        2003 :                                 allocated_keys += 1;
    1986             :                         }
    1987        2003 :                         break;
    1988           0 :                 } else if (aa->array[i].AuthType == TRUST_AUTH_TYPE_NT4OWF) {
    1989           0 :                         const struct AuthInfoNT4Owf *nt4owf =
    1990           0 :                                 &aa->array[i].AuthInfo.nt4owf;
    1991             : 
    1992           0 :                         if (supported_enctypes & ENC_RC4_HMAC_MD5) {
    1993           0 :                                 password_hash = &nt4owf->password;
    1994           0 :                                 allocated_keys += 1;
    1995             :                         }
    1996             :                 }
    1997             :         }
    1998             : 
    1999        2105 :         allocated_keys = MAX(1, allocated_keys);
    2000             : 
    2001             :         /* allocate space to decode into */
    2002        2105 :         p->skeys->len = 0;
    2003        2105 :         p->skeys->val = calloc(allocated_keys, sizeof(struct sdb_key));
    2004        2105 :         if (p->skeys->val == NULL) {
    2005           0 :                 krb5_clear_error_message(context);
    2006           0 :                 ret = ENOMEM;
    2007           0 :                 goto fail;
    2008             :         }
    2009             : 
    2010        2105 :         if (password_utf8.length != 0) {
    2011        2003 :                 struct sdb_key key = {};
    2012           0 :                 krb5_data salt;
    2013           0 :                 krb5_data cleartext_data;
    2014             : 
    2015        2003 :                 cleartext_data.data = discard_const_p(char, password_utf8.data);
    2016        2003 :                 cleartext_data.length = password_utf8.length;
    2017             : 
    2018        2003 :                 ret = smb_krb5_get_pw_salt(context,
    2019             :                                            p->salt_principal,
    2020             :                                            &salt);
    2021        2003 :                 if (ret != 0) {
    2022           0 :                         goto fail;
    2023             :                 }
    2024             : 
    2025        2003 :                 if (supported_enctypes & ENC_HMAC_SHA1_96_AES256) {
    2026        2003 :                         key.salt = calloc(1, sizeof(*key.salt));
    2027        2003 :                         if (key.salt == NULL) {
    2028           0 :                                 smb_krb5_free_data_contents(context, &salt);
    2029           0 :                                 ret = ENOMEM;
    2030           0 :                                 goto fail;
    2031             :                         }
    2032             : 
    2033        2003 :                         key.salt->type = KRB5_PW_SALT;
    2034             : 
    2035        2003 :                         ret = smb_krb5_copy_data_contents(&key.salt->salt,
    2036        2003 :                                                           salt.data,
    2037           0 :                                                           salt.length);
    2038        2003 :                         if (ret) {
    2039           0 :                                 *key.salt = (struct sdb_salt) {};
    2040           0 :                                 sdb_key_free(&key);
    2041           0 :                                 smb_krb5_free_data_contents(context, &salt);
    2042           0 :                                 goto fail;
    2043             :                         }
    2044             : 
    2045        2003 :                         ret = smb_krb5_create_key_from_string(context,
    2046             :                                                               p->salt_principal,
    2047             :                                                               &salt,
    2048             :                                                               &cleartext_data,
    2049             :                                                               ENCTYPE_AES256_CTS_HMAC_SHA1_96,
    2050             :                                                               &key.key);
    2051        2003 :                         if (ret == 0) {
    2052        2003 :                                 p->skeys->val[p->skeys->len++] = key;
    2053        2003 :                                 *available_enctypes |= ENC_HMAC_SHA1_96_AES256;
    2054           0 :                         } else if (ret == KRB5_PROG_ETYPE_NOSUPP) {
    2055           0 :                                 DBG_NOTICE("Unsupported keytype ignored - type %u\n",
    2056             :                                            ENCTYPE_AES256_CTS_HMAC_SHA1_96);
    2057           0 :                                 ZERO_STRUCT(key.key);
    2058           0 :                                 sdb_key_free(&key);
    2059           0 :                                 ret = 0;
    2060             :                         }
    2061        2003 :                         if (ret != 0) {
    2062           0 :                                 ZERO_STRUCT(key.key);
    2063           0 :                                 sdb_key_free(&key);
    2064           0 :                                 smb_krb5_free_data_contents(context, &salt);
    2065           0 :                                 goto fail;
    2066             :                         }
    2067             :                 }
    2068             : 
    2069        2003 :                 if (supported_enctypes & ENC_HMAC_SHA1_96_AES128) {
    2070         131 :                         key.salt = calloc(1, sizeof(*key.salt));
    2071         131 :                         if (key.salt == NULL) {
    2072           0 :                                 smb_krb5_free_data_contents(context, &salt);
    2073           0 :                                 ret = ENOMEM;
    2074           0 :                                 goto fail;
    2075             :                         }
    2076             : 
    2077         131 :                         key.salt->type = KRB5_PW_SALT;
    2078             : 
    2079         131 :                         ret = smb_krb5_copy_data_contents(&key.salt->salt,
    2080         131 :                                                           salt.data,
    2081           0 :                                                           salt.length);
    2082         131 :                         if (ret) {
    2083           0 :                                 *key.salt = (struct sdb_salt) {};
    2084           0 :                                 sdb_key_free(&key);
    2085           0 :                                 smb_krb5_free_data_contents(context, &salt);
    2086           0 :                                 goto fail;
    2087             :                         }
    2088             : 
    2089         131 :                         ret = smb_krb5_create_key_from_string(context,
    2090             :                                                               p->salt_principal,
    2091             :                                                               &salt,
    2092             :                                                               &cleartext_data,
    2093             :                                                               ENCTYPE_AES128_CTS_HMAC_SHA1_96,
    2094             :                                                               &key.key);
    2095         131 :                         if (ret == 0) {
    2096         131 :                                 p->skeys->val[p->skeys->len++] = key;
    2097         131 :                                 *available_enctypes |= ENC_HMAC_SHA1_96_AES128;
    2098           0 :                         } else if (ret == KRB5_PROG_ETYPE_NOSUPP) {
    2099           0 :                                 DBG_NOTICE("Unsupported keytype ignored - type %u\n",
    2100             :                                            ENCTYPE_AES128_CTS_HMAC_SHA1_96);
    2101           0 :                                 ZERO_STRUCT(key.key);
    2102           0 :                                 sdb_key_free(&key);
    2103           0 :                                 ret = 0;
    2104             :                         }
    2105         131 :                         if (ret != 0) {
    2106           0 :                                 ZERO_STRUCT(key.key);
    2107           0 :                                 sdb_key_free(&key);
    2108           0 :                                 smb_krb5_free_data_contents(context, &salt);
    2109           0 :                                 goto fail;
    2110             :                         }
    2111             :                 }
    2112             : 
    2113        2003 :                 smb_krb5_free_data_contents(context, &salt);
    2114             :         }
    2115             : 
    2116        2105 :         if (password_hash != NULL) {
    2117         102 :                 struct sdb_key key = {};
    2118             : 
    2119         102 :                 ret = smb_krb5_keyblock_init_contents(context,
    2120             :                                                       ENCTYPE_ARCFOUR_HMAC,
    2121         102 :                                                       password_hash->hash,
    2122             :                                                       sizeof(password_hash->hash),
    2123             :                                                       &key.key);
    2124         102 :                 if (ret == 0) {
    2125         102 :                         p->skeys->val[p->skeys->len++] = key;
    2126             : 
    2127         102 :                         *available_enctypes |= ENC_RC4_HMAC_MD5;
    2128           0 :                 } else if (ret == KRB5_PROG_ETYPE_NOSUPP) {
    2129           0 :                         DEBUG(2,("Unsupported keytype ignored - type %u\n",
    2130             :                                  ENCTYPE_ARCFOUR_HMAC));
    2131           0 :                         ZERO_STRUCT(key.key);
    2132           0 :                         sdb_key_free(&key);
    2133           0 :                         ret = 0;
    2134             :                 }
    2135         102 :                 if (ret != 0) {
    2136           0 :                         ZERO_STRUCT(key.key);
    2137           0 :                         sdb_key_free(&key);
    2138           0 :                         goto fail;
    2139             :                 }
    2140             :         }
    2141             : 
    2142        2105 :         samba_kdc_sort_keys(p->skeys);
    2143             : 
    2144        2105 :         return 0;
    2145           0 : fail:
    2146           0 :         sdb_keys_free(p->skeys);
    2147           0 :         TALLOC_FREE(frame);
    2148           0 :         return ret;
    2149             : }
    2150             : 
    2151             : /*
    2152             :  * Construct an hdb_entry from a directory entry.
    2153             :  * The kvno is what the remote client asked for
    2154             :  */
    2155        2107 : static krb5_error_code samba_kdc_trust_message2entry(krb5_context context,
    2156             :                                                struct samba_kdc_db_context *kdc_db_ctx,
    2157             :                                                TALLOC_CTX *mem_ctx,
    2158             :                                                enum trust_direction direction,
    2159             :                                                struct ldb_dn *realm_dn,
    2160             :                                                unsigned flags,
    2161             :                                                uint32_t kvno,
    2162             :                                                struct ldb_message *msg,
    2163             :                                                struct sdb_entry *entry)
    2164             : {
    2165        2107 :         TALLOC_CTX *tmp_ctx = NULL;
    2166        2107 :         struct loadparm_context *lp_ctx = kdc_db_ctx->lp_ctx;
    2167        2107 :         const char *our_realm = lpcfg_realm(lp_ctx);
    2168        2107 :         char *partner_realm = NULL;
    2169        2107 :         const char *realm = NULL;
    2170        2107 :         const char *krbtgt_realm = NULL;
    2171           0 :         const struct ldb_val *password_val;
    2172           0 :         struct trustAuthInOutBlob password_blob;
    2173           0 :         struct samba_kdc_entry *p;
    2174        2107 :         bool use_previous = false;
    2175        2107 :         bool include_previous = false;
    2176           0 :         uint32_t current_kvno;
    2177           0 :         uint32_t previous_kvno;
    2178        2107 :         struct samba_kdc_trust_keys current_keys = {};
    2179        2107 :         struct samba_kdc_trust_keys previous_keys = {};
    2180           0 :         enum ndr_err_code ndr_err;
    2181           0 :         int ret;
    2182           0 :         unsigned int i;
    2183           0 :         struct timeval tv;
    2184           0 :         NTTIME an_hour_ago;
    2185        2107 :         bool prefer_current = false;
    2186        2107 :         bool force_rc4 = lpcfg_kdc_force_enable_rc4_weak_session_keys(lp_ctx);
    2187        2107 :         uint32_t supported_enctypes = ENC_RC4_HMAC_MD5;
    2188           0 :         uint32_t pa_supported_enctypes;
    2189           0 :         uint32_t supported_session_etypes;
    2190        2107 :         uint32_t config_kdc_enctypes = lpcfg_kdc_supported_enctypes(lp_ctx);
    2191        2107 :         uint32_t kdc_enctypes =
    2192             :                 config_kdc_enctypes != 0 ?
    2193        2107 :                 config_kdc_enctypes :
    2194             :                 ENC_ALL_TYPES;
    2195        2107 :         struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
    2196           0 :         NTSTATUS status;
    2197        2107 :         uint32_t returned_kvno = 0;
    2198        2107 :         uint32_t available_enctypes = 0;
    2199             : 
    2200        2107 :         *entry = (struct sdb_entry) {};
    2201             : 
    2202        2107 :         tmp_ctx = talloc_new(mem_ctx);
    2203        2107 :         if (tmp_ctx == NULL) {
    2204           0 :                 return ENOMEM;
    2205             :         }
    2206             : 
    2207        2107 :         if (dsdb_functional_level(kdc_db_ctx->samdb) >= DS_DOMAIN_FUNCTION_2008) {
    2208             :                 /* If not told otherwise, Windows now assumes that trusts support AES. */
    2209        2054 :                 supported_enctypes = ldb_msg_find_attr_as_uint(msg,
    2210             :                                         "msDS-SupportedEncryptionTypes",
    2211             :                                         ENC_HMAC_SHA1_96_AES256);
    2212             :         }
    2213             : 
    2214        2107 :         pa_supported_enctypes = supported_enctypes;
    2215        2107 :         supported_session_etypes = supported_enctypes;
    2216        2107 :         if (supported_session_etypes & ENC_HMAC_SHA1_96_AES256_SK) {
    2217           0 :                 supported_session_etypes |= ENC_HMAC_SHA1_96_AES256;
    2218           0 :                 supported_session_etypes |= ENC_HMAC_SHA1_96_AES128;
    2219             :         }
    2220        2107 :         if (force_rc4) {
    2221           0 :                 supported_session_etypes |= ENC_RC4_HMAC_MD5;
    2222             :         }
    2223             :         /*
    2224             :          * now that we remembered what to announce in pa_supported_enctypes
    2225             :          * and normalized ENC_HMAC_SHA1_96_AES256_SK, we restrict the
    2226             :          * rest to the enc types the local kdc supports.
    2227             :          */
    2228        2107 :         supported_enctypes &= kdc_enctypes;
    2229        2107 :         supported_session_etypes &= kdc_enctypes;
    2230             : 
    2231        2107 :         status = dsdb_trust_parse_tdo_info(tmp_ctx, msg, &tdo);
    2232        2107 :         if (!NT_STATUS_IS_OK(status)) {
    2233           0 :                 krb5_clear_error_message(context);
    2234           0 :                 ret = ENOMEM;
    2235           0 :                 goto out;
    2236             :         }
    2237             : 
    2238        2107 :         if (!(tdo->trust_direction & direction)) {
    2239           2 :                 krb5_clear_error_message(context);
    2240           2 :                 ret = SDB_ERR_NOENTRY;
    2241           2 :                 goto out;
    2242             :         }
    2243             : 
    2244        2105 :         if (tdo->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
    2245             :                 /*
    2246             :                  * Only UPLEVEL domains support kerberos here,
    2247             :                  * as we don't support LSA_TRUST_TYPE_MIT.
    2248             :                  */
    2249           0 :                 krb5_clear_error_message(context);
    2250           0 :                 ret = SDB_ERR_NOENTRY;
    2251           0 :                 goto out;
    2252             :         }
    2253             : 
    2254        2105 :         if (tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_CROSS_ORGANIZATION) {
    2255             :                 /*
    2256             :                  * We don't support selective authentication yet.
    2257             :                  */
    2258           0 :                 krb5_clear_error_message(context);
    2259           0 :                 ret = SDB_ERR_NOENTRY;
    2260           0 :                 goto out;
    2261             :         }
    2262             : 
    2263        2105 :         if (tdo->domain_name.string == NULL) {
    2264           0 :                 krb5_clear_error_message(context);
    2265           0 :                 ret = SDB_ERR_NOENTRY;
    2266           0 :                 goto out;
    2267             :         }
    2268        2105 :         partner_realm = strupper_talloc(tmp_ctx, tdo->domain_name.string);
    2269        2105 :         if (partner_realm == NULL) {
    2270           0 :                 krb5_clear_error_message(context);
    2271           0 :                 ret = ENOMEM;
    2272           0 :                 goto out;
    2273             :         }
    2274             : 
    2275        2105 :         if (direction == INBOUND) {
    2276        1986 :                 realm = our_realm;
    2277        1986 :                 krbtgt_realm = partner_realm;
    2278             : 
    2279        1986 :                 password_val = ldb_msg_find_ldb_val(msg, "trustAuthIncoming");
    2280             :         } else { /* OUTBOUND */
    2281         119 :                 realm = partner_realm;
    2282         119 :                 krbtgt_realm = our_realm;
    2283             : 
    2284         119 :                 password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
    2285             :         }
    2286             : 
    2287        2105 :         if (password_val == NULL) {
    2288           0 :                 krb5_clear_error_message(context);
    2289           0 :                 ret = SDB_ERR_NOENTRY;
    2290           0 :                 goto out;
    2291             :         }
    2292             : 
    2293        2105 :         ndr_err = ndr_pull_struct_blob(password_val, tmp_ctx, &password_blob,
    2294             :                                        (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
    2295        2105 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    2296           0 :                 krb5_clear_error_message(context);
    2297           0 :                 ret = EINVAL;
    2298           0 :                 goto out;
    2299             :         }
    2300             : 
    2301        2105 :         p = talloc_zero(tmp_ctx, struct samba_kdc_entry);
    2302        2105 :         if (!p) {
    2303           0 :                 ret = ENOMEM;
    2304           0 :                 goto out;
    2305             :         }
    2306             : 
    2307        2105 :         p->is_trust = true;
    2308        2105 :         p->kdc_db_ctx = kdc_db_ctx;
    2309        2105 :         p->realm_dn = realm_dn;
    2310        2105 :         p->supported_enctypes = pa_supported_enctypes;
    2311             : 
    2312        2105 :         talloc_set_destructor(p, samba_kdc_entry_destructor);
    2313             : 
    2314        2105 :         entry->skdc_entry = p;
    2315             : 
    2316             :         /* use 'whenCreated' */
    2317        2105 :         entry->created_by.time = ldb_msg_find_krb5time_ldap_time(msg, "whenCreated", 0);
    2318             :         /* use 'kadmin' for now (needed by mit_samba) */
    2319        2105 :         ret = smb_krb5_make_principal(context,
    2320             :                                       &entry->created_by.principal,
    2321             :                                       realm, "kadmin", NULL);
    2322        2105 :         if (ret) {
    2323           0 :                 krb5_clear_error_message(context);
    2324           0 :                 goto out;
    2325             :         }
    2326             : 
    2327             :         /*
    2328             :          * We always need to generate the canonicalized principal
    2329             :          * with the values of our database.
    2330             :          */
    2331        2105 :         ret = smb_krb5_make_principal(context, &entry->principal, realm,
    2332             :                                       "krbtgt", krbtgt_realm, NULL);
    2333        2105 :         if (ret) {
    2334           0 :                 krb5_clear_error_message(context);
    2335           0 :                 goto out;
    2336             :         }
    2337        2105 :         smb_krb5_principal_set_type(context, entry->principal,
    2338             :                                     KRB5_NT_SRV_INST);
    2339             : 
    2340        2105 :         entry->valid_start = NULL;
    2341             : 
    2342             :         /* we need to work out if we are going to use the current or
    2343             :          * the previous password hash.
    2344             :          * We base this on the kvno the client passes in. If the kvno
    2345             :          * passed in is equal to the current kvno in our database then
    2346             :          * we use the current structure. If it is the current kvno-1,
    2347             :          * then we use the previous substructure.
    2348             :          */
    2349             : 
    2350             :         /*
    2351             :          * Windows prefers the previous key for one hour.
    2352             :          */
    2353        2105 :         tv = timeval_current();
    2354        2105 :         if (tv.tv_sec > 3600) {
    2355        2105 :                 tv.tv_sec -= 3600;
    2356             :         }
    2357        2105 :         an_hour_ago = timeval_to_nttime(&tv);
    2358             : 
    2359             :         /* first work out the current kvno */
    2360        2105 :         current_kvno = 0;
    2361        5900 :         for (i=0; i < password_blob.count; i++) {
    2362        3795 :                 struct AuthenticationInformation *a =
    2363        3795 :                         &password_blob.current.array[i];
    2364             : 
    2365        3795 :                 if (a->LastUpdateTime <= an_hour_ago) {
    2366           0 :                         prefer_current = true;
    2367             :                 }
    2368             : 
    2369        3795 :                 if (a->AuthType == TRUST_AUTH_TYPE_VERSION) {
    2370        1690 :                         current_kvno = a->AuthInfo.version.version;
    2371             :                 }
    2372             :         }
    2373        2105 :         if (current_kvno == 0) {
    2374         415 :                 previous_kvno = 255;
    2375             :         } else {
    2376        1690 :                 previous_kvno = current_kvno - 1;
    2377             :         }
    2378        5900 :         for (i=0; i < password_blob.count; i++) {
    2379        3795 :                 struct AuthenticationInformation *a =
    2380        3795 :                         &password_blob.previous.array[i];
    2381             : 
    2382        3795 :                 if (a->AuthType == TRUST_AUTH_TYPE_VERSION) {
    2383         624 :                         previous_kvno = a->AuthInfo.version.version;
    2384             :                 }
    2385             :         }
    2386             : 
    2387             :         /* work out whether we will use the previous or current
    2388             :            password */
    2389        2105 :         if (password_blob.previous.count == 0) {
    2390             :                 /* there is no previous password */
    2391           0 :                 use_previous = false;
    2392        2105 :         } else if (!(flags & SDB_F_KVNO_SPECIFIED)) {
    2393             :                 /*
    2394             :                  * If not specified we use the lowest kvno
    2395             :                  * for the first hour after an update.
    2396             :                  */
    2397        2105 :                 if (prefer_current) {
    2398           0 :                         use_previous = false;
    2399        2105 :                 } else if (previous_kvno < current_kvno) {
    2400        1690 :                         use_previous = true;
    2401             :                 } else {
    2402         415 :                         use_previous = false;
    2403             :                 }
    2404             : 
    2405        2105 :                 if (flags & SDB_F_ADMIN_DATA) {
    2406             :                         /*
    2407             :                          * let admin tool
    2408             :                          * get to all keys
    2409             :                          */
    2410           0 :                         use_previous = false;
    2411           0 :                         include_previous = true;
    2412             :                 }
    2413           0 :         } else if (kvno == current_kvno) {
    2414             :                 /*
    2415             :                  * Exact match ...
    2416             :                  */
    2417           0 :                 use_previous = false;
    2418           0 :         } else if (kvno == previous_kvno) {
    2419             :                 /*
    2420             :                  * Exact match ...
    2421             :                  */
    2422           0 :                 use_previous = true;
    2423             :         } else {
    2424             :                 /*
    2425             :                  * Fallback to the current one for anything else
    2426             :                  */
    2427           0 :                 use_previous = false;
    2428             :         }
    2429             : 
    2430        2105 :         current_keys = (struct samba_kdc_trust_keys) {
    2431             :                 .kvno = current_kvno,
    2432             :                 .supported_enctypes = supported_enctypes,
    2433        2105 :                 .salt_principal = entry->principal,
    2434             :                 .auth_array = &password_blob.current,
    2435             :         };
    2436             : 
    2437        2105 :         previous_keys = (struct samba_kdc_trust_keys) {
    2438             :                 .kvno = previous_kvno,
    2439             :                 .supported_enctypes = supported_enctypes,
    2440        2105 :                 .salt_principal = entry->principal,
    2441             :                 .auth_array = &password_blob.previous,
    2442             :         };
    2443             : 
    2444        2105 :         if (use_previous) {
    2445             :                 /*
    2446             :                  * return the old keys as default keys
    2447             :                  * with the requested kvno.
    2448             :                  */
    2449        1690 :                 previous_keys.skeys = &entry->keys;
    2450        1690 :                 previous_keys.available_enctypes = &available_enctypes;
    2451        1690 :                 previous_keys.returned_kvno = &returned_kvno;
    2452             :         } else {
    2453             :                 /*
    2454             :                  * return the current keys as default keys
    2455             :                  * with the requested kvno.
    2456             :                  */
    2457         415 :                 current_keys.skeys = &entry->keys;
    2458         415 :                 current_keys.available_enctypes = &available_enctypes;
    2459         415 :                 current_keys.returned_kvno = &returned_kvno;
    2460             : 
    2461         415 :                 if (include_previous) {
    2462             :                         /*
    2463             :                          * return the old keys in addition.
    2464             :                          */
    2465           0 :                         previous_keys.skeys = &entry->old_keys;
    2466             :                 }
    2467             :         }
    2468             : 
    2469        2105 :         if (current_keys.skeys != NULL) {
    2470         415 :                 ret = samba_kdc_fill_trust_keys(context, &current_keys);
    2471         415 :                 if (ret != 0) {
    2472           0 :                         goto out;
    2473             :                 }
    2474             :         }
    2475             : 
    2476        2105 :         if (previous_keys.skeys != NULL) {
    2477        1690 :                 ret = samba_kdc_fill_trust_keys(context, &previous_keys);
    2478        1690 :                 if (ret != 0) {
    2479           0 :                         goto out;
    2480             :                 }
    2481             :         }
    2482             : 
    2483             :         /* use the kvno the client specified, if available */
    2484        2105 :         if (flags & SDB_F_KVNO_SPECIFIED) {
    2485           0 :                 returned_kvno = kvno;
    2486             :         }
    2487             : 
    2488             :         /* Must have found a cleartext or MD4 password */
    2489        2105 :         if (entry->keys.len == 0) {
    2490           0 :                 DBG_WARNING("no usable key found\n");
    2491           0 :                 krb5_clear_error_message(context);
    2492           0 :                 ret = SDB_ERR_NOENTRY;
    2493           0 :                 goto out;
    2494             :         }
    2495             : 
    2496        2105 :         entry->flags = (struct SDBFlags) {};
    2497        2105 :         entry->flags.immutable = 1;
    2498        2105 :         entry->flags.invalid = 0;
    2499        2105 :         entry->flags.server = 1;
    2500        2105 :         entry->flags.require_preauth = 1;
    2501             : 
    2502        2105 :         entry->pw_end = NULL;
    2503             : 
    2504        2105 :         entry->max_life = NULL;
    2505             : 
    2506        2105 :         entry->max_renew = NULL;
    2507             : 
    2508             :         /* Match Windows behavior and allow forwardable flag in cross-realm. */
    2509        2105 :         entry->flags.forwardable = 1;
    2510             : 
    2511        2105 :         entry->kvno = returned_kvno;
    2512             : 
    2513             :         /*
    2514             :          * We need to support all session keys enctypes for
    2515             :          * all keys we provide
    2516             :          */
    2517        2105 :         supported_session_etypes |= available_enctypes;
    2518             : 
    2519        2105 :         ret = sdb_entry_set_etypes(entry);
    2520        2105 :         if (ret) {
    2521           0 :                 goto out;
    2522             :         }
    2523             : 
    2524             :         {
    2525        2105 :                 bool add_aes256 =
    2526        2105 :                         supported_session_etypes & KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96;
    2527        2105 :                 bool add_aes128 =
    2528        2105 :                         supported_session_etypes & KERB_ENCTYPE_AES128_CTS_HMAC_SHA1_96;
    2529        2105 :                 bool add_rc4 =
    2530        2105 :                         supported_session_etypes & ENC_RC4_HMAC_MD5;
    2531        2105 :                 ret = sdb_entry_set_session_etypes(entry,
    2532             :                                                    add_aes256,
    2533             :                                                    add_aes128,
    2534             :                                                    add_rc4);
    2535        2105 :                 if (ret) {
    2536           0 :                         goto out;
    2537             :                 }
    2538             :         }
    2539             : 
    2540        2105 :         p->msg = talloc_steal(p, msg);
    2541             : 
    2542        2105 :         talloc_steal(kdc_db_ctx, p);
    2543             : 
    2544        2107 : out:
    2545        2107 :         TALLOC_FREE(partner_realm);
    2546             : 
    2547        2107 :         if (ret != 0) {
    2548             :                 /* This doesn't free ent itself, that is for the eventual caller to do */
    2549           2 :                 sdb_entry_free(entry);
    2550             :         }
    2551             : 
    2552        2107 :         talloc_free(tmp_ctx);
    2553        2107 :         return ret;
    2554             : 
    2555             : }
    2556             : 
    2557        2115 : static krb5_error_code samba_kdc_lookup_trust(krb5_context context, struct ldb_context *ldb_ctx,
    2558             :                                         TALLOC_CTX *mem_ctx,
    2559             :                                         const char *realm,
    2560             :                                         struct ldb_dn *realm_dn,
    2561             :                                         struct ldb_message **pmsg)
    2562             : {
    2563           0 :         NTSTATUS status;
    2564        2115 :         const char * const *attrs = trust_attrs;
    2565             : 
    2566        2115 :         status = dsdb_trust_search_tdo(ldb_ctx, realm, realm,
    2567             :                                        attrs, mem_ctx, pmsg);
    2568        2115 :         if (NT_STATUS_IS_OK(status)) {
    2569        2107 :                 return 0;
    2570           8 :         } else if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
    2571           8 :                 return SDB_ERR_NOENTRY;
    2572           0 :         } else if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
    2573           0 :                 int ret = ENOMEM;
    2574           0 :                 krb5_set_error_message(context, ret, "samba_kdc_lookup_trust: out of memory");
    2575           0 :                 return ret;
    2576             :         } else {
    2577           0 :                 int ret = EINVAL;
    2578           0 :                 krb5_set_error_message(context, ret, "samba_kdc_lookup_trust: %s", nt_errstr(status));
    2579           0 :                 return ret;
    2580             :         }
    2581             : }
    2582             : 
    2583      102909 : static krb5_error_code samba_kdc_lookup_client(krb5_context context,
    2584             :                                                 struct samba_kdc_db_context *kdc_db_ctx,
    2585             :                                                 TALLOC_CTX *mem_ctx,
    2586             :                                                 krb5_const_principal principal,
    2587             :                                                 const char **attrs,
    2588             :                                                 const uint32_t dsdb_flags,
    2589             :                                                 struct ldb_dn **realm_dn,
    2590             :                                                 struct ldb_message **msg)
    2591             : {
    2592        3448 :         NTSTATUS nt_status;
    2593      102909 :         char *principal_string = NULL;
    2594             : 
    2595      102909 :         if (smb_krb5_principal_get_type(context, principal) == KRB5_NT_ENTERPRISE_PRINCIPAL) {
    2596        2758 :                 krb5_error_code ret = 0;
    2597             : 
    2598        2758 :                 ret = smb_krb5_principal_get_comp_string(mem_ctx, context,
    2599             :                                                          principal, 0, &principal_string);
    2600        2758 :                 if (ret) {
    2601           0 :                         return ret;
    2602             :                 }
    2603             :         } else {
    2604      100151 :                 char *principal_string_m = NULL;
    2605        3448 :                 krb5_error_code ret;
    2606             : 
    2607      100151 :                 ret = krb5_unparse_name(context, principal, &principal_string_m);
    2608      100151 :                 if (ret != 0) {
    2609           0 :                         return ret;
    2610             :                 }
    2611             : 
    2612      100151 :                 principal_string = talloc_strdup(mem_ctx, principal_string_m);
    2613      100151 :                 SAFE_FREE(principal_string_m);
    2614      100151 :                 if (principal_string == NULL) {
    2615           0 :                         return ENOMEM;
    2616             :                 }
    2617             :         }
    2618             : 
    2619      102909 :         nt_status = sam_get_results_principal(kdc_db_ctx->samdb,
    2620             :                                               mem_ctx, principal_string, attrs, dsdb_flags,
    2621             :                                               realm_dn, msg);
    2622      102909 :         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) {
    2623        2725 :                 krb5_principal fallback_principal = NULL;
    2624           0 :                 unsigned int num_comp;
    2625        2725 :                 char *fallback_realm = NULL;
    2626        2725 :                 char *fallback_account = NULL;
    2627           0 :                 krb5_error_code ret;
    2628             : 
    2629        2725 :                 ret = krb5_parse_name(context, principal_string,
    2630             :                                       &fallback_principal);
    2631        2725 :                 TALLOC_FREE(principal_string);
    2632        2725 :                 if (ret != 0) {
    2633           0 :                         return ret;
    2634             :                 }
    2635             : 
    2636        2725 :                 num_comp = krb5_princ_size(context, fallback_principal);
    2637        2725 :                 fallback_realm = smb_krb5_principal_get_realm(
    2638             :                         mem_ctx, context, fallback_principal);
    2639        2725 :                 if (fallback_realm == NULL) {
    2640           0 :                         krb5_free_principal(context, fallback_principal);
    2641           0 :                         return ENOMEM;
    2642             :                 }
    2643             : 
    2644        2725 :                 if (num_comp == 1) {
    2645           0 :                         size_t len;
    2646             : 
    2647        2292 :                         ret = smb_krb5_principal_get_comp_string(mem_ctx,
    2648             :                                                                  context, fallback_principal, 0, &fallback_account);
    2649        2292 :                         if (ret) {
    2650           0 :                                 krb5_free_principal(context, fallback_principal);
    2651           0 :                                 TALLOC_FREE(fallback_realm);
    2652           0 :                                 return ret;
    2653             :                         }
    2654             : 
    2655        2292 :                         len = strlen(fallback_account);
    2656        2292 :                         if (len >= 2 && fallback_account[len - 1] == '$') {
    2657          18 :                                 TALLOC_FREE(fallback_account);
    2658             :                         }
    2659             :                 }
    2660        2725 :                 krb5_free_principal(context, fallback_principal);
    2661        2725 :                 fallback_principal = NULL;
    2662             : 
    2663        2725 :                 if (fallback_account != NULL) {
    2664           0 :                         char *with_dollar;
    2665             : 
    2666        2274 :                         with_dollar = talloc_asprintf(mem_ctx, "%s$",
    2667             :                                                      fallback_account);
    2668        2274 :                         if (with_dollar == NULL) {
    2669           0 :                                 TALLOC_FREE(fallback_realm);
    2670           0 :                                 return ENOMEM;
    2671             :                         }
    2672        2274 :                         TALLOC_FREE(fallback_account);
    2673             : 
    2674        2274 :                         ret = smb_krb5_make_principal(context,
    2675             :                                                       &fallback_principal,
    2676             :                                                       fallback_realm,
    2677             :                                                       with_dollar, NULL);
    2678        2274 :                         TALLOC_FREE(with_dollar);
    2679        2274 :                         if (ret != 0) {
    2680           0 :                                 TALLOC_FREE(fallback_realm);
    2681           0 :                                 return ret;
    2682             :                         }
    2683             :                 }
    2684        2725 :                 TALLOC_FREE(fallback_realm);
    2685             : 
    2686        2725 :                 if (fallback_principal != NULL) {
    2687        2274 :                         char *fallback_string = NULL;
    2688             : 
    2689        2274 :                         ret = krb5_unparse_name(context,
    2690             :                                                 fallback_principal,
    2691             :                                                 &fallback_string);
    2692        2274 :                         if (ret != 0) {
    2693           0 :                                 krb5_free_principal(context, fallback_principal);
    2694           0 :                                 return ret;
    2695             :                         }
    2696             : 
    2697        2274 :                         nt_status = sam_get_results_principal(kdc_db_ctx->samdb,
    2698             :                                                               mem_ctx,
    2699             :                                                               fallback_string,
    2700             :                                                               attrs, dsdb_flags,
    2701             :                                                               realm_dn, msg);
    2702        2274 :                         SAFE_FREE(fallback_string);
    2703             :                 }
    2704        2725 :                 krb5_free_principal(context, fallback_principal);
    2705        2725 :                 fallback_principal = NULL;
    2706             :         }
    2707      102909 :         TALLOC_FREE(principal_string);
    2708             : 
    2709      102909 :         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) {
    2710         510 :                 return SDB_ERR_NOENTRY;
    2711      102399 :         } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_MEMORY)) {
    2712           0 :                 return ENOMEM;
    2713      102399 :         } else if (!NT_STATUS_IS_OK(nt_status)) {
    2714           0 :                 return EINVAL;
    2715             :         }
    2716             : 
    2717       98951 :         return 0;
    2718             : }
    2719             : 
    2720      101998 : static krb5_error_code samba_kdc_fetch_client(krb5_context context,
    2721             :                                                struct samba_kdc_db_context *kdc_db_ctx,
    2722             :                                                TALLOC_CTX *mem_ctx,
    2723             :                                                krb5_const_principal principal,
    2724             :                                                unsigned flags,
    2725             :                                                krb5_kvno kvno,
    2726             :                                                struct sdb_entry *entry)
    2727             : {
    2728        3448 :         struct ldb_dn *realm_dn;
    2729        3448 :         krb5_error_code ret;
    2730      101998 :         struct ldb_message *msg = NULL;
    2731             : 
    2732      101998 :         ret = samba_kdc_lookup_client(context, kdc_db_ctx,
    2733             :                                       mem_ctx, principal, user_attrs, DSDB_SEARCH_UPDATE_MANAGED_PASSWORDS,
    2734             :                                       &realm_dn, &msg);
    2735      101998 :         if (ret != 0) {
    2736         510 :                 return ret;
    2737             :         }
    2738             : 
    2739      101488 :         ret = samba_kdc_message2entry(context, kdc_db_ctx, mem_ctx,
    2740             :                                       principal, SAMBA_KDC_ENT_TYPE_CLIENT,
    2741             :                                       flags, kvno,
    2742             :                                       realm_dn, msg, entry);
    2743      101488 :         return ret;
    2744             : }
    2745             : 
    2746      208667 : static krb5_error_code samba_kdc_fetch_krbtgt(krb5_context context,
    2747             :                                               struct samba_kdc_db_context *kdc_db_ctx,
    2748             :                                               TALLOC_CTX *mem_ctx,
    2749             :                                               krb5_const_principal principal,
    2750             :                                               unsigned flags,
    2751             :                                               uint32_t kvno,
    2752             :                                               struct sdb_entry *entry)
    2753             : {
    2754      208667 :         TALLOC_CTX *tmp_ctx = NULL;
    2755      208667 :         struct loadparm_context *lp_ctx = kdc_db_ctx->lp_ctx;
    2756      208667 :         krb5_error_code ret = 0;
    2757        6792 :         int is_krbtgt;
    2758      208667 :         struct ldb_message *msg = NULL;
    2759      208667 :         struct ldb_dn *realm_dn = ldb_get_default_basedn(kdc_db_ctx->samdb);
    2760        6792 :         char *realm_from_princ;
    2761      208667 :         char *realm_princ_comp = NULL;
    2762             : 
    2763      208667 :         tmp_ctx = talloc_new(mem_ctx);
    2764      208667 :         if (tmp_ctx == NULL) {
    2765           0 :                 ret = ENOMEM;
    2766           0 :                 goto out;
    2767             :         }
    2768             : 
    2769      208667 :         realm_from_princ = smb_krb5_principal_get_realm(
    2770             :                 tmp_ctx, context, principal);
    2771      208667 :         if (realm_from_princ == NULL) {
    2772             :                 /* can't happen */
    2773           0 :                 ret = SDB_ERR_NOENTRY;
    2774           0 :                 goto out;
    2775             :         }
    2776             : 
    2777      208667 :         is_krbtgt = smb_krb5_principal_is_tgs(context, principal);
    2778      208667 :         if (is_krbtgt == -1) {
    2779           0 :                 ret = ENOMEM;
    2780           0 :                 goto out;
    2781      208667 :         } else if (!is_krbtgt) {
    2782             :                 /* Not a krbtgt */
    2783       28818 :                 ret = SDB_ERR_NOENTRY;
    2784       28818 :                 goto out;
    2785             :         }
    2786             : 
    2787             :         /* krbtgt case.  Either us or a trusted realm */
    2788             : 
    2789      179849 :         ret = smb_krb5_principal_get_comp_string(tmp_ctx, context, principal, 1, &realm_princ_comp);
    2790      179849 :         if (ret == ENOENT) {
    2791             :                 /* OK. */
    2792      179812 :         } else if (ret) {
    2793           0 :                 goto out;
    2794             :         }
    2795             : 
    2796      179849 :         if (lpcfg_is_my_domain_or_realm(lp_ctx, realm_from_princ)
    2797      349951 :             && (realm_princ_comp == NULL || lpcfg_is_my_domain_or_realm(lp_ctx, realm_princ_comp))) {
    2798             :                 /* us, or someone quite like us */
    2799             :                 /* Kludge, kludge, kludge.  If the realm part of krbtgt/realm,
    2800             :                  * is in our db, then direct the caller at our primary
    2801             :                  * krbtgt */
    2802             : 
    2803        6162 :                 int lret;
    2804        6162 :                 unsigned int krbtgt_number;
    2805             :                 /* w2k8r2 sometimes gives us a kvno of 255 for inter-domain
    2806             :                    trust tickets. We don't yet know what this means, but we do
    2807             :                    seem to need to treat it as unspecified */
    2808      177734 :                 if (flags & (SDB_F_KVNO_SPECIFIED|SDB_F_RODC_NUMBER_SPECIFIED)) {
    2809       53248 :                         krbtgt_number = SAMBA_KVNO_GET_KRBTGT(kvno);
    2810       53248 :                         if (kdc_db_ctx->rodc) {
    2811        3980 :                                 if (krbtgt_number != kdc_db_ctx->my_krbtgt_number) {
    2812        1351 :                                         ret = SDB_ERR_NOT_FOUND_HERE;
    2813        1351 :                                         goto out;
    2814             :                                 }
    2815             :                         }
    2816             :                 } else {
    2817      124486 :                         krbtgt_number = kdc_db_ctx->my_krbtgt_number;
    2818             :                 }
    2819             : 
    2820      176383 :                 if (krbtgt_number == kdc_db_ctx->my_krbtgt_number) {
    2821      176161 :                         lret = dsdb_search_one(kdc_db_ctx->samdb, tmp_ctx,
    2822             :                                                &msg, kdc_db_ctx->krbtgt_dn, LDB_SCOPE_BASE,
    2823             :                                                krbtgt_attrs, DSDB_SEARCH_NO_GLOBAL_CATALOG | DSDB_SEARCH_UPDATE_MANAGED_PASSWORDS,
    2824             :                                                "(objectClass=user)");
    2825             :                 } else {
    2826             :                         /* We need to look up an RODC krbtgt (perhaps
    2827             :                          * ours, if we are an RODC, perhaps another
    2828             :                          * RODC if we are a read-write DC */
    2829         222 :                         lret = dsdb_search_one(kdc_db_ctx->samdb, tmp_ctx,
    2830             :                                                &msg, realm_dn, LDB_SCOPE_SUBTREE,
    2831             :                                                krbtgt_attrs,
    2832             :                                                DSDB_SEARCH_SHOW_EXTENDED_DN | DSDB_SEARCH_NO_GLOBAL_CATALOG | DSDB_SEARCH_UPDATE_MANAGED_PASSWORDS,
    2833             :                                                "(&(objectClass=user)(msDS-SecondaryKrbTgtNumber=%u))", (unsigned)(krbtgt_number));
    2834             :                 }
    2835             : 
    2836      176383 :                 if (lret == LDB_ERR_NO_SUCH_OBJECT) {
    2837           0 :                         krb5_warnx(context, "samba_kdc_fetch_krbtgt: could not find KRBTGT number %u in DB!",
    2838             :                                    (unsigned)(krbtgt_number));
    2839           0 :                         krb5_set_error_message(context, SDB_ERR_NOENTRY,
    2840             :                                                "samba_kdc_fetch_krbtgt: could not find KRBTGT number %u in DB!",
    2841             :                                                (unsigned)(krbtgt_number));
    2842           0 :                         ret = SDB_ERR_NOENTRY;
    2843           0 :                         goto out;
    2844      176383 :                 } else if (lret != LDB_SUCCESS) {
    2845           0 :                         krb5_warnx(context, "samba_kdc_fetch_krbtgt: could not find KRBTGT number %u in DB!",
    2846             :                                    (unsigned)(krbtgt_number));
    2847           0 :                         krb5_set_error_message(context, SDB_ERR_NOENTRY,
    2848             :                                                "samba_kdc_fetch_krbtgt: could not find KRBTGT number %u in DB!",
    2849             :                                                (unsigned)(krbtgt_number));
    2850           0 :                         ret = SDB_ERR_NOENTRY;
    2851           0 :                         goto out;
    2852             :                 }
    2853             : 
    2854      176383 :                 ret = samba_kdc_message2entry(context, kdc_db_ctx, mem_ctx,
    2855             :                                               principal, SAMBA_KDC_ENT_TYPE_KRBTGT,
    2856             :                                               flags, kvno, realm_dn, msg, entry);
    2857      176383 :                 if (ret != 0) {
    2858           0 :                         krb5_warnx(context, "samba_kdc_fetch_krbtgt: self krbtgt message2entry failed");
    2859             :                 }
    2860             :         } else {
    2861        2115 :                 enum trust_direction direction = UNKNOWN;
    2862        2115 :                 const char *realm = NULL;
    2863             : 
    2864             :                 /* Either an inbound or outbound trust */
    2865             : 
    2866        2115 :                 if (strcasecmp(lpcfg_realm(lp_ctx), realm_from_princ) == 0) {
    2867             :                         /* look for inbound trust */
    2868        1996 :                         direction = INBOUND;
    2869        1996 :                         realm = realm_princ_comp;
    2870             :                 } else {
    2871         119 :                         bool eq = false;
    2872             : 
    2873         119 :                         ret = is_principal_component_equal_ignoring_case(context, principal, 1, lpcfg_realm(lp_ctx), &eq);
    2874         119 :                         if (ret) {
    2875           0 :                                 goto out;
    2876             :                         }
    2877             : 
    2878         119 :                         if (eq) {
    2879             :                                 /* look for outbound trust */
    2880         119 :                                 direction = OUTBOUND;
    2881         119 :                                 realm = realm_from_princ;
    2882             :                         } else {
    2883           0 :                                 krb5_warnx(context, "samba_kdc_fetch_krbtgt: not our realm for trusts ('%s', '%s')",
    2884             :                                            realm_from_princ,
    2885             :                                            realm_princ_comp);
    2886           0 :                                 krb5_set_error_message(context, SDB_ERR_NOENTRY, "samba_kdc_fetch_krbtgt: not our realm for trusts ('%s', '%s')",
    2887             :                                                        realm_from_princ,
    2888             :                                                        realm_princ_comp);
    2889           0 :                                 ret = SDB_ERR_NOENTRY;
    2890           0 :                                 goto out;
    2891             :                         }
    2892             :                 }
    2893             : 
    2894             :                 /* Trusted domains are under CN=system */
    2895             : 
    2896        2115 :                 ret = samba_kdc_lookup_trust(context, kdc_db_ctx->samdb,
    2897             :                                        tmp_ctx,
    2898             :                                        realm, realm_dn, &msg);
    2899             : 
    2900        2115 :                 if (ret != 0) {
    2901           8 :                         krb5_warnx(context, "samba_kdc_fetch_krbtgt: could not find principal in DB");
    2902           8 :                         krb5_set_error_message(context, ret, "samba_kdc_fetch_krbtgt: could not find principal in DB");
    2903           8 :                         goto out;
    2904             :                 }
    2905             : 
    2906        2107 :                 ret = samba_kdc_trust_message2entry(context, kdc_db_ctx, mem_ctx,
    2907             :                                                     direction,
    2908             :                                                     realm_dn, flags, kvno, msg, entry);
    2909        2107 :                 if (ret != 0) {
    2910           2 :                         krb5_warnx(context, "samba_kdc_fetch_krbtgt: trust_message2entry failed for %s",
    2911           2 :                                    ldb_dn_get_linearized(msg->dn));
    2912           2 :                         krb5_set_error_message(context, ret, "samba_kdc_fetch_krbtgt: "
    2913             :                                                "trust_message2entry failed for %s",
    2914           2 :                                                ldb_dn_get_linearized(msg->dn));
    2915             :                 }
    2916             :         }
    2917             : 
    2918        2105 : out:
    2919      208667 :         talloc_free(tmp_ctx);
    2920      208667 :         return ret;
    2921             : }
    2922             : 
    2923       28824 : static krb5_error_code samba_kdc_lookup_server(krb5_context context,
    2924             :                                                struct samba_kdc_db_context *kdc_db_ctx,
    2925             :                                                TALLOC_CTX *mem_ctx,
    2926             :                                                krb5_const_principal principal,
    2927             :                                                unsigned flags,
    2928             :                                                struct ldb_dn **realm_dn,
    2929             :                                                struct ldb_message **msg)
    2930             : {
    2931         630 :         krb5_error_code ret;
    2932       28824 :         if ((smb_krb5_principal_get_type(context, principal) != KRB5_NT_ENTERPRISE_PRINCIPAL)
    2933       27832 :             && krb5_princ_size(context, principal) >= 2) {
    2934             :                 /* 'normal server' case */
    2935         630 :                 int ldb_ret;
    2936         630 :                 NTSTATUS nt_status;
    2937         630 :                 struct ldb_dn *user_dn;
    2938         630 :                 char *principal_string;
    2939             : 
    2940       26202 :                 ret = krb5_unparse_name_flags(context, principal,
    2941             :                                               KRB5_PRINCIPAL_UNPARSE_NO_REALM,
    2942             :                                               &principal_string);
    2943       26202 :                 if (ret != 0) {
    2944           0 :                         return ret;
    2945             :                 }
    2946             : 
    2947             :                 /* At this point we may find the host is known to be
    2948             :                  * in a different realm, so we should generate a
    2949             :                  * referral instead */
    2950       26202 :                 nt_status = crack_service_principal_name(kdc_db_ctx->samdb,
    2951             :                                                          mem_ctx, principal_string,
    2952             :                                                          &user_dn, realm_dn);
    2953       26202 :                 free(principal_string);
    2954             : 
    2955       26202 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    2956         380 :                         return SDB_ERR_NOENTRY;
    2957             :                 }
    2958             : 
    2959       25822 :                 ldb_ret = dsdb_search_one(kdc_db_ctx->samdb,
    2960             :                                           mem_ctx,
    2961             :                                           msg, user_dn, LDB_SCOPE_BASE,
    2962             :                                           server_attrs,
    2963             :                                           DSDB_SEARCH_SHOW_EXTENDED_DN | DSDB_SEARCH_NO_GLOBAL_CATALOG | DSDB_SEARCH_UPDATE_MANAGED_PASSWORDS,
    2964             :                                           "(objectClass=*)");
    2965       25822 :                 if (ldb_ret != LDB_SUCCESS) {
    2966           0 :                         return SDB_ERR_NOENTRY;
    2967             :                 }
    2968       25822 :                 return 0;
    2969        2622 :         } else if (!(flags & SDB_F_FOR_AS_REQ)
    2970        2257 :                    && smb_krb5_principal_get_type(context, principal) == KRB5_NT_ENTERPRISE_PRINCIPAL) {
    2971             :                 /*
    2972             :                  * The behaviour of accepting an
    2973             :                  * KRB5_NT_ENTERPRISE_PRINCIPAL server principal
    2974             :                  * containing a UPN only applies to TGS-REQ packets,
    2975             :                  * not AS-REQ packets.
    2976             :                  */
    2977         864 :                 return samba_kdc_lookup_client(context, kdc_db_ctx,
    2978             :                                                mem_ctx, principal, server_attrs, DSDB_SEARCH_UPDATE_MANAGED_PASSWORDS,
    2979             :                                                realm_dn, msg);
    2980             :         } else {
    2981             :                 /*
    2982             :                  * This case is for:
    2983             :                  *  - the AS-REQ, where we only accept
    2984             :                  *    samAccountName based lookups for the server, no
    2985             :                  *    matter if the name is an
    2986             :                  *    KRB5_NT_ENTERPRISE_PRINCIPAL or not
    2987             :                  *  - for the TGS-REQ when we are not given an
    2988             :                  *    KRB5_NT_ENTERPRISE_PRINCIPAL, which also must
    2989             :                  *    only lookup samAccountName based names.
    2990             :                  */
    2991           0 :                 int lret;
    2992           0 :                 char *short_princ;
    2993        1758 :                 krb5_principal enterprise_principal = NULL;
    2994        1758 :                 krb5_const_principal used_principal = NULL;
    2995        1758 :                 char *name1 = NULL;
    2996        1758 :                 size_t len1 = 0;
    2997        1758 :                 char *filter = NULL;
    2998             : 
    2999        1758 :                 if (smb_krb5_principal_get_type(context, principal) == KRB5_NT_ENTERPRISE_PRINCIPAL) {
    3000         128 :                         char *str = NULL;
    3001             :                         /* Need to reparse the enterprise principal to find the real target */
    3002         128 :                         if (krb5_princ_size(context, principal) != 1) {
    3003           0 :                                 ret = KRB5_PARSE_MALFORMED;
    3004           0 :                                 krb5_set_error_message(context, ret, "samba_kdc_lookup_server: request for an "
    3005             :                                                        "enterprise principal with wrong (%d) number of components",
    3006           0 :                                                        krb5_princ_size(context, principal));
    3007           0 :                                 return ret;
    3008             :                         }
    3009         128 :                         ret = smb_krb5_principal_get_comp_string(mem_ctx, context, principal, 0, &str);
    3010         128 :                         if (ret) {
    3011           0 :                                 return KRB5_PARSE_MALFORMED;
    3012             :                         }
    3013         128 :                         ret = krb5_parse_name(context, str,
    3014             :                                               &enterprise_principal);
    3015         128 :                         talloc_free(str);
    3016         128 :                         if (ret) {
    3017           0 :                                 return ret;
    3018             :                         }
    3019         128 :                         used_principal = enterprise_principal;
    3020             :                 } else {
    3021        1630 :                         used_principal = principal;
    3022             :                 }
    3023             : 
    3024             :                 /* server as client principal case, but we must not lookup userPrincipalNames */
    3025        1758 :                 *realm_dn = ldb_get_default_basedn(kdc_db_ctx->samdb);
    3026             : 
    3027             :                 /* TODO: Check if it is our realm, otherwise give referral */
    3028             : 
    3029        1758 :                 ret = krb5_unparse_name_flags(context, used_principal,
    3030             :                                               KRB5_PRINCIPAL_UNPARSE_NO_REALM |
    3031             :                                               KRB5_PRINCIPAL_UNPARSE_DISPLAY,
    3032             :                                               &short_princ);
    3033        1758 :                 used_principal = NULL;
    3034        1758 :                 krb5_free_principal(context, enterprise_principal);
    3035        1758 :                 enterprise_principal = NULL;
    3036             : 
    3037        1758 :                 if (ret != 0) {
    3038           0 :                         krb5_set_error_message(context, ret, "samba_kdc_lookup_server: could not parse principal");
    3039           0 :                         krb5_warnx(context, "samba_kdc_lookup_server: could not parse principal");
    3040           0 :                         return ret;
    3041             :                 }
    3042             : 
    3043        1758 :                 name1 = ldb_binary_encode_string(mem_ctx, short_princ);
    3044        1758 :                 SAFE_FREE(short_princ);
    3045        1758 :                 if (name1 == NULL) {
    3046           0 :                         return ENOMEM;
    3047             :                 }
    3048        1758 :                 len1 = strlen(name1);
    3049        1758 :                 if (len1 >= 1 && name1[len1 - 1] != '$') {
    3050        1189 :                         filter = talloc_asprintf(mem_ctx,
    3051             :                                         "(&(objectClass=user)(|(samAccountName=%s)(samAccountName=%s$)))",
    3052             :                                         name1, name1);
    3053        1189 :                         if (filter == NULL) {
    3054           0 :                                 return ENOMEM;
    3055             :                         }
    3056             :                 } else {
    3057         569 :                         filter = talloc_asprintf(mem_ctx,
    3058             :                                         "(&(objectClass=user)(samAccountName=%s))",
    3059             :                                         name1);
    3060         569 :                         if (filter == NULL) {
    3061           0 :                                 return ENOMEM;
    3062             :                         }
    3063             :                 }
    3064             : 
    3065        1758 :                 lret = dsdb_search_one(kdc_db_ctx->samdb, mem_ctx, msg,
    3066             :                                        *realm_dn, LDB_SCOPE_SUBTREE,
    3067             :                                        server_attrs,
    3068             :                                        DSDB_SEARCH_SHOW_EXTENDED_DN | DSDB_SEARCH_NO_GLOBAL_CATALOG | DSDB_SEARCH_UPDATE_MANAGED_PASSWORDS,
    3069             :                                        "%s", filter);
    3070        1758 :                 if (lret == LDB_ERR_NO_SUCH_OBJECT) {
    3071         192 :                         DBG_DEBUG("Failed to find an entry for %s filter:%s\n",
    3072             :                                   name1, filter);
    3073         192 :                         return SDB_ERR_NOENTRY;
    3074             :                 }
    3075        1566 :                 if (lret == LDB_ERR_CONSTRAINT_VIOLATION) {
    3076           0 :                         DBG_DEBUG("Failed to find unique entry for %s filter:%s\n",
    3077             :                                   name1, filter);
    3078           0 :                         return SDB_ERR_NOENTRY;
    3079             :                 }
    3080        1566 :                 if (lret != LDB_SUCCESS) {
    3081           0 :                         DBG_ERR("Failed single search for %s - %s\n",
    3082             :                                 name1, ldb_errstring(kdc_db_ctx->samdb));
    3083           0 :                         return SDB_ERR_NOENTRY;
    3084             :                 }
    3085        1566 :                 return 0;
    3086             :         }
    3087             :         return SDB_ERR_NOENTRY;
    3088             : }
    3089             : 
    3090             : 
    3091             : 
    3092       28824 : static krb5_error_code samba_kdc_fetch_server(krb5_context context,
    3093             :                                               struct samba_kdc_db_context *kdc_db_ctx,
    3094             :                                               TALLOC_CTX *mem_ctx,
    3095             :                                               krb5_const_principal principal,
    3096             :                                               unsigned flags,
    3097             :                                               krb5_kvno kvno,
    3098             :                                               struct sdb_entry *entry)
    3099             : {
    3100         630 :         krb5_error_code ret;
    3101         630 :         struct ldb_dn *realm_dn;
    3102         630 :         struct ldb_message *msg;
    3103             : 
    3104       28824 :         ret = samba_kdc_lookup_server(context, kdc_db_ctx, mem_ctx, principal,
    3105             :                                       flags, &realm_dn, &msg);
    3106       28824 :         if (ret != 0) {
    3107         572 :                 return ret;
    3108             :         }
    3109             : 
    3110       28252 :         ret = samba_kdc_message2entry(context, kdc_db_ctx, mem_ctx,
    3111             :                                       principal, SAMBA_KDC_ENT_TYPE_SERVER,
    3112             :                                       flags, kvno,
    3113             :                                       realm_dn, msg, entry);
    3114       28252 :         if (ret != 0) {
    3115         718 :                 char *client_name = NULL;
    3116           0 :                 krb5_error_code code;
    3117             : 
    3118         718 :                 code = krb5_unparse_name(context, principal, &client_name);
    3119         718 :                 if (code == 0) {
    3120         718 :                         krb5_warnx(context,
    3121             :                                    "samba_kdc_fetch_server: message2entry failed for "
    3122             :                                    "%s",
    3123             :                                    client_name);
    3124             :                 } else {
    3125           0 :                         krb5_warnx(context,
    3126             :                                    "samba_kdc_fetch_server: message2entry and "
    3127             :                                    "krb5_unparse_name failed");
    3128             :                 }
    3129         718 :                 SAFE_FREE(client_name);
    3130             :         }
    3131             : 
    3132       27622 :         return ret;
    3133             : }
    3134             : 
    3135      312352 : static krb5_error_code samba_kdc_lookup_realm(krb5_context context,
    3136             :                                               struct samba_kdc_db_context *kdc_db_ctx,
    3137             :                                               krb5_const_principal principal,
    3138             :                                               unsigned flags,
    3139             :                                               struct sdb_entry *entry)
    3140             : {
    3141      312352 :         TALLOC_CTX *frame = talloc_stackframe();
    3142       10240 :         NTSTATUS status;
    3143       10240 :         krb5_error_code ret;
    3144      312352 :         bool check_realm = false;
    3145      312352 :         const char *realm = NULL;
    3146      312352 :         struct dsdb_trust_routing_table *trt = NULL;
    3147      312352 :         const struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
    3148       10240 :         unsigned int num_comp;
    3149       10240 :         bool ok;
    3150      312352 :         char *upper = NULL;
    3151             : 
    3152      312352 :         *entry = (struct sdb_entry) {};
    3153             : 
    3154      312352 :         num_comp = krb5_princ_size(context, principal);
    3155             : 
    3156      312352 :         if (flags & SDB_F_GET_CLIENT) {
    3157      102536 :                 if (flags & SDB_F_FOR_AS_REQ) {
    3158       51651 :                         check_realm = true;
    3159             :                 }
    3160             :         }
    3161      312352 :         if (flags & SDB_F_GET_SERVER) {
    3162      101358 :                 if (flags & SDB_F_FOR_TGS_REQ) {
    3163       50997 :                         check_realm = true;
    3164             :                 }
    3165             :         }
    3166             : 
    3167      310680 :         if (!check_realm) {
    3168      208032 :                 TALLOC_FREE(frame);
    3169      208032 :                 return 0;
    3170             :         }
    3171             : 
    3172      104320 :         realm = smb_krb5_principal_get_realm(frame, context, principal);
    3173      104320 :         if (realm == NULL) {
    3174           0 :                 TALLOC_FREE(frame);
    3175           0 :                 return ENOMEM;
    3176             :         }
    3177             : 
    3178             :         /*
    3179             :          * The requested realm needs to be our own
    3180             :          */
    3181      104320 :         ok = lpcfg_is_my_domain_or_realm(kdc_db_ctx->lp_ctx, realm);
    3182      104320 :         if (!ok) {
    3183             :                 /*
    3184             :                  * The request is not for us...
    3185             :                  */
    3186           1 :                 TALLOC_FREE(frame);
    3187           1 :                 return SDB_ERR_NOENTRY;
    3188             :         }
    3189             : 
    3190      104319 :         if (smb_krb5_principal_get_type(context, principal) == KRB5_NT_ENTERPRISE_PRINCIPAL) {
    3191        3097 :                 char *principal_string = NULL;
    3192        3097 :                 krb5_principal enterprise_principal = NULL;
    3193        3097 :                 char *enterprise_realm = NULL;
    3194             : 
    3195        3097 :                 if (num_comp != 1) {
    3196           0 :                         TALLOC_FREE(frame);
    3197           0 :                         return SDB_ERR_NOENTRY;
    3198             :                 }
    3199             : 
    3200        3097 :                 ret = smb_krb5_principal_get_comp_string(frame, context,
    3201             :                                                          principal, 0, &principal_string);
    3202        3097 :                 if (ret) {
    3203           0 :                         TALLOC_FREE(frame);
    3204           0 :                         return ret;
    3205             :                 }
    3206             : 
    3207        3097 :                 ret = krb5_parse_name(context, principal_string,
    3208             :                                       &enterprise_principal);
    3209        3097 :                 TALLOC_FREE(principal_string);
    3210        3097 :                 if (ret) {
    3211           0 :                         TALLOC_FREE(frame);
    3212           0 :                         return ret;
    3213             :                 }
    3214             : 
    3215        3097 :                 enterprise_realm = smb_krb5_principal_get_realm(
    3216             :                         frame, context, enterprise_principal);
    3217        3097 :                 krb5_free_principal(context, enterprise_principal);
    3218        3097 :                 if (enterprise_realm != NULL) {
    3219        3097 :                         realm = enterprise_realm;
    3220             :                 }
    3221             :         }
    3222             : 
    3223      104319 :         if (flags & SDB_F_GET_SERVER) {
    3224       52672 :                 bool is_krbtgt = false;
    3225             : 
    3226       52672 :                 ret = is_principal_component_equal(context, principal, 0, KRB5_TGS_NAME, &is_krbtgt);
    3227       52672 :                 if (ret) {
    3228           0 :                         TALLOC_FREE(frame);
    3229       28142 :                         return ret;
    3230             :                 }
    3231             : 
    3232       52672 :                 if (is_krbtgt) {
    3233             :                         /*
    3234             :                          * we need to search krbtgt/ locally
    3235             :                          */
    3236       28142 :                         TALLOC_FREE(frame);
    3237       28142 :                         return 0;
    3238             :                 }
    3239             : 
    3240             :                 /*
    3241             :                  * We need to check the last component against the routing table.
    3242             :                  *
    3243             :                  * Note this works only with 2 or 3 component principals, e.g:
    3244             :                  *
    3245             :                  * servicePrincipalName: ldap/W2K8R2-219.bla.base
    3246             :                  * servicePrincipalName: ldap/W2K8R2-219.bla.base/bla.base
    3247             :                  * servicePrincipalName: ldap/W2K8R2-219.bla.base/ForestDnsZones.bla.base
    3248             :                  * servicePrincipalName: ldap/W2K8R2-219.bla.base/DomainDnsZones.bla.base
    3249             :                  */
    3250             : 
    3251       24530 :                 if (num_comp == 2 || num_comp == 3) {
    3252       21981 :                         char *service_realm = NULL;
    3253             : 
    3254       21981 :                         ret = smb_krb5_principal_get_comp_string(frame,
    3255             :                                                                  context,
    3256             :                                                                  principal,
    3257             :                                                                  num_comp - 1,
    3258             :                                                                  &service_realm);
    3259       21981 :                         if (ret) {
    3260           0 :                                 TALLOC_FREE(frame);
    3261           0 :                                 return ret;
    3262             :                         } else {
    3263       21981 :                                 realm = service_realm;
    3264             :                         }
    3265             :                 }
    3266             :         }
    3267             : 
    3268       76177 :         ok = lpcfg_is_my_domain_or_realm(kdc_db_ctx->lp_ctx, realm);
    3269       76177 :         if (ok) {
    3270             :                 /*
    3271             :                  * skip the expensive routing lookup
    3272             :                  */
    3273       53451 :                 TALLOC_FREE(frame);
    3274       53451 :                 return 0;
    3275             :         }
    3276             : 
    3277       22726 :         status = dsdb_trust_routing_table_load(kdc_db_ctx->samdb,
    3278             :                                                frame, &trt);
    3279       22726 :         if (!NT_STATUS_IS_OK(status)) {
    3280           0 :                 TALLOC_FREE(frame);
    3281           0 :                 return EINVAL;
    3282             :         }
    3283             : 
    3284       22726 :         tdo = dsdb_trust_routing_by_name(trt, realm);
    3285       22726 :         if (tdo == NULL) {
    3286             :                 /*
    3287             :                  * This principal has to be local
    3288             :                  */
    3289       19016 :                 TALLOC_FREE(frame);
    3290       19016 :                 return 0;
    3291             :         }
    3292             : 
    3293        3710 :         if (tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
    3294             :                 /*
    3295             :                  * TODO: handle the routing within the forest
    3296             :                  *
    3297             :                  * This should likely be handled in
    3298             :                  * samba_kdc_message2entry() in case we're
    3299             :                  * a global catalog. We'd need to check
    3300             :                  * if realm_dn is our own domain and derive
    3301             :                  * the dns domain name from realm_dn and check that
    3302             :                  * against the routing table or fallback to
    3303             :                  * the tdo we found here.
    3304             :                  *
    3305             :                  * But for now we don't support multiple domains
    3306             :                  * in our forest correctly anyway.
    3307             :                  *
    3308             :                  * Just search in our local database.
    3309             :                  */
    3310        2020 :                 TALLOC_FREE(frame);
    3311        2020 :                 return 0;
    3312             :         }
    3313             : 
    3314        1690 :         ret = krb5_copy_principal(context, principal,
    3315             :                                   &entry->principal);
    3316        1690 :         if (ret) {
    3317           0 :                 TALLOC_FREE(frame);
    3318           0 :                 return ret;
    3319             :         }
    3320             : 
    3321        1690 :         upper = strupper_talloc(frame, tdo->domain_name.string);
    3322        1690 :         if (upper == NULL) {
    3323           0 :                 TALLOC_FREE(frame);
    3324           0 :                 return ENOMEM;
    3325             :         }
    3326             : 
    3327        1690 :         ret = smb_krb5_principal_set_realm(context,
    3328             :                                            entry->principal,
    3329             :                                            upper);
    3330        1690 :         if (ret) {
    3331           0 :                 TALLOC_FREE(frame);
    3332           0 :                 return ret;
    3333             :         }
    3334             : 
    3335        1690 :         TALLOC_FREE(frame);
    3336        1690 :         return SDB_ERR_WRONG_REALM;
    3337             : }
    3338             : 
    3339      312352 : krb5_error_code samba_kdc_fetch(krb5_context context,
    3340             :                                 struct samba_kdc_db_context *kdc_db_ctx,
    3341             :                                 krb5_const_principal principal,
    3342             :                                 unsigned flags,
    3343             :                                 krb5_kvno kvno,
    3344             :                                 struct sdb_entry *entry)
    3345             : {
    3346      312352 :         krb5_error_code ret = SDB_ERR_NOENTRY;
    3347       10240 :         TALLOC_CTX *mem_ctx;
    3348             : 
    3349      312352 :         mem_ctx = talloc_named(kdc_db_ctx, 0, "samba_kdc_fetch context");
    3350      312352 :         if (!mem_ctx) {
    3351           0 :                 ret = ENOMEM;
    3352           0 :                 krb5_set_error_message(context, ret, "samba_kdc_fetch: talloc_named() failed!");
    3353           0 :                 return ret;
    3354             :         }
    3355             : 
    3356      312352 :         ret = samba_kdc_lookup_realm(context, kdc_db_ctx,
    3357             :                                      principal, flags, entry);
    3358      312352 :         if (ret != 0) {
    3359        1691 :                 goto done;
    3360             :         }
    3361             : 
    3362      310661 :         ret = SDB_ERR_NOENTRY;
    3363             : 
    3364      310661 :         if (flags & SDB_F_GET_CLIENT) {
    3365      101998 :                 ret = samba_kdc_fetch_client(context, kdc_db_ctx, mem_ctx, principal, flags, kvno, entry);
    3366      101998 :                 if (ret != SDB_ERR_NOENTRY) goto done;
    3367             :         }
    3368      209173 :         if (flags & SDB_F_GET_SERVER) {
    3369             :                 /* krbtgt fits into this situation for trusted realms, and for resolving different versions of our own realm name */
    3370      100159 :                 ret = samba_kdc_fetch_krbtgt(context, kdc_db_ctx, mem_ctx, principal, flags, kvno, entry);
    3371      100159 :                 if (ret != SDB_ERR_NOENTRY) goto done;
    3372             : 
    3373             :                 /* We return 'no entry' if it does not start with krbtgt/, so move to the common case quickly */
    3374       28824 :                 ret = samba_kdc_fetch_server(context, kdc_db_ctx, mem_ctx, principal, flags, kvno, entry);
    3375       28824 :                 if (ret != SDB_ERR_NOENTRY) goto done;
    3376             :         }
    3377      110261 :         if (flags & SDB_F_GET_KRBTGT) {
    3378      108508 :                 ret = samba_kdc_fetch_krbtgt(context, kdc_db_ctx, mem_ctx, principal, flags, kvno, entry);
    3379      108508 :                 if (ret != SDB_ERR_NOENTRY) goto done;
    3380             :         }
    3381             : 
    3382        1757 : done:
    3383      312352 :         talloc_free(mem_ctx);
    3384      312352 :         return ret;
    3385             : }
    3386             : 
    3387             : struct samba_kdc_seq {
    3388             :         unsigned int index;
    3389             :         unsigned int count;
    3390             :         struct ldb_message **msgs;
    3391             :         enum trust_direction trust_direction;
    3392             :         unsigned int trust_index;
    3393             :         unsigned int trust_count;
    3394             :         struct ldb_message **trust_msgs;
    3395             :         struct ldb_dn *realm_dn;
    3396             : };
    3397             : 
    3398         136 : static krb5_error_code samba_kdc_seq(krb5_context context,
    3399             :                                      struct samba_kdc_db_context *kdc_db_ctx,
    3400             :                                      const unsigned sdb_flags,
    3401             :                                      struct sdb_entry *entry)
    3402             : {
    3403           0 :         krb5_error_code ret;
    3404         136 :         struct samba_kdc_seq *priv = kdc_db_ctx->seq_ctx;
    3405         136 :         const char *realm = lpcfg_realm(kdc_db_ctx->lp_ctx);
    3406         136 :         struct ldb_message *msg = NULL;
    3407         136 :         const char *sAMAccountName = NULL;
    3408         136 :         krb5_principal principal = NULL;
    3409           0 :         TALLOC_CTX *mem_ctx;
    3410             : 
    3411         136 :         if (!priv) {
    3412           0 :                 return SDB_ERR_NOENTRY;
    3413             :         }
    3414             : 
    3415         136 :         mem_ctx = talloc_named(priv, 0, "samba_kdc_seq context");
    3416             : 
    3417         136 :         if (!mem_ctx) {
    3418           0 :                 ret = ENOMEM;
    3419           0 :                 krb5_set_error_message(context, ret, "samba_kdc_seq: talloc_named() failed!");
    3420           0 :                 goto out;
    3421             :         }
    3422             : 
    3423         136 :         if (priv->index == priv->count) {
    3424          10 :                 goto trusts;
    3425             :         }
    3426             : 
    3427         126 :         while (priv->index < priv->count) {
    3428         126 :                 msg = priv->msgs[priv->index++];
    3429             : 
    3430         126 :                 sAMAccountName = ldb_msg_find_attr_as_string(msg, "sAMAccountName", NULL);
    3431         126 :                 if (sAMAccountName != NULL) {
    3432         126 :                         break;
    3433             :                 }
    3434             :         }
    3435             : 
    3436         126 :         if (sAMAccountName == NULL) {
    3437             :                 /*
    3438             :                  * This is not really possible,
    3439             :                  * but instead returning
    3440             :                  * SDB_ERR_NOENTRY, we
    3441             :                  * go on with trusts
    3442             :                  */
    3443           0 :                 goto trusts;
    3444             :         }
    3445             : 
    3446         126 :         ret = smb_krb5_make_principal(context, &principal,
    3447             :                                       realm, sAMAccountName, NULL);
    3448         126 :         if (ret != 0) {
    3449           0 :                 goto out;
    3450             :         }
    3451             : 
    3452         126 :         ret = samba_kdc_message2entry(context, kdc_db_ctx, mem_ctx,
    3453             :                                       principal, SAMBA_KDC_ENT_TYPE_ANY,
    3454             :                                       sdb_flags|SDB_F_GET_ANY,
    3455             :                                       0 /* kvno */,
    3456             :                                       priv->realm_dn, msg, entry);
    3457         126 :         krb5_free_principal(context, principal);
    3458             : 
    3459         136 : out:
    3460         136 :         if (ret != 0) {
    3461          10 :                 TALLOC_FREE(priv);
    3462          10 :                 kdc_db_ctx->seq_ctx = NULL;
    3463             :         } else {
    3464         126 :                 talloc_free(mem_ctx);
    3465             :         }
    3466             : 
    3467         136 :         return ret;
    3468             : 
    3469          10 : trusts:
    3470          10 :         while (priv->trust_index < priv->trust_count) {
    3471           0 :                 enum trust_direction trust_direction = priv->trust_direction;
    3472             : 
    3473           0 :                 msg = priv->trust_msgs[priv->trust_index];
    3474             : 
    3475           0 :                 if (trust_direction == INBOUND) {
    3476             :                         /*
    3477             :                          * This time we try INBOUND keys,
    3478             :                          * next time we'll do OUTBOUND
    3479             :                          * for the same trust.
    3480             :                          */
    3481           0 :                         priv->trust_direction = OUTBOUND;
    3482             : 
    3483             :                         /*
    3484             :                          * samba_kdc_trust_message2entry()
    3485             :                          * will likely steal msg from us,
    3486             :                          * so we need to make a copy for
    3487             :                          * the first run with INBOUND,
    3488             :                          * and let it steal without
    3489             :                          * a copy in the OUTBOUND run.
    3490             :                          */
    3491           0 :                         msg = ldb_msg_copy(priv->trust_msgs, msg);
    3492           0 :                         if (msg == NULL) {
    3493           0 :                                 return ENOMEM;
    3494             :                         }
    3495             :                 } else {
    3496             :                         /*
    3497             :                          * This time we try OUTBOUND keys,
    3498             :                          * next time we'll do INBOUND for
    3499             :                          * the next trust.
    3500             :                          */
    3501           0 :                         priv->trust_direction = INBOUND;
    3502           0 :                         priv->trust_index++;
    3503             :                 }
    3504             : 
    3505           0 :                 ret = samba_kdc_trust_message2entry(context,
    3506             :                                                     kdc_db_ctx,
    3507             :                                                     mem_ctx,
    3508             :                                                     trust_direction,
    3509             :                                                     priv->realm_dn,
    3510             :                                                     sdb_flags|SDB_F_GET_ANY,
    3511             :                                                     0, /* kvno */
    3512             :                                                     msg,
    3513             :                                                     entry);
    3514           0 :                 if (ret == SDB_ERR_NOENTRY) {
    3515           0 :                         continue;
    3516             :                 }
    3517           0 :                 goto out;
    3518             :         }
    3519             : 
    3520          10 :         ret = SDB_ERR_NOENTRY;
    3521          10 :         goto out;
    3522             : }
    3523             : 
    3524          10 : krb5_error_code samba_kdc_firstkey(krb5_context context,
    3525             :                                    struct samba_kdc_db_context *kdc_db_ctx,
    3526             :                                    const unsigned sdb_flags,
    3527             :                                    struct sdb_entry *entry)
    3528             : {
    3529          10 :         struct ldb_context *ldb_ctx = kdc_db_ctx->samdb;
    3530          10 :         struct samba_kdc_seq *priv = kdc_db_ctx->seq_ctx;
    3531           0 :         char *realm;
    3532          10 :         struct ldb_result *res = NULL;
    3533           0 :         krb5_error_code ret;
    3534           0 :         int lret;
    3535           0 :         NTSTATUS status;
    3536             : 
    3537          10 :         if (priv) {
    3538           0 :                 TALLOC_FREE(priv);
    3539           0 :                 kdc_db_ctx->seq_ctx = NULL;
    3540             :         }
    3541             : 
    3542          10 :         priv = talloc_zero(kdc_db_ctx, struct samba_kdc_seq);
    3543          10 :         if (!priv) {
    3544           0 :                 ret = ENOMEM;
    3545           0 :                 krb5_set_error_message(context, ret, "talloc: out of memory");
    3546           0 :                 return ret;
    3547             :         }
    3548             : 
    3549          10 :         priv->realm_dn = ldb_get_default_basedn(ldb_ctx);
    3550             : 
    3551          10 :         ret = krb5_get_default_realm(context, &realm);
    3552          10 :         if (ret != 0) {
    3553           0 :                 TALLOC_FREE(priv);
    3554           0 :                 return ret;
    3555             :         }
    3556          10 :         krb5_free_default_realm(context, realm);
    3557             : 
    3558          10 :         lret = dsdb_search(ldb_ctx, priv, &res,
    3559             :                            priv->realm_dn, LDB_SCOPE_SUBTREE, user_attrs,
    3560             :                            DSDB_SEARCH_NO_GLOBAL_CATALOG | DSDB_SEARCH_UPDATE_MANAGED_PASSWORDS,
    3561             :                            "(objectClass=user)");
    3562             : 
    3563          10 :         if (lret != LDB_SUCCESS) {
    3564           0 :                 TALLOC_FREE(priv);
    3565           0 :                 return SDB_ERR_NOENTRY;
    3566             :         }
    3567             : 
    3568          10 :         priv->count = res->count;
    3569          10 :         priv->msgs = talloc_move(priv, &res->msgs);
    3570          10 :         TALLOC_FREE(res);
    3571             : 
    3572          10 :         status = dsdb_trust_search_tdos(ldb_ctx,
    3573             :                                         NULL, /* exclude */
    3574             :                                         trust_attrs,
    3575             :                                         priv,
    3576             :                                         &res);
    3577          10 :         if (!NT_STATUS_IS_OK(status)) {
    3578           0 :                 DBG_ERR("dsdb_trust_search_tdos() - %s\n",
    3579             :                         nt_errstr(status));
    3580           0 :                 TALLOC_FREE(priv);
    3581           0 :                 return SDB_ERR_NOENTRY;
    3582             :         }
    3583             : 
    3584          10 :         priv->trust_direction = INBOUND;
    3585          10 :         priv->trust_count = res->count;
    3586          10 :         priv->trust_msgs = talloc_move(priv, &res->msgs);
    3587          10 :         TALLOC_FREE(res);
    3588             : 
    3589          10 :         kdc_db_ctx->seq_ctx = priv;
    3590             : 
    3591          10 :         ret = samba_kdc_seq(context, kdc_db_ctx, sdb_flags, entry);
    3592             : 
    3593          10 :         if (ret != 0) {
    3594           0 :                 TALLOC_FREE(priv);
    3595           0 :                 kdc_db_ctx->seq_ctx = NULL;
    3596             :         }
    3597          10 :         return ret;
    3598             : }
    3599             : 
    3600         126 : krb5_error_code samba_kdc_nextkey(krb5_context context,
    3601             :                                   struct samba_kdc_db_context *kdc_db_ctx,
    3602             :                                   const unsigned sdb_flags,
    3603             :                                   struct sdb_entry *entry)
    3604             : {
    3605         126 :         return samba_kdc_seq(context, kdc_db_ctx, sdb_flags, entry);
    3606             : }
    3607             : 
    3608             : /* Check if a given entry may delegate or do s4u2self to this target principal
    3609             :  *
    3610             :  * The safest way to determine 'self' is to check the DB record made at
    3611             :  * the time the principal was presented to the KDC.
    3612             :  */
    3613             : krb5_error_code
    3614         950 : samba_kdc_check_client_matches_target_service(krb5_context context,
    3615             :                                               struct samba_kdc_entry *skdc_entry_client,
    3616             :                                               struct samba_kdc_entry *skdc_entry_server_target)
    3617             : {
    3618           0 :         struct dom_sid *orig_sid;
    3619           0 :         struct dom_sid *target_sid;
    3620         950 :         TALLOC_CTX *frame = talloc_stackframe();
    3621             : 
    3622         950 :         orig_sid = samdb_result_dom_sid(frame,
    3623         950 :                                         skdc_entry_client->msg,
    3624             :                                         "objectSid");
    3625         950 :         target_sid = samdb_result_dom_sid(frame,
    3626         950 :                                           skdc_entry_server_target->msg,
    3627             :                                           "objectSid");
    3628             : 
    3629             :         /*
    3630             :          * Allow delegation to the same record (representing a
    3631             :          * principal), even if by a different name.  The easy and safe
    3632             :          * way to prove this is by SID comparison
    3633             :          */
    3634         950 :         if (!(orig_sid && target_sid && dom_sid_equal(orig_sid, target_sid))) {
    3635           6 :                 talloc_free(frame);
    3636           6 :                 return KRB5KRB_AP_ERR_BADMATCH;
    3637             :         }
    3638             : 
    3639         944 :         talloc_free(frame);
    3640         944 :         return 0;
    3641             : }
    3642             : 
    3643             : /* Certificates printed by the Certificate Authority might have a
    3644             :  * slightly different form of the user principal name to that in the
    3645             :  * database.  Allow a mismatch where they both refer to the same
    3646             :  * SID */
    3647             : 
    3648             : krb5_error_code
    3649          47 : samba_kdc_check_pkinit_ms_upn_match(krb5_context context,
    3650             :                                     struct samba_kdc_db_context *kdc_db_ctx,
    3651             :                                     struct samba_kdc_entry *skdc_entry,
    3652             :                                      krb5_const_principal certificate_principal)
    3653             : {
    3654           0 :         krb5_error_code ret;
    3655           0 :         struct ldb_dn *realm_dn;
    3656           0 :         struct ldb_message *msg;
    3657           0 :         struct dom_sid *orig_sid;
    3658           0 :         struct dom_sid *target_sid;
    3659          47 :         const char *ms_upn_check_attrs[] = {
    3660             :                 "objectSid", NULL
    3661             :         };
    3662             : 
    3663          47 :         TALLOC_CTX *mem_ctx = talloc_named(kdc_db_ctx, 0, "samba_kdc_check_pkinit_ms_upn_match");
    3664             : 
    3665          47 :         if (!mem_ctx) {
    3666           0 :                 ret = ENOMEM;
    3667           0 :                 krb5_set_error_message(context, ret, "samba_kdc_check_pkinit_ms_upn_match: talloc_named() failed!");
    3668           0 :                 return ret;
    3669             :         }
    3670             : 
    3671          47 :         ret = samba_kdc_lookup_client(context, kdc_db_ctx,
    3672             :                                       mem_ctx, certificate_principal,
    3673             :                                       ms_upn_check_attrs, 0, &realm_dn, &msg);
    3674             : 
    3675          47 :         if (ret != 0) {
    3676           0 :                 talloc_free(mem_ctx);
    3677           0 :                 return ret;
    3678             :         }
    3679             : 
    3680          47 :         orig_sid = samdb_result_dom_sid(mem_ctx, skdc_entry->msg, "objectSid");
    3681          47 :         target_sid = samdb_result_dom_sid(mem_ctx, msg, "objectSid");
    3682             : 
    3683             :         /* Consider these to be the same principal, even if by a different
    3684             :          * name.  The easy and safe way to prove this is by SID
    3685             :          * comparison */
    3686          47 :         if (!(orig_sid && target_sid && dom_sid_equal(orig_sid, target_sid))) {
    3687           2 :                 talloc_free(mem_ctx);
    3688             : #if defined(KRB5KDC_ERR_CLIENT_NAME_MISMATCH) /* MIT */
    3689           0 :                 return KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
    3690             : #else /* Heimdal (where this is an enum) */
    3691           2 :                 return KRB5_KDC_ERR_CLIENT_NAME_MISMATCH;
    3692             : #endif
    3693             :         }
    3694             : 
    3695          45 :         talloc_free(mem_ctx);
    3696          45 :         return ret;
    3697             : }
    3698             : 
    3699             : /*
    3700             :  * Check if a given entry may delegate to this target principal
    3701             :  * with S4U2Proxy.
    3702             :  */
    3703             : krb5_error_code
    3704         146 : samba_kdc_check_s4u2proxy(krb5_context context,
    3705             :                           struct samba_kdc_db_context *kdc_db_ctx,
    3706             :                           struct samba_kdc_entry *skdc_entry,
    3707             :                           krb5_const_principal target_principal)
    3708             : {
    3709           0 :         krb5_error_code ret;
    3710         146 :         char *tmp = NULL;
    3711         146 :         const char *client_dn = NULL;
    3712         146 :         const char *target_principal_name = NULL;
    3713           0 :         struct ldb_message_element *el;
    3714           0 :         struct ldb_val val;
    3715           0 :         unsigned int i;
    3716         146 :         bool found = false;
    3717             : 
    3718         146 :         TALLOC_CTX *mem_ctx = talloc_named(kdc_db_ctx, 0, "samba_kdc_check_s4u2proxy");
    3719             : 
    3720         146 :         if (!mem_ctx) {
    3721           0 :                 ret = ENOMEM;
    3722           0 :                 krb5_set_error_message(context, ret,
    3723             :                                        "samba_kdc_check_s4u2proxy:"
    3724             :                                        " talloc_named() failed!");
    3725           0 :                 return ret;
    3726             :         }
    3727             : 
    3728         146 :         client_dn = ldb_dn_get_linearized(skdc_entry->msg->dn);
    3729         146 :         if (!client_dn) {
    3730           0 :                 if (errno == 0) {
    3731           0 :                         errno = ENOMEM;
    3732             :                 }
    3733           0 :                 ret = errno;
    3734           0 :                 krb5_set_error_message(context, ret,
    3735             :                                        "samba_kdc_check_s4u2proxy:"
    3736             :                                        " ldb_dn_get_linearized() failed!");
    3737           0 :                 talloc_free(mem_ctx);
    3738           0 :                 return ret;
    3739             :         }
    3740             : 
    3741         146 :         el = ldb_msg_find_element(skdc_entry->msg, "msDS-AllowedToDelegateTo");
    3742         146 :         if (el == NULL) {
    3743          29 :                 ret = ENOENT;
    3744          29 :                 goto bad_option;
    3745             :         }
    3746         117 :         SMB_ASSERT(el->num_values != 0);
    3747             : 
    3748             :         /*
    3749             :          * This is the Microsoft forwardable flag behavior.
    3750             :          *
    3751             :          * If the proxy (target) principal is NULL, and we have any authorized
    3752             :          * delegation target, allow to forward.
    3753             :          */
    3754         117 :         if (target_principal == NULL) {
    3755           0 :                 talloc_free(mem_ctx);
    3756           0 :                 return 0;
    3757             :         }
    3758             : 
    3759             : 
    3760             :         /*
    3761             :          * The main heimdal code already checked that the target_principal
    3762             :          * belongs to the same realm as the client.
    3763             :          *
    3764             :          * So we just need the principal without the realm,
    3765             :          * as that is what is configured in the "msDS-AllowedToDelegateTo"
    3766             :          * attribute.
    3767             :          */
    3768         117 :         ret = krb5_unparse_name_flags(context, target_principal,
    3769             :                                       KRB5_PRINCIPAL_UNPARSE_NO_REALM, &tmp);
    3770         117 :         if (ret) {
    3771           0 :                 talloc_free(mem_ctx);
    3772           0 :                 krb5_set_error_message(context, ret,
    3773             :                                        "samba_kdc_check_s4u2proxy:"
    3774             :                                        " krb5_unparse_name_flags() failed!");
    3775           0 :                 return ret;
    3776             :         }
    3777         117 :         DBG_DEBUG("client[%s] for target[%s]\n",
    3778             :                   client_dn, tmp);
    3779             : 
    3780         117 :         target_principal_name = talloc_strdup(mem_ctx, tmp);
    3781         117 :         SAFE_FREE(tmp);
    3782         117 :         if (target_principal_name == NULL) {
    3783           0 :                 ret = ENOMEM;
    3784           0 :                 krb5_set_error_message(context, ret,
    3785             :                                        "samba_kdc_check_s4u2proxy:"
    3786             :                                        " talloc_strdup() failed!");
    3787           0 :                 talloc_free(mem_ctx);
    3788           0 :                 return ret;
    3789             :         }
    3790             : 
    3791         117 :         val = data_blob_string_const(target_principal_name);
    3792             : 
    3793         118 :         for (i=0; i<el->num_values; i++) {
    3794         117 :                 struct ldb_val *val1 = &val;
    3795         117 :                 struct ldb_val *val2 = &el->values[i];
    3796           0 :                 int cmp;
    3797             : 
    3798         117 :                 if (val1->length != val2->length) {
    3799           1 :                         continue;
    3800             :                 }
    3801             : 
    3802         116 :                 cmp = strncasecmp((const char *)val1->data,
    3803         116 :                                   (const char *)val2->data,
    3804             :                                   val1->length);
    3805         116 :                 if (cmp != 0) {
    3806           0 :                         continue;
    3807             :                 }
    3808             : 
    3809         116 :                 found = true;
    3810         116 :                 break;
    3811             :         }
    3812             : 
    3813         117 :         if (!found) {
    3814           1 :                 ret = ENOENT;
    3815           1 :                 goto bad_option;
    3816             :         }
    3817             : 
    3818         116 :         DBG_DEBUG("client[%s] allowed target[%s]\n",
    3819             :                   client_dn, target_principal_name);
    3820         116 :         talloc_free(mem_ctx);
    3821         116 :         return 0;
    3822             : 
    3823          30 : bad_option:
    3824          30 :         krb5_set_error_message(context, ret,
    3825             :                                "samba_kdc_check_s4u2proxy: client[%s] "
    3826             :                                "not allowed for delegation to target[%s]",
    3827             :                                client_dn,
    3828             :                                target_principal_name);
    3829          30 :         talloc_free(mem_ctx);
    3830          30 :         return KRB5KDC_ERR_BADOPTION;
    3831             : }
    3832             : 
    3833             : /*
    3834             :  * This method is called for S4U2Proxy requests and implements the
    3835             :  * resource-based constrained delegation variant, which can support
    3836             :  * cross-realm delegation.
    3837             :  */
    3838         136 : krb5_error_code samba_kdc_check_s4u2proxy_rbcd(
    3839             :                 krb5_context context,
    3840             :                 struct samba_kdc_db_context *kdc_db_ctx,
    3841             :                 krb5_const_principal client_principal,
    3842             :                 krb5_const_principal server_principal,
    3843             :                 const struct auth_user_info_dc *user_info_dc,
    3844             :                 const struct auth_user_info_dc *device_info_dc,
    3845             :                 const struct auth_claims auth_claims,
    3846             :                 struct samba_kdc_entry *proxy_skdc_entry)
    3847             : {
    3848           0 :         krb5_error_code code;
    3849           0 :         enum ndr_err_code ndr_err;
    3850         136 :         char *client_name = NULL;
    3851         136 :         char *server_name = NULL;
    3852         136 :         const char *proxy_dn = NULL;
    3853         136 :         const DATA_BLOB *data = NULL;
    3854         136 :         struct security_descriptor *rbcd_security_descriptor = NULL;
    3855         136 :         struct security_token *security_token = NULL;
    3856         136 :         uint32_t session_info_flags =
    3857             :                 AUTH_SESSION_INFO_DEFAULT_GROUPS |
    3858             :                 AUTH_SESSION_INFO_DEVICE_DEFAULT_GROUPS |
    3859             :                 AUTH_SESSION_INFO_SIMPLE_PRIVILEGES |
    3860             :                 AUTH_SESSION_INFO_FORCE_COMPOUNDED_AUTHENTICATION;
    3861             :         /*
    3862             :          * Testing shows that although Windows grants SEC_ADS_GENERIC_ALL access
    3863             :          * in security descriptors it creates for RBCD, its KDC only requires
    3864             :          * SEC_ADS_CONTROL_ACCESS for the access check to succeed.
    3865             :          */
    3866         136 :         uint32_t access_desired = SEC_ADS_CONTROL_ACCESS;
    3867         136 :         uint32_t access_granted = 0;
    3868           0 :         NTSTATUS nt_status;
    3869         136 :         TALLOC_CTX *mem_ctx = NULL;
    3870             : 
    3871         136 :         mem_ctx = talloc_named(kdc_db_ctx,
    3872             :                                0,
    3873             :                                "samba_kdc_check_s4u2proxy_rbcd");
    3874         136 :         if (mem_ctx == NULL) {
    3875           0 :                 errno = ENOMEM;
    3876           0 :                 code = errno;
    3877             : 
    3878           0 :                 return code;
    3879             :         }
    3880             : 
    3881         136 :         proxy_dn = ldb_dn_get_linearized(proxy_skdc_entry->msg->dn);
    3882         136 :         if (proxy_dn == NULL) {
    3883           0 :                 DBG_ERR("ldb_dn_get_linearized failed for proxy_dn!\n");
    3884           0 :                 if (errno == 0) {
    3885           0 :                         errno = ENOMEM;
    3886             :                 }
    3887           0 :                 code = errno;
    3888             : 
    3889           0 :                 goto out;
    3890             :         }
    3891             : 
    3892         136 :         rbcd_security_descriptor = talloc_zero(mem_ctx,
    3893             :                                                struct security_descriptor);
    3894         136 :         if (rbcd_security_descriptor == NULL) {
    3895           0 :                 errno = ENOMEM;
    3896           0 :                 code = errno;
    3897             : 
    3898           0 :                 goto out;
    3899             :         }
    3900             : 
    3901         136 :         code = krb5_unparse_name_flags(context,
    3902             :                                        client_principal,
    3903             :                                        KRB5_PRINCIPAL_UNPARSE_DISPLAY,
    3904             :                                        &client_name);
    3905         136 :         if (code != 0) {
    3906           0 :                 DBG_ERR("Unable to parse client_principal!\n");
    3907           0 :                 goto out;
    3908             :         }
    3909             : 
    3910         136 :         code = krb5_unparse_name_flags(context,
    3911             :                                        server_principal,
    3912             :                                        KRB5_PRINCIPAL_UNPARSE_DISPLAY,
    3913             :                                        &server_name);
    3914         136 :         if (code != 0) {
    3915           0 :                 DBG_ERR("Unable to parse server_principal!\n");
    3916           0 :                 goto out;
    3917             :         }
    3918             : 
    3919         136 :         DBG_INFO("Check delegation from client[%s] to server[%s] via "
    3920             :                  "proxy[%s]\n",
    3921             :                  client_name,
    3922             :                  server_name,
    3923             :                  proxy_dn);
    3924             : 
    3925         136 :         if (!(user_info_dc->info->user_flags & NETLOGON_GUEST)) {
    3926         136 :                 session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
    3927             :         }
    3928             : 
    3929         136 :         if (device_info_dc != NULL && !(device_info_dc->info->user_flags & NETLOGON_GUEST)) {
    3930          90 :                 session_info_flags |= AUTH_SESSION_INFO_DEVICE_AUTHENTICATED;
    3931             :         }
    3932             : 
    3933         136 :         nt_status = auth_generate_security_token(mem_ctx,
    3934             :                                                  kdc_db_ctx->lp_ctx,
    3935             :                                                  kdc_db_ctx->samdb,
    3936             :                                                  user_info_dc,
    3937             :                                                  device_info_dc,
    3938             :                                                  auth_claims,
    3939             :                                                  session_info_flags,
    3940             :                                                  &security_token);
    3941         136 :         if (!NT_STATUS_IS_OK(nt_status)) {
    3942           0 :                 code = map_errno_from_nt_status(nt_status);
    3943           0 :                 goto out;
    3944             :         }
    3945             : 
    3946         136 :         data = ldb_msg_find_ldb_val(proxy_skdc_entry->msg,
    3947             :                                     "msDS-AllowedToActOnBehalfOfOtherIdentity");
    3948         136 :         if (data == NULL) {
    3949           5 :                 DBG_WARNING("Could not find security descriptor "
    3950             :                             "msDS-AllowedToActOnBehalfOfOtherIdentity in "
    3951             :                             "proxy[%s]\n",
    3952             :                             proxy_dn);
    3953           5 :                 code = KRB5KDC_ERR_BADOPTION;
    3954           5 :                 goto out;
    3955             :         }
    3956             : 
    3957         131 :         ndr_err = ndr_pull_struct_blob(
    3958             :                         data,
    3959             :                         mem_ctx,
    3960             :                         rbcd_security_descriptor,
    3961             :                         (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
    3962         131 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    3963           0 :                 errno = ndr_map_error2errno(ndr_err);
    3964           0 :                 DBG_ERR("Failed to unmarshall "
    3965             :                         "msDS-AllowedToActOnBehalfOfOtherIdentity "
    3966             :                         "security descriptor of proxy[%s]\n",
    3967             :                         proxy_dn);
    3968           0 :                 code = KRB5KDC_ERR_BADOPTION;
    3969           0 :                 goto out;
    3970             :         }
    3971             : 
    3972         131 :         if (DEBUGLEVEL >= 10) {
    3973           0 :                 NDR_PRINT_DEBUG(security_token, security_token);
    3974           0 :                 NDR_PRINT_DEBUG(security_descriptor, rbcd_security_descriptor);
    3975             :         }
    3976             : 
    3977         131 :         nt_status = sec_access_check_ds(rbcd_security_descriptor,
    3978             :                                         security_token,
    3979             :                                         access_desired,
    3980             :                                         &access_granted,
    3981             :                                         NULL,
    3982             :                                         NULL);
    3983             : 
    3984         131 :         if (!NT_STATUS_IS_OK(nt_status)) {
    3985          22 :                 DBG_WARNING("RBCD: sec_access_check_ds(access_desired=%#08x, "
    3986             :                             "access_granted:%#08x) failed with: %s\n",
    3987             :                             access_desired,
    3988             :                             access_granted,
    3989             :                             nt_errstr(nt_status));
    3990             : 
    3991          22 :                 code = KRB5KDC_ERR_BADOPTION;
    3992          22 :                 goto out;
    3993             :         }
    3994             : 
    3995         109 :         DBG_NOTICE("RBCD: Access granted for client[%s]\n", client_name);
    3996             : 
    3997         109 :         code = 0;
    3998         136 : out:
    3999         136 :         SAFE_FREE(client_name);
    4000         136 :         SAFE_FREE(server_name);
    4001             : 
    4002         136 :         TALLOC_FREE(mem_ctx);
    4003         136 :         return code;
    4004             : }
    4005             : 
    4006         259 : NTSTATUS samba_kdc_setup_db_ctx(TALLOC_CTX *mem_ctx, struct samba_kdc_base_context *base_ctx,
    4007             :                                 struct samba_kdc_db_context **kdc_db_ctx_out)
    4008             : {
    4009           8 :         int ldb_ret;
    4010         259 :         struct ldb_message *msg = NULL;
    4011         259 :         struct samba_kdc_db_context *kdc_db_ctx = NULL;
    4012             :         /* The idea here is very simple.  Using Kerberos to
    4013             :          * authenticate the KDC to the LDAP server is highly likely to
    4014             :          * be circular.
    4015             :          *
    4016             :          * In future we may set this up to use EXTERNAL and SSL
    4017             :          * certificates, for now it will almost certainly be NTLMSSP_SET_USERNAME
    4018             :         */
    4019             : 
    4020         259 :         kdc_db_ctx = talloc_zero(mem_ctx, struct samba_kdc_db_context);
    4021         259 :         if (kdc_db_ctx == NULL) {
    4022           0 :                 return NT_STATUS_NO_MEMORY;
    4023             :         }
    4024         259 :         kdc_db_ctx->ev_ctx = base_ctx->ev_ctx;
    4025         259 :         kdc_db_ctx->lp_ctx = base_ctx->lp_ctx;
    4026         259 :         kdc_db_ctx->msg_ctx = base_ctx->msg_ctx;
    4027             : 
    4028             :         /* get default kdc policy */
    4029         259 :         lpcfg_default_kdc_policy(mem_ctx,
    4030             :                                  base_ctx->lp_ctx,
    4031             :                                  &kdc_db_ctx->policy.svc_tkt_lifetime,
    4032             :                                  &kdc_db_ctx->policy.usr_tkt_lifetime,
    4033             :                                  &kdc_db_ctx->policy.renewal_lifetime);
    4034             : 
    4035             :         /* This is to allow "samba-tool domain exportkeytab to take a -H */
    4036         259 :         if (base_ctx->samdb != NULL) {
    4037             :                 /*
    4038             :                  * Caller is responsible for lifetimes.  In reality
    4039             :                  * the whole thing is destroyed before leaving the
    4040             :                  * function the samdb was passed into
    4041             :                  */
    4042          24 :                 kdc_db_ctx->samdb = base_ctx->samdb;
    4043             :         } else {
    4044         235 :                 struct auth_session_info *session_info = NULL;
    4045         235 :                 session_info = system_session(kdc_db_ctx->lp_ctx);
    4046         235 :                 if (session_info == NULL) {
    4047           0 :                         talloc_free(kdc_db_ctx);
    4048           0 :                         return NT_STATUS_INTERNAL_ERROR;
    4049             :                 }
    4050             : 
    4051             :                 /* Setup the link to LDB */
    4052         235 :                 kdc_db_ctx->samdb = samdb_connect(kdc_db_ctx,
    4053             :                                                   base_ctx->ev_ctx,
    4054             :                                                   base_ctx->lp_ctx,
    4055             :                                                   session_info,
    4056             :                                                   NULL,
    4057             :                                                   0);
    4058         235 :                 if (kdc_db_ctx->samdb == NULL) {
    4059           0 :                         DBG_WARNING("Cannot open samdb for KDC backend!\n");
    4060           0 :                         talloc_free(kdc_db_ctx);
    4061           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    4062             :                 }
    4063             :         }
    4064             : 
    4065             :         /* Find out our own krbtgt kvno */
    4066         259 :         ldb_ret = samdb_rodc(kdc_db_ctx->samdb, &kdc_db_ctx->rodc);
    4067         259 :         if (ldb_ret != LDB_SUCCESS) {
    4068           0 :                 DBG_WARNING("Cannot determine if we are an RODC in KDC backend: %s\n",
    4069             :                             ldb_errstring(kdc_db_ctx->samdb));
    4070           0 :                 talloc_free(kdc_db_ctx);
    4071           0 :                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    4072             :         }
    4073         259 :         if (kdc_db_ctx->rodc) {
    4074           0 :                 int my_krbtgt_number;
    4075           1 :                 const char *secondary_keytab[] = { "msDS-SecondaryKrbTgtNumber", NULL };
    4076           1 :                 struct ldb_dn *account_dn = NULL;
    4077           1 :                 struct ldb_dn *server_dn = samdb_server_dn(kdc_db_ctx->samdb, kdc_db_ctx);
    4078           1 :                 if (!server_dn) {
    4079           0 :                         DBG_WARNING("Cannot determine server DN in KDC backend: %s\n",
    4080             :                                     ldb_errstring(kdc_db_ctx->samdb));
    4081           0 :                         talloc_free(kdc_db_ctx);
    4082           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    4083             :                 }
    4084             : 
    4085           1 :                 ldb_ret = samdb_reference_dn(kdc_db_ctx->samdb, kdc_db_ctx, server_dn,
    4086             :                                              "serverReference", &account_dn);
    4087           1 :                 if (ldb_ret != LDB_SUCCESS) {
    4088           0 :                         DBG_WARNING("Cannot determine server account in KDC backend: %s\n",
    4089             :                                     ldb_errstring(kdc_db_ctx->samdb));
    4090           0 :                         talloc_free(kdc_db_ctx);
    4091           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    4092             :                 }
    4093             : 
    4094           1 :                 ldb_ret = samdb_reference_dn(kdc_db_ctx->samdb, kdc_db_ctx, account_dn,
    4095             :                                              "msDS-KrbTgtLink", &kdc_db_ctx->krbtgt_dn);
    4096           1 :                 talloc_free(account_dn);
    4097           1 :                 if (ldb_ret != LDB_SUCCESS) {
    4098           0 :                         DBG_WARNING("Cannot determine RODC krbtgt account in KDC backend: %s\n",
    4099             :                                     ldb_errstring(kdc_db_ctx->samdb));
    4100           0 :                         talloc_free(kdc_db_ctx);
    4101           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    4102             :                 }
    4103             : 
    4104           1 :                 ldb_ret = dsdb_search_one(kdc_db_ctx->samdb, kdc_db_ctx,
    4105             :                                           &msg, kdc_db_ctx->krbtgt_dn, LDB_SCOPE_BASE,
    4106             :                                           secondary_keytab,
    4107             :                                           DSDB_SEARCH_NO_GLOBAL_CATALOG,
    4108             :                                           "(&(objectClass=user)(msDS-SecondaryKrbTgtNumber=*))");
    4109           1 :                 if (ldb_ret != LDB_SUCCESS) {
    4110           0 :                         DBG_WARNING("Cannot read krbtgt account %s in KDC backend to get msDS-SecondaryKrbTgtNumber: %s: %s\n",
    4111             :                                     ldb_dn_get_linearized(kdc_db_ctx->krbtgt_dn),
    4112             :                                     ldb_errstring(kdc_db_ctx->samdb),
    4113             :                                     ldb_strerror(ldb_ret));
    4114           0 :                         talloc_free(kdc_db_ctx);
    4115           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    4116             :                 }
    4117           1 :                 my_krbtgt_number = ldb_msg_find_attr_as_int(msg, "msDS-SecondaryKrbTgtNumber", -1);
    4118           1 :                 if (my_krbtgt_number == -1) {
    4119           0 :                         DBG_WARNING("Cannot read msDS-SecondaryKrbTgtNumber from krbtgt account %s in KDC backend: got %d\n",
    4120             :                                     ldb_dn_get_linearized(kdc_db_ctx->krbtgt_dn),
    4121             :                                     my_krbtgt_number);
    4122           0 :                         talloc_free(kdc_db_ctx);
    4123           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    4124             :                 }
    4125           1 :                 kdc_db_ctx->my_krbtgt_number = my_krbtgt_number;
    4126             : 
    4127             :         } else {
    4128         258 :                 kdc_db_ctx->my_krbtgt_number = 0;
    4129         258 :                 ldb_ret = dsdb_search_one(kdc_db_ctx->samdb, kdc_db_ctx,
    4130             :                                           &msg,
    4131             :                                           ldb_get_default_basedn(kdc_db_ctx->samdb),
    4132             :                                           LDB_SCOPE_SUBTREE,
    4133             :                                           krbtgt_attrs,
    4134             :                                           DSDB_SEARCH_NO_GLOBAL_CATALOG | DSDB_SEARCH_UPDATE_MANAGED_PASSWORDS,
    4135             :                                           "(&(objectClass=user)(samAccountName=krbtgt))");
    4136             : 
    4137         258 :                 if (ldb_ret != LDB_SUCCESS) {
    4138           0 :                         DBG_WARNING("could not find own KRBTGT in DB: %s\n", ldb_errstring(kdc_db_ctx->samdb));
    4139           0 :                         talloc_free(kdc_db_ctx);
    4140           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    4141             :                 }
    4142         258 :                 kdc_db_ctx->krbtgt_dn = talloc_steal(kdc_db_ctx, msg->dn);
    4143         258 :                 kdc_db_ctx->my_krbtgt_number = 0;
    4144         258 :                 talloc_free(msg);
    4145             :         }
    4146         259 :         *kdc_db_ctx_out = kdc_db_ctx;
    4147         259 :         return NT_STATUS_OK;
    4148             : }
    4149             : 
    4150       18843 : krb5_error_code dsdb_extract_aes_256_key(krb5_context context,
    4151             :                                          TALLOC_CTX *mem_ctx,
    4152             :                                          struct ldb_context *ldb,
    4153             :                                          const struct ldb_message *msg,
    4154             :                                          uint32_t user_account_control,
    4155             :                                          const uint32_t *kvno,
    4156             :                                          uint32_t *kvno_out,
    4157             :                                          DATA_BLOB *aes_256_key,
    4158             :                                          DATA_BLOB *salt)
    4159             : {
    4160         139 :         krb5_error_code krb5_ret;
    4161         139 :         uint32_t supported_enctypes;
    4162       18843 :         unsigned flags = SDB_F_GET_CLIENT;
    4163       18843 :         struct sdb_entry sentry = {};
    4164             : 
    4165       18843 :         if (kvno != NULL) {
    4166         658 :                 flags |= SDB_F_KVNO_SPECIFIED;
    4167             :         }
    4168             : 
    4169       19331 :         krb5_ret = samba_kdc_message2entry_keys(context,
    4170             :                                                 mem_ctx,
    4171             :                                                 ldb,
    4172             :                                                 msg,
    4173             :                                                 false, /* is_krbtgt */
    4174             :                                                 false, /* is_rodc */
    4175             :                                                 user_account_control,
    4176             :                                                 SAMBA_KDC_ENT_TYPE_CLIENT,
    4177             :                                                 flags,
    4178         488 :                                                 (kvno != NULL) ? *kvno : 0,
    4179             :                                                 &sentry,
    4180             :                                                 ENC_HMAC_SHA1_96_AES256,
    4181             :                                                 &supported_enctypes);
    4182       18843 :         if (krb5_ret != 0) {
    4183           0 :                 const char *krb5_err = krb5_get_error_message(context, krb5_ret);
    4184             : 
    4185           0 :                 DBG_ERR("Failed to parse supplementalCredentials "
    4186             :                         "of %s with %s kvno using "
    4187             :                         "ENCTYPE_HMAC_SHA1_96_AES256 "
    4188             :                         "Kerberos Key: %s\n",
    4189             :                         ldb_dn_get_linearized(msg->dn),
    4190             :                         (kvno != NULL) ? "previous" : "current",
    4191             :                         krb5_err != NULL ? krb5_err : "<unknown>");
    4192             : 
    4193           0 :                 krb5_free_error_message(context, krb5_err);
    4194             : 
    4195           0 :                 return krb5_ret;
    4196             :         }
    4197             : 
    4198       18843 :         if ((supported_enctypes & ENC_HMAC_SHA1_96_AES256) == 0 ||
    4199        3071 :             sentry.keys.len != 1) {
    4200       15772 :                 DBG_INFO("Failed to find a ENCTYPE_HMAC_SHA1_96_AES256 "
    4201             :                          "key in supplementalCredentials "
    4202             :                          "of %s at KVNO %u (got %u keys, expected 1)\n",
    4203             :                          ldb_dn_get_linearized(msg->dn),
    4204             :                          sentry.kvno,
    4205             :                          sentry.keys.len);
    4206       15772 :                 sdb_entry_free(&sentry);
    4207       15772 :                 return ENOENT;
    4208             :         }
    4209             : 
    4210        3071 :         if (sentry.keys.val[0].salt == NULL) {
    4211           0 :                 DBG_INFO("Failed to find a salt in "
    4212             :                          "supplementalCredentials "
    4213             :                          "of %s at KVNO %u\n",
    4214             :                          ldb_dn_get_linearized(msg->dn),
    4215             :                          sentry.kvno);
    4216           0 :                 sdb_entry_free(&sentry);
    4217           0 :                 return ENOENT;
    4218             :         }
    4219             : 
    4220        3071 :         if (aes_256_key != NULL) {
    4221        3071 :                 *aes_256_key = data_blob_talloc(mem_ctx,
    4222             :                                                 KRB5_KEY_DATA(&sentry.keys.val[0].key),
    4223             :                                                 KRB5_KEY_LENGTH(&sentry.keys.val[0].key));
    4224        3071 :                 if (aes_256_key->data == NULL) {
    4225           0 :                         sdb_entry_free(&sentry);
    4226           0 :                         return ENOMEM;
    4227             :                 }
    4228        3071 :                 talloc_keep_secret(aes_256_key->data);
    4229             :         }
    4230             : 
    4231        3071 :         if (salt != NULL) {
    4232        2711 :                 *salt = data_blob_talloc(mem_ctx,
    4233             :                                          sentry.keys.val[0].salt->salt.data,
    4234             :                                          sentry.keys.val[0].salt->salt.length);
    4235        2711 :                 if (salt->data == NULL) {
    4236           0 :                         sdb_entry_free(&sentry);
    4237           0 :                         return ENOMEM;
    4238             :                 }
    4239             :         }
    4240             : 
    4241        3071 :         if (kvno_out != NULL) {
    4242        2689 :                 *kvno_out = sentry.kvno;
    4243             :         }
    4244             : 
    4245        3071 :         sdb_entry_free(&sentry);
    4246             : 
    4247        3071 :         return 0;
    4248             : }

Generated by: LCOV version 1.14