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