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