LCOV - code coverage report
Current view: top level - source4/kdc - db-glue.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 1105 1548 71.4 %
Date: 2024-06-13 04:01:37 Functions: 32 35 91.4 %

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

Generated by: LCOV version 1.13