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

Generated by: LCOV version 1.14