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