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