1 /*
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4 
5    Copyright (C) Andrew Tridgell 2004
6    Copyright (C) Volker Lendecke 2004
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006
8    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
9 
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
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 "events/events.h"
26 #include "ldb.h"
27 #include "ldb_module.h"
28 #include "ldb_errors.h"
29 #include "../lib/util/util_ldb.h"
30 #include "../lib/crypto/crypto.h"
31 #include "dsdb/samdb/samdb.h"
32 #include "libcli/security/security.h"
33 #include "librpc/gen_ndr/ndr_security.h"
34 #include "librpc/gen_ndr/ndr_misc.h"
35 #include "../libds/common/flags.h"
36 #include "dsdb/common/proto.h"
37 #include "libcli/ldap/ldap_ndr.h"
38 #include "param/param.h"
39 #include "libcli/auth/libcli_auth.h"
40 #include "librpc/gen_ndr/ndr_drsblobs.h"
41 #include "system/locale.h"
42 #include "system/filesys.h"
43 #include "lib/util/tsort.h"
44 #include "dsdb/common/util.h"
45 #include "lib/socket/socket.h"
46 #include "librpc/gen_ndr/irpc.h"
47 #include "libds/common/flag_mapping.h"
48 #include "lib/util/access.h"
49 #include "lib/util/util_str_hex.h"
50 #include "lib/util/sys_rw_data.h"
51 #include "libcli/util/ntstatus.h"
52 
53 /*
54  * This included to allow us to handle DSDB_FLAG_REPLICATED_UPDATE in
55  * dsdb_request_add_controls()
56  */
57 #include "dsdb/samdb/ldb_modules/util.h"
58 
59 /* default is 30 minutes: -1e7 * 30 * 60 */
60 #define DEFAULT_OBSERVATION_WINDOW              -18000000000
61 
62 /*
63   search the sam for the specified attributes in a specific domain, filter on
64   objectSid being in domain_sid.
65 */
samdb_search_domain(struct ldb_context * sam_ldb,TALLOC_CTX * mem_ctx,struct ldb_dn * basedn,struct ldb_message *** res,const char * const * attrs,const struct dom_sid * domain_sid,const char * format,...)66 int samdb_search_domain(struct ldb_context *sam_ldb,
67 			TALLOC_CTX *mem_ctx,
68 			struct ldb_dn *basedn,
69 			struct ldb_message ***res,
70 			const char * const *attrs,
71 			const struct dom_sid *domain_sid,
72 			const char *format, ...)  _PRINTF_ATTRIBUTE(7,8)
73 {
74 	va_list ap;
75 	int i, count;
76 
77 	va_start(ap, format);
78 	count = gendb_search_v(sam_ldb, mem_ctx, basedn,
79 			       res, attrs, format, ap);
80 	va_end(ap);
81 
82 	i=0;
83 
84 	while (i<count) {
85 		struct dom_sid *entry_sid;
86 
87 		entry_sid = samdb_result_dom_sid(mem_ctx, (*res)[i], "objectSid");
88 
89 		if ((entry_sid == NULL) ||
90 		    (!dom_sid_in_domain(domain_sid, entry_sid))) {
91 			/* Delete that entry from the result set */
92 			(*res)[i] = (*res)[count-1];
93 			count -= 1;
94 			talloc_free(entry_sid);
95 			continue;
96 		}
97 		talloc_free(entry_sid);
98 		i += 1;
99 	}
100 
101 	return count;
102 }
103 
104 /*
105   search the sam for a single string attribute in exactly 1 record
106 */
samdb_search_string_v(struct ldb_context * sam_ldb,TALLOC_CTX * mem_ctx,struct ldb_dn * basedn,const char * attr_name,const char * format,va_list ap)107 const char *samdb_search_string_v(struct ldb_context *sam_ldb,
108 				  TALLOC_CTX *mem_ctx,
109 				  struct ldb_dn *basedn,
110 				  const char *attr_name,
111 				  const char *format, va_list ap) _PRINTF_ATTRIBUTE(5,0)
112 {
113 	int count;
114 	const char *attrs[2] = { NULL, NULL };
115 	struct ldb_message **res = NULL;
116 
117 	attrs[0] = attr_name;
118 
119 	count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
120 	if (count > 1) {
121 		DEBUG(1,("samdb: search for %s %s not single valued (count=%d)\n",
122 			 attr_name, format, count));
123 	}
124 	if (count != 1) {
125 		talloc_free(res);
126 		return NULL;
127 	}
128 
129 	return ldb_msg_find_attr_as_string(res[0], attr_name, NULL);
130 }
131 
132 /*
133   search the sam for a single string attribute in exactly 1 record
134 */
samdb_search_string(struct ldb_context * sam_ldb,TALLOC_CTX * mem_ctx,struct ldb_dn * basedn,const char * attr_name,const char * format,...)135 const char *samdb_search_string(struct ldb_context *sam_ldb,
136 				TALLOC_CTX *mem_ctx,
137 				struct ldb_dn *basedn,
138 				const char *attr_name,
139 				const char *format, ...) _PRINTF_ATTRIBUTE(5,6)
140 {
141 	va_list ap;
142 	const char *str;
143 
144 	va_start(ap, format);
145 	str = samdb_search_string_v(sam_ldb, mem_ctx, basedn, attr_name, format, ap);
146 	va_end(ap);
147 
148 	return str;
149 }
150 
samdb_search_dn(struct ldb_context * sam_ldb,TALLOC_CTX * mem_ctx,struct ldb_dn * basedn,const char * format,...)151 struct ldb_dn *samdb_search_dn(struct ldb_context *sam_ldb,
152 			       TALLOC_CTX *mem_ctx,
153 			       struct ldb_dn *basedn,
154 			       const char *format, ...) _PRINTF_ATTRIBUTE(4,5)
155 {
156 	va_list ap;
157 	struct ldb_dn *ret;
158 	struct ldb_message **res = NULL;
159 	int count;
160 
161 	va_start(ap, format);
162 	count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, NULL, format, ap);
163 	va_end(ap);
164 
165 	if (count != 1) return NULL;
166 
167 	ret = talloc_steal(mem_ctx, res[0]->dn);
168 	talloc_free(res);
169 
170 	return ret;
171 }
172 
173 /*
174   search the sam for a dom_sid attribute in exactly 1 record
175 */
samdb_search_dom_sid(struct ldb_context * sam_ldb,TALLOC_CTX * mem_ctx,struct ldb_dn * basedn,const char * attr_name,const char * format,...)176 struct dom_sid *samdb_search_dom_sid(struct ldb_context *sam_ldb,
177 				     TALLOC_CTX *mem_ctx,
178 				     struct ldb_dn *basedn,
179 				     const char *attr_name,
180 				     const char *format, ...) _PRINTF_ATTRIBUTE(5,6)
181 {
182 	va_list ap;
183 	int count;
184 	struct ldb_message **res;
185 	const char *attrs[2] = { NULL, NULL };
186 	struct dom_sid *sid;
187 
188 	attrs[0] = attr_name;
189 
190 	va_start(ap, format);
191 	count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
192 	va_end(ap);
193 	if (count > 1) {
194 		DEBUG(1,("samdb: search for %s %s not single valued (count=%d)\n",
195 			 attr_name, format, count));
196 	}
197 	if (count != 1) {
198 		talloc_free(res);
199 		return NULL;
200 	}
201 	sid = samdb_result_dom_sid(mem_ctx, res[0], attr_name);
202 	talloc_free(res);
203 	return sid;
204 }
205 
206 /*
207   search the sam for a single integer attribute in exactly 1 record
208 */
samdb_search_uint(struct ldb_context * sam_ldb,TALLOC_CTX * mem_ctx,unsigned int default_value,struct ldb_dn * basedn,const char * attr_name,const char * format,...)209 unsigned int samdb_search_uint(struct ldb_context *sam_ldb,
210 			 TALLOC_CTX *mem_ctx,
211 			 unsigned int default_value,
212 			 struct ldb_dn *basedn,
213 			 const char *attr_name,
214 			 const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
215 {
216 	va_list ap;
217 	int count;
218 	struct ldb_message **res;
219 	const char *attrs[2] = { NULL, NULL };
220 
221 	attrs[0] = attr_name;
222 
223 	va_start(ap, format);
224 	count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
225 	va_end(ap);
226 
227 	if (count != 1) {
228 		return default_value;
229 	}
230 
231 	return ldb_msg_find_attr_as_uint(res[0], attr_name, default_value);
232 }
233 
234 /*
235   search the sam for a single signed 64 bit integer attribute in exactly 1 record
236 */
samdb_search_int64(struct ldb_context * sam_ldb,TALLOC_CTX * mem_ctx,int64_t default_value,struct ldb_dn * basedn,const char * attr_name,const char * format,...)237 int64_t samdb_search_int64(struct ldb_context *sam_ldb,
238 			   TALLOC_CTX *mem_ctx,
239 			   int64_t default_value,
240 			   struct ldb_dn *basedn,
241 			   const char *attr_name,
242 			   const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
243 {
244 	va_list ap;
245 	int count;
246 	struct ldb_message **res;
247 	const char *attrs[2] = { NULL, NULL };
248 
249 	attrs[0] = attr_name;
250 
251 	va_start(ap, format);
252 	count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
253 	va_end(ap);
254 
255 	if (count != 1) {
256 		return default_value;
257 	}
258 
259 	return ldb_msg_find_attr_as_int64(res[0], attr_name, default_value);
260 }
261 
262 /*
263   search the sam for multipe records each giving a single string attribute
264   return the number of matches, or -1 on error
265 */
samdb_search_string_multiple(struct ldb_context * sam_ldb,TALLOC_CTX * mem_ctx,struct ldb_dn * basedn,const char *** strs,const char * attr_name,const char * format,...)266 int samdb_search_string_multiple(struct ldb_context *sam_ldb,
267 				 TALLOC_CTX *mem_ctx,
268 				 struct ldb_dn *basedn,
269 				 const char ***strs,
270 				 const char *attr_name,
271 				 const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
272 {
273 	va_list ap;
274 	int count, i;
275 	const char *attrs[2] = { NULL, NULL };
276 	struct ldb_message **res = NULL;
277 
278 	attrs[0] = attr_name;
279 
280 	va_start(ap, format);
281 	count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
282 	va_end(ap);
283 
284 	if (count <= 0) {
285 		return count;
286 	}
287 
288 	/* make sure its single valued */
289 	for (i=0;i<count;i++) {
290 		if (res[i]->num_elements != 1) {
291 			DEBUG(1,("samdb: search for %s %s not single valued\n",
292 				 attr_name, format));
293 			talloc_free(res);
294 			return -1;
295 		}
296 	}
297 
298 	*strs = talloc_array(mem_ctx, const char *, count+1);
299 	if (! *strs) {
300 		talloc_free(res);
301 		return -1;
302 	}
303 
304 	for (i=0;i<count;i++) {
305 		(*strs)[i] = ldb_msg_find_attr_as_string(res[i], attr_name, NULL);
306 	}
307 	(*strs)[count] = NULL;
308 
309 	return count;
310 }
311 
samdb_result_dn(struct ldb_context * ldb,TALLOC_CTX * mem_ctx,const struct ldb_message * msg,const char * attr,struct ldb_dn * default_value)312 struct ldb_dn *samdb_result_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const struct ldb_message *msg,
313 			       const char *attr, struct ldb_dn *default_value)
314 {
315 	struct ldb_dn *ret_dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, msg, attr);
316 	if (!ret_dn) {
317 		return default_value;
318 	}
319 	return ret_dn;
320 }
321 
322 /*
323   pull a rid from a objectSid in a result set.
324 */
samdb_result_rid_from_sid(TALLOC_CTX * mem_ctx,const struct ldb_message * msg,const char * attr,uint32_t default_value)325 uint32_t samdb_result_rid_from_sid(TALLOC_CTX *mem_ctx, const struct ldb_message *msg,
326 				   const char *attr, uint32_t default_value)
327 {
328 	struct dom_sid *sid;
329 	uint32_t rid;
330 
331 	sid = samdb_result_dom_sid(mem_ctx, msg, attr);
332 	if (sid == NULL) {
333 		return default_value;
334 	}
335 	rid = sid->sub_auths[sid->num_auths-1];
336 	talloc_free(sid);
337 	return rid;
338 }
339 
340 /*
341   pull a dom_sid structure from a objectSid in a result set.
342 */
samdb_result_dom_sid(TALLOC_CTX * mem_ctx,const struct ldb_message * msg,const char * attr)343 struct dom_sid *samdb_result_dom_sid(TALLOC_CTX *mem_ctx, const struct ldb_message *msg,
344 				     const char *attr)
345 {
346 	ssize_t ret;
347 	const struct ldb_val *v;
348 	struct dom_sid *sid;
349 	v = ldb_msg_find_ldb_val(msg, attr);
350 	if (v == NULL) {
351 		return NULL;
352 	}
353 	sid = talloc(mem_ctx, struct dom_sid);
354 	if (sid == NULL) {
355 		return NULL;
356 	}
357 	ret = sid_parse(v->data, v->length, sid);
358 	if (ret == -1) {
359 		talloc_free(sid);
360 		return NULL;
361 	}
362 	return sid;
363 }
364 
365 /*
366   pull a guid structure from a objectGUID in a result set.
367 */
samdb_result_guid(const struct ldb_message * msg,const char * attr)368 struct GUID samdb_result_guid(const struct ldb_message *msg, const char *attr)
369 {
370 	const struct ldb_val *v;
371 	struct GUID guid;
372 	NTSTATUS status;
373 
374 	v = ldb_msg_find_ldb_val(msg, attr);
375 	if (!v) return GUID_zero();
376 
377 	status = GUID_from_ndr_blob(v, &guid);
378 	if (!NT_STATUS_IS_OK(status)) {
379 		return GUID_zero();
380 	}
381 
382 	return guid;
383 }
384 
385 /*
386   pull a sid prefix from a objectSid in a result set.
387   this is used to find the domain sid for a user
388 */
samdb_result_sid_prefix(TALLOC_CTX * mem_ctx,const struct ldb_message * msg,const char * attr)389 struct dom_sid *samdb_result_sid_prefix(TALLOC_CTX *mem_ctx, const struct ldb_message *msg,
390 					const char *attr)
391 {
392 	struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, msg, attr);
393 	if (!sid || sid->num_auths < 1) return NULL;
394 	sid->num_auths--;
395 	return sid;
396 }
397 
398 /*
399   pull a NTTIME in a result set.
400 */
samdb_result_nttime(const struct ldb_message * msg,const char * attr,NTTIME default_value)401 NTTIME samdb_result_nttime(const struct ldb_message *msg, const char *attr,
402 			   NTTIME default_value)
403 {
404 	return ldb_msg_find_attr_as_uint64(msg, attr, default_value);
405 }
406 
407 /*
408  * Windows stores 0 for lastLogoff.
409  * But when a MS DC return the lastLogoff (as Logoff Time)
410  * it returns 0x7FFFFFFFFFFFFFFF, not returning this value in this case
411  * cause windows 2008 and newer version to fail for SMB requests
412  */
samdb_result_last_logoff(const struct ldb_message * msg)413 NTTIME samdb_result_last_logoff(const struct ldb_message *msg)
414 {
415 	NTTIME ret = ldb_msg_find_attr_as_uint64(msg, "lastLogoff",0);
416 
417 	if (ret == 0)
418 		ret = 0x7FFFFFFFFFFFFFFFULL;
419 
420 	return ret;
421 }
422 
423 /*
424  * Windows uses both 0 and 9223372036854775807 (0x7FFFFFFFFFFFFFFFULL) to
425  * indicate an account doesn't expire.
426  *
427  * When Windows initially creates an account, it sets
428  * accountExpires = 9223372036854775807 (0x7FFFFFFFFFFFFFFF).  However,
429  * when changing from an account having a specific expiration date to
430  * that account never expiring, it sets accountExpires = 0.
431  *
432  * Consolidate that logic here to allow clearer logic for account expiry in
433  * the rest of the code.
434  */
samdb_result_account_expires(const struct ldb_message * msg)435 NTTIME samdb_result_account_expires(const struct ldb_message *msg)
436 {
437 	NTTIME ret = ldb_msg_find_attr_as_uint64(msg, "accountExpires",
438 						 0);
439 
440 	if (ret == 0)
441 		ret = 0x7FFFFFFFFFFFFFFFULL;
442 
443 	return ret;
444 }
445 
446 /*
447   construct the allow_password_change field from the PwdLastSet attribute and the
448   domain password settings
449 */
samdb_result_allow_password_change(struct ldb_context * sam_ldb,TALLOC_CTX * mem_ctx,struct ldb_dn * domain_dn,struct ldb_message * msg,const char * attr)450 NTTIME samdb_result_allow_password_change(struct ldb_context *sam_ldb,
451 					  TALLOC_CTX *mem_ctx,
452 					  struct ldb_dn *domain_dn,
453 					  struct ldb_message *msg,
454 					  const char *attr)
455 {
456 	uint64_t attr_time = ldb_msg_find_attr_as_uint64(msg, attr, 0);
457 	int64_t minPwdAge;
458 
459 	if (attr_time == 0) {
460 		return 0;
461 	}
462 
463 	minPwdAge = samdb_search_int64(sam_ldb, mem_ctx, 0, domain_dn, "minPwdAge", NULL);
464 
465 	/* yes, this is a -= not a += as minPwdAge is stored as the negative
466 	   of the number of 100-nano-seconds */
467 	attr_time -= minPwdAge;
468 
469 	return attr_time;
470 }
471 
472 /*
473   pull a samr_Password structutre from a result set.
474 */
samdb_result_hash(TALLOC_CTX * mem_ctx,const struct ldb_message * msg,const char * attr)475 struct samr_Password *samdb_result_hash(TALLOC_CTX *mem_ctx, const struct ldb_message *msg, const char *attr)
476 {
477 	struct samr_Password *hash = NULL;
478 	const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
479 	if (val && (val->length >= sizeof(hash->hash))) {
480 		hash = talloc(mem_ctx, struct samr_Password);
481 		memcpy(hash->hash, val->data, MIN(val->length, sizeof(hash->hash)));
482 	}
483 	return hash;
484 }
485 
486 /*
487   pull an array of samr_Password structures from a result set.
488 */
samdb_result_hashes(TALLOC_CTX * mem_ctx,const struct ldb_message * msg,const char * attr,struct samr_Password ** hashes)489 unsigned int samdb_result_hashes(TALLOC_CTX *mem_ctx, const struct ldb_message *msg,
490 			   const char *attr, struct samr_Password **hashes)
491 {
492 	unsigned int count, i;
493 	const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
494 
495 	*hashes = NULL;
496 	if (!val) {
497 		return 0;
498 	}
499 	count = val->length / 16;
500 	if (count == 0) {
501 		return 0;
502 	}
503 
504 	*hashes = talloc_array(mem_ctx, struct samr_Password, count);
505 	if (! *hashes) {
506 		return 0;
507 	}
508 
509 	for (i=0;i<count;i++) {
510 		memcpy((*hashes)[i].hash, (i*16)+(char *)val->data, 16);
511 	}
512 
513 	return count;
514 }
515 
samdb_result_passwords_from_history(TALLOC_CTX * mem_ctx,struct loadparm_context * lp_ctx,struct ldb_message * msg,unsigned int idx,struct samr_Password ** lm_pwd,struct samr_Password ** nt_pwd)516 NTSTATUS samdb_result_passwords_from_history(TALLOC_CTX *mem_ctx,
517 					     struct loadparm_context *lp_ctx,
518 					     struct ldb_message *msg,
519 					     unsigned int idx,
520 					     struct samr_Password **lm_pwd,
521 					     struct samr_Password **nt_pwd)
522 {
523 	struct samr_Password *lmPwdHash, *ntPwdHash;
524 
525 	if (nt_pwd) {
526 		unsigned int num_nt;
527 		num_nt = samdb_result_hashes(mem_ctx, msg, "ntPwdHistory", &ntPwdHash);
528 		if (num_nt <= idx) {
529 			*nt_pwd = NULL;
530 		} else {
531 			*nt_pwd = &ntPwdHash[idx];
532 		}
533 	}
534 	if (lm_pwd) {
535 		/* Ensure that if we have turned off LM
536 		 * authentication, that we never use the LM hash, even
537 		 * if we store it */
538 		if (lpcfg_lanman_auth(lp_ctx)) {
539 			unsigned int num_lm;
540 			num_lm = samdb_result_hashes(mem_ctx, msg, "lmPwdHistory", &lmPwdHash);
541 			if (num_lm <= idx) {
542 				*lm_pwd = NULL;
543 			} else {
544 				*lm_pwd = &lmPwdHash[idx];
545 			}
546 		} else {
547 			*lm_pwd = NULL;
548 		}
549 	}
550 	return NT_STATUS_OK;
551 }
552 
samdb_result_passwords_no_lockout(TALLOC_CTX * mem_ctx,struct loadparm_context * lp_ctx,const struct ldb_message * msg,struct samr_Password ** lm_pwd,struct samr_Password ** nt_pwd)553 NTSTATUS samdb_result_passwords_no_lockout(TALLOC_CTX *mem_ctx,
554 					   struct loadparm_context *lp_ctx,
555 					   const struct ldb_message *msg,
556 					   struct samr_Password **lm_pwd,
557 					   struct samr_Password **nt_pwd)
558 {
559 	struct samr_Password *lmPwdHash, *ntPwdHash;
560 
561 	if (nt_pwd) {
562 		unsigned int num_nt;
563 		num_nt = samdb_result_hashes(mem_ctx, msg, "unicodePwd", &ntPwdHash);
564 		if (num_nt == 0) {
565 			*nt_pwd = NULL;
566 		} else if (num_nt > 1) {
567 			return NT_STATUS_INTERNAL_DB_CORRUPTION;
568 		} else {
569 			*nt_pwd = &ntPwdHash[0];
570 		}
571 	}
572 	if (lm_pwd) {
573 		/* Ensure that if we have turned off LM
574 		 * authentication, that we never use the LM hash, even
575 		 * if we store it */
576 		if (lpcfg_lanman_auth(lp_ctx)) {
577 			unsigned int num_lm;
578 			num_lm = samdb_result_hashes(mem_ctx, msg, "dBCSPwd", &lmPwdHash);
579 			if (num_lm == 0) {
580 				*lm_pwd = NULL;
581 			} else if (num_lm > 1) {
582 				return NT_STATUS_INTERNAL_DB_CORRUPTION;
583 			} else {
584 				*lm_pwd = &lmPwdHash[0];
585 			}
586 		} else {
587 			*lm_pwd = NULL;
588 		}
589 	}
590 	return NT_STATUS_OK;
591 }
592 
samdb_result_passwords(TALLOC_CTX * mem_ctx,struct loadparm_context * lp_ctx,const struct ldb_message * msg,struct samr_Password ** lm_pwd,struct samr_Password ** nt_pwd)593 NTSTATUS samdb_result_passwords(TALLOC_CTX *mem_ctx,
594 				struct loadparm_context *lp_ctx,
595 				const struct ldb_message *msg,
596 				struct samr_Password **lm_pwd,
597 				struct samr_Password **nt_pwd)
598 {
599 	uint16_t acct_flags;
600 
601 	acct_flags = samdb_result_acct_flags(msg,
602 					     "msDS-User-Account-Control-Computed");
603 	/* Quit if the account was locked out. */
604 	if (acct_flags & ACB_AUTOLOCK) {
605 		DEBUG(3,("samdb_result_passwords: Account for user %s was locked out.\n",
606 			 ldb_dn_get_linearized(msg->dn)));
607 		return NT_STATUS_ACCOUNT_LOCKED_OUT;
608 	}
609 
610 	return samdb_result_passwords_no_lockout(mem_ctx, lp_ctx, msg,
611 						 lm_pwd, nt_pwd);
612 }
613 
614 /*
615   pull a samr_LogonHours structutre from a result set.
616 */
samdb_result_logon_hours(TALLOC_CTX * mem_ctx,struct ldb_message * msg,const char * attr)617 struct samr_LogonHours samdb_result_logon_hours(TALLOC_CTX *mem_ctx, struct ldb_message *msg, const char *attr)
618 {
619 	struct samr_LogonHours hours;
620 	size_t units_per_week = 168;
621 	const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
622 
623 	ZERO_STRUCT(hours);
624 
625 	if (val) {
626 		units_per_week = val->length * 8;
627 	}
628 
629 	hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week/8);
630 	if (!hours.bits) {
631 		return hours;
632 	}
633 	hours.units_per_week = units_per_week;
634 	memset(hours.bits, 0xFF, units_per_week/8);
635 	if (val) {
636 		memcpy(hours.bits, val->data, val->length);
637 	}
638 
639 	return hours;
640 }
641 
642 /*
643   pull a set of account_flags from a result set.
644 
645   Naturally, this requires that userAccountControl and
646   (if not null) the attributes 'attr' be already
647   included in msg
648 */
samdb_result_acct_flags(const struct ldb_message * msg,const char * attr)649 uint32_t samdb_result_acct_flags(const struct ldb_message *msg, const char *attr)
650 {
651 	uint32_t userAccountControl = ldb_msg_find_attr_as_uint(msg, "userAccountControl", 0);
652 	uint32_t attr_flags = 0;
653 	uint32_t acct_flags = ds_uf2acb(userAccountControl);
654 	if (attr) {
655 		attr_flags = ldb_msg_find_attr_as_uint(msg, attr, UF_ACCOUNTDISABLE);
656 		if (attr_flags == UF_ACCOUNTDISABLE) {
657 			DEBUG(0, ("Attribute %s not found, disabling account %s!\n", attr,
658 				  ldb_dn_get_linearized(msg->dn)));
659 		}
660 		acct_flags |= ds_uf2acb(attr_flags);
661 	}
662 
663 	return acct_flags;
664 }
665 
samdb_result_parameters(TALLOC_CTX * mem_ctx,struct ldb_message * msg,const char * attr,struct lsa_BinaryString * s)666 NTSTATUS samdb_result_parameters(TALLOC_CTX *mem_ctx,
667 				 struct ldb_message *msg,
668 				 const char *attr,
669 				 struct lsa_BinaryString *s)
670 {
671 	int i;
672 	const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
673 
674 	ZERO_STRUCTP(s);
675 
676 	if (!val) {
677 		return NT_STATUS_OK;
678 	}
679 
680 	if ((val->length % 2) != 0) {
681 		/*
682 		 * If the on-disk data is not even in length, we know
683 		 * it is corrupt, and can not be safely pushed.  We
684 		 * would either truncate, send either a un-initilaised
685 		 * byte or send a forced zero byte
686 		 */
687 		return NT_STATUS_INTERNAL_DB_CORRUPTION;
688 	}
689 
690 	s->array = talloc_array(mem_ctx, uint16_t, val->length/2);
691 	if (!s->array) {
692 		return NT_STATUS_NO_MEMORY;
693 	}
694 	s->length = s->size = val->length;
695 
696 	/* The on-disk format is the 'network' format, being UTF16LE (sort of) */
697 	for (i = 0; i < s->length / 2; i++) {
698 		s->array[i] = SVAL(val->data, i * 2);
699 	}
700 
701 	return NT_STATUS_OK;
702 }
703 
704 /* Find an attribute, with a particular value */
705 
706 /* The current callers of this function expect a very specific
707  * behaviour: In particular, objectClass subclass equivalence is not
708  * wanted.  This means that we should not lookup the schema for the
709  * comparison function */
samdb_find_attribute(struct ldb_context * ldb,const struct ldb_message * msg,const char * name,const char * value)710 struct ldb_message_element *samdb_find_attribute(struct ldb_context *ldb,
711 						 const struct ldb_message *msg,
712 						 const char *name, const char *value)
713 {
714 	unsigned int i;
715 	struct ldb_message_element *el = ldb_msg_find_element(msg, name);
716 
717 	if (!el) {
718 		return NULL;
719 	}
720 
721 	for (i=0;i<el->num_values;i++) {
722 		if (ldb_attr_cmp(value, (char *)el->values[i].data) == 0) {
723 			return el;
724 		}
725 	}
726 
727 	return NULL;
728 }
729 
samdb_find_or_add_attribute_ex(struct ldb_context * ldb,struct ldb_message * msg,const char * name,const char * set_value,unsigned attr_flags,bool * added)730 static int samdb_find_or_add_attribute_ex(struct ldb_context *ldb,
731 					  struct ldb_message *msg,
732 					  const char *name,
733 					  const char *set_value,
734 					  unsigned attr_flags,
735 					  bool *added)
736 {
737 	int ret;
738 	struct ldb_message_element *el;
739 
740 	SMB_ASSERT(attr_flags != 0);
741 
742        	el = ldb_msg_find_element(msg, name);
743 	if (el) {
744 		if (added != NULL) {
745 			*added = false;
746 		}
747 
748 		return LDB_SUCCESS;
749 	}
750 
751 	ret = ldb_msg_add_empty(msg, name,
752 				attr_flags,
753 				&el);
754 	if (ret != LDB_SUCCESS) {
755 		return ret;
756 	}
757 
758 	if (set_value != NULL) {
759 		ret = ldb_msg_add_string(msg, name, set_value);
760 		if (ret != LDB_SUCCESS) {
761 			return ret;
762 		}
763 	}
764 
765 	if (added != NULL) {
766 		*added = true;
767 	}
768 	return LDB_SUCCESS;
769 }
770 
samdb_find_or_add_attribute(struct ldb_context * ldb,struct ldb_message * msg,const char * name,const char * set_value)771 int samdb_find_or_add_attribute(struct ldb_context *ldb, struct ldb_message *msg, const char *name, const char *set_value)
772 {
773 	return samdb_find_or_add_attribute_ex(ldb, msg, name, set_value, LDB_FLAG_MOD_ADD, NULL);
774 }
775 
776 /*
777   add a dom_sid element to a message
778 */
samdb_msg_add_dom_sid(struct ldb_context * sam_ldb,TALLOC_CTX * mem_ctx,struct ldb_message * msg,const char * attr_name,const struct dom_sid * sid)779 int samdb_msg_add_dom_sid(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
780 			  const char *attr_name, const struct dom_sid *sid)
781 {
782 	struct ldb_val v;
783 	enum ndr_err_code ndr_err;
784 
785 	ndr_err = ndr_push_struct_blob(&v, mem_ctx,
786 				       sid,
787 				       (ndr_push_flags_fn_t)ndr_push_dom_sid);
788 	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
789 		return ldb_operr(sam_ldb);
790 	}
791 	return ldb_msg_add_value(msg, attr_name, &v, NULL);
792 }
793 
794 
795 /*
796   add a delete element operation to a message
797 */
samdb_msg_add_delete(struct ldb_context * sam_ldb,TALLOC_CTX * mem_ctx,struct ldb_message * msg,const char * attr_name)798 int samdb_msg_add_delete(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
799 			 const char *attr_name)
800 {
801 	/* we use an empty replace rather than a delete, as it allows for
802 	   dsdb_replace() to be used everywhere */
803 	return ldb_msg_add_empty(msg, attr_name, LDB_FLAG_MOD_REPLACE, NULL);
804 }
805 
806 /*
807   add an add attribute value to a message or enhance an existing attribute
808   which has the same name and the add flag set.
809 */
samdb_msg_add_addval(struct ldb_context * sam_ldb,TALLOC_CTX * mem_ctx,struct ldb_message * msg,const char * attr_name,const char * value)810 int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
811 			 struct ldb_message *msg, const char *attr_name,
812 			 const char *value)
813 {
814 	struct ldb_message_element *el;
815 	struct ldb_val val, *vals;
816 	char *v;
817 	unsigned int i;
818 	bool found = false;
819 	int ret;
820 
821 	v = talloc_strdup(mem_ctx, value);
822 	if (v == NULL) {
823 		return ldb_oom(sam_ldb);
824 	}
825 
826 	val.data = (uint8_t *) v;
827 	val.length = strlen(v);
828 
829 	if (val.length == 0) {
830 		/* allow empty strings as non-existent attributes */
831 		return LDB_SUCCESS;
832 	}
833 
834 	for (i = 0; i < msg->num_elements; i++) {
835 		el = &msg->elements[i];
836 		if ((ldb_attr_cmp(el->name, attr_name) == 0) &&
837 		    (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_ADD)) {
838 			found = true;
839 			break;
840 		}
841 	}
842 	if (!found) {
843 		ret = ldb_msg_add_empty(msg, attr_name, LDB_FLAG_MOD_ADD,
844 					&el);
845 		if (ret != LDB_SUCCESS) {
846 			return ret;
847 		}
848 	}
849 
850 	vals = talloc_realloc(msg->elements, el->values, struct ldb_val,
851 			      el->num_values + 1);
852 	if (vals == NULL) {
853 		return ldb_oom(sam_ldb);
854 	}
855 	el->values = vals;
856 	el->values[el->num_values] = val;
857 	++(el->num_values);
858 
859 	return LDB_SUCCESS;
860 }
861 
862 /*
863   add a delete attribute value to a message or enhance an existing attribute
864   which has the same name and the delete flag set.
865 */
samdb_msg_add_delval(struct ldb_context * sam_ldb,TALLOC_CTX * mem_ctx,struct ldb_message * msg,const char * attr_name,const char * value)866 int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
867 			 struct ldb_message *msg, const char *attr_name,
868 			 const char *value)
869 {
870 	struct ldb_message_element *el;
871 	struct ldb_val val, *vals;
872 	char *v;
873 	unsigned int i;
874 	bool found = false;
875 	int ret;
876 
877 	v = talloc_strdup(mem_ctx, value);
878 	if (v == NULL) {
879 		return ldb_oom(sam_ldb);
880 	}
881 
882 	val.data = (uint8_t *) v;
883 	val.length = strlen(v);
884 
885 	if (val.length == 0) {
886 		/* allow empty strings as non-existent attributes */
887 		return LDB_SUCCESS;
888 	}
889 
890 	for (i = 0; i < msg->num_elements; i++) {
891 		el = &msg->elements[i];
892 		if ((ldb_attr_cmp(el->name, attr_name) == 0) &&
893 		    (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE)) {
894 			found = true;
895 			break;
896 		}
897 	}
898 	if (!found) {
899 		ret = ldb_msg_add_empty(msg, attr_name, LDB_FLAG_MOD_DELETE,
900 					&el);
901 		if (ret != LDB_SUCCESS) {
902 			return ret;
903 		}
904 	}
905 
906 	vals = talloc_realloc(msg->elements, el->values, struct ldb_val,
907 			      el->num_values + 1);
908 	if (vals == NULL) {
909 		return ldb_oom(sam_ldb);
910 	}
911 	el->values = vals;
912 	el->values[el->num_values] = val;
913 	++(el->num_values);
914 
915 	return LDB_SUCCESS;
916 }
917 
918 /*
919   add a int element to a message
920 */
samdb_msg_add_int(struct ldb_context * sam_ldb,TALLOC_CTX * mem_ctx,struct ldb_message * msg,const char * attr_name,int v)921 int samdb_msg_add_int(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
922 		       const char *attr_name, int v)
923 {
924 	const char *s = talloc_asprintf(mem_ctx, "%d", v);
925 	if (s == NULL) {
926 		return ldb_oom(sam_ldb);
927 	}
928 	return ldb_msg_add_string(msg, attr_name, s);
929 }
930 
931 /*
932  * Add an unsigned int element to a message
933  *
934  * The issue here is that we have not yet first cast to int32_t explicitly,
935  * before we cast to an signed int to printf() into the %d or cast to a
936  * int64_t before we then cast to a long long to printf into a %lld.
937  *
938  * There are *no* unsigned integers in Active Directory LDAP, even the RID
939  * allocations and ms-DS-Secondary-KrbTgt-Number are *signed* quantities.
940  * (See the schema, and the syntax definitions in schema_syntax.c).
941  *
942  */
samdb_msg_add_uint(struct ldb_context * sam_ldb,TALLOC_CTX * mem_ctx,struct ldb_message * msg,const char * attr_name,unsigned int v)943 int samdb_msg_add_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
944 		       const char *attr_name, unsigned int v)
945 {
946 	return samdb_msg_add_int(sam_ldb, mem_ctx, msg, attr_name, (int)v);
947 }
948 
949 /*
950   add a (signed) int64_t element to a message
951 */
samdb_msg_add_int64(struct ldb_context * sam_ldb,TALLOC_CTX * mem_ctx,struct ldb_message * msg,const char * attr_name,int64_t v)952 int samdb_msg_add_int64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
953 			const char *attr_name, int64_t v)
954 {
955 	const char *s = talloc_asprintf(mem_ctx, "%lld", (long long)v);
956 	if (s == NULL) {
957 		return ldb_oom(sam_ldb);
958 	}
959 	return ldb_msg_add_string(msg, attr_name, s);
960 }
961 
962 /*
963  * Add an unsigned int64_t (uint64_t) element to a message
964  *
965  * The issue here is that we have not yet first cast to int32_t explicitly,
966  * before we cast to an signed int to printf() into the %d or cast to a
967  * int64_t before we then cast to a long long to printf into a %lld.
968  *
969  * There are *no* unsigned integers in Active Directory LDAP, even the RID
970  * allocations and ms-DS-Secondary-KrbTgt-Number are *signed* quantities.
971  * (See the schema, and the syntax definitions in schema_syntax.c).
972  *
973  */
samdb_msg_add_uint64(struct ldb_context * sam_ldb,TALLOC_CTX * mem_ctx,struct ldb_message * msg,const char * attr_name,uint64_t v)974 int samdb_msg_add_uint64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
975 			const char *attr_name, uint64_t v)
976 {
977 	return samdb_msg_add_int64(sam_ldb, mem_ctx, msg, attr_name, (int64_t)v);
978 }
979 
980 /*
981   add a samr_Password element to a message
982 */
samdb_msg_add_hash(struct ldb_context * sam_ldb,TALLOC_CTX * mem_ctx,struct ldb_message * msg,const char * attr_name,const struct samr_Password * hash)983 int samdb_msg_add_hash(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
984 		       const char *attr_name, const struct samr_Password *hash)
985 {
986 	struct ldb_val val;
987 	val.data = talloc_memdup(mem_ctx, hash->hash, 16);
988 	if (!val.data) {
989 		return ldb_oom(sam_ldb);
990 	}
991 	val.length = 16;
992 	return ldb_msg_add_value(msg, attr_name, &val, NULL);
993 }
994 
995 /*
996   add a samr_Password array to a message
997 */
samdb_msg_add_hashes(struct ldb_context * ldb,TALLOC_CTX * mem_ctx,struct ldb_message * msg,const char * attr_name,struct samr_Password * hashes,unsigned int count)998 int samdb_msg_add_hashes(struct ldb_context *ldb,
999 			 TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1000 			 const char *attr_name, struct samr_Password *hashes,
1001 			 unsigned int count)
1002 {
1003 	struct ldb_val val;
1004 	unsigned int i;
1005 	val.data = talloc_array_size(mem_ctx, 16, count);
1006 	val.length = count*16;
1007 	if (!val.data) {
1008 		return ldb_oom(ldb);
1009 	}
1010 	for (i=0;i<count;i++) {
1011 		memcpy(i*16 + (char *)val.data, hashes[i].hash, 16);
1012 	}
1013 	return ldb_msg_add_value(msg, attr_name, &val, NULL);
1014 }
1015 
1016 /*
1017   add a acct_flags element to a message
1018 */
samdb_msg_add_acct_flags(struct ldb_context * sam_ldb,TALLOC_CTX * mem_ctx,struct ldb_message * msg,const char * attr_name,uint32_t v)1019 int samdb_msg_add_acct_flags(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1020 			     const char *attr_name, uint32_t v)
1021 {
1022 	return samdb_msg_add_uint(sam_ldb, mem_ctx, msg, attr_name, ds_acb2uf(v));
1023 }
1024 
1025 /*
1026   add a logon_hours element to a message
1027 */
samdb_msg_add_logon_hours(struct ldb_context * sam_ldb,TALLOC_CTX * mem_ctx,struct ldb_message * msg,const char * attr_name,struct samr_LogonHours * hours)1028 int samdb_msg_add_logon_hours(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1029 			      const char *attr_name, struct samr_LogonHours *hours)
1030 {
1031 	struct ldb_val val;
1032 	val.length = hours->units_per_week / 8;
1033 	val.data = hours->bits;
1034 	return ldb_msg_add_value(msg, attr_name, &val, NULL);
1035 }
1036 
1037 /*
1038   add a parameters element to a message
1039 */
samdb_msg_add_parameters(struct ldb_context * sam_ldb,TALLOC_CTX * mem_ctx,struct ldb_message * msg,const char * attr_name,struct lsa_BinaryString * parameters)1040 int samdb_msg_add_parameters(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1041 			     const char *attr_name, struct lsa_BinaryString *parameters)
1042 {
1043 	int i;
1044 	struct ldb_val val;
1045 	if ((parameters->length % 2) != 0) {
1046 		return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1047 	}
1048 
1049 	val.data = talloc_array(mem_ctx, uint8_t, parameters->length);
1050 	if (val.data == NULL) {
1051 		return LDB_ERR_OPERATIONS_ERROR;
1052 	}
1053 	val.length = parameters->length;
1054 	for (i = 0; i < parameters->length / 2; i++) {
1055 		/*
1056 		 * The on-disk format needs to be in the 'network'
1057 		 * format, parmeters->array is a uint16_t array of
1058 		 * length parameters->length / 2
1059 		 */
1060 		SSVAL(val.data, i * 2, parameters->array[i]);
1061 	}
1062 	return ldb_msg_add_steal_value(msg, attr_name, &val);
1063 }
1064 
1065 /*
1066  * Sets an unsigned int element in a message
1067  *
1068  * The issue here is that we have not yet first cast to int32_t explicitly,
1069  * before we cast to an signed int to printf() into the %d or cast to a
1070  * int64_t before we then cast to a long long to printf into a %lld.
1071  *
1072  * There are *no* unsigned integers in Active Directory LDAP, even the RID
1073  * allocations and ms-DS-Secondary-KrbTgt-Number are *signed* quantities.
1074  * (See the schema, and the syntax definitions in schema_syntax.c).
1075  *
1076  */
samdb_msg_set_uint(struct ldb_context * sam_ldb,TALLOC_CTX * mem_ctx,struct ldb_message * msg,const char * attr_name,unsigned int v)1077 int samdb_msg_set_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
1078 		       struct ldb_message *msg, const char *attr_name,
1079 		       unsigned int v)
1080 {
1081 	struct ldb_message_element *el;
1082 
1083 	el = ldb_msg_find_element(msg, attr_name);
1084 	if (el) {
1085 		el->num_values = 0;
1086 	}
1087 	return samdb_msg_add_uint(sam_ldb, mem_ctx, msg, attr_name, v);
1088 }
1089 
1090 /*
1091  * Handle ldb_request in transaction
1092  */
dsdb_autotransaction_request(struct ldb_context * sam_ldb,struct ldb_request * req)1093 int dsdb_autotransaction_request(struct ldb_context *sam_ldb,
1094 				 struct ldb_request *req)
1095 {
1096 	int ret;
1097 
1098 	ret = ldb_transaction_start(sam_ldb);
1099 	if (ret != LDB_SUCCESS) {
1100 		return ret;
1101 	}
1102 
1103 	ret = ldb_request(sam_ldb, req);
1104 	if (ret == LDB_SUCCESS) {
1105 		ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1106 	}
1107 
1108 	if (ret == LDB_SUCCESS) {
1109 		return ldb_transaction_commit(sam_ldb);
1110 	}
1111 	ldb_transaction_cancel(sam_ldb);
1112 
1113 	return ret;
1114 }
1115 
1116 /*
1117   return a default security descriptor
1118 */
samdb_default_security_descriptor(TALLOC_CTX * mem_ctx)1119 struct security_descriptor *samdb_default_security_descriptor(TALLOC_CTX *mem_ctx)
1120 {
1121 	struct security_descriptor *sd;
1122 
1123 	sd = security_descriptor_initialise(mem_ctx);
1124 
1125 	return sd;
1126 }
1127 
samdb_aggregate_schema_dn(struct ldb_context * sam_ctx,TALLOC_CTX * mem_ctx)1128 struct ldb_dn *samdb_aggregate_schema_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx)
1129 {
1130 	struct ldb_dn *schema_dn = ldb_get_schema_basedn(sam_ctx);
1131 	struct ldb_dn *aggregate_dn;
1132 	if (!schema_dn) {
1133 		return NULL;
1134 	}
1135 
1136 	aggregate_dn = ldb_dn_copy(mem_ctx, schema_dn);
1137 	if (!aggregate_dn) {
1138 		return NULL;
1139 	}
1140 	if (!ldb_dn_add_child_fmt(aggregate_dn, "CN=Aggregate")) {
1141 		return NULL;
1142 	}
1143 	return aggregate_dn;
1144 }
1145 
samdb_partitions_dn(struct ldb_context * sam_ctx,TALLOC_CTX * mem_ctx)1146 struct ldb_dn *samdb_partitions_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx)
1147 {
1148 	struct ldb_dn *new_dn;
1149 
1150 	new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(sam_ctx));
1151 	if ( ! ldb_dn_add_child_fmt(new_dn, "CN=Partitions")) {
1152 		talloc_free(new_dn);
1153 		return NULL;
1154 	}
1155 	return new_dn;
1156 }
1157 
samdb_infrastructure_dn(struct ldb_context * sam_ctx,TALLOC_CTX * mem_ctx)1158 struct ldb_dn *samdb_infrastructure_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx)
1159 {
1160        struct ldb_dn *new_dn;
1161 
1162        new_dn = ldb_dn_copy(mem_ctx, ldb_get_default_basedn(sam_ctx));
1163        if ( ! ldb_dn_add_child_fmt(new_dn, "CN=Infrastructure")) {
1164                talloc_free(new_dn);
1165                return NULL;
1166        }
1167        return new_dn;
1168 }
1169 
samdb_sites_dn(struct ldb_context * sam_ctx,TALLOC_CTX * mem_ctx)1170 struct ldb_dn *samdb_sites_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx)
1171 {
1172 	struct ldb_dn *new_dn;
1173 
1174 	new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(sam_ctx));
1175 	if ( ! ldb_dn_add_child_fmt(new_dn, "CN=Sites")) {
1176 		talloc_free(new_dn);
1177 		return NULL;
1178 	}
1179 	return new_dn;
1180 }
1181 
1182 /*
1183   work out the domain sid for the current open ldb
1184 */
samdb_domain_sid(struct ldb_context * ldb)1185 const struct dom_sid *samdb_domain_sid(struct ldb_context *ldb)
1186 {
1187 	TALLOC_CTX *tmp_ctx;
1188 	const struct dom_sid *domain_sid;
1189 	const char *attrs[] = {
1190 		"objectSid",
1191 		NULL
1192 	};
1193 	struct ldb_result *res;
1194 	int ret;
1195 
1196 	/* see if we have a cached copy */
1197 	domain_sid = (struct dom_sid *)ldb_get_opaque(ldb, "cache.domain_sid");
1198 	if (domain_sid) {
1199 		return domain_sid;
1200 	}
1201 
1202 	tmp_ctx = talloc_new(ldb);
1203 	if (tmp_ctx == NULL) {
1204 		goto failed;
1205 	}
1206 
1207 	ret = ldb_search(ldb, tmp_ctx, &res, ldb_get_default_basedn(ldb), LDB_SCOPE_BASE, attrs, "objectSid=*");
1208 
1209 	if (ret != LDB_SUCCESS) {
1210 		goto failed;
1211 	}
1212 
1213 	if (res->count != 1) {
1214 		goto failed;
1215 	}
1216 
1217 	domain_sid = samdb_result_dom_sid(tmp_ctx, res->msgs[0], "objectSid");
1218 	if (domain_sid == NULL) {
1219 		goto failed;
1220 	}
1221 
1222 	/* cache the domain_sid in the ldb */
1223 	if (ldb_set_opaque(ldb, "cache.domain_sid", discard_const_p(struct dom_sid, domain_sid)) != LDB_SUCCESS) {
1224 		goto failed;
1225 	}
1226 
1227 	talloc_steal(ldb, domain_sid);
1228 	talloc_free(tmp_ctx);
1229 
1230 	return domain_sid;
1231 
1232 failed:
1233 	talloc_free(tmp_ctx);
1234 	return NULL;
1235 }
1236 
1237 /*
1238   get domain sid from cache
1239 */
samdb_domain_sid_cache_only(struct ldb_context * ldb)1240 const struct dom_sid *samdb_domain_sid_cache_only(struct ldb_context *ldb)
1241 {
1242 	return (struct dom_sid *)ldb_get_opaque(ldb, "cache.domain_sid");
1243 }
1244 
samdb_set_domain_sid(struct ldb_context * ldb,const struct dom_sid * dom_sid_in)1245 bool samdb_set_domain_sid(struct ldb_context *ldb, const struct dom_sid *dom_sid_in)
1246 {
1247 	TALLOC_CTX *tmp_ctx;
1248 	struct dom_sid *dom_sid_new;
1249 	struct dom_sid *dom_sid_old;
1250 
1251 	/* see if we have a cached copy */
1252 	dom_sid_old = talloc_get_type(ldb_get_opaque(ldb,
1253 						     "cache.domain_sid"), struct dom_sid);
1254 
1255 	tmp_ctx = talloc_new(ldb);
1256 	if (tmp_ctx == NULL) {
1257 		goto failed;
1258 	}
1259 
1260 	dom_sid_new = dom_sid_dup(tmp_ctx, dom_sid_in);
1261 	if (!dom_sid_new) {
1262 		goto failed;
1263 	}
1264 
1265 	/* cache the domain_sid in the ldb */
1266 	if (ldb_set_opaque(ldb, "cache.domain_sid", dom_sid_new) != LDB_SUCCESS) {
1267 		goto failed;
1268 	}
1269 
1270 	talloc_steal(ldb, dom_sid_new);
1271 	talloc_free(tmp_ctx);
1272 	talloc_free(dom_sid_old);
1273 
1274 	return true;
1275 
1276 failed:
1277 	DEBUG(1,("Failed to set our own cached domain SID in the ldb!\n"));
1278 	talloc_free(tmp_ctx);
1279 	return false;
1280 }
1281 
1282 /*
1283   work out the domain guid for the current open ldb
1284 */
samdb_domain_guid(struct ldb_context * ldb)1285 const struct GUID *samdb_domain_guid(struct ldb_context *ldb)
1286 {
1287 	TALLOC_CTX *tmp_ctx = NULL;
1288 	struct GUID *domain_guid = NULL;
1289 	const char *attrs[] = {
1290 		"objectGUID",
1291 		NULL
1292 	};
1293 	struct ldb_result *res = NULL;
1294 	int ret;
1295 
1296 	/* see if we have a cached copy */
1297 	domain_guid = (struct GUID *)ldb_get_opaque(ldb, "cache.domain_guid");
1298 	if (domain_guid) {
1299 		return domain_guid;
1300 	}
1301 
1302 	tmp_ctx = talloc_new(ldb);
1303 	if (tmp_ctx == NULL) {
1304 		goto failed;
1305 	}
1306 
1307 	ret = ldb_search(ldb, tmp_ctx, &res, ldb_get_default_basedn(ldb), LDB_SCOPE_BASE, attrs, "objectGUID=*");
1308 	if (ret != LDB_SUCCESS) {
1309 		goto failed;
1310 	}
1311 
1312 	if (res->count != 1) {
1313 		goto failed;
1314 	}
1315 
1316 	domain_guid = talloc(tmp_ctx, struct GUID);
1317 	if (domain_guid == NULL) {
1318 		goto failed;
1319 	}
1320 	*domain_guid = samdb_result_guid(res->msgs[0], "objectGUID");
1321 
1322 	/* cache the domain_sid in the ldb */
1323 	if (ldb_set_opaque(ldb, "cache.domain_guid", domain_guid) != LDB_SUCCESS) {
1324 		goto failed;
1325 	}
1326 
1327 	talloc_steal(ldb, domain_guid);
1328 	talloc_free(tmp_ctx);
1329 
1330 	return domain_guid;
1331 
1332 failed:
1333 	talloc_free(tmp_ctx);
1334 	return NULL;
1335 }
1336 
samdb_set_ntds_settings_dn(struct ldb_context * ldb,struct ldb_dn * ntds_settings_dn_in)1337 bool samdb_set_ntds_settings_dn(struct ldb_context *ldb, struct ldb_dn *ntds_settings_dn_in)
1338 {
1339 	TALLOC_CTX *tmp_ctx;
1340 	struct ldb_dn *ntds_settings_dn_new;
1341 	struct ldb_dn *ntds_settings_dn_old;
1342 
1343 	/* see if we have a forced copy from provision */
1344 	ntds_settings_dn_old = talloc_get_type(ldb_get_opaque(ldb,
1345 							      "forced.ntds_settings_dn"), struct ldb_dn);
1346 
1347 	tmp_ctx = talloc_new(ldb);
1348 	if (tmp_ctx == NULL) {
1349 		goto failed;
1350 	}
1351 
1352 	ntds_settings_dn_new = ldb_dn_copy(tmp_ctx, ntds_settings_dn_in);
1353 	if (!ntds_settings_dn_new) {
1354 		goto failed;
1355 	}
1356 
1357 	/* set the DN in the ldb to avoid lookups during provision */
1358 	if (ldb_set_opaque(ldb, "forced.ntds_settings_dn", ntds_settings_dn_new) != LDB_SUCCESS) {
1359 		goto failed;
1360 	}
1361 
1362 	talloc_steal(ldb, ntds_settings_dn_new);
1363 	talloc_free(tmp_ctx);
1364 	talloc_free(ntds_settings_dn_old);
1365 
1366 	return true;
1367 
1368 failed:
1369 	DEBUG(1,("Failed to set our NTDS Settings DN in the ldb!\n"));
1370 	talloc_free(tmp_ctx);
1371 	return false;
1372 }
1373 
1374 /*
1375   work out the ntds settings dn for the current open ldb
1376 */
samdb_ntds_settings_dn(struct ldb_context * ldb,TALLOC_CTX * mem_ctx)1377 struct ldb_dn *samdb_ntds_settings_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
1378 {
1379 	TALLOC_CTX *tmp_ctx;
1380 	const char *root_attrs[] = { "dsServiceName", NULL };
1381 	int ret;
1382 	struct ldb_result *root_res;
1383 	struct ldb_dn *settings_dn;
1384 
1385 	/* see if we have a cached copy */
1386 	settings_dn = (struct ldb_dn *)ldb_get_opaque(ldb, "forced.ntds_settings_dn");
1387 	if (settings_dn) {
1388 		return ldb_dn_copy(mem_ctx, settings_dn);
1389 	}
1390 
1391 	tmp_ctx = talloc_new(mem_ctx);
1392 	if (tmp_ctx == NULL) {
1393 		goto failed;
1394 	}
1395 
1396 	ret = ldb_search(ldb, tmp_ctx, &root_res, ldb_dn_new(tmp_ctx, ldb, ""), LDB_SCOPE_BASE, root_attrs, NULL);
1397 	if (ret != LDB_SUCCESS) {
1398 		DEBUG(1,("Searching for dsServiceName in rootDSE failed: %s\n",
1399 			 ldb_errstring(ldb)));
1400 		goto failed;
1401 	}
1402 
1403 	if (root_res->count != 1) {
1404 		goto failed;
1405 	}
1406 
1407 	settings_dn = ldb_msg_find_attr_as_dn(ldb, tmp_ctx, root_res->msgs[0], "dsServiceName");
1408 
1409 	/* note that we do not cache the DN here, as that would mean
1410 	 * we could not handle server renames at runtime. Only
1411 	 * provision sets up forced.ntds_settings_dn */
1412 
1413 	talloc_steal(mem_ctx, settings_dn);
1414 	talloc_free(tmp_ctx);
1415 
1416 	return settings_dn;
1417 
1418 failed:
1419 	DEBUG(1,("Failed to find our own NTDS Settings DN in the ldb!\n"));
1420 	talloc_free(tmp_ctx);
1421 	return NULL;
1422 }
1423 
1424 /*
1425   work out the ntds settings invocationID/objectGUID for the current open ldb
1426 */
samdb_ntds_GUID(struct ldb_context * ldb,const char * attribute,const char * cache_name)1427 static const struct GUID *samdb_ntds_GUID(struct ldb_context *ldb,
1428 					  const char *attribute,
1429 					  const char *cache_name)
1430 {
1431 	TALLOC_CTX *tmp_ctx;
1432 	const char *attrs[] = { attribute, NULL };
1433 	int ret;
1434 	struct ldb_result *res;
1435 	struct GUID *ntds_guid;
1436 	struct ldb_dn *ntds_settings_dn = NULL;
1437 	const char *errstr = NULL;
1438 
1439 	/* see if we have a cached copy */
1440 	ntds_guid = (struct GUID *)ldb_get_opaque(ldb, cache_name);
1441 	if (ntds_guid != NULL) {
1442 		return ntds_guid;
1443 	}
1444 
1445 	tmp_ctx = talloc_new(ldb);
1446 	if (tmp_ctx == NULL) {
1447 		goto failed;
1448 	}
1449 
1450 	ntds_settings_dn = samdb_ntds_settings_dn(ldb, tmp_ctx);
1451 	if (ntds_settings_dn == NULL) {
1452 		errstr = "samdb_ntds_settings_dn() returned NULL";
1453 		goto failed;
1454 	}
1455 
1456 	ret = ldb_search(ldb, tmp_ctx, &res, ntds_settings_dn,
1457 			 LDB_SCOPE_BASE, attrs, NULL);
1458 	if (ret) {
1459 		errstr = ldb_errstring(ldb);
1460 		goto failed;
1461 	}
1462 
1463 	if (res->count != 1) {
1464 		errstr = "incorrect number of results from base search";
1465 		goto failed;
1466 	}
1467 
1468 	ntds_guid = talloc(tmp_ctx, struct GUID);
1469 	if (ntds_guid == NULL) {
1470 		goto failed;
1471 	}
1472 
1473 	*ntds_guid = samdb_result_guid(res->msgs[0], attribute);
1474 
1475 	if (GUID_all_zero(ntds_guid)) {
1476 		if (ldb_msg_find_ldb_val(res->msgs[0], attribute)) {
1477 			errstr = "failed to find the GUID attribute";
1478 		} else {
1479 			errstr = "failed to parse the GUID";
1480 		}
1481 		goto failed;
1482 	}
1483 
1484 	/* cache the domain_sid in the ldb */
1485 	if (ldb_set_opaque(ldb, cache_name, ntds_guid) != LDB_SUCCESS) {
1486 		errstr = "ldb_set_opaque() failed";
1487 		goto failed;
1488 	}
1489 
1490 	talloc_steal(ldb, ntds_guid);
1491 	talloc_free(tmp_ctx);
1492 
1493 	return ntds_guid;
1494 
1495 failed:
1496 	DBG_WARNING("Failed to find our own NTDS Settings %s in the ldb: %s!\n",
1497 		    attribute, errstr);
1498 	talloc_free(tmp_ctx);
1499 	return NULL;
1500 }
1501 
1502 /*
1503   work out the ntds settings objectGUID for the current open ldb
1504 */
samdb_ntds_objectGUID(struct ldb_context * ldb)1505 const struct GUID *samdb_ntds_objectGUID(struct ldb_context *ldb)
1506 {
1507 	return samdb_ntds_GUID(ldb, "objectGUID", "cache.ntds_guid");
1508 }
1509 
1510 /*
1511   work out the ntds settings invocationId for the current open ldb
1512 */
samdb_ntds_invocation_id(struct ldb_context * ldb)1513 const struct GUID *samdb_ntds_invocation_id(struct ldb_context *ldb)
1514 {
1515 	return samdb_ntds_GUID(ldb, "invocationId", "cache.invocation_id");
1516 }
1517 
samdb_set_ntds_GUID(struct ldb_context * ldb,const struct GUID * ntds_guid_in,const char * attribute,const char * cache_name)1518 static bool samdb_set_ntds_GUID(struct ldb_context *ldb,
1519 				const struct GUID *ntds_guid_in,
1520 				const char *attribute,
1521 				const char *cache_name)
1522 {
1523 	TALLOC_CTX *tmp_ctx;
1524 	struct GUID *ntds_guid_new;
1525 	struct GUID *ntds_guid_old;
1526 
1527 	/* see if we have a cached copy */
1528 	ntds_guid_old = (struct GUID *)ldb_get_opaque(ldb, cache_name);
1529 
1530 	tmp_ctx = talloc_new(ldb);
1531 	if (tmp_ctx == NULL) {
1532 		goto failed;
1533 	}
1534 
1535 	ntds_guid_new = talloc(tmp_ctx, struct GUID);
1536 	if (!ntds_guid_new) {
1537 		goto failed;
1538 	}
1539 
1540 	*ntds_guid_new = *ntds_guid_in;
1541 
1542 	/* cache the domain_sid in the ldb */
1543 	if (ldb_set_opaque(ldb, cache_name, ntds_guid_new) != LDB_SUCCESS) {
1544 		goto failed;
1545 	}
1546 
1547 	talloc_steal(ldb, ntds_guid_new);
1548 	talloc_free(tmp_ctx);
1549 	talloc_free(ntds_guid_old);
1550 
1551 	return true;
1552 
1553 failed:
1554 	DBG_WARNING("Failed to set our own cached %s in the ldb!\n",
1555 		    attribute);
1556 	talloc_free(tmp_ctx);
1557 	return false;
1558 }
1559 
samdb_set_ntds_objectGUID(struct ldb_context * ldb,const struct GUID * ntds_guid_in)1560 bool samdb_set_ntds_objectGUID(struct ldb_context *ldb, const struct GUID *ntds_guid_in)
1561 {
1562 	return samdb_set_ntds_GUID(ldb,
1563 				   ntds_guid_in,
1564 				   "objectGUID",
1565 				   "cache.ntds_guid");
1566 }
1567 
samdb_set_ntds_invocation_id(struct ldb_context * ldb,const struct GUID * invocation_id_in)1568 bool samdb_set_ntds_invocation_id(struct ldb_context *ldb, const struct GUID *invocation_id_in)
1569 {
1570 	return samdb_set_ntds_GUID(ldb,
1571 				   invocation_id_in,
1572 				   "invocationId",
1573 				   "cache.invocation_id");
1574 }
1575 
1576 /*
1577   work out the server dn for the current open ldb
1578 */
samdb_server_dn(struct ldb_context * ldb,TALLOC_CTX * mem_ctx)1579 struct ldb_dn *samdb_server_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
1580 {
1581 	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1582 	struct ldb_dn *dn;
1583 	if (!tmp_ctx) {
1584 		return NULL;
1585 	}
1586 	dn = ldb_dn_get_parent(mem_ctx, samdb_ntds_settings_dn(ldb, tmp_ctx));
1587 	talloc_free(tmp_ctx);
1588 	return dn;
1589 
1590 }
1591 
1592 /*
1593   work out the server dn for the current open ldb
1594 */
samdb_server_site_dn(struct ldb_context * ldb,TALLOC_CTX * mem_ctx)1595 struct ldb_dn *samdb_server_site_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
1596 {
1597 	struct ldb_dn *server_dn;
1598 	struct ldb_dn *servers_dn;
1599 	struct ldb_dn *server_site_dn;
1600 
1601 	/* TODO: there must be a saner way to do this!! */
1602 	server_dn = samdb_server_dn(ldb, mem_ctx);
1603 	if (!server_dn) return NULL;
1604 
1605 	servers_dn = ldb_dn_get_parent(mem_ctx, server_dn);
1606 	talloc_free(server_dn);
1607 	if (!servers_dn) return NULL;
1608 
1609 	server_site_dn = ldb_dn_get_parent(mem_ctx, servers_dn);
1610 	talloc_free(servers_dn);
1611 
1612 	return server_site_dn;
1613 }
1614 
1615 /*
1616   find the site name from a computers DN record
1617  */
samdb_find_site_for_computer(struct ldb_context * ldb,TALLOC_CTX * mem_ctx,struct ldb_dn * computer_dn,const char ** site_name)1618 int samdb_find_site_for_computer(struct ldb_context *ldb,
1619 				 TALLOC_CTX *mem_ctx, struct ldb_dn *computer_dn,
1620 				 const char **site_name)
1621 {
1622 	int ret;
1623 	struct ldb_dn *dn;
1624 	const struct ldb_val *rdn_val;
1625 
1626 	*site_name = NULL;
1627 
1628 	ret = samdb_reference_dn(ldb, mem_ctx, computer_dn, "serverReferenceBL", &dn);
1629 	if (ret != LDB_SUCCESS) {
1630 		return ret;
1631 	}
1632 
1633 	if (!ldb_dn_remove_child_components(dn, 2)) {
1634 		talloc_free(dn);
1635 		return LDB_ERR_INVALID_DN_SYNTAX;
1636 	}
1637 
1638 	rdn_val = ldb_dn_get_rdn_val(dn);
1639 	if (rdn_val == NULL) {
1640 		return LDB_ERR_OPERATIONS_ERROR;
1641 	}
1642 
1643 	(*site_name) = talloc_strndup(mem_ctx, (const char *)rdn_val->data, rdn_val->length);
1644 	talloc_free(dn);
1645 	if (!*site_name) {
1646 		return LDB_ERR_OPERATIONS_ERROR;
1647 	}
1648 	return LDB_SUCCESS;
1649 }
1650 
1651 /*
1652   find the NTDS GUID from a computers DN record
1653  */
samdb_find_ntdsguid_for_computer(struct ldb_context * ldb,struct ldb_dn * computer_dn,struct GUID * ntds_guid)1654 int samdb_find_ntdsguid_for_computer(struct ldb_context *ldb, struct ldb_dn *computer_dn,
1655 				     struct GUID *ntds_guid)
1656 {
1657 	int ret;
1658 	struct ldb_dn *dn;
1659 
1660 	*ntds_guid = GUID_zero();
1661 
1662 	ret = samdb_reference_dn(ldb, ldb, computer_dn, "serverReferenceBL", &dn);
1663 	if (ret != LDB_SUCCESS) {
1664 		return ret;
1665 	}
1666 
1667 	if (!ldb_dn_add_child_fmt(dn, "CN=NTDS Settings")) {
1668 		talloc_free(dn);
1669 		return LDB_ERR_OPERATIONS_ERROR;
1670 	}
1671 
1672 	ret = dsdb_find_guid_by_dn(ldb, dn, ntds_guid);
1673 	talloc_free(dn);
1674 	return ret;
1675 }
1676 
1677 /*
1678   find a 'reference' DN that points at another object
1679   (eg. serverReference, rIDManagerReference etc)
1680  */
samdb_reference_dn(struct ldb_context * ldb,TALLOC_CTX * mem_ctx,struct ldb_dn * base,const char * attribute,struct ldb_dn ** dn)1681 int samdb_reference_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
1682 		       const char *attribute, struct ldb_dn **dn)
1683 {
1684 	const char *attrs[2];
1685 	struct ldb_result *res;
1686 	int ret;
1687 
1688 	attrs[0] = attribute;
1689 	attrs[1] = NULL;
1690 
1691 	ret = dsdb_search(ldb, mem_ctx, &res, base, LDB_SCOPE_BASE, attrs, DSDB_SEARCH_ONE_ONLY|DSDB_SEARCH_SHOW_EXTENDED_DN, NULL);
1692 	if (ret != LDB_SUCCESS) {
1693 		ldb_asprintf_errstring(ldb, "Cannot find DN %s to get attribute %s for reference dn: %s",
1694 				       ldb_dn_get_linearized(base), attribute, ldb_errstring(ldb));
1695 		return ret;
1696 	}
1697 
1698 	*dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, res->msgs[0], attribute);
1699 	if (!*dn) {
1700 		if (!ldb_msg_find_element(res->msgs[0], attribute)) {
1701 			ldb_asprintf_errstring(ldb, "Cannot find attribute %s of %s to calculate reference dn", attribute,
1702 					       ldb_dn_get_linearized(base));
1703 		} else {
1704 			ldb_asprintf_errstring(ldb, "Cannot interpret attribute %s of %s as a dn", attribute,
1705 					       ldb_dn_get_linearized(base));
1706 		}
1707 		talloc_free(res);
1708 		return LDB_ERR_NO_SUCH_ATTRIBUTE;
1709 	}
1710 
1711 	talloc_free(res);
1712 	return LDB_SUCCESS;
1713 }
1714 
1715 /*
1716   find if a DN (must have GUID component!) is our ntdsDsa
1717  */
samdb_dn_is_our_ntdsa(struct ldb_context * ldb,struct ldb_dn * dn,bool * is_ntdsa)1718 int samdb_dn_is_our_ntdsa(struct ldb_context *ldb, struct ldb_dn *dn, bool *is_ntdsa)
1719 {
1720 	NTSTATUS status;
1721 	struct GUID dn_guid;
1722 	const struct GUID *our_ntds_guid;
1723 	status = dsdb_get_extended_dn_guid(dn, &dn_guid, "GUID");
1724 	if (!NT_STATUS_IS_OK(status)) {
1725 		return LDB_ERR_OPERATIONS_ERROR;
1726 	}
1727 
1728 	our_ntds_guid = samdb_ntds_objectGUID(ldb);
1729 	if (!our_ntds_guid) {
1730 		DEBUG(0, ("Failed to find our NTDS Settings GUID for comparison with %s - %s\n", ldb_dn_get_linearized(dn), ldb_errstring(ldb)));
1731 		return LDB_ERR_OPERATIONS_ERROR;
1732 	}
1733 
1734 	*is_ntdsa = GUID_equal(&dn_guid, our_ntds_guid);
1735 	return LDB_SUCCESS;
1736 }
1737 
1738 /*
1739   find a 'reference' DN that points at another object and indicate if it is our ntdsDsa
1740  */
samdb_reference_dn_is_our_ntdsa(struct ldb_context * ldb,struct ldb_dn * base,const char * attribute,bool * is_ntdsa)1741 int samdb_reference_dn_is_our_ntdsa(struct ldb_context *ldb, struct ldb_dn *base,
1742 				    const char *attribute, bool *is_ntdsa)
1743 {
1744 	int ret;
1745 	struct ldb_dn *referenced_dn;
1746 	TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1747 	if (tmp_ctx == NULL) {
1748 		return LDB_ERR_OPERATIONS_ERROR;
1749 	}
1750 	ret = samdb_reference_dn(ldb, tmp_ctx, base, attribute, &referenced_dn);
1751 	if (ret != LDB_SUCCESS) {
1752 		DEBUG(0, ("Failed to find object %s for attribute %s - %s\n", ldb_dn_get_linearized(base), attribute, ldb_errstring(ldb)));
1753 		return ret;
1754 	}
1755 
1756 	ret = samdb_dn_is_our_ntdsa(ldb, referenced_dn, is_ntdsa);
1757 
1758 	talloc_free(tmp_ctx);
1759 	return ret;
1760 }
1761 
1762 /*
1763   find our machine account via the serverReference attribute in the
1764   server DN
1765  */
samdb_server_reference_dn(struct ldb_context * ldb,TALLOC_CTX * mem_ctx,struct ldb_dn ** dn)1766 int samdb_server_reference_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn **dn)
1767 {
1768 	struct ldb_dn *server_dn;
1769 	int ret;
1770 
1771 	server_dn = samdb_server_dn(ldb, mem_ctx);
1772 	if (server_dn == NULL) {
1773 		return ldb_error(ldb, LDB_ERR_NO_SUCH_OBJECT, __func__);
1774 	}
1775 
1776 	ret = samdb_reference_dn(ldb, mem_ctx, server_dn, "serverReference", dn);
1777 	talloc_free(server_dn);
1778 
1779 	return ret;
1780 }
1781 
1782 /*
1783   find the RID Manager$ DN via the rIDManagerReference attribute in the
1784   base DN
1785  */
samdb_rid_manager_dn(struct ldb_context * ldb,TALLOC_CTX * mem_ctx,struct ldb_dn ** dn)1786 int samdb_rid_manager_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn **dn)
1787 {
1788 	return samdb_reference_dn(ldb, mem_ctx, ldb_get_default_basedn(ldb),
1789 				  "rIDManagerReference", dn);
1790 }
1791 
1792 /*
1793   find the RID Set DN via the rIDSetReferences attribute in our
1794   machine account DN
1795  */
samdb_rid_set_dn(struct ldb_context * ldb,TALLOC_CTX * mem_ctx,struct ldb_dn ** dn)1796 int samdb_rid_set_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn **dn)
1797 {
1798 	struct ldb_dn *server_ref_dn = NULL;
1799 	int ret;
1800 
1801 	ret = samdb_server_reference_dn(ldb, mem_ctx, &server_ref_dn);
1802 	if (ret != LDB_SUCCESS) {
1803 		return ret;
1804 	}
1805 	ret = samdb_reference_dn(ldb, mem_ctx, server_ref_dn, "rIDSetReferences", dn);
1806 	talloc_free(server_ref_dn);
1807 	return ret;
1808 }
1809 
samdb_server_site_name(struct ldb_context * ldb,TALLOC_CTX * mem_ctx)1810 const char *samdb_server_site_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
1811 {
1812 	const struct ldb_val *val = ldb_dn_get_rdn_val(samdb_server_site_dn(ldb,
1813 									    mem_ctx));
1814 
1815 	if (val == NULL) {
1816 		return NULL;
1817 	}
1818 
1819 	return (const char *) val->data;
1820 }
1821 
1822 /*
1823  * Finds the client site by using the client's IP address.
1824  * The "subnet_name" returns the name of the subnet if parameter != NULL
1825  *
1826  * Has a Windows-based fallback to provide the only site available, or an empty
1827  * string if there are multiple sites.
1828  */
samdb_client_site_name(struct ldb_context * ldb,TALLOC_CTX * mem_ctx,const char * ip_address,char ** subnet_name,bool fallback)1829 const char *samdb_client_site_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
1830 				   const char *ip_address, char **subnet_name,
1831 				   bool fallback)
1832 {
1833 	const char *attrs[] = { "cn", "siteObject", NULL };
1834 	struct ldb_dn *sites_container_dn = NULL;
1835 	struct ldb_dn *subnets_dn = NULL;
1836 	struct ldb_dn *sites_dn = NULL;
1837 	struct ldb_result *res = NULL;
1838 	const struct ldb_val *val = NULL;
1839 	const char *site_name = NULL;
1840 	const char *l_subnet_name = NULL;
1841 	const char *allow_list[2] = { NULL, NULL };
1842 	unsigned int i, count;
1843 	int ret;
1844 
1845 	/*
1846 	 * if we don't have a client ip e.g. ncalrpc
1847 	 * the server site is the client site
1848 	 */
1849 	if (ip_address == NULL) {
1850 		return samdb_server_site_name(ldb, mem_ctx);
1851 	}
1852 
1853 	sites_container_dn = samdb_sites_dn(ldb, mem_ctx);
1854 	if (sites_container_dn == NULL) {
1855 		goto exit;
1856 	}
1857 
1858 	subnets_dn = ldb_dn_copy(mem_ctx, sites_container_dn);
1859 	if ( ! ldb_dn_add_child_fmt(subnets_dn, "CN=Subnets")) {
1860 		goto exit;
1861 	}
1862 
1863 	ret = ldb_search(ldb, mem_ctx, &res, subnets_dn, LDB_SCOPE_ONELEVEL,
1864 			 attrs, NULL);
1865 	if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1866 		count = 0;
1867 	} else if (ret != LDB_SUCCESS) {
1868 		goto exit;
1869 	} else {
1870 		count = res->count;
1871 	}
1872 
1873 	for (i = 0; i < count; i++) {
1874 		l_subnet_name = ldb_msg_find_attr_as_string(res->msgs[i], "cn",
1875 							    NULL);
1876 
1877 		allow_list[0] = l_subnet_name;
1878 
1879 		if (allow_access_nolog(NULL, allow_list, "", ip_address)) {
1880 			sites_dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx,
1881 							   res->msgs[i],
1882 							   "siteObject");
1883 			if (sites_dn == NULL) {
1884 				/* No reference, maybe another subnet matches */
1885 				continue;
1886 			}
1887 
1888 			/* "val" cannot be NULL here since "sites_dn" != NULL */
1889 			val = ldb_dn_get_rdn_val(sites_dn);
1890 			site_name = talloc_strdup(mem_ctx,
1891 						  (const char *) val->data);
1892 
1893 			TALLOC_FREE(sites_dn);
1894 
1895 			break;
1896 		}
1897 	}
1898 
1899 	if (site_name == NULL && fallback) {
1900 		/* This is the Windows Server fallback rule: when no subnet
1901 		 * exists and we have only one site available then use it (it
1902 		 * is for sure the same as our server site). If more sites do
1903 		 * exist then we don't know which one to use and set the site
1904 		 * name to "". */
1905 		size_t cnt = 0;
1906 		ret = dsdb_domain_count(
1907 			ldb,
1908 			&cnt,
1909 			sites_container_dn,
1910 			NULL,
1911 			LDB_SCOPE_SUBTREE,
1912 			"(objectClass=site)");
1913 		if (ret != LDB_SUCCESS) {
1914 			goto exit;
1915 		}
1916 		if (cnt == 1) {
1917 			site_name = samdb_server_site_name(ldb, mem_ctx);
1918 		} else {
1919 			site_name = talloc_strdup(mem_ctx, "");
1920 		}
1921 		l_subnet_name = NULL;
1922 	}
1923 
1924 	if (subnet_name != NULL) {
1925 		*subnet_name = talloc_strdup(mem_ctx, l_subnet_name);
1926 	}
1927 
1928 exit:
1929 	TALLOC_FREE(sites_container_dn);
1930 	TALLOC_FREE(subnets_dn);
1931 	TALLOC_FREE(res);
1932 
1933 	return site_name;
1934 }
1935 
1936 /*
1937   work out if we are the PDC for the domain of the current open ldb
1938 */
samdb_is_pdc(struct ldb_context * ldb)1939 bool samdb_is_pdc(struct ldb_context *ldb)
1940 {
1941 	int ret;
1942 	bool is_pdc;
1943 
1944 	ret = samdb_reference_dn_is_our_ntdsa(ldb, ldb_get_default_basedn(ldb), "fsmoRoleOwner",
1945 					      &is_pdc);
1946 	if (ret != LDB_SUCCESS) {
1947 		DEBUG(1,("Failed to find if we are the PDC for this ldb: Searching for fSMORoleOwner in %s failed: %s\n",
1948 			 ldb_dn_get_linearized(ldb_get_default_basedn(ldb)),
1949 			 ldb_errstring(ldb)));
1950 		return false;
1951 	}
1952 
1953 	return is_pdc;
1954 }
1955 
1956 /*
1957   work out if we are a Global Catalog server for the domain of the current open ldb
1958 */
samdb_is_gc(struct ldb_context * ldb)1959 bool samdb_is_gc(struct ldb_context *ldb)
1960 {
1961 	uint32_t options = 0;
1962 	if (samdb_ntds_options(ldb, &options) != LDB_SUCCESS) {
1963 		return false;
1964 	}
1965 	return (options & DS_NTDSDSA_OPT_IS_GC) != 0;
1966 }
1967 
1968 /* Find a domain object in the parents of a particular DN.  */
samdb_search_for_parent_domain(struct ldb_context * ldb,TALLOC_CTX * mem_ctx,struct ldb_dn * dn,struct ldb_dn ** parent_dn,const char ** errstring)1969 int samdb_search_for_parent_domain(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn *dn,
1970 				   struct ldb_dn **parent_dn, const char **errstring)
1971 {
1972 	TALLOC_CTX *local_ctx;
1973 	struct ldb_dn *sdn = dn;
1974 	struct ldb_result *res = NULL;
1975 	int ret = LDB_SUCCESS;
1976 	const char *attrs[] = { NULL };
1977 
1978 	local_ctx = talloc_new(mem_ctx);
1979 	if (local_ctx == NULL) return ldb_oom(ldb);
1980 
1981 	while ((sdn = ldb_dn_get_parent(local_ctx, sdn))) {
1982 		ret = ldb_search(ldb, local_ctx, &res, sdn, LDB_SCOPE_BASE, attrs,
1983 				 "(|(objectClass=domain)(objectClass=builtinDomain))");
1984 		if (ret == LDB_SUCCESS) {
1985 			if (res->count == 1) {
1986 				break;
1987 			}
1988 		} else {
1989 			break;
1990 		}
1991 	}
1992 
1993 	if (ret != LDB_SUCCESS) {
1994 		*errstring = talloc_asprintf(mem_ctx, "Error searching for parent domain of %s, failed searching for %s: %s",
1995 					     ldb_dn_get_linearized(dn),
1996 					     ldb_dn_get_linearized(sdn),
1997 					     ldb_errstring(ldb));
1998 		talloc_free(local_ctx);
1999 		return ret;
2000 	}
2001 	/* should never be true with 'ret=LDB_SUCCESS', here to satisfy clang */
2002 	if (res == NULL) {
2003 		talloc_free(local_ctx);
2004 		return LDB_ERR_OTHER;
2005 	}
2006 	if (res->count != 1) {
2007 		*errstring = talloc_asprintf(mem_ctx, "Invalid dn (%s), not child of a domain object",
2008 					     ldb_dn_get_linearized(dn));
2009 		DEBUG(0,(__location__ ": %s\n", *errstring));
2010 		talloc_free(local_ctx);
2011 		return LDB_ERR_CONSTRAINT_VIOLATION;
2012 	}
2013 
2014 	*parent_dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
2015 	talloc_free(local_ctx);
2016 	return ret;
2017 }
2018 
pwd_timeout_debug(struct tevent_context * unused1,struct tevent_timer * unused2,struct timeval unused3,void * unused4)2019 static void pwd_timeout_debug(struct tevent_context *unused1,
2020 			      struct tevent_timer *unused2,
2021 			      struct timeval unused3,
2022 			      void *unused4)
2023 {
2024 	DEBUG(0, ("WARNING: check_password_complexity: password script "
2025 		  "took more than 1 second to run\n"));
2026 }
2027 
2028 
2029 /*
2030  * Performs checks on a user password (plaintext UNIX format - attribute
2031  * "password"). The remaining parameters have to be extracted from the domain
2032  * object in the AD.
2033  *
2034  * Result codes from "enum samr_ValidationStatus" (consider "samr.idl")
2035  */
samdb_check_password(TALLOC_CTX * mem_ctx,struct loadparm_context * lp_ctx,const char * account_name,const char * user_principal_name,const char * full_name,const DATA_BLOB * utf8_blob,const uint32_t pwdProperties,const uint32_t minPwdLength)2036 enum samr_ValidationStatus samdb_check_password(TALLOC_CTX *mem_ctx,
2037 						struct loadparm_context *lp_ctx,
2038 						const char *account_name,
2039 						const char *user_principal_name,
2040 						const char *full_name,
2041 						const DATA_BLOB *utf8_blob,
2042 						const uint32_t pwdProperties,
2043 						const uint32_t minPwdLength)
2044 {
2045 	const struct loadparm_substitution *lp_sub =
2046 		lpcfg_noop_substitution();
2047 	char *password_script = NULL;
2048 	const char *utf8_pw = (const char *)utf8_blob->data;
2049 
2050 	/*
2051 	 * This looks strange because it is.
2052 	 *
2053 	 * The check for the number of characters in the password
2054 	 * should clearly not be against the byte length, or else a
2055 	 * single UTF8 character would count for more than one.
2056 	 *
2057 	 * We have chosen to use the number of 16-bit units that the
2058 	 * password encodes to as the measure of length.  This is not
2059 	 * the same as the number of codepoints, if a password
2060 	 * contains a character beyond the Basic Multilingual Plane
2061 	 * (above 65535) it will count for more than one "character".
2062 	 */
2063 
2064 	size_t password_characters_roughly = strlen_m(utf8_pw);
2065 
2066 	/* checks if the "minPwdLength" property is satisfied */
2067 	if (minPwdLength > password_characters_roughly) {
2068 		return SAMR_VALIDATION_STATUS_PWD_TOO_SHORT;
2069 	}
2070 
2071 	/* We might not be asked to check the password complexity */
2072 	if (!(pwdProperties & DOMAIN_PASSWORD_COMPLEX)) {
2073 		return SAMR_VALIDATION_STATUS_SUCCESS;
2074 	}
2075 
2076 	if (password_characters_roughly == 0) {
2077 		return SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH;
2078 	}
2079 
2080 	password_script = lpcfg_check_password_script(lp_ctx, lp_sub, mem_ctx);
2081 	if (password_script != NULL && *password_script != '\0') {
2082 		int check_ret = 0;
2083 		int error = 0;
2084 		ssize_t nwritten = 0;
2085 		struct tevent_context *event_ctx = NULL;
2086 		struct tevent_req *req = NULL;
2087 		int cps_stdin = -1;
2088 		const char * const cmd[4] = {
2089 			"/bin/sh", "-c",
2090 			password_script,
2091 			NULL
2092 		};
2093 
2094 		event_ctx = tevent_context_init(mem_ctx);
2095 		if (event_ctx == NULL) {
2096 			TALLOC_FREE(password_script);
2097 			return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
2098 		}
2099 
2100 		/* Gives a warning after 1 second, terminates after 10 */
2101 		tevent_add_timer(event_ctx, event_ctx,
2102 				 tevent_timeval_current_ofs(1, 0),
2103 				 pwd_timeout_debug, NULL);
2104 
2105 		check_ret = setenv("SAMBA_CPS_ACCOUNT_NAME", account_name, 1);
2106 		if (check_ret != 0) {
2107 			TALLOC_FREE(password_script);
2108 			TALLOC_FREE(event_ctx);
2109 			return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
2110 		}
2111 		if (user_principal_name != NULL) {
2112 			check_ret = setenv("SAMBA_CPS_USER_PRINCIPAL_NAME",
2113 					   user_principal_name, 1);
2114 		} else {
2115 			unsetenv("SAMBA_CPS_USER_PRINCIPAL_NAME");
2116 		}
2117 		if (check_ret != 0) {
2118 			TALLOC_FREE(password_script);
2119 			TALLOC_FREE(event_ctx);
2120 			return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
2121 		}
2122 		if (full_name != NULL) {
2123 			check_ret = setenv("SAMBA_CPS_FULL_NAME", full_name, 1);
2124 		} else {
2125 			unsetenv("SAMBA_CPS_FULL_NAME");
2126 		}
2127 		if (check_ret != 0) {
2128 			TALLOC_FREE(password_script);
2129 			TALLOC_FREE(event_ctx);
2130 			return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
2131 		}
2132 
2133 		req = samba_runcmd_send(event_ctx, event_ctx,
2134 					tevent_timeval_current_ofs(10, 0),
2135 					100, 100, cmd, NULL);
2136 		unsetenv("SAMBA_CPS_ACCOUNT_NAME");
2137 		unsetenv("SAMBA_CPS_USER_PRINCIPAL_NAME");
2138 		unsetenv("SAMBA_CPS_FULL_NAME");
2139 		if (req == NULL) {
2140 			TALLOC_FREE(password_script);
2141 			TALLOC_FREE(event_ctx);
2142 			return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
2143 		}
2144 
2145 		cps_stdin = samba_runcmd_export_stdin(req);
2146 
2147 		nwritten = write_data(
2148 			cps_stdin, utf8_blob->data, utf8_blob->length);
2149 		if (nwritten == -1) {
2150 			close(cps_stdin);
2151 			TALLOC_FREE(password_script);
2152 			TALLOC_FREE(event_ctx);
2153 			return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
2154 		}
2155 
2156 		close(cps_stdin);
2157 
2158 		if (!tevent_req_poll(req, event_ctx)) {
2159 			TALLOC_FREE(password_script);
2160 			TALLOC_FREE(event_ctx);
2161 			return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
2162 		}
2163 
2164 		check_ret = samba_runcmd_recv(req, &error);
2165 		TALLOC_FREE(event_ctx);
2166 
2167 		if (error == ETIMEDOUT) {
2168 			DEBUG(0, ("check_password_complexity: check password script took too long!\n"));
2169 			TALLOC_FREE(password_script);
2170 			return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
2171 		}
2172 		DEBUG(5,("check_password_complexity: check password script (%s) "
2173 			 "returned [%d]\n", password_script, check_ret));
2174 
2175 		if (check_ret != 0) {
2176 			DEBUG(1,("check_password_complexity: "
2177 				 "check password script said new password is not good "
2178 				 "enough!\n"));
2179 			TALLOC_FREE(password_script);
2180 			return SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH;
2181 		}
2182 
2183 		TALLOC_FREE(password_script);
2184 		return SAMR_VALIDATION_STATUS_SUCCESS;
2185 	}
2186 
2187 	TALLOC_FREE(password_script);
2188 
2189 	/*
2190 	 * Here are the standard AD password quality rules, which we
2191 	 * run after the script.
2192 	 */
2193 
2194 	if (!check_password_quality(utf8_pw)) {
2195 		return SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH;
2196 	}
2197 
2198 	return SAMR_VALIDATION_STATUS_SUCCESS;
2199 }
2200 
2201 /*
2202  * Callback for "samdb_set_password" password change
2203  */
samdb_set_password_callback(struct ldb_request * req,struct ldb_reply * ares)2204 int samdb_set_password_callback(struct ldb_request *req, struct ldb_reply *ares)
2205 {
2206 	int ret;
2207 
2208 	if (!ares) {
2209 		return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2210 	}
2211 
2212 	if (ares->error != LDB_SUCCESS) {
2213 		ret = ares->error;
2214 		req->context = talloc_steal(req,
2215 					    ldb_reply_get_control(ares, DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID));
2216 		talloc_free(ares);
2217 		return ldb_request_done(req, ret);
2218 	}
2219 
2220 	if (ares->type != LDB_REPLY_DONE) {
2221 		talloc_free(ares);
2222 		return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2223 	}
2224 
2225 	req->context = talloc_steal(req,
2226 				    ldb_reply_get_control(ares, DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID));
2227 	talloc_free(ares);
2228 	return ldb_request_done(req, LDB_SUCCESS);
2229 }
2230 
2231 /*
2232  * Sets the user password using plaintext UTF16 (attribute "new_password") or
2233  * LM (attribute "lmNewHash") or NT (attribute "ntNewHash") hash. Also pass
2234  * the old LM and/or NT hash (attributes "lmOldHash"/"ntOldHash") if it is a
2235  * user change or not. The "rejectReason" gives some more information if the
2236  * change failed.
2237  *
2238  * Results: NT_STATUS_OK, NT_STATUS_INVALID_PARAMETER, NT_STATUS_UNSUCCESSFUL,
2239  *   NT_STATUS_WRONG_PASSWORD, NT_STATUS_PASSWORD_RESTRICTION
2240  */
samdb_set_password_internal(struct ldb_context * ldb,TALLOC_CTX * mem_ctx,struct ldb_dn * user_dn,struct ldb_dn * domain_dn,const DATA_BLOB * new_password,const struct samr_Password * lmNewHash,const struct samr_Password * ntNewHash,const struct samr_Password * lmOldHash,const struct samr_Password * ntOldHash,enum samPwdChangeReason * reject_reason,struct samr_DomInfo1 ** _dominfo,bool permit_interdomain_trust)2241 static NTSTATUS samdb_set_password_internal(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
2242 			    struct ldb_dn *user_dn, struct ldb_dn *domain_dn,
2243 			    const DATA_BLOB *new_password,
2244 			    const struct samr_Password *lmNewHash,
2245 			    const struct samr_Password *ntNewHash,
2246 			    const struct samr_Password *lmOldHash,
2247 			    const struct samr_Password *ntOldHash,
2248 			    enum samPwdChangeReason *reject_reason,
2249 			    struct samr_DomInfo1 **_dominfo,
2250 			    bool permit_interdomain_trust)
2251 {
2252 	struct ldb_message *msg;
2253 	struct ldb_message_element *el;
2254 	struct ldb_request *req;
2255 	struct dsdb_control_password_change_status *pwd_stat = NULL;
2256 	int ret;
2257 	bool hash_values = false;
2258 	NTSTATUS status = NT_STATUS_OK;
2259 
2260 #define CHECK_RET(x) \
2261 	if (x != LDB_SUCCESS) { \
2262 		talloc_free(msg); \
2263 		return NT_STATUS_NO_MEMORY; \
2264 	}
2265 
2266 	msg = ldb_msg_new(mem_ctx);
2267 	if (msg == NULL) {
2268 		return NT_STATUS_NO_MEMORY;
2269 	}
2270 	msg->dn = user_dn;
2271 	if ((new_password != NULL)
2272 			&& ((lmNewHash == NULL) && (ntNewHash == NULL))) {
2273 		/* we have the password as plaintext UTF16 */
2274 		CHECK_RET(ldb_msg_add_value(msg, "clearTextPassword",
2275 					    new_password, NULL));
2276 		el = ldb_msg_find_element(msg, "clearTextPassword");
2277 		el->flags = LDB_FLAG_MOD_REPLACE;
2278 	} else if ((new_password == NULL)
2279 			&& ((lmNewHash != NULL) || (ntNewHash != NULL))) {
2280 		/* we have a password as LM and/or NT hash */
2281 		if (lmNewHash != NULL) {
2282 			CHECK_RET(samdb_msg_add_hash(ldb, mem_ctx, msg,
2283 				"dBCSPwd", lmNewHash));
2284 			el = ldb_msg_find_element(msg, "dBCSPwd");
2285 			el->flags = LDB_FLAG_MOD_REPLACE;
2286 		}
2287 		if (ntNewHash != NULL) {
2288 			CHECK_RET(samdb_msg_add_hash(ldb, mem_ctx, msg,
2289 				"unicodePwd", ntNewHash));
2290 			el = ldb_msg_find_element(msg, "unicodePwd");
2291 			el->flags = LDB_FLAG_MOD_REPLACE;
2292 		}
2293 		hash_values = true;
2294 	} else {
2295 		/* the password wasn't specified correctly */
2296 		talloc_free(msg);
2297 		return NT_STATUS_INVALID_PARAMETER;
2298 	}
2299 
2300 	/* build modify request */
2301 	ret = ldb_build_mod_req(&req, ldb, mem_ctx, msg, NULL, NULL,
2302 				samdb_set_password_callback, NULL);
2303         if (ret != LDB_SUCCESS) {
2304 		talloc_free(msg);
2305 		return NT_STATUS_NO_MEMORY;
2306         }
2307 
2308 	/* A password change operation */
2309 	if ((ntOldHash != NULL) || (lmOldHash != NULL)) {
2310 		struct dsdb_control_password_change *change;
2311 
2312 		change = talloc(req, struct dsdb_control_password_change);
2313 		if (change == NULL) {
2314 			talloc_free(req);
2315 			talloc_free(msg);
2316 			return NT_STATUS_NO_MEMORY;
2317 		}
2318 
2319 		change->old_nt_pwd_hash = ntOldHash;
2320 		change->old_lm_pwd_hash = lmOldHash;
2321 
2322 		ret = ldb_request_add_control(req,
2323 					      DSDB_CONTROL_PASSWORD_CHANGE_OID,
2324 					      true, change);
2325 		if (ret != LDB_SUCCESS) {
2326 			talloc_free(req);
2327 			talloc_free(msg);
2328 			return NT_STATUS_NO_MEMORY;
2329 		}
2330 	}
2331 	if (hash_values) {
2332 		ret = ldb_request_add_control(req,
2333 					      DSDB_CONTROL_PASSWORD_HASH_VALUES_OID,
2334 					      true, NULL);
2335 		if (ret != LDB_SUCCESS) {
2336 			talloc_free(req);
2337 			talloc_free(msg);
2338 			return NT_STATUS_NO_MEMORY;
2339 		}
2340 	}
2341 	if (permit_interdomain_trust) {
2342 		ret = ldb_request_add_control(req,
2343 					      DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
2344 					      false, NULL);
2345 		if (ret != LDB_SUCCESS) {
2346 			talloc_free(req);
2347 			talloc_free(msg);
2348 			return NT_STATUS_NO_MEMORY;
2349 		}
2350 	}
2351 	ret = ldb_request_add_control(req,
2352 				      DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID,
2353 				      true, NULL);
2354 	if (ret != LDB_SUCCESS) {
2355 		talloc_free(req);
2356 		talloc_free(msg);
2357 		return NT_STATUS_NO_MEMORY;
2358 	}
2359 
2360 	ret = dsdb_autotransaction_request(ldb, req);
2361 
2362 	if (req->context != NULL) {
2363 		struct ldb_control *control = talloc_get_type_abort(req->context,
2364 								    struct ldb_control);
2365 		pwd_stat = talloc_get_type_abort(control->data,
2366 						 struct dsdb_control_password_change_status);
2367 		talloc_steal(mem_ctx, pwd_stat);
2368 	}
2369 
2370 	talloc_free(req);
2371 	talloc_free(msg);
2372 
2373 	/* Sets the domain info (if requested) */
2374 	if (_dominfo != NULL) {
2375 		struct samr_DomInfo1 *dominfo;
2376 
2377 		dominfo = talloc_zero(mem_ctx, struct samr_DomInfo1);
2378 		if (dominfo == NULL) {
2379 			return NT_STATUS_NO_MEMORY;
2380 		}
2381 
2382 		if (pwd_stat != NULL) {
2383 			dominfo->min_password_length     = pwd_stat->domain_data.minPwdLength;
2384 			dominfo->password_properties     = pwd_stat->domain_data.pwdProperties;
2385 			dominfo->password_history_length = pwd_stat->domain_data.pwdHistoryLength;
2386 			dominfo->max_password_age        = pwd_stat->domain_data.maxPwdAge;
2387 			dominfo->min_password_age        = pwd_stat->domain_data.minPwdAge;
2388 		}
2389 
2390 		*_dominfo = dominfo;
2391 	}
2392 
2393 	if (reject_reason != NULL) {
2394 		if (pwd_stat != NULL) {
2395 			*reject_reason = pwd_stat->reject_reason;
2396 		} else {
2397 			*reject_reason = SAM_PWD_CHANGE_NO_ERROR;
2398 		}
2399 	}
2400 
2401 	if (pwd_stat != NULL) {
2402 		talloc_free(pwd_stat);
2403 	}
2404 
2405 	if (ret == LDB_ERR_CONSTRAINT_VIOLATION) {
2406 		const char *errmsg = ldb_errstring(ldb);
2407 		char *endptr = NULL;
2408 		WERROR werr = WERR_GEN_FAILURE;
2409 		status = NT_STATUS_UNSUCCESSFUL;
2410 		if (errmsg != NULL) {
2411 			werr = W_ERROR(strtol(errmsg, &endptr, 16));
2412 			DBG_WARNING("%s\n", errmsg);
2413 		}
2414 		if (endptr != errmsg) {
2415 			if (W_ERROR_EQUAL(werr, WERR_INVALID_PASSWORD)) {
2416 				status = NT_STATUS_WRONG_PASSWORD;
2417 			}
2418 			if (W_ERROR_EQUAL(werr, WERR_PASSWORD_RESTRICTION)) {
2419 				status = NT_STATUS_PASSWORD_RESTRICTION;
2420 			}
2421 		}
2422 	} else if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2423 		/* don't let the caller know if an account doesn't exist */
2424 		status = NT_STATUS_WRONG_PASSWORD;
2425 	} else if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
2426 		status = NT_STATUS_ACCESS_DENIED;
2427 	} else if (ret != LDB_SUCCESS) {
2428 		DEBUG(1, ("Failed to set password on %s: %s\n",
2429 			  ldb_dn_get_linearized(user_dn),
2430 			  ldb_errstring(ldb)));
2431 		status = NT_STATUS_UNSUCCESSFUL;
2432 	}
2433 
2434 	return status;
2435 }
2436 
samdb_set_password(struct ldb_context * ldb,TALLOC_CTX * mem_ctx,struct ldb_dn * user_dn,struct ldb_dn * domain_dn,const DATA_BLOB * new_password,const struct samr_Password * lmNewHash,const struct samr_Password * ntNewHash,const struct samr_Password * lmOldHash,const struct samr_Password * ntOldHash,enum samPwdChangeReason * reject_reason,struct samr_DomInfo1 ** _dominfo)2437 NTSTATUS samdb_set_password(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
2438 			    struct ldb_dn *user_dn, struct ldb_dn *domain_dn,
2439 			    const DATA_BLOB *new_password,
2440 			    const struct samr_Password *lmNewHash,
2441 			    const struct samr_Password *ntNewHash,
2442 			    const struct samr_Password *lmOldHash,
2443 			    const struct samr_Password *ntOldHash,
2444 			    enum samPwdChangeReason *reject_reason,
2445 			    struct samr_DomInfo1 **_dominfo)
2446 {
2447 	return samdb_set_password_internal(ldb, mem_ctx,
2448 			    user_dn, domain_dn,
2449 			    new_password,
2450 			    lmNewHash, ntNewHash,
2451 			    lmOldHash, ntOldHash,
2452 			    reject_reason, _dominfo,
2453 			    false); /* reject trusts */
2454 }
2455 
2456 /*
2457  * Sets the user password using plaintext UTF16 (attribute "new_password") or
2458  * LM (attribute "lmNewHash") or NT (attribute "ntNewHash") hash. Also pass
2459  * the old LM and/or NT hash (attributes "lmOldHash"/"ntOldHash") if it is a
2460  * user change or not. The "rejectReason" gives some more information if the
2461  * change failed.
2462  *
2463  * This wrapper function for "samdb_set_password" takes a SID as input rather
2464  * than a user DN.
2465  *
2466  * This call encapsulates a new LDB transaction for changing the password;
2467  * therefore the user hasn't to start a new one.
2468  *
2469  * Results: NT_STATUS_OK, NT_STATUS_INTERNAL_DB_CORRUPTION,
2470  *   NT_STATUS_INVALID_PARAMETER, NT_STATUS_UNSUCCESSFUL,
2471  *   NT_STATUS_WRONG_PASSWORD, NT_STATUS_PASSWORD_RESTRICTION,
2472  *   NT_STATUS_TRANSACTION_ABORTED, NT_STATUS_NO_SUCH_USER
2473  */
samdb_set_password_sid(struct ldb_context * ldb,TALLOC_CTX * mem_ctx,const struct dom_sid * user_sid,const uint32_t * new_version,const DATA_BLOB * new_password,const struct samr_Password * lmNewHash,const struct samr_Password * ntNewHash,const struct samr_Password * lmOldHash,const struct samr_Password * ntOldHash,enum samPwdChangeReason * reject_reason,struct samr_DomInfo1 ** _dominfo)2474 NTSTATUS samdb_set_password_sid(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
2475 				const struct dom_sid *user_sid,
2476 				const uint32_t *new_version, /* optional for trusts */
2477 				const DATA_BLOB *new_password,
2478 				const struct samr_Password *lmNewHash,
2479 				const struct samr_Password *ntNewHash,
2480 				const struct samr_Password *lmOldHash,
2481 				const struct samr_Password *ntOldHash,
2482 				enum samPwdChangeReason *reject_reason,
2483 				struct samr_DomInfo1 **_dominfo)
2484 {
2485 	TALLOC_CTX *frame = talloc_stackframe();
2486 	NTSTATUS nt_status;
2487 	const char * const user_attrs[] = {
2488 		"userAccountControl",
2489 		"sAMAccountName",
2490 		NULL
2491 	};
2492 	struct ldb_message *user_msg = NULL;
2493 	int ret;
2494 	uint32_t uac = 0;
2495 
2496 	ret = ldb_transaction_start(ldb);
2497 	if (ret != LDB_SUCCESS) {
2498 		DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(ldb)));
2499 		TALLOC_FREE(frame);
2500 		return NT_STATUS_TRANSACTION_ABORTED;
2501 	}
2502 
2503 	ret = dsdb_search_one(ldb, frame, &user_msg, ldb_get_default_basedn(ldb),
2504 			      LDB_SCOPE_SUBTREE, user_attrs, 0,
2505 			      "(&(objectSid=%s)(objectClass=user))",
2506 			      ldap_encode_ndr_dom_sid(frame, user_sid));
2507 	if (ret != LDB_SUCCESS) {
2508 		ldb_transaction_cancel(ldb);
2509 		DEBUG(3, ("samdb_set_password_sid: SID[%s] not found in samdb %s - %s, "
2510 			  "returning NO_SUCH_USER\n",
2511 			  dom_sid_string(frame, user_sid),
2512 			  ldb_strerror(ret), ldb_errstring(ldb)));
2513 		TALLOC_FREE(frame);
2514 		return NT_STATUS_NO_SUCH_USER;
2515 	}
2516 
2517 	uac = ldb_msg_find_attr_as_uint(user_msg, "userAccountControl", 0);
2518 	if (!(uac & UF_ACCOUNT_TYPE_MASK)) {
2519 		ldb_transaction_cancel(ldb);
2520 		DEBUG(1, ("samdb_set_password_sid: invalid "
2521 			  "userAccountControl[0x%08X] for SID[%s] DN[%s], "
2522 			  "returning NO_SUCH_USER\n",
2523 			  (unsigned)uac, dom_sid_string(frame, user_sid),
2524 			  ldb_dn_get_linearized(user_msg->dn)));
2525 		TALLOC_FREE(frame);
2526 		return NT_STATUS_NO_SUCH_USER;
2527 	}
2528 
2529 	if (uac & UF_INTERDOMAIN_TRUST_ACCOUNT) {
2530 		const char * const tdo_attrs[] = {
2531 			"trustAuthIncoming",
2532 			"trustDirection",
2533 			NULL
2534 		};
2535 		struct ldb_message *tdo_msg = NULL;
2536 		const char *account_name = NULL;
2537 		uint32_t trust_direction;
2538 		uint32_t i;
2539 		const struct ldb_val *old_val = NULL;
2540 		struct trustAuthInOutBlob old_blob = {
2541 			.count = 0,
2542 		};
2543 		uint32_t old_version = 0;
2544 		struct AuthenticationInformation *old_version_a = NULL;
2545 		uint32_t _new_version = 0;
2546 		struct trustAuthInOutBlob new_blob = {
2547 			.count = 0,
2548 		};
2549 		struct ldb_val new_val = {
2550 			.length = 0,
2551 		};
2552 		struct timeval tv = timeval_current();
2553 		NTTIME now = timeval_to_nttime(&tv);
2554 		enum ndr_err_code ndr_err;
2555 
2556 		if (new_password == NULL && ntNewHash == NULL) {
2557 			ldb_transaction_cancel(ldb);
2558 			DEBUG(1, ("samdb_set_password_sid: "
2559 				  "no new password provided "
2560 				  "sAMAccountName for SID[%s] DN[%s], "
2561 				  "returning INVALID_PARAMETER\n",
2562 				  dom_sid_string(frame, user_sid),
2563 				  ldb_dn_get_linearized(user_msg->dn)));
2564 			TALLOC_FREE(frame);
2565 			return NT_STATUS_INVALID_PARAMETER;
2566 		}
2567 
2568 		if (new_password != NULL && ntNewHash != NULL) {
2569 			ldb_transaction_cancel(ldb);
2570 			DEBUG(1, ("samdb_set_password_sid: "
2571 				  "two new passwords provided "
2572 				  "sAMAccountName for SID[%s] DN[%s], "
2573 				  "returning INVALID_PARAMETER\n",
2574 				  dom_sid_string(frame, user_sid),
2575 				  ldb_dn_get_linearized(user_msg->dn)));
2576 			TALLOC_FREE(frame);
2577 			return NT_STATUS_INVALID_PARAMETER;
2578 		}
2579 
2580 		if (new_password != NULL && (new_password->length % 2)) {
2581 			ldb_transaction_cancel(ldb);
2582 			DEBUG(2, ("samdb_set_password_sid: "
2583 				  "invalid utf16 length (%zu) "
2584 				  "sAMAccountName for SID[%s] DN[%s], "
2585 				  "returning WRONG_PASSWORD\n",
2586 				  new_password->length,
2587 				  dom_sid_string(frame, user_sid),
2588 				  ldb_dn_get_linearized(user_msg->dn)));
2589 			TALLOC_FREE(frame);
2590 			return NT_STATUS_WRONG_PASSWORD;
2591 		}
2592 
2593 		if (new_password != NULL && new_password->length >= 500) {
2594 			ldb_transaction_cancel(ldb);
2595 			DEBUG(2, ("samdb_set_password_sid: "
2596 				  "utf16 password too long (%zu) "
2597 				  "sAMAccountName for SID[%s] DN[%s], "
2598 				  "returning WRONG_PASSWORD\n",
2599 				  new_password->length,
2600 				  dom_sid_string(frame, user_sid),
2601 				  ldb_dn_get_linearized(user_msg->dn)));
2602 			TALLOC_FREE(frame);
2603 			return NT_STATUS_WRONG_PASSWORD;
2604 		}
2605 
2606 		account_name = ldb_msg_find_attr_as_string(user_msg,
2607 							"sAMAccountName", NULL);
2608 		if (account_name == NULL) {
2609 			ldb_transaction_cancel(ldb);
2610 			DEBUG(1, ("samdb_set_password_sid: missing "
2611 				  "sAMAccountName for SID[%s] DN[%s], "
2612 				  "returning NO_SUCH_USER\n",
2613 				  dom_sid_string(frame, user_sid),
2614 				  ldb_dn_get_linearized(user_msg->dn)));
2615 			TALLOC_FREE(frame);
2616 			return NT_STATUS_NO_SUCH_USER;
2617 		}
2618 
2619 		nt_status = dsdb_trust_search_tdo_by_type(ldb,
2620 							  SEC_CHAN_DOMAIN,
2621 							  account_name,
2622 							  tdo_attrs,
2623 							  frame, &tdo_msg);
2624 		if (!NT_STATUS_IS_OK(nt_status)) {
2625 			ldb_transaction_cancel(ldb);
2626 			DEBUG(1, ("samdb_set_password_sid: dsdb_trust_search_tdo "
2627 				  "failed(%s) for sAMAccountName[%s] SID[%s] DN[%s], "
2628 				  "returning INTERNAL_DB_CORRUPTION\n",
2629 				  nt_errstr(nt_status), account_name,
2630 				  dom_sid_string(frame, user_sid),
2631 				  ldb_dn_get_linearized(user_msg->dn)));
2632 			TALLOC_FREE(frame);
2633 			return NT_STATUS_INTERNAL_DB_CORRUPTION;
2634 		}
2635 
2636 		trust_direction = ldb_msg_find_attr_as_int(tdo_msg,
2637 							   "trustDirection", 0);
2638 		if (!(trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
2639 			ldb_transaction_cancel(ldb);
2640 			DEBUG(1, ("samdb_set_password_sid: direction[0x%08X] is "
2641 				  "not inbound for sAMAccountName[%s] "
2642 				  "DN[%s] TDO[%s], "
2643 				  "returning INTERNAL_DB_CORRUPTION\n",
2644 				  (unsigned)trust_direction,
2645 				  account_name,
2646 				  ldb_dn_get_linearized(user_msg->dn),
2647 				  ldb_dn_get_linearized(tdo_msg->dn)));
2648 			TALLOC_FREE(frame);
2649 			return NT_STATUS_INTERNAL_DB_CORRUPTION;
2650 		}
2651 
2652 		old_val = ldb_msg_find_ldb_val(tdo_msg, "trustAuthIncoming");
2653 		if (old_val != NULL) {
2654 			ndr_err = ndr_pull_struct_blob(old_val, frame, &old_blob,
2655 					(ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2656 			if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2657 				ldb_transaction_cancel(ldb);
2658 				DEBUG(1, ("samdb_set_password_sid: "
2659 					  "failed(%s) to parse "
2660 					  "trustAuthOutgoing sAMAccountName[%s] "
2661 					  "DN[%s] TDO[%s], "
2662 					  "returning INTERNAL_DB_CORRUPTION\n",
2663 					  ndr_map_error2string(ndr_err),
2664 					  account_name,
2665 					  ldb_dn_get_linearized(user_msg->dn),
2666 					  ldb_dn_get_linearized(tdo_msg->dn)));
2667 
2668 				TALLOC_FREE(frame);
2669 				return NT_STATUS_INTERNAL_DB_CORRUPTION;
2670 			}
2671 		}
2672 
2673 		for (i = old_blob.current.count; i > 0; i--) {
2674 			struct AuthenticationInformation *a =
2675 				&old_blob.current.array[i - 1];
2676 
2677 			switch (a->AuthType) {
2678 			case TRUST_AUTH_TYPE_NONE:
2679 				if (i == old_blob.current.count) {
2680 					/*
2681 					 * remove TRUST_AUTH_TYPE_NONE at the
2682 					 * end
2683 					 */
2684 					old_blob.current.count--;
2685 				}
2686 				break;
2687 
2688 			case TRUST_AUTH_TYPE_VERSION:
2689 				old_version_a = a;
2690 				old_version = a->AuthInfo.version.version;
2691 				break;
2692 
2693 			case TRUST_AUTH_TYPE_CLEAR:
2694 				break;
2695 
2696 			case TRUST_AUTH_TYPE_NT4OWF:
2697 				break;
2698 			}
2699 		}
2700 
2701 		if (new_version == NULL) {
2702 			_new_version = 0;
2703 			new_version = &_new_version;
2704 		}
2705 
2706 		if (old_version_a != NULL && *new_version != (old_version + 1)) {
2707 			old_version_a->LastUpdateTime = now;
2708 			old_version_a->AuthType = TRUST_AUTH_TYPE_NONE;
2709 		}
2710 
2711 		new_blob.count = MAX(old_blob.current.count, 2);
2712 		new_blob.current.array = talloc_zero_array(frame,
2713 						struct AuthenticationInformation,
2714 						new_blob.count);
2715 		if (new_blob.current.array == NULL) {
2716 			ldb_transaction_cancel(ldb);
2717 			TALLOC_FREE(frame);
2718 			return NT_STATUS_NO_MEMORY;
2719 		}
2720 		new_blob.previous.array = talloc_zero_array(frame,
2721 						struct AuthenticationInformation,
2722 						new_blob.count);
2723 		if (new_blob.current.array == NULL) {
2724 			ldb_transaction_cancel(ldb);
2725 			TALLOC_FREE(frame);
2726 			return NT_STATUS_NO_MEMORY;
2727 		}
2728 
2729 		for (i = 0; i < old_blob.current.count; i++) {
2730 			struct AuthenticationInformation *o =
2731 				&old_blob.current.array[i];
2732 			struct AuthenticationInformation *p =
2733 				&new_blob.previous.array[i];
2734 
2735 			*p = *o;
2736 			new_blob.previous.count++;
2737 		}
2738 		for (; i < new_blob.count; i++) {
2739 			struct AuthenticationInformation *pi =
2740 				&new_blob.previous.array[i];
2741 
2742 			if (i == 0) {
2743 				/*
2744 				 * new_blob.previous is still empty so
2745 				 * we'll do new_blob.previous = new_blob.current
2746 				 * below.
2747 				 */
2748 				break;
2749 			}
2750 
2751 			pi->LastUpdateTime = now;
2752 			pi->AuthType = TRUST_AUTH_TYPE_NONE;
2753 			new_blob.previous.count++;
2754 		}
2755 
2756 		for (i = 0; i < new_blob.count; i++) {
2757 			struct AuthenticationInformation *ci =
2758 				&new_blob.current.array[i];
2759 
2760 			ci->LastUpdateTime = now;
2761 			switch (i) {
2762 			case 0:
2763 				if (ntNewHash != NULL) {
2764 					ci->AuthType = TRUST_AUTH_TYPE_NT4OWF;
2765 					ci->AuthInfo.nt4owf.password = *ntNewHash;
2766 					break;
2767 				}
2768 
2769 				ci->AuthType = TRUST_AUTH_TYPE_CLEAR;
2770 				ci->AuthInfo.clear.size = new_password->length;
2771 				ci->AuthInfo.clear.password = new_password->data;
2772 				break;
2773 			case 1:
2774 				ci->AuthType = TRUST_AUTH_TYPE_VERSION;
2775 				ci->AuthInfo.version.version = *new_version;
2776 				break;
2777 			default:
2778 				ci->AuthType = TRUST_AUTH_TYPE_NONE;
2779 				break;
2780 			}
2781 
2782 			new_blob.current.count++;
2783 		}
2784 
2785 		if (new_blob.previous.count == 0) {
2786 			TALLOC_FREE(new_blob.previous.array);
2787 			new_blob.previous = new_blob.current;
2788 		}
2789 
2790 		ndr_err = ndr_push_struct_blob(&new_val, frame, &new_blob,
2791 				(ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
2792 		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2793 			ldb_transaction_cancel(ldb);
2794 			DEBUG(1, ("samdb_set_password_sid: "
2795 				  "failed(%s) to generate "
2796 				  "trustAuthOutgoing sAMAccountName[%s] "
2797 				  "DN[%s] TDO[%s], "
2798 				  "returning UNSUCCESSFUL\n",
2799 				  ndr_map_error2string(ndr_err),
2800 				  account_name,
2801 				  ldb_dn_get_linearized(user_msg->dn),
2802 				  ldb_dn_get_linearized(tdo_msg->dn)));
2803 			TALLOC_FREE(frame);
2804 			return NT_STATUS_UNSUCCESSFUL;
2805 		}
2806 
2807 		tdo_msg->num_elements = 0;
2808 		TALLOC_FREE(tdo_msg->elements);
2809 
2810 		ret = ldb_msg_add_empty(tdo_msg, "trustAuthIncoming",
2811 					LDB_FLAG_MOD_REPLACE, NULL);
2812 		if (ret != LDB_SUCCESS) {
2813 			ldb_transaction_cancel(ldb);
2814 			TALLOC_FREE(frame);
2815 			return NT_STATUS_NO_MEMORY;
2816 		}
2817 		ret = ldb_msg_add_value(tdo_msg, "trustAuthIncoming",
2818 					&new_val, NULL);
2819 		if (ret != LDB_SUCCESS) {
2820 			ldb_transaction_cancel(ldb);
2821 			TALLOC_FREE(frame);
2822 			return NT_STATUS_NO_MEMORY;
2823 		}
2824 
2825 		ret = ldb_modify(ldb, tdo_msg);
2826 		if (ret != LDB_SUCCESS) {
2827 			nt_status = dsdb_ldb_err_to_ntstatus(ret);
2828 			ldb_transaction_cancel(ldb);
2829 			DEBUG(1, ("samdb_set_password_sid: "
2830 				  "failed to replace "
2831 				  "trustAuthOutgoing sAMAccountName[%s] "
2832 				  "DN[%s] TDO[%s], "
2833 				  "%s - %s\n",
2834 				  account_name,
2835 				  ldb_dn_get_linearized(user_msg->dn),
2836 				  ldb_dn_get_linearized(tdo_msg->dn),
2837 				  nt_errstr(nt_status), ldb_errstring(ldb)));
2838 			TALLOC_FREE(frame);
2839 			return nt_status;
2840 		}
2841 	}
2842 
2843 	nt_status = samdb_set_password_internal(ldb, mem_ctx,
2844 						user_msg->dn, NULL,
2845 						new_password,
2846 						lmNewHash, ntNewHash,
2847 						lmOldHash, ntOldHash,
2848 						reject_reason, _dominfo,
2849 						true); /* permit trusts */
2850 	if (!NT_STATUS_IS_OK(nt_status)) {
2851 		ldb_transaction_cancel(ldb);
2852 		TALLOC_FREE(frame);
2853 		return nt_status;
2854 	}
2855 
2856 	ret = ldb_transaction_commit(ldb);
2857 	if (ret != LDB_SUCCESS) {
2858 		DEBUG(0,("Failed to commit transaction to change password on %s: %s\n",
2859 			 ldb_dn_get_linearized(user_msg->dn),
2860 			 ldb_errstring(ldb)));
2861 		TALLOC_FREE(frame);
2862 		return NT_STATUS_TRANSACTION_ABORTED;
2863 	}
2864 
2865 	TALLOC_FREE(frame);
2866 	return NT_STATUS_OK;
2867 }
2868 
2869 
samdb_create_foreign_security_principal(struct ldb_context * sam_ctx,TALLOC_CTX * mem_ctx,struct dom_sid * sid,struct ldb_dn ** ret_dn)2870 NTSTATUS samdb_create_foreign_security_principal(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
2871 						 struct dom_sid *sid, struct ldb_dn **ret_dn)
2872 {
2873 	struct ldb_message *msg;
2874 	struct ldb_dn *basedn = NULL;
2875 	char *sidstr;
2876 	int ret;
2877 
2878 	sidstr = dom_sid_string(mem_ctx, sid);
2879 	NT_STATUS_HAVE_NO_MEMORY(sidstr);
2880 
2881 	/* We might have to create a ForeignSecurityPrincipal, even if this user
2882 	 * is in our own domain */
2883 
2884 	msg = ldb_msg_new(sidstr);
2885 	if (msg == NULL) {
2886 		talloc_free(sidstr);
2887 		return NT_STATUS_NO_MEMORY;
2888 	}
2889 
2890 	ret = dsdb_wellknown_dn(sam_ctx, sidstr,
2891 				ldb_get_default_basedn(sam_ctx),
2892 				DS_GUID_FOREIGNSECURITYPRINCIPALS_CONTAINER,
2893 				&basedn);
2894 	if (ret != LDB_SUCCESS) {
2895 		DEBUG(0, ("Failed to find DN for "
2896 			  "ForeignSecurityPrincipal container - %s\n", ldb_errstring(sam_ctx)));
2897 		talloc_free(sidstr);
2898 		return NT_STATUS_INTERNAL_DB_CORRUPTION;
2899 	}
2900 
2901 	/* add core elements to the ldb_message for the alias */
2902 	msg->dn = basedn;
2903 	if ( ! ldb_dn_add_child_fmt(msg->dn, "CN=%s", sidstr)) {
2904 		talloc_free(sidstr);
2905 		return NT_STATUS_NO_MEMORY;
2906 	}
2907 
2908 	ret = ldb_msg_add_string(msg, "objectClass",
2909 				 "foreignSecurityPrincipal");
2910 	if (ret != LDB_SUCCESS) {
2911 		talloc_free(sidstr);
2912 		return NT_STATUS_NO_MEMORY;
2913 	}
2914 
2915 	/* create the alias */
2916 	ret = ldb_add(sam_ctx, msg);
2917 	if (ret != LDB_SUCCESS) {
2918 		DEBUG(0,("Failed to create foreignSecurityPrincipal "
2919 			 "record %s: %s\n",
2920 			 ldb_dn_get_linearized(msg->dn),
2921 			 ldb_errstring(sam_ctx)));
2922 		talloc_free(sidstr);
2923 		return NT_STATUS_INTERNAL_DB_CORRUPTION;
2924 	}
2925 
2926 	*ret_dn = talloc_steal(mem_ctx, msg->dn);
2927 	talloc_free(sidstr);
2928 
2929 	return NT_STATUS_OK;
2930 }
2931 
2932 
2933 /*
2934   Find the DN of a domain, assuming it to be a dotted.dns name
2935 */
2936 
samdb_dns_domain_to_dn(struct ldb_context * ldb,TALLOC_CTX * mem_ctx,const char * dns_domain)2937 struct ldb_dn *samdb_dns_domain_to_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *dns_domain)
2938 {
2939 	unsigned int i;
2940 	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
2941 	const char *binary_encoded;
2942 	const char * const *split_realm;
2943 	struct ldb_dn *dn;
2944 
2945 	if (!tmp_ctx) {
2946 		return NULL;
2947 	}
2948 
2949 	split_realm = (const char * const *)str_list_make(tmp_ctx, dns_domain, ".");
2950 	if (!split_realm) {
2951 		talloc_free(tmp_ctx);
2952 		return NULL;
2953 	}
2954 	dn = ldb_dn_new(mem_ctx, ldb, NULL);
2955 	for (i=0; split_realm[i]; i++) {
2956 		binary_encoded = ldb_binary_encode_string(tmp_ctx, split_realm[i]);
2957 		if (!ldb_dn_add_base_fmt(dn, "dc=%s", binary_encoded)) {
2958 			DEBUG(2, ("Failed to add dc=%s element to DN %s\n",
2959 				  binary_encoded, ldb_dn_get_linearized(dn)));
2960 			talloc_free(tmp_ctx);
2961 			return NULL;
2962 		}
2963 	}
2964 	if (!ldb_dn_validate(dn)) {
2965 		DEBUG(2, ("Failed to validated DN %s\n",
2966 			  ldb_dn_get_linearized(dn)));
2967 		talloc_free(tmp_ctx);
2968 		return NULL;
2969 	}
2970 	talloc_free(tmp_ctx);
2971 	return dn;
2972 }
2973 
2974 
2975 /*
2976   Find the DNS equivalent of a DN, in dotted DNS form
2977 */
samdb_dn_to_dns_domain(TALLOC_CTX * mem_ctx,struct ldb_dn * dn)2978 char *samdb_dn_to_dns_domain(TALLOC_CTX *mem_ctx, struct ldb_dn *dn)
2979 {
2980 	int i, num_components = ldb_dn_get_comp_num(dn);
2981 	char *dns_name = talloc_strdup(mem_ctx, "");
2982 	if (dns_name == NULL) {
2983 		return NULL;
2984 	}
2985 
2986 	for (i=0; i<num_components; i++) {
2987 		const struct ldb_val *v = ldb_dn_get_component_val(dn, i);
2988 		char *s;
2989 		if (v == NULL) {
2990 			talloc_free(dns_name);
2991 			return NULL;
2992 		}
2993 		s = talloc_asprintf_append_buffer(dns_name, "%*.*s.",
2994 						  (int)v->length, (int)v->length, (char *)v->data);
2995 		if (s == NULL) {
2996 			talloc_free(dns_name);
2997 			return NULL;
2998 		}
2999 		dns_name = s;
3000 	}
3001 
3002 	/* remove the last '.' */
3003 	if (dns_name[0] != 0) {
3004 		dns_name[strlen(dns_name)-1] = 0;
3005 	}
3006 
3007 	return dns_name;
3008 }
3009 
3010 /*
3011   Find the DNS _msdcs name for a given NTDS GUID. The resulting DNS
3012   name is based on the forest DNS name
3013 */
samdb_ntds_msdcs_dns_name(struct ldb_context * samdb,TALLOC_CTX * mem_ctx,const struct GUID * ntds_guid)3014 char *samdb_ntds_msdcs_dns_name(struct ldb_context *samdb,
3015 				TALLOC_CTX *mem_ctx,
3016 				const struct GUID *ntds_guid)
3017 {
3018 	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
3019 	const char *guid_str;
3020 	struct ldb_dn *forest_dn;
3021 	const char *dnsforest;
3022 	char *ret;
3023 
3024 	guid_str = GUID_string(tmp_ctx, ntds_guid);
3025 	if (guid_str == NULL) {
3026 		talloc_free(tmp_ctx);
3027 		return NULL;
3028 	}
3029 	forest_dn = ldb_get_root_basedn(samdb);
3030 	if (forest_dn == NULL) {
3031 		talloc_free(tmp_ctx);
3032 		return NULL;
3033 	}
3034 	dnsforest = samdb_dn_to_dns_domain(tmp_ctx, forest_dn);
3035 	if (dnsforest == NULL) {
3036 		talloc_free(tmp_ctx);
3037 		return NULL;
3038 	}
3039 	ret = talloc_asprintf(mem_ctx, "%s._msdcs.%s", guid_str, dnsforest);
3040 	talloc_free(tmp_ctx);
3041 	return ret;
3042 }
3043 
3044 
3045 /*
3046   Find the DN of a domain, be it the netbios or DNS name
3047 */
samdb_domain_to_dn(struct ldb_context * ldb,TALLOC_CTX * mem_ctx,const char * domain_name)3048 struct ldb_dn *samdb_domain_to_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
3049 				  const char *domain_name)
3050 {
3051 	const char * const domain_ref_attrs[] = {
3052 		"ncName", NULL
3053 	};
3054 	const char * const domain_ref2_attrs[] = {
3055 		NULL
3056 	};
3057 	struct ldb_result *res_domain_ref;
3058 	char *escaped_domain = ldb_binary_encode_string(mem_ctx, domain_name);
3059 	/* find the domain's DN */
3060 	int ret_domain = ldb_search(ldb, mem_ctx,
3061 					    &res_domain_ref,
3062 					    samdb_partitions_dn(ldb, mem_ctx),
3063 					    LDB_SCOPE_ONELEVEL,
3064 					    domain_ref_attrs,
3065 					    "(&(nETBIOSName=%s)(objectclass=crossRef))",
3066 					    escaped_domain);
3067 	if (ret_domain != LDB_SUCCESS) {
3068 		return NULL;
3069 	}
3070 
3071 	if (res_domain_ref->count == 0) {
3072 		ret_domain = ldb_search(ldb, mem_ctx,
3073 						&res_domain_ref,
3074 						samdb_dns_domain_to_dn(ldb, mem_ctx, domain_name),
3075 						LDB_SCOPE_BASE,
3076 						domain_ref2_attrs,
3077 						"(objectclass=domain)");
3078 		if (ret_domain != LDB_SUCCESS) {
3079 			return NULL;
3080 		}
3081 
3082 		if (res_domain_ref->count == 1) {
3083 			return res_domain_ref->msgs[0]->dn;
3084 		}
3085 		return NULL;
3086 	}
3087 
3088 	if (res_domain_ref->count > 1) {
3089 		DEBUG(0,("Found %d records matching domain [%s]\n",
3090 			 ret_domain, domain_name));
3091 		return NULL;
3092 	}
3093 
3094 	return samdb_result_dn(ldb, mem_ctx, res_domain_ref->msgs[0], "nCName", NULL);
3095 
3096 }
3097 
3098 
3099 /*
3100   use a GUID to find a DN
3101  */
dsdb_find_dn_by_guid(struct ldb_context * ldb,TALLOC_CTX * mem_ctx,const struct GUID * guid,uint32_t dsdb_flags,struct ldb_dn ** dn)3102 int dsdb_find_dn_by_guid(struct ldb_context *ldb,
3103 			 TALLOC_CTX *mem_ctx,
3104 			 const struct GUID *guid,
3105 			 uint32_t dsdb_flags,
3106 			 struct ldb_dn **dn)
3107 {
3108 	int ret;
3109 	struct ldb_result *res;
3110 	const char *attrs[] = { NULL };
3111 	char *guid_str = GUID_string(mem_ctx, guid);
3112 
3113 	if (!guid_str) {
3114 		return ldb_operr(ldb);
3115 	}
3116 
3117 	ret = dsdb_search(ldb, mem_ctx, &res, NULL, LDB_SCOPE_SUBTREE, attrs,
3118 			  DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
3119 			  DSDB_SEARCH_SHOW_EXTENDED_DN |
3120 			  DSDB_SEARCH_ONE_ONLY | dsdb_flags,
3121 			  "objectGUID=%s", guid_str);
3122 	talloc_free(guid_str);
3123 	if (ret != LDB_SUCCESS) {
3124 		return ret;
3125 	}
3126 
3127 	*dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
3128 	talloc_free(res);
3129 
3130 	return LDB_SUCCESS;
3131 }
3132 
3133 /*
3134   use a DN to find a GUID with a given attribute name
3135  */
dsdb_find_guid_attr_by_dn(struct ldb_context * ldb,struct ldb_dn * dn,const char * attribute,struct GUID * guid)3136 int dsdb_find_guid_attr_by_dn(struct ldb_context *ldb,
3137 			      struct ldb_dn *dn, const char *attribute,
3138 			      struct GUID *guid)
3139 {
3140 	int ret;
3141 	struct ldb_result *res = NULL;
3142 	const char *attrs[2];
3143 	TALLOC_CTX *tmp_ctx = talloc_new(ldb);
3144 
3145 	attrs[0] = attribute;
3146 	attrs[1] = NULL;
3147 
3148 	ret = dsdb_search_dn(ldb, tmp_ctx, &res, dn, attrs,
3149 			     DSDB_SEARCH_SHOW_DELETED |
3150 			     DSDB_SEARCH_SHOW_RECYCLED);
3151 	if (ret != LDB_SUCCESS) {
3152 		talloc_free(tmp_ctx);
3153 		return ret;
3154 	}
3155 	/* satisfy clang */
3156 	if (res == NULL) {
3157 		talloc_free(tmp_ctx);
3158 		return LDB_ERR_OTHER;
3159 	}
3160 	if (res->count < 1) {
3161 		talloc_free(tmp_ctx);
3162 		return ldb_error(ldb, LDB_ERR_NO_SUCH_OBJECT, __func__);
3163 	}
3164 	*guid = samdb_result_guid(res->msgs[0], attribute);
3165 	talloc_free(tmp_ctx);
3166 	return LDB_SUCCESS;
3167 }
3168 
3169 /*
3170   use a DN to find a GUID
3171  */
dsdb_find_guid_by_dn(struct ldb_context * ldb,struct ldb_dn * dn,struct GUID * guid)3172 int dsdb_find_guid_by_dn(struct ldb_context *ldb,
3173 			 struct ldb_dn *dn, struct GUID *guid)
3174 {
3175 	return dsdb_find_guid_attr_by_dn(ldb, dn, "objectGUID", guid);
3176 }
3177 
3178 
3179 
3180 /*
3181  adds the given GUID to the given ldb_message. This value is added
3182  for the given attr_name (may be either "objectGUID" or "parentGUID").
3183  */
dsdb_msg_add_guid(struct ldb_message * msg,struct GUID * guid,const char * attr_name)3184 int dsdb_msg_add_guid(struct ldb_message *msg,
3185 		struct GUID *guid,
3186 		const char *attr_name)
3187 {
3188 	int ret;
3189 	struct ldb_val v;
3190 	NTSTATUS status;
3191 	TALLOC_CTX *tmp_ctx =  talloc_init("dsdb_msg_add_guid");
3192 
3193 	status = GUID_to_ndr_blob(guid, tmp_ctx, &v);
3194 	if (!NT_STATUS_IS_OK(status)) {
3195 		ret = LDB_ERR_OPERATIONS_ERROR;
3196 		goto done;
3197 	}
3198 
3199 	ret = ldb_msg_add_steal_value(msg, attr_name, &v);
3200 	if (ret != LDB_SUCCESS) {
3201 		DEBUG(4,(__location__ ": Failed to add %s to the message\n",
3202 					 attr_name));
3203 		goto done;
3204 	}
3205 
3206 	ret = LDB_SUCCESS;
3207 
3208 done:
3209 	talloc_free(tmp_ctx);
3210 	return ret;
3211 
3212 }
3213 
3214 
3215 /*
3216   use a DN to find a SID
3217  */
dsdb_find_sid_by_dn(struct ldb_context * ldb,struct ldb_dn * dn,struct dom_sid * sid)3218 int dsdb_find_sid_by_dn(struct ldb_context *ldb,
3219 			struct ldb_dn *dn, struct dom_sid *sid)
3220 {
3221 	int ret;
3222 	struct ldb_result *res = NULL;
3223 	const char *attrs[] = { "objectSid", NULL };
3224 	TALLOC_CTX *tmp_ctx = talloc_new(ldb);
3225 	struct dom_sid *s;
3226 
3227 	ZERO_STRUCTP(sid);
3228 
3229 	ret = dsdb_search_dn(ldb, tmp_ctx, &res, dn, attrs,
3230 			     DSDB_SEARCH_SHOW_DELETED |
3231 			     DSDB_SEARCH_SHOW_RECYCLED);
3232 	if (ret != LDB_SUCCESS) {
3233 		talloc_free(tmp_ctx);
3234 		return ret;
3235 	}
3236 	if (res == NULL) {
3237 		talloc_free(tmp_ctx);
3238 		return LDB_ERR_OTHER;
3239 	}
3240 	if (res->count < 1) {
3241 		talloc_free(tmp_ctx);
3242 		return ldb_error(ldb, LDB_ERR_NO_SUCH_OBJECT, __func__);
3243 	}
3244 	s = samdb_result_dom_sid(tmp_ctx, res->msgs[0], "objectSid");
3245 	if (s == NULL) {
3246 		talloc_free(tmp_ctx);
3247 		return ldb_error(ldb, LDB_ERR_NO_SUCH_OBJECT, __func__);
3248 	}
3249 	*sid = *s;
3250 	talloc_free(tmp_ctx);
3251 	return LDB_SUCCESS;
3252 }
3253 
3254 /*
3255   use a SID to find a DN
3256  */
dsdb_find_dn_by_sid(struct ldb_context * ldb,TALLOC_CTX * mem_ctx,struct dom_sid * sid,struct ldb_dn ** dn)3257 int dsdb_find_dn_by_sid(struct ldb_context *ldb,
3258 			TALLOC_CTX *mem_ctx,
3259 			struct dom_sid *sid, struct ldb_dn **dn)
3260 {
3261 	int ret;
3262 	struct ldb_result *res;
3263 	const char *attrs[] = { NULL };
3264 	char *sid_str = ldap_encode_ndr_dom_sid(mem_ctx, sid);
3265 
3266 	if (!sid_str) {
3267 		return ldb_operr(ldb);
3268 	}
3269 
3270 	ret = dsdb_search(ldb, mem_ctx, &res, NULL, LDB_SCOPE_SUBTREE, attrs,
3271 			  DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
3272 			  DSDB_SEARCH_SHOW_EXTENDED_DN |
3273 			  DSDB_SEARCH_ONE_ONLY,
3274 			  "objectSid=%s", sid_str);
3275 	talloc_free(sid_str);
3276 	if (ret != LDB_SUCCESS) {
3277 		return ret;
3278 	}
3279 
3280 	*dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
3281 	talloc_free(res);
3282 
3283 	return LDB_SUCCESS;
3284 }
3285 
3286 /*
3287   load a repsFromTo blob list for a given partition GUID
3288   attr must be "repsFrom" or "repsTo"
3289  */
dsdb_loadreps(struct ldb_context * sam_ctx,TALLOC_CTX * mem_ctx,struct ldb_dn * dn,const char * attr,struct repsFromToBlob ** r,uint32_t * count)3290 WERROR dsdb_loadreps(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_dn *dn,
3291 		     const char *attr, struct repsFromToBlob **r, uint32_t *count)
3292 {
3293 	const char *attrs[] = { attr, NULL };
3294 	struct ldb_result *res = NULL;
3295 	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
3296 	unsigned int i;
3297 	struct ldb_message_element *el;
3298 	int ret;
3299 
3300 	*r = NULL;
3301 	*count = 0;
3302 
3303 	ret = dsdb_search_dn(sam_ctx, tmp_ctx, &res, dn, attrs, 0);
3304 	if (ret == LDB_ERR_NO_SUCH_OBJECT) {
3305 		/* partition hasn't been replicated yet */
3306 		return WERR_OK;
3307 	}
3308 	if (ret != LDB_SUCCESS) {
3309 		DEBUG(0,("dsdb_loadreps: failed to read partition object: %s\n", ldb_errstring(sam_ctx)));
3310 		talloc_free(tmp_ctx);
3311 		return WERR_DS_DRA_INTERNAL_ERROR;
3312 	}
3313 
3314 	/* satisfy clang */
3315 	if (res == NULL) {
3316 		talloc_free(tmp_ctx);
3317 		return WERR_DS_DRA_INTERNAL_ERROR;
3318 	}
3319 	el = ldb_msg_find_element(res->msgs[0], attr);
3320 	if (el == NULL) {
3321 		/* it's OK to be empty */
3322 		talloc_free(tmp_ctx);
3323 		return WERR_OK;
3324 	}
3325 
3326 	*count = el->num_values;
3327 	*r = talloc_array(mem_ctx, struct repsFromToBlob, *count);
3328 	if (*r == NULL) {
3329 		talloc_free(tmp_ctx);
3330 		return WERR_DS_DRA_INTERNAL_ERROR;
3331 	}
3332 
3333 	for (i=0; i<(*count); i++) {
3334 		enum ndr_err_code ndr_err;
3335 		ndr_err = ndr_pull_struct_blob(&el->values[i],
3336 					       mem_ctx,
3337 					       &(*r)[i],
3338 					       (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob);
3339 		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3340 			talloc_free(tmp_ctx);
3341 			return WERR_DS_DRA_INTERNAL_ERROR;
3342 		}
3343 	}
3344 
3345 	talloc_free(tmp_ctx);
3346 
3347 	return WERR_OK;
3348 }
3349 
3350 /*
3351   save the repsFromTo blob list for a given partition GUID
3352   attr must be "repsFrom" or "repsTo"
3353  */
dsdb_savereps(struct ldb_context * sam_ctx,TALLOC_CTX * mem_ctx,struct ldb_dn * dn,const char * attr,struct repsFromToBlob * r,uint32_t count)3354 WERROR dsdb_savereps(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_dn *dn,
3355 		     const char *attr, struct repsFromToBlob *r, uint32_t count)
3356 {
3357 	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
3358 	struct ldb_message *msg;
3359 	struct ldb_message_element *el;
3360 	unsigned int i;
3361 
3362 	msg = ldb_msg_new(tmp_ctx);
3363 	msg->dn = dn;
3364 	if (ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_REPLACE, &el) != LDB_SUCCESS) {
3365 		goto failed;
3366 	}
3367 
3368 	el->values = talloc_array(msg, struct ldb_val, count);
3369 	if (!el->values) {
3370 		goto failed;
3371 	}
3372 
3373 	for (i=0; i<count; i++) {
3374 		struct ldb_val v;
3375 		enum ndr_err_code ndr_err;
3376 
3377 		ndr_err = ndr_push_struct_blob(&v, tmp_ctx,
3378 					       &r[i],
3379 					       (ndr_push_flags_fn_t)ndr_push_repsFromToBlob);
3380 		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3381 			goto failed;
3382 		}
3383 
3384 		el->num_values++;
3385 		el->values[i] = v;
3386 	}
3387 
3388 	if (dsdb_modify(sam_ctx, msg, 0) != LDB_SUCCESS) {
3389 		DEBUG(0,("Failed to store %s - %s\n", attr, ldb_errstring(sam_ctx)));
3390 		goto failed;
3391 	}
3392 
3393 	talloc_free(tmp_ctx);
3394 
3395 	return WERR_OK;
3396 
3397 failed:
3398 	talloc_free(tmp_ctx);
3399 	return WERR_DS_DRA_INTERNAL_ERROR;
3400 }
3401 
3402 
3403 /*
3404   load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
3405   object for a partition
3406  */
dsdb_load_partition_usn(struct ldb_context * ldb,struct ldb_dn * dn,uint64_t * uSN,uint64_t * urgent_uSN)3407 int dsdb_load_partition_usn(struct ldb_context *ldb, struct ldb_dn *dn,
3408 				uint64_t *uSN, uint64_t *urgent_uSN)
3409 {
3410 	struct ldb_request *req;
3411 	int ret;
3412 	TALLOC_CTX *tmp_ctx = talloc_new(ldb);
3413 	struct dsdb_control_current_partition *p_ctrl;
3414 	struct ldb_result *res;
3415 
3416 	res = talloc_zero(tmp_ctx, struct ldb_result);
3417 	if (!res) {
3418 		talloc_free(tmp_ctx);
3419 		return ldb_oom(ldb);
3420 	}
3421 
3422 	ret = ldb_build_search_req(&req, ldb, tmp_ctx,
3423 				   ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
3424 				   LDB_SCOPE_BASE,
3425 				   NULL, NULL,
3426 				   NULL,
3427 				   res, ldb_search_default_callback,
3428 				   NULL);
3429 	if (ret != LDB_SUCCESS) {
3430 		talloc_free(tmp_ctx);
3431 		return ret;
3432 	}
3433 
3434 	p_ctrl = talloc(req, struct dsdb_control_current_partition);
3435 	if (p_ctrl == NULL) {
3436 		talloc_free(tmp_ctx);
3437 		return ldb_oom(ldb);
3438 	}
3439 	p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
3440 	p_ctrl->dn = dn;
3441 
3442 	ret = ldb_request_add_control(req,
3443 				      DSDB_CONTROL_CURRENT_PARTITION_OID,
3444 				      false, p_ctrl);
3445 	if (ret != LDB_SUCCESS) {
3446 		talloc_free(tmp_ctx);
3447 		return ret;
3448 	}
3449 
3450 	/* Run the new request */
3451 	ret = ldb_request(ldb, req);
3452 
3453 	if (ret == LDB_SUCCESS) {
3454 		ret = ldb_wait(req->handle, LDB_WAIT_ALL);
3455 	}
3456 
3457 	if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
3458 		/* it hasn't been created yet, which means
3459 		   an implicit value of zero */
3460 		*uSN = 0;
3461 		talloc_free(tmp_ctx);
3462 		return LDB_SUCCESS;
3463 	}
3464 
3465 	if (ret != LDB_SUCCESS) {
3466 		talloc_free(tmp_ctx);
3467 		return ret;
3468 	}
3469 
3470 	if (res->count < 1) {
3471 		*uSN = 0;
3472 		if (urgent_uSN) {
3473 			*urgent_uSN = 0;
3474 		}
3475 	} else {
3476 		*uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
3477 		if (urgent_uSN) {
3478 			*urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
3479 		}
3480 	}
3481 
3482 	talloc_free(tmp_ctx);
3483 
3484 	return LDB_SUCCESS;
3485 }
3486 
drsuapi_DsReplicaCursor2_compare(const struct drsuapi_DsReplicaCursor2 * c1,const struct drsuapi_DsReplicaCursor2 * c2)3487 int drsuapi_DsReplicaCursor2_compare(const struct drsuapi_DsReplicaCursor2 *c1,
3488 						   const struct drsuapi_DsReplicaCursor2 *c2)
3489 {
3490 	return GUID_compare(&c1->source_dsa_invocation_id, &c2->source_dsa_invocation_id);
3491 }
3492 
drsuapi_DsReplicaCursor_compare(const struct drsuapi_DsReplicaCursor * c1,const struct drsuapi_DsReplicaCursor * c2)3493 int drsuapi_DsReplicaCursor_compare(const struct drsuapi_DsReplicaCursor *c1,
3494 				    const struct drsuapi_DsReplicaCursor *c2)
3495 {
3496 	return GUID_compare(&c1->source_dsa_invocation_id, &c2->source_dsa_invocation_id);
3497 }
3498 
3499 
3500 /*
3501   see if a computer identified by its invocationId is a RODC
3502 */
samdb_is_rodc(struct ldb_context * sam_ctx,const struct GUID * objectGUID,bool * is_rodc)3503 int samdb_is_rodc(struct ldb_context *sam_ctx, const struct GUID *objectGUID, bool *is_rodc)
3504 {
3505 	/* 1) find the DN for this servers NTDSDSA object
3506 	   2) search for the msDS-isRODC attribute
3507 	   3) if not present then not a RODC
3508 	   4) if present and TRUE then is a RODC
3509 	*/
3510 	struct ldb_dn *config_dn;
3511 	const char *attrs[] = { "msDS-isRODC", NULL };
3512 	int ret;
3513 	struct ldb_result *res;
3514 	TALLOC_CTX *tmp_ctx = talloc_new(sam_ctx);
3515 
3516 	config_dn = ldb_get_config_basedn(sam_ctx);
3517 	if (!config_dn) {
3518 		talloc_free(tmp_ctx);
3519 		return ldb_operr(sam_ctx);
3520 	}
3521 
3522 	ret = dsdb_search(sam_ctx, tmp_ctx, &res, config_dn, LDB_SCOPE_SUBTREE, attrs,
3523 			  DSDB_SEARCH_ONE_ONLY, "objectGUID=%s", GUID_string(tmp_ctx, objectGUID));
3524 
3525 	if (ret == LDB_ERR_NO_SUCH_OBJECT) {
3526 		*is_rodc = false;
3527 		talloc_free(tmp_ctx);
3528 		return LDB_SUCCESS;
3529 	}
3530 
3531 	if (ret != LDB_SUCCESS) {
3532 		DEBUG(1,(("Failed to find our own NTDS Settings object by objectGUID=%s!\n"),
3533 			 GUID_string(tmp_ctx, objectGUID)));
3534 		*is_rodc = false;
3535 		talloc_free(tmp_ctx);
3536 		return ret;
3537 	}
3538 
3539 	ret = ldb_msg_find_attr_as_bool(res->msgs[0], "msDS-isRODC", 0);
3540 	*is_rodc = (ret == 1);
3541 
3542 	talloc_free(tmp_ctx);
3543 	return LDB_SUCCESS;
3544 }
3545 
3546 
3547 /*
3548   see if we are a RODC
3549 */
samdb_rodc(struct ldb_context * sam_ctx,bool * am_rodc)3550 int samdb_rodc(struct ldb_context *sam_ctx, bool *am_rodc)
3551 {
3552 	const struct GUID *objectGUID;
3553 	int ret;
3554 	bool *cached;
3555 
3556 	/* see if we have a cached copy */
3557 	cached = (bool *)ldb_get_opaque(sam_ctx, "cache.am_rodc");
3558 	if (cached) {
3559 		*am_rodc = *cached;
3560 		return LDB_SUCCESS;
3561 	}
3562 
3563 	objectGUID = samdb_ntds_objectGUID(sam_ctx);
3564 	if (!objectGUID) {
3565 		return ldb_operr(sam_ctx);
3566 	}
3567 
3568 	ret = samdb_is_rodc(sam_ctx, objectGUID, am_rodc);
3569 	if (ret != LDB_SUCCESS) {
3570 		return ret;
3571 	}
3572 
3573 	cached = talloc(sam_ctx, bool);
3574 	if (cached == NULL) {
3575 		return ldb_oom(sam_ctx);
3576 	}
3577 	*cached = *am_rodc;
3578 
3579 	ret = ldb_set_opaque(sam_ctx, "cache.am_rodc", cached);
3580 	if (ret != LDB_SUCCESS) {
3581 		talloc_free(cached);
3582 		return ldb_operr(sam_ctx);
3583 	}
3584 
3585 	return LDB_SUCCESS;
3586 }
3587 
samdb_dns_host_name(struct ldb_context * sam_ctx,const char ** host_name)3588 int samdb_dns_host_name(struct ldb_context *sam_ctx, const char **host_name)
3589 {
3590 	const char *_host_name = NULL;
3591 	const char *attrs[] = { "dnsHostName", NULL };
3592 	TALLOC_CTX *tmp_ctx = NULL;
3593 	int ret;
3594 	struct ldb_result *res = NULL;
3595 
3596 	_host_name = (const char *)ldb_get_opaque(sam_ctx, "cache.dns_host_name");
3597 	if (_host_name != NULL) {
3598 		*host_name = _host_name;
3599 		return LDB_SUCCESS;
3600 	}
3601 
3602 	tmp_ctx = talloc_new(sam_ctx);
3603 
3604 	ret = dsdb_search_dn(sam_ctx, tmp_ctx, &res, NULL, attrs, 0);
3605 
3606 	if (res == NULL || res->count != 1 || ret != LDB_SUCCESS) {
3607 		DEBUG(0, ("Failed to get rootDSE for dnsHostName: %s",
3608 			  ldb_errstring(sam_ctx)));
3609 		TALLOC_FREE(tmp_ctx);
3610 		return ret;
3611 	}
3612 
3613 	_host_name = ldb_msg_find_attr_as_string(res->msgs[0],
3614 						 "dnsHostName",
3615 						 NULL);
3616 	if (_host_name == NULL) {
3617 		DEBUG(0, ("Failed to get dnsHostName from rootDSE"));
3618 		TALLOC_FREE(tmp_ctx);
3619 		return LDB_ERR_OPERATIONS_ERROR;
3620 	}
3621 	ret = ldb_set_opaque(sam_ctx, "cache.dns_host_name",
3622 			     discard_const_p(char *, _host_name));
3623 	if (ret != LDB_SUCCESS) {
3624 		TALLOC_FREE(tmp_ctx);
3625 		return ldb_operr(sam_ctx);
3626 	}
3627 
3628 	*host_name = talloc_steal(sam_ctx, _host_name);
3629 
3630 	TALLOC_FREE(tmp_ctx);
3631 	return LDB_SUCCESS;
3632 }
3633 
samdb_set_am_rodc(struct ldb_context * ldb,bool am_rodc)3634 bool samdb_set_am_rodc(struct ldb_context *ldb, bool am_rodc)
3635 {
3636 	TALLOC_CTX *tmp_ctx;
3637 	bool *cached;
3638 
3639 	tmp_ctx = talloc_new(ldb);
3640 	if (tmp_ctx == NULL) {
3641 		goto failed;
3642 	}
3643 
3644 	cached = talloc(tmp_ctx, bool);
3645 	if (!cached) {
3646 		goto failed;
3647 	}
3648 
3649 	*cached = am_rodc;
3650 	if (ldb_set_opaque(ldb, "cache.am_rodc", cached) != LDB_SUCCESS) {
3651 		goto failed;
3652 	}
3653 
3654 	talloc_steal(ldb, cached);
3655 	talloc_free(tmp_ctx);
3656 	return true;
3657 
3658 failed:
3659 	DEBUG(1,("Failed to set our own cached am_rodc in the ldb!\n"));
3660 	talloc_free(tmp_ctx);
3661 	return false;
3662 }
3663 
3664 
3665 /*
3666  * return NTDSSiteSettings options. See MS-ADTS 7.1.1.2.2.1.1
3667  * flags are DS_NTDSSETTINGS_OPT_*
3668  */
samdb_ntds_site_settings_options(struct ldb_context * ldb_ctx,uint32_t * options)3669 int samdb_ntds_site_settings_options(struct ldb_context *ldb_ctx,
3670 					uint32_t *options)
3671 {
3672 	int rc;
3673 	TALLOC_CTX *tmp_ctx;
3674 	struct ldb_result *res;
3675 	struct ldb_dn *site_dn;
3676 	const char *attrs[] = { "options", NULL };
3677 
3678 	tmp_ctx = talloc_new(ldb_ctx);
3679 	if (tmp_ctx == NULL)
3680 		goto failed;
3681 
3682         /* Retrieve the site dn for the ldb that we
3683 	 * have open.  This is our local site.
3684          */
3685         site_dn = samdb_server_site_dn(ldb_ctx, tmp_ctx);
3686 	if (site_dn == NULL)
3687 		goto failed;
3688 
3689 	/* Perform a one level (child) search from the local
3690          * site distinguided name.   We're looking for the
3691          * "options" attribute within the nTDSSiteSettings
3692          * object
3693 	 */
3694 	rc = ldb_search(ldb_ctx, tmp_ctx, &res, site_dn,
3695 			LDB_SCOPE_ONELEVEL, attrs,
3696                         "objectClass=nTDSSiteSettings");
3697 
3698         if (rc != LDB_SUCCESS || res->count != 1)
3699 		goto failed;
3700 
3701 	*options = ldb_msg_find_attr_as_uint(res->msgs[0], "options", 0);
3702 
3703 	talloc_free(tmp_ctx);
3704 
3705 	return LDB_SUCCESS;
3706 
3707 failed:
3708 	DEBUG(1,("Failed to find our NTDS Site Settings options in ldb!\n"));
3709 	talloc_free(tmp_ctx);
3710 	return ldb_error(ldb_ctx, LDB_ERR_NO_SUCH_OBJECT, __func__);
3711 }
3712 
3713 /*
3714   return NTDS options flags. See MS-ADTS 7.1.1.2.2.1.2.1.1
3715 
3716   flags are DS_NTDS_OPTION_*
3717 */
samdb_ntds_options(struct ldb_context * ldb,uint32_t * options)3718 int samdb_ntds_options(struct ldb_context *ldb, uint32_t *options)
3719 {
3720 	TALLOC_CTX *tmp_ctx;
3721 	const char *attrs[] = { "options", NULL };
3722 	int ret;
3723 	struct ldb_result *res;
3724 
3725 	tmp_ctx = talloc_new(ldb);
3726 	if (tmp_ctx == NULL) {
3727 		goto failed;
3728 	}
3729 
3730 	ret = ldb_search(ldb, tmp_ctx, &res, samdb_ntds_settings_dn(ldb, tmp_ctx), LDB_SCOPE_BASE, attrs, NULL);
3731 	if (ret != LDB_SUCCESS) {
3732 		goto failed;
3733 	}
3734 
3735 	if (res->count != 1) {
3736 		goto failed;
3737 	}
3738 
3739 	*options = ldb_msg_find_attr_as_uint(res->msgs[0], "options", 0);
3740 
3741 	talloc_free(tmp_ctx);
3742 
3743 	return LDB_SUCCESS;
3744 
3745 failed:
3746 	DEBUG(1,("Failed to find our own NTDS Settings options in the ldb!\n"));
3747 	talloc_free(tmp_ctx);
3748 	return ldb_error(ldb, LDB_ERR_NO_SUCH_OBJECT, __func__);
3749 }
3750 
samdb_ntds_object_category(TALLOC_CTX * tmp_ctx,struct ldb_context * ldb)3751 const char* samdb_ntds_object_category(TALLOC_CTX *tmp_ctx, struct ldb_context *ldb)
3752 {
3753 	const char *attrs[] = { "objectCategory", NULL };
3754 	int ret;
3755 	struct ldb_result *res;
3756 
3757 	ret = ldb_search(ldb, tmp_ctx, &res, samdb_ntds_settings_dn(ldb, tmp_ctx), LDB_SCOPE_BASE, attrs, NULL);
3758 	if (ret != LDB_SUCCESS) {
3759 		goto failed;
3760 	}
3761 
3762 	if (res->count != 1) {
3763 		goto failed;
3764 	}
3765 
3766 	return ldb_msg_find_attr_as_string(res->msgs[0], "objectCategory", NULL);
3767 
3768 failed:
3769 	DEBUG(1,("Failed to find our own NTDS Settings objectCategory in the ldb!\n"));
3770 	return NULL;
3771 }
3772 
3773 /*
3774  * Function which generates a "lDAPDisplayName" attribute from a "CN" one.
3775  * Algorithm implemented according to MS-ADTS 3.1.1.2.3.4
3776  */
samdb_cn_to_lDAPDisplayName(TALLOC_CTX * mem_ctx,const char * cn)3777 const char *samdb_cn_to_lDAPDisplayName(TALLOC_CTX *mem_ctx, const char *cn)
3778 {
3779 	char **tokens, *ret;
3780 	size_t i;
3781 
3782 	tokens = str_list_make(mem_ctx, cn, " -_");
3783 	if (tokens == NULL || tokens[0] == NULL) {
3784 		return NULL;
3785 	}
3786 
3787 	/* "tolower()" and "toupper()" should also work properly on 0x00 */
3788 	tokens[0][0] = tolower(tokens[0][0]);
3789 	for (i = 1; tokens[i] != NULL; i++)
3790 		tokens[i][0] = toupper(tokens[i][0]);
3791 
3792 	ret = talloc_strdup(mem_ctx, tokens[0]);
3793 	for (i = 1; tokens[i] != NULL; i++)
3794 		ret = talloc_asprintf_append_buffer(ret, "%s", tokens[i]);
3795 
3796 	talloc_free(tokens);
3797 
3798 	return ret;
3799 }
3800 
3801 /*
3802  * This detects and returns the domain functional level (DS_DOMAIN_FUNCTION_*)
3803  */
dsdb_functional_level(struct ldb_context * ldb)3804 int dsdb_functional_level(struct ldb_context *ldb)
3805 {
3806 	int *domainFunctionality =
3807 		talloc_get_type(ldb_get_opaque(ldb, "domainFunctionality"), int);
3808 	if (!domainFunctionality) {
3809 		/* this is expected during initial provision */
3810 		DEBUG(4,(__location__ ": WARNING: domainFunctionality not setup\n"));
3811 		return DS_DOMAIN_FUNCTION_2000;
3812 	}
3813 	return *domainFunctionality;
3814 }
3815 
3816 /*
3817  * This detects and returns the forest functional level (DS_DOMAIN_FUNCTION_*)
3818  */
dsdb_forest_functional_level(struct ldb_context * ldb)3819 int dsdb_forest_functional_level(struct ldb_context *ldb)
3820 {
3821 	int *forestFunctionality =
3822 		talloc_get_type(ldb_get_opaque(ldb, "forestFunctionality"), int);
3823 	if (!forestFunctionality) {
3824 		DEBUG(0,(__location__ ": WARNING: forestFunctionality not setup\n"));
3825 		return DS_DOMAIN_FUNCTION_2000;
3826 	}
3827 	return *forestFunctionality;
3828 }
3829 
3830 /*
3831   set a GUID in an extended DN structure
3832  */
dsdb_set_extended_dn_guid(struct ldb_dn * dn,const struct GUID * guid,const char * component_name)3833 int dsdb_set_extended_dn_guid(struct ldb_dn *dn, const struct GUID *guid, const char *component_name)
3834 {
3835 	struct ldb_val v;
3836 	NTSTATUS status;
3837 	int ret;
3838 
3839 	status = GUID_to_ndr_blob(guid, dn, &v);
3840 	if (!NT_STATUS_IS_OK(status)) {
3841 		return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
3842 	}
3843 
3844 	ret = ldb_dn_set_extended_component(dn, component_name, &v);
3845 	data_blob_free(&v);
3846 	return ret;
3847 }
3848 
3849 /*
3850   return a GUID from a extended DN structure
3851  */
dsdb_get_extended_dn_guid(struct ldb_dn * dn,struct GUID * guid,const char * component_name)3852 NTSTATUS dsdb_get_extended_dn_guid(struct ldb_dn *dn, struct GUID *guid, const char *component_name)
3853 {
3854 	const struct ldb_val *v;
3855 
3856 	v = ldb_dn_get_extended_component(dn, component_name);
3857 	if (v == NULL) {
3858 		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3859 	}
3860 
3861 	return GUID_from_ndr_blob(v, guid);
3862 }
3863 
3864 /*
3865   return a uint64_t from a extended DN structure
3866  */
dsdb_get_extended_dn_uint64(struct ldb_dn * dn,uint64_t * val,const char * component_name)3867 NTSTATUS dsdb_get_extended_dn_uint64(struct ldb_dn *dn, uint64_t *val, const char *component_name)
3868 {
3869 	const struct ldb_val *v;
3870 	int error = 0;
3871 
3872 	v = ldb_dn_get_extended_component(dn, component_name);
3873 	if (v == NULL) {
3874 		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3875 	}
3876 
3877 	/* Just check we don't allow the caller to fill our stack */
3878 	if (v->length >= 64) {
3879 		return NT_STATUS_INVALID_PARAMETER;
3880 	} else {
3881 		char s[v->length+1];
3882 		memcpy(s, v->data, v->length);
3883 		s[v->length] = 0;
3884 
3885 		*val = smb_strtoull(s, NULL, 0, &error, SMB_STR_STANDARD);
3886 		if (error != 0) {
3887 			return NT_STATUS_INVALID_PARAMETER;
3888 		}
3889 	}
3890 	return NT_STATUS_OK;
3891 }
3892 
3893 /*
3894   return a NTTIME from a extended DN structure
3895  */
dsdb_get_extended_dn_nttime(struct ldb_dn * dn,NTTIME * nttime,const char * component_name)3896 NTSTATUS dsdb_get_extended_dn_nttime(struct ldb_dn *dn, NTTIME *nttime, const char *component_name)
3897 {
3898 	return dsdb_get_extended_dn_uint64(dn, nttime, component_name);
3899 }
3900 
3901 /*
3902   return a uint32_t from a extended DN structure
3903  */
dsdb_get_extended_dn_uint32(struct ldb_dn * dn,uint32_t * val,const char * component_name)3904 NTSTATUS dsdb_get_extended_dn_uint32(struct ldb_dn *dn, uint32_t *val, const char *component_name)
3905 {
3906 	const struct ldb_val *v;
3907 	int error = 0;
3908 
3909 	v = ldb_dn_get_extended_component(dn, component_name);
3910 	if (v == NULL) {
3911 		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3912 	}
3913 
3914 	/* Just check we don't allow the caller to fill our stack */
3915 	if (v->length >= 32) {
3916 		return NT_STATUS_INVALID_PARAMETER;
3917 	} else {
3918 		char s[v->length + 1];
3919 		memcpy(s, v->data, v->length);
3920 		s[v->length] = 0;
3921 		*val = smb_strtoul(s, NULL, 0, &error, SMB_STR_STANDARD);
3922 		if (error != 0) {
3923 			return NT_STATUS_INVALID_PARAMETER;
3924 		}
3925 	}
3926 
3927 	return NT_STATUS_OK;
3928 }
3929 
3930 /*
3931   return a dom_sid from a extended DN structure
3932  */
dsdb_get_extended_dn_sid(struct ldb_dn * dn,struct dom_sid * sid,const char * component_name)3933 NTSTATUS dsdb_get_extended_dn_sid(struct ldb_dn *dn, struct dom_sid *sid, const char *component_name)
3934 {
3935 	const struct ldb_val *sid_blob;
3936 	enum ndr_err_code ndr_err;
3937 
3938 	sid_blob = ldb_dn_get_extended_component(dn, component_name);
3939 	if (!sid_blob) {
3940 		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3941 	}
3942 
3943 	ndr_err = ndr_pull_struct_blob_all_noalloc(sid_blob, sid,
3944 						   (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
3945 	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3946 		NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
3947 		return status;
3948 	}
3949 
3950 	return NT_STATUS_OK;
3951 }
3952 
3953 
3954 /*
3955   return RMD_FLAGS directly from a ldb_dn
3956   returns 0 if not found
3957  */
dsdb_dn_rmd_flags(struct ldb_dn * dn)3958 uint32_t dsdb_dn_rmd_flags(struct ldb_dn *dn)
3959 {
3960 	uint32_t rmd_flags = 0;
3961 	NTSTATUS status = dsdb_get_extended_dn_uint32(dn, &rmd_flags,
3962 						      "RMD_FLAGS");
3963 	if (NT_STATUS_IS_OK(status)) {
3964 		return rmd_flags;
3965 	}
3966 	return 0;
3967 }
3968 
3969 /*
3970   return RMD_FLAGS directly from a ldb_val for a DN
3971   returns 0 if RMD_FLAGS is not found
3972  */
dsdb_dn_val_rmd_flags(const struct ldb_val * val)3973 uint32_t dsdb_dn_val_rmd_flags(const struct ldb_val *val)
3974 {
3975 	const char *p;
3976 	uint32_t flags;
3977 	char *end;
3978 	int error = 0;
3979 
3980 	if (val->length < 13) {
3981 		return 0;
3982 	}
3983 	p = memmem(val->data, val->length, "<RMD_FLAGS=", 11);
3984 	if (!p) {
3985 		return 0;
3986 	}
3987 	flags = smb_strtoul(p+11, &end, 10, &error, SMB_STR_STANDARD);
3988 	if (!end || *end != '>' || error != 0) {
3989 		/* it must end in a > */
3990 		return 0;
3991 	}
3992 	return flags;
3993 }
3994 
3995 /*
3996   return true if a ldb_val containing a DN in storage form is deleted
3997  */
dsdb_dn_is_deleted_val(const struct ldb_val * val)3998 bool dsdb_dn_is_deleted_val(const struct ldb_val *val)
3999 {
4000 	return (dsdb_dn_val_rmd_flags(val) & DSDB_RMD_FLAG_DELETED) != 0;
4001 }
4002 
4003 /*
4004   return true if a ldb_val containing a DN in storage form is
4005   in the upgraded w2k3 linked attribute format
4006  */
dsdb_dn_is_upgraded_link_val(const struct ldb_val * val)4007 bool dsdb_dn_is_upgraded_link_val(const struct ldb_val *val)
4008 {
4009 	return memmem(val->data, val->length, "<RMD_VERSION=", 13) != NULL;
4010 }
4011 
4012 /*
4013   return a DN for a wellknown GUID
4014  */
dsdb_wellknown_dn(struct ldb_context * samdb,TALLOC_CTX * mem_ctx,struct ldb_dn * nc_root,const char * wk_guid,struct ldb_dn ** wkguid_dn)4015 int dsdb_wellknown_dn(struct ldb_context *samdb, TALLOC_CTX *mem_ctx,
4016 		      struct ldb_dn *nc_root, const char *wk_guid,
4017 		      struct ldb_dn **wkguid_dn)
4018 {
4019 	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4020 	const char *attrs[] = { NULL };
4021 	int ret;
4022 	struct ldb_dn *dn;
4023 	struct ldb_result *res = NULL;
4024 
4025 	/* construct the magic WKGUID DN */
4026 	dn = ldb_dn_new_fmt(tmp_ctx, samdb, "<WKGUID=%s,%s>",
4027 			    wk_guid, ldb_dn_get_linearized(nc_root));
4028 	if (!wkguid_dn) {
4029 		talloc_free(tmp_ctx);
4030 		return ldb_operr(samdb);
4031 	}
4032 
4033 	ret = dsdb_search_dn(samdb, tmp_ctx, &res, dn, attrs,
4034 			     DSDB_SEARCH_SHOW_DELETED |
4035 			     DSDB_SEARCH_SHOW_RECYCLED);
4036 	if (ret != LDB_SUCCESS) {
4037 		talloc_free(tmp_ctx);
4038 		return ret;
4039 	}
4040 	/* fix clang warning */
4041 	if (res == NULL){
4042 		talloc_free(tmp_ctx);
4043 		return LDB_ERR_OTHER;
4044 	}
4045 
4046 	(*wkguid_dn) = talloc_steal(mem_ctx, res->msgs[0]->dn);
4047 	talloc_free(tmp_ctx);
4048 	return LDB_SUCCESS;
4049 }
4050 
4051 
dsdb_dn_compare_ptrs(struct ldb_dn ** dn1,struct ldb_dn ** dn2)4052 static int dsdb_dn_compare_ptrs(struct ldb_dn **dn1, struct ldb_dn **dn2)
4053 {
4054 	return ldb_dn_compare(*dn1, *dn2);
4055 }
4056 
4057 /*
4058   find a NC root given a DN within the NC
4059  */
dsdb_find_nc_root(struct ldb_context * samdb,TALLOC_CTX * mem_ctx,struct ldb_dn * dn,struct ldb_dn ** nc_root)4060 int dsdb_find_nc_root(struct ldb_context *samdb, TALLOC_CTX *mem_ctx, struct ldb_dn *dn,
4061 		      struct ldb_dn **nc_root)
4062 {
4063 	const char *root_attrs[] = { "namingContexts", NULL };
4064 	TALLOC_CTX *tmp_ctx;
4065 	int ret;
4066 	struct ldb_message_element *el;
4067 	struct ldb_result *root_res;
4068 	unsigned int i;
4069 	struct ldb_dn **nc_dns;
4070 
4071 	tmp_ctx = talloc_new(samdb);
4072 	if (tmp_ctx == NULL) {
4073 		return ldb_oom(samdb);
4074 	}
4075 
4076 	ret = ldb_search(samdb, tmp_ctx, &root_res,
4077 			 ldb_dn_new(tmp_ctx, samdb, ""), LDB_SCOPE_BASE, root_attrs, NULL);
4078 	if (ret != LDB_SUCCESS || root_res->count == 0) {
4079 		DEBUG(1,("Searching for namingContexts in rootDSE failed: %s\n", ldb_errstring(samdb)));
4080 		talloc_free(tmp_ctx);
4081 		return ret;
4082 	}
4083 
4084 	el = ldb_msg_find_element(root_res->msgs[0], "namingContexts");
4085 	if ((el == NULL) || (el->num_values < 3)) {
4086 		struct ldb_message *tmp_msg;
4087 
4088 		DEBUG(5,("dsdb_find_nc_root: Finding a valid 'namingContexts' element in the RootDSE failed. Using a temporary list.\n"));
4089 
4090 		/* This generates a temporary list of NCs in order to let the
4091 		 * provisioning work. */
4092 		tmp_msg = ldb_msg_new(tmp_ctx);
4093 		if (tmp_msg == NULL) {
4094 			talloc_free(tmp_ctx);
4095 			return ldb_oom(samdb);
4096 		}
4097 		ret = ldb_msg_add_steal_string(tmp_msg, "namingContexts",
4098 					       ldb_dn_alloc_linearized(tmp_msg, ldb_get_schema_basedn(samdb)));
4099 		if (ret != LDB_SUCCESS) {
4100 			talloc_free(tmp_ctx);
4101 			return ret;
4102 		}
4103 		ret = ldb_msg_add_steal_string(tmp_msg, "namingContexts",
4104 					       ldb_dn_alloc_linearized(tmp_msg, ldb_get_config_basedn(samdb)));
4105 		if (ret != LDB_SUCCESS) {
4106 			talloc_free(tmp_ctx);
4107 			return ret;
4108 		}
4109 		ret = ldb_msg_add_steal_string(tmp_msg, "namingContexts",
4110 					       ldb_dn_alloc_linearized(tmp_msg, ldb_get_default_basedn(samdb)));
4111 		if (ret != LDB_SUCCESS) {
4112 			talloc_free(tmp_ctx);
4113 			return ret;
4114 		}
4115 		el = &tmp_msg->elements[0];
4116 	}
4117 
4118        nc_dns = talloc_array(tmp_ctx, struct ldb_dn *, el->num_values);
4119        if (!nc_dns) {
4120 	       talloc_free(tmp_ctx);
4121 	       return ldb_oom(samdb);
4122        }
4123 
4124        for (i=0; i<el->num_values; i++) {
4125 	       nc_dns[i] = ldb_dn_from_ldb_val(nc_dns, samdb, &el->values[i]);
4126 	       if (nc_dns[i] == NULL) {
4127 		       talloc_free(tmp_ctx);
4128 		       return ldb_operr(samdb);
4129 	       }
4130        }
4131 
4132        TYPESAFE_QSORT(nc_dns, el->num_values, dsdb_dn_compare_ptrs);
4133 
4134        for (i=0; i<el->num_values; i++) {
4135                if (ldb_dn_compare_base(nc_dns[i], dn) == 0) {
4136 		       (*nc_root) = talloc_steal(mem_ctx, nc_dns[i]);
4137                        talloc_free(tmp_ctx);
4138                        return LDB_SUCCESS;
4139                }
4140        }
4141 
4142        talloc_free(tmp_ctx);
4143        return ldb_error(samdb, LDB_ERR_NO_SUCH_OBJECT, __func__);
4144 }
4145 
4146 
4147 /*
4148   find the deleted objects DN for any object, by looking for the NC
4149   root, then looking up the wellknown GUID
4150  */
dsdb_get_deleted_objects_dn(struct ldb_context * ldb,TALLOC_CTX * mem_ctx,struct ldb_dn * obj_dn,struct ldb_dn ** do_dn)4151 int dsdb_get_deleted_objects_dn(struct ldb_context *ldb,
4152 				TALLOC_CTX *mem_ctx, struct ldb_dn *obj_dn,
4153 				struct ldb_dn **do_dn)
4154 {
4155 	struct ldb_dn *nc_root;
4156 	int ret;
4157 
4158 	ret = dsdb_find_nc_root(ldb, mem_ctx, obj_dn, &nc_root);
4159 	if (ret != LDB_SUCCESS) {
4160 		return ret;
4161 	}
4162 
4163 	ret = dsdb_wellknown_dn(ldb, mem_ctx, nc_root, DS_GUID_DELETED_OBJECTS_CONTAINER, do_dn);
4164 	talloc_free(nc_root);
4165 	return ret;
4166 }
4167 
4168 /*
4169   return the tombstoneLifetime, in days
4170  */
dsdb_tombstone_lifetime(struct ldb_context * ldb,uint32_t * lifetime)4171 int dsdb_tombstone_lifetime(struct ldb_context *ldb, uint32_t *lifetime)
4172 {
4173 	struct ldb_dn *dn;
4174 	dn = ldb_get_config_basedn(ldb);
4175 	if (!dn) {
4176 		return ldb_error(ldb, LDB_ERR_NO_SUCH_OBJECT, __func__);
4177 	}
4178 	dn = ldb_dn_copy(ldb, dn);
4179 	if (!dn) {
4180 		return ldb_operr(ldb);
4181 	}
4182 	/* see MS-ADTS section 7.1.1.2.4.1.1. There doesn't appear to
4183 	 be a wellknown GUID for this */
4184 	if (!ldb_dn_add_child_fmt(dn, "CN=Directory Service,CN=Windows NT,CN=Services")) {
4185 		talloc_free(dn);
4186 		return ldb_operr(ldb);
4187 	}
4188 
4189 	*lifetime = samdb_search_uint(ldb, dn, 180, dn, "tombstoneLifetime", "objectClass=nTDSService");
4190 	talloc_free(dn);
4191 	return LDB_SUCCESS;
4192 }
4193 
4194 /*
4195   compare a ldb_val to a string case insensitively
4196  */
samdb_ldb_val_case_cmp(const char * s,struct ldb_val * v)4197 int samdb_ldb_val_case_cmp(const char *s, struct ldb_val *v)
4198 {
4199 	size_t len = strlen(s);
4200 	int ret;
4201 	if (len > v->length) return 1;
4202 	ret = strncasecmp(s, (const char *)v->data, v->length);
4203 	if (ret != 0) return ret;
4204 	if (v->length > len && v->data[len] != 0) {
4205 		return -1;
4206 	}
4207 	return 0;
4208 }
4209 
4210 
4211 /*
4212   load the UDV for a partition in v2 format
4213   The list is returned sorted, and with our local cursor added
4214  */
dsdb_load_udv_v2(struct ldb_context * samdb,struct ldb_dn * dn,TALLOC_CTX * mem_ctx,struct drsuapi_DsReplicaCursor2 ** cursors,uint32_t * count)4215 int dsdb_load_udv_v2(struct ldb_context *samdb, struct ldb_dn *dn, TALLOC_CTX *mem_ctx,
4216 		     struct drsuapi_DsReplicaCursor2 **cursors, uint32_t *count)
4217 {
4218 	static const char *attrs[] = { "replUpToDateVector", NULL };
4219 	struct ldb_result *r = NULL;
4220 	const struct ldb_val *ouv_value;
4221 	unsigned int i;
4222 	int ret;
4223 	uint64_t highest_usn = 0;
4224 	const struct GUID *our_invocation_id;
4225 	static const struct timeval tv1970;
4226 	NTTIME nt1970 = timeval_to_nttime(&tv1970);
4227 
4228 	ret = dsdb_search_dn(samdb, mem_ctx, &r, dn, attrs, DSDB_SEARCH_SHOW_RECYCLED|DSDB_SEARCH_SHOW_DELETED);
4229 	if (ret != LDB_SUCCESS) {
4230 		return ret;
4231 	}
4232 	/* fix clang warning */
4233 	if (r == NULL) {
4234 		return LDB_ERR_OTHER;
4235 	}
4236 	ouv_value = ldb_msg_find_ldb_val(r->msgs[0], "replUpToDateVector");
4237 	if (ouv_value) {
4238 		enum ndr_err_code ndr_err;
4239 		struct replUpToDateVectorBlob ouv;
4240 
4241 		ndr_err = ndr_pull_struct_blob(ouv_value, r, &ouv,
4242 					       (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob);
4243 		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4244 			talloc_free(r);
4245 			return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
4246 		}
4247 		if (ouv.version != 2) {
4248 			/* we always store as version 2, and
4249 			 * replUpToDateVector is not replicated
4250 			 */
4251 			return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
4252 		}
4253 
4254 		*count = ouv.ctr.ctr2.count;
4255 		*cursors = talloc_steal(mem_ctx, ouv.ctr.ctr2.cursors);
4256 	} else {
4257 		*count = 0;
4258 		*cursors = NULL;
4259 	}
4260 
4261 	talloc_free(r);
4262 
4263 	our_invocation_id = samdb_ntds_invocation_id(samdb);
4264 	if (!our_invocation_id) {
4265 		DEBUG(0,(__location__ ": No invocationID on samdb - %s\n", ldb_errstring(samdb)));
4266 		talloc_free(*cursors);
4267 		return ldb_operr(samdb);
4268 	}
4269 
4270 	ret = ldb_sequence_number(samdb, LDB_SEQ_HIGHEST_SEQ, &highest_usn);
4271 	if (ret != LDB_SUCCESS) {
4272 		/* nothing to add - this can happen after a vampire */
4273 		TYPESAFE_QSORT(*cursors, *count, drsuapi_DsReplicaCursor2_compare);
4274 		return LDB_SUCCESS;
4275 	}
4276 
4277 	for (i=0; i<*count; i++) {
4278 		if (GUID_equal(our_invocation_id, &(*cursors)[i].source_dsa_invocation_id)) {
4279 			(*cursors)[i].highest_usn = highest_usn;
4280 			(*cursors)[i].last_sync_success = nt1970;
4281 			TYPESAFE_QSORT(*cursors, *count, drsuapi_DsReplicaCursor2_compare);
4282 			return LDB_SUCCESS;
4283 		}
4284 	}
4285 
4286 	(*cursors) = talloc_realloc(mem_ctx, *cursors, struct drsuapi_DsReplicaCursor2, (*count)+1);
4287 	if (! *cursors) {
4288 		return ldb_oom(samdb);
4289 	}
4290 
4291 	(*cursors)[*count].source_dsa_invocation_id = *our_invocation_id;
4292 	(*cursors)[*count].highest_usn = highest_usn;
4293 	(*cursors)[*count].last_sync_success = nt1970;
4294 	(*count)++;
4295 
4296 	TYPESAFE_QSORT(*cursors, *count, drsuapi_DsReplicaCursor2_compare);
4297 
4298 	return LDB_SUCCESS;
4299 }
4300 
4301 /*
4302   load the UDV for a partition in version 1 format
4303   The list is returned sorted, and with our local cursor added
4304  */
dsdb_load_udv_v1(struct ldb_context * samdb,struct ldb_dn * dn,TALLOC_CTX * mem_ctx,struct drsuapi_DsReplicaCursor ** cursors,uint32_t * count)4305 int dsdb_load_udv_v1(struct ldb_context *samdb, struct ldb_dn *dn, TALLOC_CTX *mem_ctx,
4306 		     struct drsuapi_DsReplicaCursor **cursors, uint32_t *count)
4307 {
4308 	struct drsuapi_DsReplicaCursor2 *v2 = NULL;
4309 	uint32_t i;
4310 	int ret;
4311 
4312 	ret = dsdb_load_udv_v2(samdb, dn, mem_ctx, &v2, count);
4313 	if (ret != LDB_SUCCESS) {
4314 		return ret;
4315 	}
4316 
4317 	if (*count == 0) {
4318 		talloc_free(v2);
4319 		*cursors = NULL;
4320 		return LDB_SUCCESS;
4321 	}
4322 
4323 	*cursors = talloc_array(mem_ctx, struct drsuapi_DsReplicaCursor, *count);
4324 	if (*cursors == NULL) {
4325 		talloc_free(v2);
4326 		return ldb_oom(samdb);
4327 	}
4328 
4329 	for (i=0; i<*count; i++) {
4330 		(*cursors)[i].source_dsa_invocation_id = v2[i].source_dsa_invocation_id;
4331 		(*cursors)[i].highest_usn = v2[i].highest_usn;
4332 	}
4333 	talloc_free(v2);
4334 	return LDB_SUCCESS;
4335 }
4336 
4337 /*
4338   add a set of controls to a ldb_request structure based on a set of
4339   flags. See util.h for a list of available flags
4340  */
dsdb_request_add_controls(struct ldb_request * req,uint32_t dsdb_flags)4341 int dsdb_request_add_controls(struct ldb_request *req, uint32_t dsdb_flags)
4342 {
4343 	int ret;
4344 	if (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) {
4345 		struct ldb_search_options_control *options;
4346 		/* Using the phantom root control allows us to search all partitions */
4347 		options = talloc(req, struct ldb_search_options_control);
4348 		if (options == NULL) {
4349 			return LDB_ERR_OPERATIONS_ERROR;
4350 		}
4351 		options->search_options = LDB_SEARCH_OPTION_PHANTOM_ROOT;
4352 
4353 		ret = ldb_request_add_control(req,
4354 					      LDB_CONTROL_SEARCH_OPTIONS_OID,
4355 					      true, options);
4356 		if (ret != LDB_SUCCESS) {
4357 			return ret;
4358 		}
4359 	}
4360 
4361 	if (dsdb_flags & DSDB_SEARCH_NO_GLOBAL_CATALOG) {
4362 		ret = ldb_request_add_control(req,
4363 					      DSDB_CONTROL_NO_GLOBAL_CATALOG,
4364 					      false, NULL);
4365 		if (ret != LDB_SUCCESS) {
4366 			return ret;
4367 		}
4368 	}
4369 
4370 	if (dsdb_flags & DSDB_SEARCH_SHOW_DELETED) {
4371 		ret = ldb_request_add_control(req, LDB_CONTROL_SHOW_DELETED_OID, true, NULL);
4372 		if (ret != LDB_SUCCESS) {
4373 			return ret;
4374 		}
4375 	}
4376 
4377 	if (dsdb_flags & DSDB_SEARCH_SHOW_RECYCLED) {
4378 		ret = ldb_request_add_control(req, LDB_CONTROL_SHOW_RECYCLED_OID, false, NULL);
4379 		if (ret != LDB_SUCCESS) {
4380 			return ret;
4381 		}
4382 	}
4383 
4384 	if (dsdb_flags & DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT) {
4385 		ret = ldb_request_add_control(req, DSDB_CONTROL_DN_STORAGE_FORMAT_OID, false, NULL);
4386 		if (ret != LDB_SUCCESS) {
4387 			return ret;
4388 		}
4389 	}
4390 
4391 	if (dsdb_flags & DSDB_SEARCH_SHOW_EXTENDED_DN) {
4392 		struct ldb_extended_dn_control *extended_ctrl = talloc(req, struct ldb_extended_dn_control);
4393 		if (!extended_ctrl) {
4394 			return LDB_ERR_OPERATIONS_ERROR;
4395 		}
4396 		extended_ctrl->type = 1;
4397 
4398 		ret = ldb_request_add_control(req, LDB_CONTROL_EXTENDED_DN_OID, true, extended_ctrl);
4399 		if (ret != LDB_SUCCESS) {
4400 			return ret;
4401 		}
4402 	}
4403 
4404 	if (dsdb_flags & DSDB_SEARCH_REVEAL_INTERNALS) {
4405 		ret = ldb_request_add_control(req, LDB_CONTROL_REVEAL_INTERNALS, false, NULL);
4406 		if (ret != LDB_SUCCESS) {
4407 			return ret;
4408 		}
4409 	}
4410 
4411 	if (dsdb_flags & DSDB_MODIFY_RELAX) {
4412 		ret = ldb_request_add_control(req, LDB_CONTROL_RELAX_OID, false, NULL);
4413 		if (ret != LDB_SUCCESS) {
4414 			return ret;
4415 		}
4416 	}
4417 
4418 	if (dsdb_flags & DSDB_MODIFY_PERMISSIVE) {
4419 		ret = ldb_request_add_control(req, LDB_CONTROL_PERMISSIVE_MODIFY_OID, false, NULL);
4420 		if (ret != LDB_SUCCESS) {
4421 			return ret;
4422 		}
4423 	}
4424 
4425 	if (dsdb_flags & DSDB_FLAG_AS_SYSTEM) {
4426 		ret = ldb_request_add_control(req, LDB_CONTROL_AS_SYSTEM_OID, false, NULL);
4427 		if (ret != LDB_SUCCESS) {
4428 			return ret;
4429 		}
4430 	}
4431 
4432 	if (dsdb_flags & DSDB_TREE_DELETE) {
4433 		ret = ldb_request_add_control(req, LDB_CONTROL_TREE_DELETE_OID, false, NULL);
4434 		if (ret != LDB_SUCCESS) {
4435 			return ret;
4436 		}
4437 	}
4438 
4439 	if (dsdb_flags & DSDB_PROVISION) {
4440 		ret = ldb_request_add_control(req, LDB_CONTROL_PROVISION_OID, false, NULL);
4441 		if (ret != LDB_SUCCESS) {
4442 			return ret;
4443 		}
4444 	}
4445 
4446 	/* This is a special control to bypass the password_hash module for use in pdb_samba4 for Samba3 upgrades */
4447 	if (dsdb_flags & DSDB_BYPASS_PASSWORD_HASH) {
4448 		ret = ldb_request_add_control(req, DSDB_CONTROL_BYPASS_PASSWORD_HASH_OID, true, NULL);
4449 		if (ret != LDB_SUCCESS) {
4450 			return ret;
4451 		}
4452 	}
4453 
4454 	if (dsdb_flags & DSDB_PASSWORD_BYPASS_LAST_SET) {
4455 		/*
4456 		 * This must not be critical, as it will only be
4457 		 * handled (and need to be handled) if the other
4458 		 * attributes in the request bring password_hash into
4459 		 * action
4460 		 */
4461 		ret = ldb_request_add_control(req, DSDB_CONTROL_PASSWORD_BYPASS_LAST_SET_OID, false, NULL);
4462 		if (ret != LDB_SUCCESS) {
4463 			return ret;
4464 		}
4465 	}
4466 
4467 	if (dsdb_flags & DSDB_REPLMD_VANISH_LINKS) {
4468 		ret = ldb_request_add_control(req, DSDB_CONTROL_REPLMD_VANISH_LINKS, true, NULL);
4469 		if (ret != LDB_SUCCESS) {
4470 			return ret;
4471 		}
4472 	}
4473 
4474 	if (dsdb_flags & DSDB_MODIFY_PARTIAL_REPLICA) {
4475 		ret = ldb_request_add_control(req, DSDB_CONTROL_PARTIAL_REPLICA, false, NULL);
4476 		if (ret != LDB_SUCCESS) {
4477 			return ret;
4478 		}
4479 	}
4480 
4481 	if (dsdb_flags & DSDB_FLAG_REPLICATED_UPDATE) {
4482 		ret = ldb_request_add_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID, false, NULL);
4483 		if (ret != LDB_SUCCESS) {
4484 			return ret;
4485 		}
4486 	}
4487 
4488 	return LDB_SUCCESS;
4489 }
4490 
4491 /*
4492    returns true if a control with the specified "oid" exists
4493 */
dsdb_request_has_control(struct ldb_request * req,const char * oid)4494 bool dsdb_request_has_control(struct ldb_request *req, const char *oid)
4495 {
4496 	return (ldb_request_get_control(req, oid) != NULL);
4497 }
4498 
4499 /*
4500   an add with a set of controls
4501 */
dsdb_add(struct ldb_context * ldb,const struct ldb_message * message,uint32_t dsdb_flags)4502 int dsdb_add(struct ldb_context *ldb, const struct ldb_message *message,
4503 	     uint32_t dsdb_flags)
4504 {
4505 	struct ldb_request *req;
4506 	int ret;
4507 
4508 	ret = ldb_build_add_req(&req, ldb, ldb,
4509 				message,
4510 				NULL,
4511 				NULL,
4512 				ldb_op_default_callback,
4513 				NULL);
4514 
4515 	if (ret != LDB_SUCCESS) return ret;
4516 
4517 	ret = dsdb_request_add_controls(req, dsdb_flags);
4518 	if (ret != LDB_SUCCESS) {
4519 		talloc_free(req);
4520 		return ret;
4521 	}
4522 
4523 	ret = dsdb_autotransaction_request(ldb, req);
4524 
4525 	talloc_free(req);
4526 	return ret;
4527 }
4528 
4529 /*
4530   a modify with a set of controls
4531 */
dsdb_modify(struct ldb_context * ldb,const struct ldb_message * message,uint32_t dsdb_flags)4532 int dsdb_modify(struct ldb_context *ldb, const struct ldb_message *message,
4533 		uint32_t dsdb_flags)
4534 {
4535 	struct ldb_request *req;
4536 	int ret;
4537 
4538 	ret = ldb_build_mod_req(&req, ldb, ldb,
4539 				message,
4540 				NULL,
4541 				NULL,
4542 				ldb_op_default_callback,
4543 				NULL);
4544 
4545 	if (ret != LDB_SUCCESS) return ret;
4546 
4547 	ret = dsdb_request_add_controls(req, dsdb_flags);
4548 	if (ret != LDB_SUCCESS) {
4549 		talloc_free(req);
4550 		return ret;
4551 	}
4552 
4553 	ret = dsdb_autotransaction_request(ldb, req);
4554 
4555 	talloc_free(req);
4556 	return ret;
4557 }
4558 
4559 /*
4560   a delete with a set of flags
4561 */
dsdb_delete(struct ldb_context * ldb,struct ldb_dn * dn,uint32_t dsdb_flags)4562 int dsdb_delete(struct ldb_context *ldb, struct ldb_dn *dn,
4563 		uint32_t dsdb_flags)
4564 {
4565 	struct ldb_request *req;
4566 	int ret;
4567 
4568 	ret = ldb_build_del_req(&req, ldb, ldb,
4569 				dn,
4570 				NULL,
4571 				NULL,
4572 				ldb_op_default_callback,
4573 				NULL);
4574 
4575 	if (ret != LDB_SUCCESS) return ret;
4576 
4577 	ret = dsdb_request_add_controls(req, dsdb_flags);
4578 	if (ret != LDB_SUCCESS) {
4579 		talloc_free(req);
4580 		return ret;
4581 	}
4582 
4583 	ret = dsdb_autotransaction_request(ldb, req);
4584 
4585 	talloc_free(req);
4586 	return ret;
4587 }
4588 
4589 /*
4590   like dsdb_modify() but set all the element flags to
4591   LDB_FLAG_MOD_REPLACE
4592  */
dsdb_replace(struct ldb_context * ldb,struct ldb_message * msg,uint32_t dsdb_flags)4593 int dsdb_replace(struct ldb_context *ldb, struct ldb_message *msg, uint32_t dsdb_flags)
4594 {
4595 	unsigned int i;
4596 
4597 	/* mark all the message elements as LDB_FLAG_MOD_REPLACE */
4598 	for (i=0;i<msg->num_elements;i++) {
4599 		msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
4600 	}
4601 
4602 	return dsdb_modify(ldb, msg, dsdb_flags);
4603 }
4604 
4605 
4606 /*
4607   search for attrs on one DN, allowing for dsdb_flags controls
4608  */
dsdb_search_dn(struct ldb_context * ldb,TALLOC_CTX * mem_ctx,struct ldb_result ** _result,struct ldb_dn * basedn,const char * const * attrs,uint32_t dsdb_flags)4609 int dsdb_search_dn(struct ldb_context *ldb,
4610 		   TALLOC_CTX *mem_ctx,
4611 		   struct ldb_result **_result,
4612 		   struct ldb_dn *basedn,
4613 		   const char * const *attrs,
4614 		   uint32_t dsdb_flags)
4615 {
4616 	int ret;
4617 	struct ldb_request *req;
4618 	struct ldb_result *res;
4619 
4620 	res = talloc_zero(mem_ctx, struct ldb_result);
4621 	if (!res) {
4622 		return ldb_oom(ldb);
4623 	}
4624 
4625 	ret = ldb_build_search_req(&req, ldb, res,
4626 				   basedn,
4627 				   LDB_SCOPE_BASE,
4628 				   NULL,
4629 				   attrs,
4630 				   NULL,
4631 				   res,
4632 				   ldb_search_default_callback,
4633 				   NULL);
4634 	if (ret != LDB_SUCCESS) {
4635 		talloc_free(res);
4636 		return ret;
4637 	}
4638 
4639 	ret = dsdb_request_add_controls(req, dsdb_flags);
4640 	if (ret != LDB_SUCCESS) {
4641 		talloc_free(res);
4642 		return ret;
4643 	}
4644 
4645 	ret = ldb_request(ldb, req);
4646 	if (ret == LDB_SUCCESS) {
4647 		ret = ldb_wait(req->handle, LDB_WAIT_ALL);
4648 	}
4649 
4650 	talloc_free(req);
4651 	if (ret != LDB_SUCCESS) {
4652 		talloc_free(res);
4653 		return ret;
4654 	}
4655 
4656 	*_result = res;
4657 	return LDB_SUCCESS;
4658 }
4659 
4660 /*
4661   search for attrs on one DN, by the GUID of the DN, allowing for
4662   dsdb_flags controls
4663  */
dsdb_search_by_dn_guid(struct ldb_context * ldb,TALLOC_CTX * mem_ctx,struct ldb_result ** _result,const struct GUID * guid,const char * const * attrs,uint32_t dsdb_flags)4664 int dsdb_search_by_dn_guid(struct ldb_context *ldb,
4665 			   TALLOC_CTX *mem_ctx,
4666 			   struct ldb_result **_result,
4667 			   const struct GUID *guid,
4668 			   const char * const *attrs,
4669 			   uint32_t dsdb_flags)
4670 {
4671 	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4672 	struct ldb_dn *dn;
4673 	int ret;
4674 
4675 	dn = ldb_dn_new_fmt(tmp_ctx, ldb, "<GUID=%s>", GUID_string(tmp_ctx, guid));
4676 	if (dn == NULL) {
4677 		talloc_free(tmp_ctx);
4678 		return ldb_oom(ldb);
4679 	}
4680 
4681 	ret = dsdb_search_dn(ldb, mem_ctx, _result, dn, attrs, dsdb_flags);
4682 	talloc_free(tmp_ctx);
4683 	return ret;
4684 }
4685 
4686 /*
4687   general search with dsdb_flags for controls
4688  */
dsdb_search(struct ldb_context * ldb,TALLOC_CTX * mem_ctx,struct ldb_result ** _result,struct ldb_dn * basedn,enum ldb_scope scope,const char * const * attrs,uint32_t dsdb_flags,const char * exp_fmt,...)4689 int dsdb_search(struct ldb_context *ldb,
4690 		TALLOC_CTX *mem_ctx,
4691 		struct ldb_result **_result,
4692 		struct ldb_dn *basedn,
4693 		enum ldb_scope scope,
4694 		const char * const *attrs,
4695 		uint32_t dsdb_flags,
4696 		const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(8, 9)
4697 {
4698 	int ret;
4699 	struct ldb_request *req;
4700 	struct ldb_result *res;
4701 	va_list ap;
4702 	char *expression = NULL;
4703 	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4704 
4705 	/* cross-partitions searches with a basedn break multi-domain support */
4706 	SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
4707 
4708 	res = talloc_zero(tmp_ctx, struct ldb_result);
4709 	if (!res) {
4710 		talloc_free(tmp_ctx);
4711 		return ldb_oom(ldb);
4712 	}
4713 
4714 	if (exp_fmt) {
4715 		va_start(ap, exp_fmt);
4716 		expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
4717 		va_end(ap);
4718 
4719 		if (!expression) {
4720 			talloc_free(tmp_ctx);
4721 			return ldb_oom(ldb);
4722 		}
4723 	}
4724 
4725 	ret = ldb_build_search_req(&req, ldb, tmp_ctx,
4726 				   basedn,
4727 				   scope,
4728 				   expression,
4729 				   attrs,
4730 				   NULL,
4731 				   res,
4732 				   ldb_search_default_callback,
4733 				   NULL);
4734 	if (ret != LDB_SUCCESS) {
4735 		talloc_free(tmp_ctx);
4736 		return ret;
4737 	}
4738 
4739 	ret = dsdb_request_add_controls(req, dsdb_flags);
4740 	if (ret != LDB_SUCCESS) {
4741 		talloc_free(tmp_ctx);
4742 		ldb_reset_err_string(ldb);
4743 		return ret;
4744 	}
4745 
4746 	ret = ldb_request(ldb, req);
4747 	if (ret == LDB_SUCCESS) {
4748 		ret = ldb_wait(req->handle, LDB_WAIT_ALL);
4749 	}
4750 
4751 	if (ret != LDB_SUCCESS) {
4752 		talloc_free(tmp_ctx);
4753 		return ret;
4754 	}
4755 
4756 	if (dsdb_flags & DSDB_SEARCH_ONE_ONLY) {
4757 		if (res->count == 0) {
4758 			talloc_free(tmp_ctx);
4759 			ldb_reset_err_string(ldb);
4760 			return ldb_error(ldb, LDB_ERR_NO_SUCH_OBJECT, __func__);
4761 		}
4762 		if (res->count != 1) {
4763 			talloc_free(tmp_ctx);
4764 			ldb_reset_err_string(ldb);
4765 			return LDB_ERR_CONSTRAINT_VIOLATION;
4766 		}
4767 	}
4768 
4769 	*_result = talloc_steal(mem_ctx, res);
4770 	talloc_free(tmp_ctx);
4771 
4772 	return LDB_SUCCESS;
4773 }
4774 
4775 
4776 /*
4777   general search with dsdb_flags for controls
4778   returns exactly 1 record or an error
4779  */
dsdb_search_one(struct ldb_context * ldb,TALLOC_CTX * mem_ctx,struct ldb_message ** msg,struct ldb_dn * basedn,enum ldb_scope scope,const char * const * attrs,uint32_t dsdb_flags,const char * exp_fmt,...)4780 int dsdb_search_one(struct ldb_context *ldb,
4781 		    TALLOC_CTX *mem_ctx,
4782 		    struct ldb_message **msg,
4783 		    struct ldb_dn *basedn,
4784 		    enum ldb_scope scope,
4785 		    const char * const *attrs,
4786 		    uint32_t dsdb_flags,
4787 		    const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(8, 9)
4788 {
4789 	int ret;
4790 	struct ldb_result *res;
4791 	va_list ap;
4792 	char *expression = NULL;
4793 	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4794 
4795 	dsdb_flags |= DSDB_SEARCH_ONE_ONLY;
4796 
4797 	res = talloc_zero(tmp_ctx, struct ldb_result);
4798 	if (!res) {
4799 		talloc_free(tmp_ctx);
4800 		return ldb_oom(ldb);
4801 	}
4802 
4803 	if (exp_fmt) {
4804 		va_start(ap, exp_fmt);
4805 		expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
4806 		va_end(ap);
4807 
4808 		if (!expression) {
4809 			talloc_free(tmp_ctx);
4810 			return ldb_oom(ldb);
4811 		}
4812 		ret = dsdb_search(ldb, tmp_ctx, &res, basedn, scope, attrs,
4813 				  dsdb_flags, "%s", expression);
4814 	} else {
4815 		ret = dsdb_search(ldb, tmp_ctx, &res, basedn, scope, attrs,
4816 				  dsdb_flags, NULL);
4817 	}
4818 
4819 	if (ret != LDB_SUCCESS) {
4820 		talloc_free(tmp_ctx);
4821 		return ret;
4822 	}
4823 
4824 	*msg = talloc_steal(mem_ctx, res->msgs[0]);
4825 	talloc_free(tmp_ctx);
4826 
4827 	return LDB_SUCCESS;
4828 }
4829 
4830 /* returns back the forest DNS name */
samdb_forest_name(struct ldb_context * ldb,TALLOC_CTX * mem_ctx)4831 const char *samdb_forest_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
4832 {
4833 	const char *forest_name = ldb_dn_canonical_string(mem_ctx,
4834 							  ldb_get_root_basedn(ldb));
4835 	char *p;
4836 
4837 	if (forest_name == NULL) {
4838 		return NULL;
4839 	}
4840 
4841 	p = strchr(forest_name, '/');
4842 	if (p) {
4843 		*p = '\0';
4844 	}
4845 
4846 	return forest_name;
4847 }
4848 
4849 /* returns back the default domain DNS name */
samdb_default_domain_name(struct ldb_context * ldb,TALLOC_CTX * mem_ctx)4850 const char *samdb_default_domain_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
4851 {
4852 	const char *domain_name = ldb_dn_canonical_string(mem_ctx,
4853 							  ldb_get_default_basedn(ldb));
4854 	char *p;
4855 
4856 	if (domain_name == NULL) {
4857 		return NULL;
4858 	}
4859 
4860 	p = strchr(domain_name, '/');
4861 	if (p) {
4862 		*p = '\0';
4863 	}
4864 
4865 	return domain_name;
4866 }
4867 
4868 /*
4869    validate that an DSA GUID belongs to the specified user sid.
4870    The user SID must be a domain controller account (either RODC or
4871    RWDC)
4872  */
dsdb_validate_dsa_guid(struct ldb_context * ldb,const struct GUID * dsa_guid,const struct dom_sid * sid)4873 int dsdb_validate_dsa_guid(struct ldb_context *ldb,
4874 			   const struct GUID *dsa_guid,
4875 			   const struct dom_sid *sid)
4876 {
4877 	/* strategy:
4878 	    - find DN of record with the DSA GUID in the
4879 	      configuration partition (objectGUID)
4880             - remove "NTDS Settings" component from DN
4881 	    - do a base search on that DN for serverReference with
4882 	      extended-dn enabled
4883             - extract objectSid from resulting serverReference
4884               attribute
4885 	    - check this sid matches the sid argument
4886 	*/
4887 	struct ldb_dn *config_dn;
4888 	TALLOC_CTX *tmp_ctx = talloc_new(ldb);
4889 	struct ldb_message *msg;
4890 	const char *attrs1[] = { NULL };
4891 	const char *attrs2[] = { "serverReference", NULL };
4892 	int ret;
4893 	struct ldb_dn *dn, *account_dn;
4894 	struct dom_sid sid2;
4895 	NTSTATUS status;
4896 
4897 	config_dn = ldb_get_config_basedn(ldb);
4898 
4899 	ret = dsdb_search_one(ldb, tmp_ctx, &msg, config_dn, LDB_SCOPE_SUBTREE,
4900 			      attrs1, 0, "(&(objectGUID=%s)(objectClass=nTDSDSA))", GUID_string(tmp_ctx, dsa_guid));
4901 	if (ret != LDB_SUCCESS) {
4902 		DEBUG(1,(__location__ ": Failed to find DSA objectGUID %s for sid %s\n",
4903 			 GUID_string(tmp_ctx, dsa_guid), dom_sid_string(tmp_ctx, sid)));
4904 		talloc_free(tmp_ctx);
4905 		return ldb_operr(ldb);
4906 	}
4907 	dn = msg->dn;
4908 
4909 	if (!ldb_dn_remove_child_components(dn, 1)) {
4910 		talloc_free(tmp_ctx);
4911 		return ldb_operr(ldb);
4912 	}
4913 
4914 	ret = dsdb_search_one(ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE,
4915 			      attrs2, DSDB_SEARCH_SHOW_EXTENDED_DN,
4916 			      "(objectClass=server)");
4917 	if (ret != LDB_SUCCESS) {
4918 		DEBUG(1,(__location__ ": Failed to find server record for DSA with objectGUID %s, sid %s\n",
4919 			 GUID_string(tmp_ctx, dsa_guid), dom_sid_string(tmp_ctx, sid)));
4920 		talloc_free(tmp_ctx);
4921 		return ldb_operr(ldb);
4922 	}
4923 
4924 	account_dn = ldb_msg_find_attr_as_dn(ldb, tmp_ctx, msg, "serverReference");
4925 	if (account_dn == NULL) {
4926 		DEBUG(1,(__location__ ": Failed to find account dn "
4927 			 "(serverReference) for %s, parent of DSA with "
4928 			 "objectGUID %s, sid %s\n",
4929 			 ldb_dn_get_linearized(msg->dn),
4930 			 GUID_string(tmp_ctx, dsa_guid),
4931 			 dom_sid_string(tmp_ctx, sid)));
4932 		talloc_free(tmp_ctx);
4933 		return ldb_operr(ldb);
4934 	}
4935 
4936 	status = dsdb_get_extended_dn_sid(account_dn, &sid2, "SID");
4937 	if (!NT_STATUS_IS_OK(status)) {
4938 		DEBUG(1,(__location__ ": Failed to find SID for DSA with objectGUID %s, sid %s\n",
4939 			 GUID_string(tmp_ctx, dsa_guid), dom_sid_string(tmp_ctx, sid)));
4940 		talloc_free(tmp_ctx);
4941 		return ldb_operr(ldb);
4942 	}
4943 
4944 	if (!dom_sid_equal(sid, &sid2)) {
4945 		/* someone is trying to spoof another account */
4946 		DEBUG(0,(__location__ ": Bad DSA objectGUID %s for sid %s - expected sid %s\n",
4947 			 GUID_string(tmp_ctx, dsa_guid),
4948 			 dom_sid_string(tmp_ctx, sid),
4949 			 dom_sid_string(tmp_ctx, &sid2)));
4950 		talloc_free(tmp_ctx);
4951 		return ldb_operr(ldb);
4952 	}
4953 
4954 	talloc_free(tmp_ctx);
4955 	return LDB_SUCCESS;
4956 }
4957 
4958 static const char * const secret_attributes[] = {
4959 	DSDB_SECRET_ATTRIBUTES,
4960 	NULL
4961 };
4962 
4963 /*
4964   check if the attribute belongs to the RODC filtered attribute set
4965   Note that attributes that are in the filtered attribute set are the
4966   ones that _are_ always sent to a RODC
4967 */
dsdb_attr_in_rodc_fas(const struct dsdb_attribute * sa)4968 bool dsdb_attr_in_rodc_fas(const struct dsdb_attribute *sa)
4969 {
4970 	/* they never get secret attributes */
4971 	if (is_attr_in_list(secret_attributes, sa->lDAPDisplayName)) {
4972 		return false;
4973 	}
4974 
4975 	/* they do get non-secret critical attributes */
4976 	if (sa->schemaFlagsEx & SCHEMA_FLAG_ATTR_IS_CRITICAL) {
4977 		return true;
4978 	}
4979 
4980 	/* they do get non-secret attributes marked as being in the FAS  */
4981 	if (sa->searchFlags & SEARCH_FLAG_RODC_ATTRIBUTE) {
4982 		return true;
4983 	}
4984 
4985 	/* other attributes are denied */
4986 	return false;
4987 }
4988 
4989 /* return fsmo role dn and role owner dn for a particular role*/
dsdb_get_fsmo_role_info(TALLOC_CTX * tmp_ctx,struct ldb_context * ldb,uint32_t role,struct ldb_dn ** fsmo_role_dn,struct ldb_dn ** role_owner_dn)4990 WERROR dsdb_get_fsmo_role_info(TALLOC_CTX *tmp_ctx,
4991 			       struct ldb_context *ldb,
4992 			       uint32_t role,
4993 			       struct ldb_dn **fsmo_role_dn,
4994 			       struct ldb_dn **role_owner_dn)
4995 {
4996 	int ret;
4997 	switch (role) {
4998 	case DREPL_NAMING_MASTER:
4999 		*fsmo_role_dn = samdb_partitions_dn(ldb, tmp_ctx);
5000 		ret = samdb_reference_dn(ldb, tmp_ctx, *fsmo_role_dn, "fSMORoleOwner", role_owner_dn);
5001 		if (ret != LDB_SUCCESS) {
5002 			DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Naming Master object - %s",
5003 				 ldb_errstring(ldb)));
5004 			talloc_free(tmp_ctx);
5005 			return WERR_DS_DRA_INTERNAL_ERROR;
5006 		}
5007 		break;
5008 	case DREPL_INFRASTRUCTURE_MASTER:
5009 		*fsmo_role_dn = samdb_infrastructure_dn(ldb, tmp_ctx);
5010 		ret = samdb_reference_dn(ldb, tmp_ctx, *fsmo_role_dn, "fSMORoleOwner", role_owner_dn);
5011 		if (ret != LDB_SUCCESS) {
5012 			DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Schema Master object - %s",
5013 				 ldb_errstring(ldb)));
5014 			talloc_free(tmp_ctx);
5015 			return WERR_DS_DRA_INTERNAL_ERROR;
5016 		}
5017 		break;
5018 	case DREPL_RID_MASTER:
5019 		ret = samdb_rid_manager_dn(ldb, tmp_ctx, fsmo_role_dn);
5020 		if (ret != LDB_SUCCESS) {
5021 			DEBUG(0, (__location__ ": Failed to find RID Manager object - %s", ldb_errstring(ldb)));
5022 			talloc_free(tmp_ctx);
5023 			return WERR_DS_DRA_INTERNAL_ERROR;
5024 		}
5025 
5026 		ret = samdb_reference_dn(ldb, tmp_ctx, *fsmo_role_dn, "fSMORoleOwner", role_owner_dn);
5027 		if (ret != LDB_SUCCESS) {
5028 			DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in RID Manager object - %s",
5029 				 ldb_errstring(ldb)));
5030 			talloc_free(tmp_ctx);
5031 			return WERR_DS_DRA_INTERNAL_ERROR;
5032 		}
5033 		break;
5034 	case DREPL_SCHEMA_MASTER:
5035 		*fsmo_role_dn = ldb_get_schema_basedn(ldb);
5036 		ret = samdb_reference_dn(ldb, tmp_ctx, *fsmo_role_dn, "fSMORoleOwner", role_owner_dn);
5037 		if (ret != LDB_SUCCESS) {
5038 			DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Schema Master object - %s",
5039 				 ldb_errstring(ldb)));
5040 			talloc_free(tmp_ctx);
5041 			return WERR_DS_DRA_INTERNAL_ERROR;
5042 		}
5043 		break;
5044 	case DREPL_PDC_MASTER:
5045 		*fsmo_role_dn = ldb_get_default_basedn(ldb);
5046 		ret = samdb_reference_dn(ldb, tmp_ctx, *fsmo_role_dn, "fSMORoleOwner", role_owner_dn);
5047 		if (ret != LDB_SUCCESS) {
5048 			DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Pd Master object - %s",
5049 				 ldb_errstring(ldb)));
5050 			talloc_free(tmp_ctx);
5051 			return WERR_DS_DRA_INTERNAL_ERROR;
5052 		}
5053 		break;
5054 	default:
5055 		return WERR_DS_DRA_INTERNAL_ERROR;
5056 	}
5057 	return WERR_OK;
5058 }
5059 
samdb_dn_to_dnshostname(struct ldb_context * ldb,TALLOC_CTX * mem_ctx,struct ldb_dn * server_dn)5060 const char *samdb_dn_to_dnshostname(struct ldb_context *ldb,
5061 				    TALLOC_CTX *mem_ctx,
5062 				    struct ldb_dn *server_dn)
5063 {
5064 	int ldb_ret;
5065 	struct ldb_result *res = NULL;
5066 	const char * const attrs[] = { "dNSHostName", NULL};
5067 
5068 	ldb_ret = ldb_search(ldb, mem_ctx, &res,
5069 			     server_dn,
5070 			     LDB_SCOPE_BASE,
5071 			     attrs, NULL);
5072 	if (ldb_ret != LDB_SUCCESS) {
5073 		DEBUG(4, ("Failed to find dNSHostName for dn %s, ldb error: %s",
5074 			  ldb_dn_get_linearized(server_dn), ldb_errstring(ldb)));
5075 		return NULL;
5076 	}
5077 
5078 	return ldb_msg_find_attr_as_string(res->msgs[0], "dNSHostName", NULL);
5079 }
5080 
5081 /*
5082   returns true if an attribute is in the filter,
5083   false otherwise, provided that attribute value is provided with the expression
5084 */
dsdb_attr_in_parse_tree(struct ldb_parse_tree * tree,const char * attr)5085 bool dsdb_attr_in_parse_tree(struct ldb_parse_tree *tree,
5086 			     const char *attr)
5087 {
5088        unsigned int i;
5089        switch (tree->operation) {
5090        case LDB_OP_AND:
5091        case LDB_OP_OR:
5092                for (i=0;i<tree->u.list.num_elements;i++) {
5093                        if (dsdb_attr_in_parse_tree(tree->u.list.elements[i],
5094                                                        attr))
5095                                return true;
5096                }
5097                return false;
5098        case LDB_OP_NOT:
5099                return dsdb_attr_in_parse_tree(tree->u.isnot.child, attr);
5100        case LDB_OP_EQUALITY:
5101        case LDB_OP_GREATER:
5102        case LDB_OP_LESS:
5103        case LDB_OP_APPROX:
5104                if (ldb_attr_cmp(tree->u.equality.attr, attr) == 0) {
5105                        return true;
5106                }
5107                return false;
5108        case LDB_OP_SUBSTRING:
5109                if (ldb_attr_cmp(tree->u.substring.attr, attr) == 0) {
5110                        return true;
5111                }
5112                return false;
5113        case LDB_OP_PRESENT:
5114 	       /* (attrname=*) is not filtered out */
5115                return false;
5116        case LDB_OP_EXTENDED:
5117                if (tree->u.extended.attr &&
5118                    ldb_attr_cmp(tree->u.extended.attr, attr) == 0) {
5119 		       return true;
5120                }
5121                return false;
5122        }
5123        return false;
5124 }
5125 
is_attr_in_list(const char * const * attrs,const char * attr)5126 bool is_attr_in_list(const char * const * attrs, const char *attr)
5127 {
5128 	unsigned int i;
5129 
5130 	for (i = 0; attrs[i]; i++) {
5131 		if (ldb_attr_cmp(attrs[i], attr) == 0)
5132 			return true;
5133 	}
5134 
5135 	return false;
5136 }
5137 
dsdb_werror_at(struct ldb_context * ldb,int ldb_ecode,WERROR werr,const char * location,const char * func,const char * reason)5138 int dsdb_werror_at(struct ldb_context *ldb, int ldb_ecode, WERROR werr,
5139 		   const char *location, const char *func,
5140 		   const char *reason)
5141 {
5142 	if (reason == NULL) {
5143 		reason = win_errstr(werr);
5144 	}
5145 	ldb_asprintf_errstring(ldb, "%08X: %s at %s:%s",
5146 			       W_ERROR_V(werr), reason, location, func);
5147 	return ldb_ecode;
5148 }
5149 
5150 /*
5151   map an ldb error code to an approximate NTSTATUS code
5152  */
dsdb_ldb_err_to_ntstatus(int err)5153 NTSTATUS dsdb_ldb_err_to_ntstatus(int err)
5154 {
5155 	switch (err) {
5156 	case LDB_SUCCESS:
5157 		return NT_STATUS_OK;
5158 
5159 	case LDB_ERR_PROTOCOL_ERROR:
5160 		return NT_STATUS_DEVICE_PROTOCOL_ERROR;
5161 
5162 	case LDB_ERR_TIME_LIMIT_EXCEEDED:
5163 		return NT_STATUS_IO_TIMEOUT;
5164 
5165 	case LDB_ERR_SIZE_LIMIT_EXCEEDED:
5166 		return NT_STATUS_BUFFER_TOO_SMALL;
5167 
5168 	case LDB_ERR_COMPARE_FALSE:
5169 	case LDB_ERR_COMPARE_TRUE:
5170 		return NT_STATUS_REVISION_MISMATCH;
5171 
5172 	case LDB_ERR_AUTH_METHOD_NOT_SUPPORTED:
5173 		return NT_STATUS_NOT_SUPPORTED;
5174 
5175 	case LDB_ERR_STRONG_AUTH_REQUIRED:
5176 	case LDB_ERR_CONFIDENTIALITY_REQUIRED:
5177 	case LDB_ERR_SASL_BIND_IN_PROGRESS:
5178 	case LDB_ERR_INAPPROPRIATE_AUTHENTICATION:
5179 	case LDB_ERR_INVALID_CREDENTIALS:
5180 	case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
5181 	case LDB_ERR_UNWILLING_TO_PERFORM:
5182 		return NT_STATUS_ACCESS_DENIED;
5183 
5184 	case LDB_ERR_NO_SUCH_OBJECT:
5185 		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5186 
5187 	case LDB_ERR_REFERRAL:
5188 	case LDB_ERR_NO_SUCH_ATTRIBUTE:
5189 		return NT_STATUS_NOT_FOUND;
5190 
5191 	case LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION:
5192 		return NT_STATUS_NOT_SUPPORTED;
5193 
5194 	case LDB_ERR_ADMIN_LIMIT_EXCEEDED:
5195 		return NT_STATUS_BUFFER_TOO_SMALL;
5196 
5197 	case LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE:
5198 	case LDB_ERR_INAPPROPRIATE_MATCHING:
5199 	case LDB_ERR_CONSTRAINT_VIOLATION:
5200 	case LDB_ERR_INVALID_ATTRIBUTE_SYNTAX:
5201 	case LDB_ERR_INVALID_DN_SYNTAX:
5202 	case LDB_ERR_NAMING_VIOLATION:
5203 	case LDB_ERR_OBJECT_CLASS_VIOLATION:
5204 	case LDB_ERR_NOT_ALLOWED_ON_NON_LEAF:
5205 	case LDB_ERR_NOT_ALLOWED_ON_RDN:
5206 		return NT_STATUS_INVALID_PARAMETER;
5207 
5208 	case LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS:
5209 	case LDB_ERR_ENTRY_ALREADY_EXISTS:
5210 		return NT_STATUS_ERROR_DS_OBJ_STRING_NAME_EXISTS;
5211 
5212 	case LDB_ERR_BUSY:
5213 		return NT_STATUS_NETWORK_BUSY;
5214 
5215 	case LDB_ERR_ALIAS_PROBLEM:
5216 	case LDB_ERR_ALIAS_DEREFERENCING_PROBLEM:
5217 	case LDB_ERR_UNAVAILABLE:
5218 	case LDB_ERR_LOOP_DETECT:
5219 	case LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED:
5220 	case LDB_ERR_AFFECTS_MULTIPLE_DSAS:
5221 	case LDB_ERR_OTHER:
5222 	case LDB_ERR_OPERATIONS_ERROR:
5223 		break;
5224 	}
5225 	return NT_STATUS_UNSUCCESSFUL;
5226 }
5227 
5228 
5229 /*
5230   create a new naming context that will hold a partial replica
5231  */
dsdb_create_partial_replica_NC(struct ldb_context * ldb,struct ldb_dn * dn)5232 int dsdb_create_partial_replica_NC(struct ldb_context *ldb,  struct ldb_dn *dn)
5233 {
5234 	TALLOC_CTX *tmp_ctx = talloc_new(ldb);
5235 	struct ldb_message *msg;
5236 	int ret;
5237 
5238 	msg = ldb_msg_new(tmp_ctx);
5239 	if (msg == NULL) {
5240 		talloc_free(tmp_ctx);
5241 		return ldb_oom(ldb);
5242 	}
5243 
5244 	msg->dn = dn;
5245 	ret = ldb_msg_add_string(msg, "objectClass", "top");
5246 	if (ret != LDB_SUCCESS) {
5247 		talloc_free(tmp_ctx);
5248 		return ldb_oom(ldb);
5249 	}
5250 
5251 	/* [MS-DRSR] implies that we should only add the 'top'
5252 	 * objectclass, but that would cause lots of problems with our
5253 	 * objectclass code as top is not structural, so we add
5254 	 * 'domainDNS' as well to keep things sane. We're expecting
5255 	 * this new NC to be of objectclass domainDNS after
5256 	 * replication anyway
5257 	 */
5258 	ret = ldb_msg_add_string(msg, "objectClass", "domainDNS");
5259 	if (ret != LDB_SUCCESS) {
5260 		talloc_free(tmp_ctx);
5261 		return ldb_oom(ldb);
5262 	}
5263 
5264 	ret = ldb_msg_add_fmt(msg, "instanceType", "%u",
5265 			      INSTANCE_TYPE_IS_NC_HEAD|
5266 			      INSTANCE_TYPE_NC_ABOVE|
5267 			      INSTANCE_TYPE_UNINSTANT);
5268 	if (ret != LDB_SUCCESS) {
5269 		talloc_free(tmp_ctx);
5270 		return ldb_oom(ldb);
5271 	}
5272 
5273 	ret = dsdb_add(ldb, msg, DSDB_MODIFY_PARTIAL_REPLICA);
5274 	if (ret != LDB_SUCCESS && ret != LDB_ERR_ENTRY_ALREADY_EXISTS) {
5275 		DEBUG(0,("Failed to create new NC for %s - %s (%s)\n",
5276 			 ldb_dn_get_linearized(dn),
5277 			 ldb_errstring(ldb), ldb_strerror(ret)));
5278 		talloc_free(tmp_ctx);
5279 		return ret;
5280 	}
5281 
5282 	DEBUG(1,("Created new NC for %s\n", ldb_dn_get_linearized(dn)));
5283 
5284 	talloc_free(tmp_ctx);
5285 	return LDB_SUCCESS;
5286 }
5287 
5288 /*
5289  * Return the effective badPwdCount
5290  *
5291  * This requires that the user_msg have (if present):
5292  *  - badPasswordTime
5293  *  - badPwdCount
5294  *
5295  * This also requires that the domain_msg have (if present):
5296  *  - lockOutObservationWindow
5297  */
dsdb_effective_badPwdCount(const struct ldb_message * user_msg,int64_t lockOutObservationWindow,NTTIME now)5298 static int dsdb_effective_badPwdCount(const struct ldb_message *user_msg,
5299 				      int64_t lockOutObservationWindow,
5300 				      NTTIME now)
5301 {
5302 	int64_t badPasswordTime;
5303 	badPasswordTime = ldb_msg_find_attr_as_int64(user_msg, "badPasswordTime", 0);
5304 
5305 	if (badPasswordTime - lockOutObservationWindow >= now) {
5306 		return ldb_msg_find_attr_as_int(user_msg, "badPwdCount", 0);
5307 	} else {
5308 		return 0;
5309 	}
5310 }
5311 
5312 /*
5313  * Returns a user's PSO, or NULL if none was found
5314  */
lookup_user_pso(struct ldb_context * sam_ldb,TALLOC_CTX * mem_ctx,const struct ldb_message * user_msg,const char * const * attrs)5315 static struct ldb_result *lookup_user_pso(struct ldb_context *sam_ldb,
5316 					  TALLOC_CTX *mem_ctx,
5317 					  const struct ldb_message *user_msg,
5318 					  const char * const *attrs)
5319 {
5320 	struct ldb_result *res = NULL;
5321 	struct ldb_dn *pso_dn = NULL;
5322 	int ret;
5323 
5324 	/* if the user has a PSO that applies, then use the PSO's setting */
5325 	pso_dn = ldb_msg_find_attr_as_dn(sam_ldb, mem_ctx, user_msg,
5326 					 "msDS-ResultantPSO");
5327 
5328 	if (pso_dn != NULL) {
5329 
5330 		ret = dsdb_search_dn(sam_ldb, mem_ctx, &res, pso_dn, attrs, 0);
5331 		if (ret != LDB_SUCCESS) {
5332 
5333 			/*
5334 			 * log the error. The caller should fallback to using
5335 			 * the default domain password settings
5336 			 */
5337 			DBG_ERR("Error retrieving msDS-ResultantPSO %s for %s",
5338 				ldb_dn_get_linearized(pso_dn),
5339 				ldb_dn_get_linearized(user_msg->dn));
5340 		}
5341 		talloc_free(pso_dn);
5342 	}
5343 	return res;
5344 }
5345 
5346 /*
5347  * Return the effective badPwdCount
5348  *
5349  * This requires that the user_msg have (if present):
5350  *  - badPasswordTime
5351  *  - badPwdCount
5352  *  - msDS-ResultantPSO
5353  */
samdb_result_effective_badPwdCount(struct ldb_context * sam_ldb,TALLOC_CTX * mem_ctx,struct ldb_dn * domain_dn,const struct ldb_message * user_msg)5354 int samdb_result_effective_badPwdCount(struct ldb_context *sam_ldb,
5355 				       TALLOC_CTX *mem_ctx,
5356 				       struct ldb_dn *domain_dn,
5357 				       const struct ldb_message *user_msg)
5358 {
5359 	struct timeval tv_now = timeval_current();
5360 	NTTIME now = timeval_to_nttime(&tv_now);
5361 	int64_t lockOutObservationWindow;
5362 	struct ldb_result *res = NULL;
5363 	const char *attrs[] = { "msDS-LockoutObservationWindow",
5364 				NULL };
5365 
5366 	res = lookup_user_pso(sam_ldb, mem_ctx, user_msg, attrs);
5367 
5368 	if (res != NULL) {
5369 		lockOutObservationWindow =
5370 			ldb_msg_find_attr_as_int64(res->msgs[0],
5371 						   "msDS-LockoutObservationWindow",
5372 						    DEFAULT_OBSERVATION_WINDOW);
5373 		talloc_free(res);
5374 	} else {
5375 
5376 		/* no PSO was found, lookup the default domain setting */
5377 		lockOutObservationWindow =
5378 			 samdb_search_int64(sam_ldb, mem_ctx, 0, domain_dn,
5379 					    "lockOutObservationWindow", NULL);
5380 	}
5381 
5382 	return dsdb_effective_badPwdCount(user_msg, lockOutObservationWindow, now);
5383 }
5384 
5385 /*
5386  * Returns the lockoutThreshold that applies. If a PSO is specified, then that
5387  * setting is used over the domain defaults
5388  */
get_lockout_threshold(struct ldb_message * domain_msg,struct ldb_message * pso_msg)5389 static int64_t get_lockout_threshold(struct ldb_message *domain_msg,
5390 				     struct ldb_message *pso_msg)
5391 {
5392 	if (pso_msg != NULL) {
5393 		return ldb_msg_find_attr_as_int(pso_msg,
5394 						"msDS-LockoutThreshold", 0);
5395 	} else {
5396 		return ldb_msg_find_attr_as_int(domain_msg,
5397 						"lockoutThreshold", 0);
5398 	}
5399 }
5400 
5401 /*
5402  * Returns the lockOutObservationWindow that applies. If a PSO is specified,
5403  * then that setting is used over the domain defaults
5404  */
get_lockout_observation_window(struct ldb_message * domain_msg,struct ldb_message * pso_msg)5405 static int64_t get_lockout_observation_window(struct ldb_message *domain_msg,
5406 					      struct ldb_message *pso_msg)
5407 {
5408 	if (pso_msg != NULL) {
5409 		return ldb_msg_find_attr_as_int64(pso_msg,
5410 						  "msDS-LockoutObservationWindow",
5411 						   DEFAULT_OBSERVATION_WINDOW);
5412 	} else {
5413 		return ldb_msg_find_attr_as_int64(domain_msg,
5414 						  "lockOutObservationWindow",
5415 						   DEFAULT_OBSERVATION_WINDOW);
5416 	}
5417 }
5418 
5419 /*
5420  * Prepare an update to the badPwdCount and associated attributes.
5421  *
5422  * This requires that the user_msg have (if present):
5423  *  - objectSid
5424  *  - badPasswordTime
5425  *  - badPwdCount
5426  *
5427  * This also requires that the domain_msg have (if present):
5428  *  - pwdProperties
5429  *  - lockoutThreshold
5430  *  - lockOutObservationWindow
5431  *
5432  * This also requires that the pso_msg have (if present):
5433  *  - msDS-LockoutThreshold
5434  *  - msDS-LockoutObservationWindow
5435  */
dsdb_update_bad_pwd_count(TALLOC_CTX * mem_ctx,struct ldb_context * sam_ctx,struct ldb_message * user_msg,struct ldb_message * domain_msg,struct ldb_message * pso_msg,struct ldb_message ** _mod_msg)5436 NTSTATUS dsdb_update_bad_pwd_count(TALLOC_CTX *mem_ctx,
5437 				   struct ldb_context *sam_ctx,
5438 				   struct ldb_message *user_msg,
5439 				   struct ldb_message *domain_msg,
5440 				   struct ldb_message *pso_msg,
5441 				   struct ldb_message **_mod_msg)
5442 {
5443 	int ret, badPwdCount;
5444 	unsigned int i;
5445 	int64_t lockoutThreshold, lockOutObservationWindow;
5446 	struct dom_sid *sid;
5447 	struct timeval tv_now = timeval_current();
5448 	NTTIME now = timeval_to_nttime(&tv_now);
5449 	NTSTATUS status;
5450 	uint32_t pwdProperties, rid = 0;
5451 	struct ldb_message *mod_msg;
5452 
5453 	sid = samdb_result_dom_sid(mem_ctx, user_msg, "objectSid");
5454 
5455 	pwdProperties = ldb_msg_find_attr_as_uint(domain_msg,
5456 						  "pwdProperties", -1);
5457 	if (sid && !(pwdProperties & DOMAIN_PASSWORD_LOCKOUT_ADMINS)) {
5458 		status = dom_sid_split_rid(NULL, sid, NULL, &rid);
5459 		if (!NT_STATUS_IS_OK(status)) {
5460 			/*
5461 			 * This can't happen anyway, but always try
5462 			 * and update the badPwdCount on failure
5463 			 */
5464 			rid = 0;
5465 		}
5466 	}
5467 	TALLOC_FREE(sid);
5468 
5469 	/*
5470 	 * Work out if we are doing password lockout on the domain.
5471 	 * Also, the built in administrator account is exempt:
5472 	 * http://msdn.microsoft.com/en-us/library/windows/desktop/aa375371%28v=vs.85%29.aspx
5473 	 */
5474 	lockoutThreshold = get_lockout_threshold(domain_msg, pso_msg);
5475 	if (lockoutThreshold == 0 || (rid == DOMAIN_RID_ADMINISTRATOR)) {
5476 		DEBUG(5, ("Not updating badPwdCount on %s after wrong password\n",
5477 			  ldb_dn_get_linearized(user_msg->dn)));
5478 		return NT_STATUS_OK;
5479 	}
5480 
5481 	mod_msg = ldb_msg_new(mem_ctx);
5482 	if (mod_msg == NULL) {
5483 		return NT_STATUS_NO_MEMORY;
5484 	}
5485 	mod_msg->dn = ldb_dn_copy(mod_msg, user_msg->dn);
5486 	if (mod_msg->dn == NULL) {
5487 		TALLOC_FREE(mod_msg);
5488 		return NT_STATUS_NO_MEMORY;
5489 	}
5490 
5491 	lockOutObservationWindow = get_lockout_observation_window(domain_msg,
5492 								  pso_msg);
5493 
5494 	badPwdCount = dsdb_effective_badPwdCount(user_msg, lockOutObservationWindow, now);
5495 
5496 	badPwdCount++;
5497 
5498 	ret = samdb_msg_add_int(sam_ctx, mod_msg, mod_msg, "badPwdCount", badPwdCount);
5499 	if (ret != LDB_SUCCESS) {
5500 		TALLOC_FREE(mod_msg);
5501 		return NT_STATUS_NO_MEMORY;
5502 	}
5503 	ret = samdb_msg_add_int64(sam_ctx, mod_msg, mod_msg, "badPasswordTime", now);
5504 	if (ret != LDB_SUCCESS) {
5505 		TALLOC_FREE(mod_msg);
5506 		return NT_STATUS_NO_MEMORY;
5507 	}
5508 
5509 	if (badPwdCount >= lockoutThreshold) {
5510 		ret = samdb_msg_add_int64(sam_ctx, mod_msg, mod_msg, "lockoutTime", now);
5511 		if (ret != LDB_SUCCESS) {
5512 			TALLOC_FREE(mod_msg);
5513 			return NT_STATUS_NO_MEMORY;
5514 		}
5515 		DEBUGC( DBGC_AUTH, 1, ("Locked out user %s after %d wrong passwords\n",
5516 			  ldb_dn_get_linearized(user_msg->dn), badPwdCount));
5517 	} else {
5518 		DEBUGC( DBGC_AUTH, 5, ("Updated badPwdCount on %s after %d wrong passwords\n",
5519 			  ldb_dn_get_linearized(user_msg->dn), badPwdCount));
5520 	}
5521 
5522 	/* mark all the message elements as LDB_FLAG_MOD_REPLACE */
5523 	for (i=0; i< mod_msg->num_elements; i++) {
5524 		mod_msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
5525 	}
5526 
5527 	*_mod_msg = mod_msg;
5528 	return NT_STATUS_OK;
5529 }
5530 
5531 /**
5532  * Sets defaults for a User object
5533  * List of default attributes set:
5534  * 	accountExpires, badPasswordTime, badPwdCount,
5535  * 	codePage, countryCode, lastLogoff, lastLogon
5536  * 	logonCount, pwdLastSet
5537  */
dsdb_user_obj_set_defaults(struct ldb_context * ldb,struct ldb_message * usr_obj,struct ldb_request * req)5538 int dsdb_user_obj_set_defaults(struct ldb_context *ldb,
5539 			       struct ldb_message *usr_obj,
5540 			       struct ldb_request *req)
5541 {
5542 	size_t i;
5543 	int ret;
5544 	const struct attribute_values {
5545 		const char *name;
5546 		const char *value;
5547 		const char *add_value;
5548 		const char *mod_value;
5549 		const char *control;
5550 		unsigned add_flags;
5551 		unsigned mod_flags;
5552 	} map[] = {
5553 		{
5554 			.name = "accountExpires",
5555 			.add_value = "9223372036854775807",
5556 			.mod_value = "0",
5557 		},
5558 		{
5559 			.name = "badPasswordTime",
5560 			.value = "0"
5561 		},
5562 		{
5563 			.name = "badPwdCount",
5564 			.value = "0"
5565 		},
5566 		{
5567 			.name = "codePage",
5568 			.value = "0"
5569 		},
5570 		{
5571 			.name = "countryCode",
5572 			.value = "0"
5573 		},
5574 		{
5575 			.name = "lastLogoff",
5576 			.value = "0"
5577 		},
5578 		{
5579 			.name = "lastLogon",
5580 			.value = "0"
5581 		},
5582 		{
5583 			.name = "logonCount",
5584 			.value = "0"
5585 		},
5586 		{
5587 			.name = "logonHours",
5588 			.add_flags = DSDB_FLAG_INTERNAL_FORCE_META_DATA,
5589 		},
5590 		{
5591 			.name = "pwdLastSet",
5592 			.value = "0",
5593 			.control = DSDB_CONTROL_PASSWORD_DEFAULT_LAST_SET_OID,
5594 		},
5595 		{
5596 			.name = "adminCount",
5597 			.mod_value = "0",
5598 		},
5599 		{
5600 			.name = "operatorCount",
5601 			.mod_value = "0",
5602 		},
5603 	};
5604 
5605 	for (i = 0; i < ARRAY_SIZE(map); i++) {
5606 		bool added = false;
5607 		const char *value = NULL;
5608 		unsigned flags = 0;
5609 
5610 		if (req != NULL && req->operation == LDB_ADD) {
5611 			value = map[i].add_value;
5612 			flags = map[i].add_flags;
5613 		} else {
5614 			value = map[i].mod_value;
5615 			flags = map[i].mod_flags;
5616 		}
5617 
5618 		if (value == NULL) {
5619 			value = map[i].value;
5620 		}
5621 
5622 		if (value != NULL) {
5623 			flags |= LDB_FLAG_MOD_ADD;
5624 		}
5625 
5626 		if (flags == 0) {
5627 			continue;
5628 		}
5629 
5630 		ret = samdb_find_or_add_attribute_ex(ldb, usr_obj,
5631 						     map[i].name,
5632 						     value, flags,
5633 						     &added);
5634 		if (ret != LDB_SUCCESS) {
5635 			return ret;
5636 		}
5637 
5638 		if (req != NULL && added && map[i].control != NULL) {
5639 			ret = ldb_request_add_control(req,
5640 						      map[i].control,
5641 						      false, NULL);
5642 			if (ret != LDB_SUCCESS) {
5643 				return ret;
5644 			}
5645 		}
5646 	}
5647 
5648 	return LDB_SUCCESS;
5649 }
5650 
5651 /**
5652  * Sets 'sAMAccountType on user object based on userAccountControl
5653  * @param ldb Current ldb_context
5654  * @param usr_obj ldb_message representing User object
5655  * @param user_account_control Value for userAccountControl flags
5656  * @param account_type_p Optional pointer to account_type to return
5657  * @return LDB_SUCCESS or LDB_ERR* code on failure
5658  */
dsdb_user_obj_set_account_type(struct ldb_context * ldb,struct ldb_message * usr_obj,uint32_t user_account_control,uint32_t * account_type_p)5659 int dsdb_user_obj_set_account_type(struct ldb_context *ldb, struct ldb_message *usr_obj,
5660 				   uint32_t user_account_control, uint32_t *account_type_p)
5661 {
5662 	int ret;
5663 	uint32_t account_type;
5664 	struct ldb_message_element *el;
5665 
5666 	account_type = ds_uf2atype(user_account_control);
5667 	if (account_type == 0) {
5668 		ldb_set_errstring(ldb, "dsdb: Unrecognized account type!");
5669 		return LDB_ERR_UNWILLING_TO_PERFORM;
5670 	}
5671 	ret = samdb_msg_add_uint(ldb, usr_obj, usr_obj,
5672 				 "sAMAccountType",
5673 				 account_type);
5674 	if (ret != LDB_SUCCESS) {
5675 		return ret;
5676 	}
5677 	el = ldb_msg_find_element(usr_obj, "sAMAccountType");
5678 	el->flags = LDB_FLAG_MOD_REPLACE;
5679 
5680 	if (account_type_p) {
5681 		*account_type_p = account_type;
5682 	}
5683 
5684 	return LDB_SUCCESS;
5685 }
5686 
5687 /**
5688  * Determine and set primaryGroupID based on userAccountControl value
5689  * @param ldb Current ldb_context
5690  * @param usr_obj ldb_message representing User object
5691  * @param user_account_control Value for userAccountControl flags
5692  * @param group_rid_p Optional pointer to group RID to return
5693  * @return LDB_SUCCESS or LDB_ERR* code on failure
5694  */
dsdb_user_obj_set_primary_group_id(struct ldb_context * ldb,struct ldb_message * usr_obj,uint32_t user_account_control,uint32_t * group_rid_p)5695 int dsdb_user_obj_set_primary_group_id(struct ldb_context *ldb, struct ldb_message *usr_obj,
5696 				       uint32_t user_account_control, uint32_t *group_rid_p)
5697 {
5698 	int ret;
5699 	uint32_t rid;
5700 	struct ldb_message_element *el;
5701 
5702 	rid = ds_uf2prim_group_rid(user_account_control);
5703 
5704 	ret = samdb_msg_add_uint(ldb, usr_obj, usr_obj,
5705 				 "primaryGroupID", rid);
5706 	if (ret != LDB_SUCCESS) {
5707 		return ret;
5708 	}
5709 	el = ldb_msg_find_element(usr_obj, "primaryGroupID");
5710 	el->flags = LDB_FLAG_MOD_REPLACE;
5711 
5712 	if (group_rid_p) {
5713 		*group_rid_p = rid;
5714 	}
5715 
5716 	return LDB_SUCCESS;
5717 }
5718 
5719 /**
5720  * Returns True if the source and target DNs both have the same naming context,
5721  * i.e. they're both in the same partition.
5722  */
dsdb_objects_have_same_nc(struct ldb_context * ldb,TALLOC_CTX * mem_ctx,struct ldb_dn * source_dn,struct ldb_dn * target_dn)5723 bool dsdb_objects_have_same_nc(struct ldb_context *ldb,
5724 			       TALLOC_CTX *mem_ctx,
5725 			       struct ldb_dn *source_dn,
5726 			       struct ldb_dn *target_dn)
5727 {
5728 	TALLOC_CTX *tmp_ctx;
5729 	struct ldb_dn *source_nc = NULL;
5730 	struct ldb_dn *target_nc = NULL;
5731 	int ret;
5732 	bool same_nc = true;
5733 
5734 	tmp_ctx = talloc_new(mem_ctx);
5735 
5736 	ret = dsdb_find_nc_root(ldb, tmp_ctx, source_dn, &source_nc);
5737 	/* fix clang warning */
5738 	if (source_nc == NULL) {
5739 		ret = LDB_ERR_OTHER;
5740 	}
5741 	if (ret != LDB_SUCCESS) {
5742 		DBG_ERR("Failed to find base DN for source %s\n",
5743 			ldb_dn_get_linearized(source_dn));
5744 		talloc_free(tmp_ctx);
5745 		return true;
5746 	}
5747 
5748 	ret = dsdb_find_nc_root(ldb, tmp_ctx, target_dn, &target_nc);
5749 	/* fix clang warning */
5750 	if (target_nc == NULL) {
5751 		ret = LDB_ERR_OTHER;
5752 	}
5753 	if (ret != LDB_SUCCESS) {
5754 		DBG_ERR("Failed to find base DN for target %s\n",
5755 			ldb_dn_get_linearized(target_dn));
5756 		talloc_free(tmp_ctx);
5757 		return true;
5758 	}
5759 
5760 	same_nc = (ldb_dn_compare(source_nc, target_nc) == 0);
5761 
5762 	talloc_free(tmp_ctx);
5763 
5764 	return same_nc;
5765 }
5766 /*
5767  * Context for dsdb_count_domain_callback
5768  */
5769 struct dsdb_count_domain_context {
5770 	/*
5771 	 * Number of matching records
5772 	 */
5773 	size_t count;
5774 	/*
5775 	 * sid of the domain that the records must belong to.
5776 	 * if NULL records can belong to any domain.
5777 	 */
5778 	struct dom_sid *dom_sid;
5779 };
5780 
5781 /*
5782  * @brief ldb aysnc callback for dsdb_domain_count.
5783  *
5784  * count the number of records in the database matching an LDAP query,
5785  * optionally filtering for domain membership.
5786  *
5787  * @param [in,out] req the ldb request being processed
5788  *                    req->context contains:
5789  *                        count   The number of matching records
5790  *                        dom_sid The domain sid, if present records must belong
5791  *                                to the domain to be counted.
5792  *@param [in,out] ares The query result.
5793  *
5794  * @return an LDB error code
5795  *
5796  */
dsdb_count_domain_callback(struct ldb_request * req,struct ldb_reply * ares)5797 static int dsdb_count_domain_callback(
5798 	struct ldb_request *req,
5799 	struct ldb_reply *ares)
5800 {
5801 
5802 	if (ares == NULL) {
5803 		return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
5804 	}
5805 	if (ares->error != LDB_SUCCESS) {
5806 		int error = ares->error;
5807 		TALLOC_FREE(ares);
5808 		return ldb_request_done(req, error);
5809 	}
5810 
5811 	switch (ares->type) {
5812 	case LDB_REPLY_ENTRY:
5813 	{
5814 		struct dsdb_count_domain_context *context = NULL;
5815 		ssize_t ret;
5816 		bool in_domain;
5817 		struct dom_sid sid;
5818 		const struct ldb_val *v;
5819 
5820 		context = req->context;
5821 		if (context->dom_sid == NULL) {
5822 			context->count++;
5823 			break;
5824 		}
5825 
5826 		v = ldb_msg_find_ldb_val(ares->message, "objectSid");
5827 		if (v == NULL) {
5828 			break;
5829 		}
5830 
5831 		ret = sid_parse(v->data, v->length, &sid);
5832 		if (ret == -1) {
5833 			break;
5834 		}
5835 
5836 		in_domain = dom_sid_in_domain(context->dom_sid, &sid);
5837 		if (!in_domain) {
5838 			break;
5839 		}
5840 
5841 		context->count++;
5842 		break;
5843 	}
5844 	case LDB_REPLY_REFERRAL:
5845 		break;
5846 
5847 	case LDB_REPLY_DONE:
5848 		TALLOC_FREE(ares);
5849 		return ldb_request_done(req, LDB_SUCCESS);
5850 	}
5851 
5852 	TALLOC_FREE(ares);
5853 
5854 	return LDB_SUCCESS;
5855 }
5856 
5857 /*
5858  * @brief Count the number of records matching a query.
5859  *
5860  * Count the number of entries in the database matching the supplied query,
5861  * optionally filtering only those entries belonging to the supplied domain.
5862  *
5863  * @param ldb [in] Current ldb context
5864  * @param count [out] Pointer to the count
5865  * @param base [in] The base dn for the quey
5866  * @param dom_sid [in] The domain sid, if non NULL records that are not a member
5867  *                     of the domain are ignored.
5868  * @param scope [in] Search scope.
5869  * @param exp_fmt [in] format string for the query.
5870  *
5871  * @return LDB_STATUS code.
5872  */
dsdb_domain_count(struct ldb_context * ldb,size_t * count,struct ldb_dn * base,struct dom_sid * dom_sid,enum ldb_scope scope,const char * exp_fmt,...)5873 int dsdb_domain_count(
5874 	struct ldb_context *ldb,
5875 	size_t *count,
5876 	struct ldb_dn *base,
5877 	struct dom_sid *dom_sid,
5878 	enum ldb_scope scope,
5879 	const char *exp_fmt, ...)
5880 {
5881 	TALLOC_CTX *tmp_ctx = NULL;
5882 	struct ldb_request *req = NULL;
5883 	struct dsdb_count_domain_context *context = NULL;
5884 	char *expression = NULL;
5885 	const char *object_sid[] = {"objectSid", NULL};
5886 	const char *none[] = {NULL};
5887 	va_list ap;
5888 	int ret;
5889 
5890 	*count = 0;
5891 	tmp_ctx = talloc_new(ldb);
5892 
5893 	context = talloc_zero(tmp_ctx, struct dsdb_count_domain_context);
5894 	if (context == NULL) {
5895 		return LDB_ERR_OPERATIONS_ERROR;
5896 	}
5897 	context->dom_sid = dom_sid;
5898 
5899 	if (exp_fmt) {
5900 		va_start(ap, exp_fmt);
5901 		expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
5902 		va_end(ap);
5903 
5904 		if (expression == NULL) {
5905 			TALLOC_FREE(context);
5906 			TALLOC_FREE(tmp_ctx);
5907 			return LDB_ERR_OPERATIONS_ERROR;
5908 		}
5909 	}
5910 
5911 	ret = ldb_build_search_req(
5912 		&req,
5913 		ldb,
5914 		tmp_ctx,
5915 		base,
5916 		scope,
5917 		expression,
5918 		(dom_sid == NULL) ? none : object_sid,
5919 		NULL,
5920 		context,
5921 		dsdb_count_domain_callback,
5922 		NULL);
5923 	ldb_req_set_location(req, "dsdb_domain_count");
5924 
5925 	if (ret != LDB_SUCCESS) goto done;
5926 
5927 	ret = ldb_request(ldb, req);
5928 
5929 	if (ret == LDB_SUCCESS) {
5930 		ret = ldb_wait(req->handle, LDB_WAIT_ALL);
5931 		if (ret == LDB_SUCCESS) {
5932 			*count = context->count;
5933 		}
5934 	}
5935 
5936 
5937 done:
5938 	TALLOC_FREE(expression);
5939 	TALLOC_FREE(req);
5940 	TALLOC_FREE(context);
5941 	TALLOC_FREE(tmp_ctx);
5942 
5943 	return ret;
5944 }
5945