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