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