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