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

Generated by: LCOV version 1.14