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