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