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