• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src/router/samba-3.5.8/source4/dsdb/samdb/ldb_modules/
1/*
2   SAM ldb module
3
4   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
5   Copyright (C) Simo Sorce  2004-2008
6   Copyright (C) Matthias Dieter Wallnöfer 2009
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 3 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program.  If not, see <http://www.gnu.org/licenses/>.
20*/
21
22/*
23 *  Name: ldb
24 *
25 *  Component: ldb samldb module
26 *
27 *  Description: add embedded user/group creation functionality
28 *
29 *  Author: Simo Sorce
30 */
31
32#include "includes.h"
33#include "libcli/ldap/ldap_ndr.h"
34#include "ldb_module.h"
35#include "dsdb/samdb/samdb.h"
36#include "libcli/security/security.h"
37#include "librpc/gen_ndr/ndr_security.h"
38#include "../lib/util/util_ldb.h"
39#include "ldb_wrap.h"
40
41struct samldb_ctx;
42
43typedef int (*samldb_step_fn_t)(struct samldb_ctx *);
44
45struct samldb_step {
46	struct samldb_step *next;
47	samldb_step_fn_t fn;
48};
49
50struct samldb_ctx {
51	struct ldb_module *module;
52	struct ldb_request *req;
53
54	/* used for add operations */
55	const char *type;
56
57	/* the resulting message */
58	struct ldb_message *msg;
59
60	/* used to find parent domain */
61	struct ldb_dn *check_dn;
62	struct ldb_dn *domain_dn;
63	struct dom_sid *domain_sid;
64	uint32_t next_rid;
65
66	/* holds the entry SID */
67	struct dom_sid *sid;
68
69	/* holds a generic dn */
70	struct ldb_dn *dn;
71
72	/* used in conjunction with "sid" in "samldb_dn_from_sid" */
73	struct ldb_dn *res_dn;
74
75	/* used in conjunction with "dn" in "samldb_sid_from_dn" */
76	struct dom_sid *res_sid;
77
78	/* used in "samldb_user_dn_to_prim_group_rid" */
79	uint32_t prim_group_rid;
80
81	/* used in conjunction with "prim_group_rid" in
82	 * "samldb_prim_group_rid_to_users_cnt" */
83	unsigned int users_cnt;
84
85	/* used in "samldb_group_add_member" and "samldb_group_del_member" */
86	struct ldb_dn *group_dn;
87	struct ldb_dn *member_dn;
88
89	/* used in "samldb_primary_group_change" */
90	struct ldb_dn *user_dn;
91	struct ldb_dn *old_prim_group_dn, *new_prim_group_dn;
92
93	/* generic counter - used in "samldb_member_check" */
94	unsigned int cnt;
95
96	/* all the async steps necessary to complete the operation */
97	struct samldb_step *steps;
98	struct samldb_step *curstep;
99};
100
101static struct samldb_ctx *samldb_ctx_init(struct ldb_module *module,
102					  struct ldb_request *req)
103{
104	struct ldb_context *ldb;
105	struct samldb_ctx *ac;
106
107	ldb = ldb_module_get_ctx(module);
108
109	ac = talloc_zero(req, struct samldb_ctx);
110	if (ac == NULL) {
111		ldb_oom(ldb);
112		return NULL;
113	}
114
115	ac->module = module;
116	ac->req = req;
117
118	return ac;
119}
120
121static int samldb_add_step(struct samldb_ctx *ac, samldb_step_fn_t fn)
122{
123	struct samldb_step *step, *stepper;
124
125	step = talloc_zero(ac, struct samldb_step);
126	if (step == NULL) {
127		return LDB_ERR_OPERATIONS_ERROR;
128	}
129
130	step->fn = fn;
131
132	if (ac->steps == NULL) {
133		ac->steps = step;
134		ac->curstep = step;
135	} else {
136		if (ac->curstep == NULL)
137			return LDB_ERR_OPERATIONS_ERROR;
138		for (stepper = ac->curstep; stepper->next != NULL;
139			stepper = stepper->next);
140		stepper->next = step;
141	}
142
143	return LDB_SUCCESS;
144}
145
146static int samldb_first_step(struct samldb_ctx *ac)
147{
148	if (ac->steps == NULL) {
149		return LDB_ERR_OPERATIONS_ERROR;
150	}
151
152	ac->curstep = ac->steps;
153	return ac->curstep->fn(ac);
154}
155
156static int samldb_next_step(struct samldb_ctx *ac)
157{
158	if (ac->curstep->next) {
159		ac->curstep = ac->curstep->next;
160		return ac->curstep->fn(ac);
161	}
162
163	/* it is an error if the last step does not properly
164	 * return to the upper module by itself */
165	return LDB_ERR_OPERATIONS_ERROR;
166}
167
168/*
169 * samldb_get_parent_domain (async)
170 */
171
172static int samldb_get_parent_domain(struct samldb_ctx *ac);
173
174static int samldb_get_parent_domain_callback(struct ldb_request *req,
175					     struct ldb_reply *ares)
176{
177	struct ldb_context *ldb;
178	struct samldb_ctx *ac;
179	const char *nextRid;
180	int ret;
181
182	ac = talloc_get_type(req->context, struct samldb_ctx);
183	ldb = ldb_module_get_ctx(ac->module);
184
185	if (!ares) {
186		ret = LDB_ERR_OPERATIONS_ERROR;
187		goto done;
188	}
189	if (ares->error != LDB_SUCCESS) {
190		return ldb_module_done(ac->req, ares->controls,
191					ares->response, ares->error);
192	}
193
194	switch (ares->type) {
195	case LDB_REPLY_ENTRY:
196		/* save entry */
197		if ((ac->domain_dn != NULL) || (ac->domain_sid != NULL)) {
198			/* one too many! */
199			ldb_set_errstring(ldb,
200				"Invalid number of results while searching "
201				"for domain object!");
202			ret = LDB_ERR_OPERATIONS_ERROR;
203			break;
204		}
205
206		nextRid = ldb_msg_find_attr_as_string(ares->message,
207						      "nextRid", NULL);
208		if (nextRid == NULL) {
209			ldb_asprintf_errstring(ldb,
210				"While looking for domain above %s attribute nextRid not found in %s!\n",
211				ldb_dn_get_linearized(
212					ac->req->op.add.message->dn),
213				ldb_dn_get_linearized(ares->message->dn));
214			ret = LDB_ERR_OPERATIONS_ERROR;
215			break;
216		}
217
218		ac->next_rid = strtol(nextRid, NULL, 0);
219
220		ac->domain_sid = samdb_result_dom_sid(ac, ares->message,
221								"objectSid");
222		if (ac->domain_sid == NULL) {
223			ldb_set_errstring(ldb,
224				"Unable to get the parent domain SID!\n");
225			ret = LDB_ERR_CONSTRAINT_VIOLATION;
226			break;
227		}
228		ac->domain_dn = ldb_dn_copy(ac, ares->message->dn);
229
230		talloc_free(ares);
231		ret = LDB_SUCCESS;
232		break;
233
234	case LDB_REPLY_REFERRAL:
235		/* ignore */
236		talloc_free(ares);
237		ret = LDB_SUCCESS;
238		break;
239
240	case LDB_REPLY_DONE:
241		talloc_free(ares);
242		if ((ac->domain_dn == NULL) || (ac->domain_sid == NULL)) {
243			/* not found -> retry */
244			ret = samldb_get_parent_domain(ac);
245		} else {
246			/* found, go on */
247			ret = samldb_next_step(ac);
248		}
249		break;
250	}
251
252done:
253	if (ret != LDB_SUCCESS) {
254		return ldb_module_done(ac->req, NULL, NULL, ret);
255	}
256
257	return LDB_SUCCESS;
258}
259
260/* Find a domain object in the parents of a particular DN.  */
261static int samldb_get_parent_domain(struct samldb_ctx *ac)
262{
263	struct ldb_context *ldb;
264	static const char * const attrs[] = { "objectSid", "nextRid", NULL };
265	struct ldb_request *req;
266	struct ldb_dn *dn;
267	int ret;
268
269	ldb = ldb_module_get_ctx(ac->module);
270
271	if (ac->check_dn == NULL) {
272		return LDB_ERR_OPERATIONS_ERROR;
273	}
274
275	dn = ldb_dn_get_parent(ac, ac->check_dn);
276	if (dn == NULL) {
277		ldb_set_errstring(ldb,
278			"Unable to find parent domain object!");
279		return LDB_ERR_CONSTRAINT_VIOLATION;
280	}
281
282	ac->check_dn = dn;
283
284	ret = ldb_build_search_req(&req, ldb, ac,
285				   dn, LDB_SCOPE_BASE,
286				   "(|(objectClass=domain)"
287				     "(objectClass=builtinDomain)"
288				     "(objectClass=samba4LocalDomain))",
289				   attrs,
290				   NULL,
291				   ac, samldb_get_parent_domain_callback,
292				   ac->req);
293
294	if (ret != LDB_SUCCESS) {
295		return ret;
296	}
297
298	return ldb_next_request(ac->module, req);
299}
300
301
302static int samldb_generate_samAccountName(struct ldb_message *msg)
303{
304	char *name;
305
306	/* Format: $000000-000000000000 */
307
308	name = talloc_asprintf(msg, "$%.6X-%.6X%.6X",
309				(unsigned int)generate_random(),
310				(unsigned int)generate_random(),
311				(unsigned int)generate_random());
312	if (name == NULL) {
313		return LDB_ERR_OPERATIONS_ERROR;
314	}
315	return ldb_msg_add_steal_string(msg, "samAccountName", name);
316}
317
318/*
319 * samldb_check_samAccountName (async)
320 */
321
322static int samldb_check_samAccountName_callback(struct ldb_request *req,
323						struct ldb_reply *ares)
324{
325	struct samldb_ctx *ac;
326	int ret;
327
328	ac = talloc_get_type(req->context, struct samldb_ctx);
329
330	if (ares->error != LDB_SUCCESS) {
331		return ldb_module_done(ac->req, ares->controls,
332                                       ares->response, ares->error);
333	}
334
335	switch (ares->type) {
336	case LDB_REPLY_ENTRY:
337		/* if we get an entry it means this samAccountName
338		 * already exists */
339		return ldb_module_done(ac->req, NULL, NULL,
340                                       LDB_ERR_ENTRY_ALREADY_EXISTS);
341
342	case LDB_REPLY_REFERRAL:
343		/* this should not happen */
344		return ldb_module_done(ac->req, NULL, NULL,
345                                       LDB_ERR_OPERATIONS_ERROR);
346
347	case LDB_REPLY_DONE:
348		/* not found, go on */
349		talloc_free(ares);
350		ret = samldb_next_step(ac);
351		break;
352	}
353
354	if (ret != LDB_SUCCESS) {
355		return ldb_module_done(ac->req, NULL, NULL, ret);
356	}
357
358	return LDB_SUCCESS;
359}
360
361static int samldb_check_samAccountName(struct samldb_ctx *ac)
362{
363	struct ldb_context *ldb;
364	struct ldb_request *req;
365	const char *name;
366	char *filter;
367        int ret;
368
369	ldb = ldb_module_get_ctx(ac->module);
370
371        if (ldb_msg_find_element(ac->msg, "samAccountName") == NULL) {
372                ret = samldb_generate_samAccountName(ac->msg);
373                if (ret != LDB_SUCCESS) {
374                        return ret;
375                }
376        }
377
378	name = ldb_msg_find_attr_as_string(ac->msg, "samAccountName", NULL);
379	if (name == NULL) {
380		return LDB_ERR_OPERATIONS_ERROR;
381	}
382	filter = talloc_asprintf(ac, "samAccountName=%s", ldb_binary_encode_string(ac, name));
383	if (filter == NULL) {
384		return LDB_ERR_OPERATIONS_ERROR;
385	}
386
387	ret = ldb_build_search_req(&req, ldb, ac,
388				   ac->domain_dn, LDB_SCOPE_SUBTREE,
389				   filter, NULL,
390				   NULL,
391				   ac, samldb_check_samAccountName_callback,
392				   ac->req);
393	talloc_free(filter);
394	if (ret != LDB_SUCCESS) {
395		return ret;
396	}
397	return ldb_next_request(ac->module, req);
398}
399
400
401static int samldb_check_samAccountType(struct samldb_ctx *ac)
402{
403	struct ldb_context *ldb;
404	unsigned int account_type;
405	unsigned int group_type;
406	unsigned int uac;
407	int ret;
408
409	ldb = ldb_module_get_ctx(ac->module);
410
411	/* make sure sAMAccountType is not specified */
412	if (ldb_msg_find_element(ac->msg, "sAMAccountType") != NULL) {
413		ldb_asprintf_errstring(ldb,
414			"sAMAccountType must not be specified!");
415		return LDB_ERR_UNWILLING_TO_PERFORM;
416	}
417
418	if (strcmp("user", ac->type) == 0) {
419		uac = samdb_result_uint(ac->msg, "userAccountControl", 0);
420		if (uac == 0) {
421			ldb_asprintf_errstring(ldb,
422				"userAccountControl invalid!");
423			return LDB_ERR_UNWILLING_TO_PERFORM;
424		} else {
425			account_type = ds_uf2atype(uac);
426			ret = samdb_msg_add_uint(ldb,
427						 ac->msg, ac->msg,
428						 "sAMAccountType",
429						 account_type);
430			if (ret != LDB_SUCCESS) {
431				return ret;
432			}
433		}
434	} else
435	if (strcmp("group", ac->type) == 0) {
436
437		group_type = samdb_result_uint(ac->msg, "groupType", 0);
438		if (group_type == 0) {
439			ldb_asprintf_errstring(ldb,
440				"groupType invalid!");
441			return LDB_ERR_UNWILLING_TO_PERFORM;
442		} else {
443			account_type = ds_gtype2atype(group_type);
444			ret = samdb_msg_add_uint(ldb,
445						 ac->msg, ac->msg,
446						 "sAMAccountType",
447						 account_type);
448			if (ret != LDB_SUCCESS) {
449				return ret;
450			}
451		}
452	}
453
454	return samldb_next_step(ac);
455}
456
457
458/*
459 * samldb_get_sid_domain (async)
460 */
461
462static int samldb_get_sid_domain_callback(struct ldb_request *req,
463					  struct ldb_reply *ares)
464{
465	struct ldb_context *ldb;
466	struct samldb_ctx *ac;
467	const char *nextRid;
468	int ret;
469
470	ac = talloc_get_type(req->context, struct samldb_ctx);
471	ldb = ldb_module_get_ctx(ac->module);
472
473	if (!ares) {
474		ret = LDB_ERR_OPERATIONS_ERROR;
475		goto done;
476	}
477	if (ares->error != LDB_SUCCESS) {
478		return ldb_module_done(ac->req, ares->controls,
479					ares->response, ares->error);
480	}
481
482	switch (ares->type) {
483	case LDB_REPLY_ENTRY:
484		/* save entry */
485		if (ac->next_rid != 0) {
486			/* one too many! */
487			ldb_set_errstring(ldb,
488				"Invalid number of results while searching "
489				"for domain object!");
490			ret = LDB_ERR_OPERATIONS_ERROR;
491			break;
492		}
493
494		nextRid = ldb_msg_find_attr_as_string(ares->message,
495							"nextRid", NULL);
496		if (nextRid == NULL) {
497			ldb_asprintf_errstring(ldb,
498				"Attribute nextRid not found in %s!\n",
499				ldb_dn_get_linearized(ares->message->dn));
500			ret = LDB_ERR_OPERATIONS_ERROR;
501			break;
502		}
503
504		ac->next_rid = strtol(nextRid, NULL, 0);
505
506		ac->domain_dn = ldb_dn_copy(ac, ares->message->dn);
507
508		talloc_free(ares);
509		ret = LDB_SUCCESS;
510		break;
511
512	case LDB_REPLY_REFERRAL:
513		/* ignore */
514		talloc_free(ares);
515		ret = LDB_SUCCESS;
516		break;
517
518	case LDB_REPLY_DONE:
519		talloc_free(ares);
520		if (ac->next_rid == 0) {
521			ldb_asprintf_errstring(ldb,
522				"Unable to get nextRid from domain entry!\n");
523			ret = LDB_ERR_OPERATIONS_ERROR;
524			break;
525		}
526
527		/* found, go on */
528		ret = samldb_next_step(ac);
529		break;
530	}
531
532done:
533	if (ret != LDB_SUCCESS) {
534		return ldb_module_done(ac->req, NULL, NULL, ret);
535	}
536
537	return LDB_SUCCESS;
538}
539
540/* Find a domain object in the parents of a particular DN.  */
541static int samldb_get_sid_domain(struct samldb_ctx *ac)
542{
543	struct ldb_context *ldb;
544	static const char * const attrs[2] = { "nextRid", NULL };
545	struct ldb_request *req;
546	char *filter;
547	int ret;
548
549	ldb = ldb_module_get_ctx(ac->module);
550
551	if (ac->sid == NULL) {
552		return LDB_ERR_OPERATIONS_ERROR;
553	}
554
555	ac->domain_sid = dom_sid_dup(ac, ac->sid);
556	if (!ac->domain_sid) {
557		return LDB_ERR_OPERATIONS_ERROR;
558	}
559	/* get the domain component part of the provided SID */
560	ac->domain_sid->num_auths--;
561
562	filter = talloc_asprintf(ac, "(&(objectSid=%s)"
563				       "(|(objectClass=domain)"
564				         "(objectClass=builtinDomain)"
565				         "(objectClass=samba4LocalDomain)))",
566				 ldap_encode_ndr_dom_sid(ac, ac->domain_sid));
567	if (filter == NULL) {
568		return LDB_ERR_OPERATIONS_ERROR;
569	}
570
571	ret = ldb_build_search_req(&req, ldb, ac,
572				   ldb_get_default_basedn(ldb),
573				   LDB_SCOPE_SUBTREE,
574				   filter, attrs,
575				   NULL,
576				   ac, samldb_get_sid_domain_callback,
577				   ac->req);
578
579	if (ret != LDB_SUCCESS) {
580		return ret;
581	}
582
583	ac->next_rid = 0;
584	return ldb_next_request(ac->module, req);
585}
586
587/*
588 * samldb_dn_from_sid (async)
589 */
590
591static int samldb_dn_from_sid(struct samldb_ctx *ac);
592
593static int samldb_dn_from_sid_callback(struct ldb_request *req,
594	struct ldb_reply *ares)
595{
596	struct ldb_context *ldb;
597	struct samldb_ctx *ac;
598	int ret;
599
600	ac = talloc_get_type(req->context, struct samldb_ctx);
601	ldb = ldb_module_get_ctx(ac->module);
602
603	if (!ares) {
604		ret = LDB_ERR_OPERATIONS_ERROR;
605		goto done;
606	}
607	if (ares->error != LDB_SUCCESS) {
608		return ldb_module_done(ac->req, ares->controls,
609					ares->response, ares->error);
610	}
611
612	switch (ares->type) {
613	case LDB_REPLY_ENTRY:
614		/* save entry */
615		if (ac->res_dn != NULL) {
616			/* one too many! */
617			ldb_set_errstring(ldb,
618				"Invalid number of results while searching "
619				"for domain objects!");
620			ret = LDB_ERR_OPERATIONS_ERROR;
621			break;
622		}
623		ac->res_dn = ldb_dn_copy(ac, ares->message->dn);
624
625		talloc_free(ares);
626		ret = LDB_SUCCESS;
627		break;
628
629	case LDB_REPLY_REFERRAL:
630		/* ignore */
631		talloc_free(ares);
632		ret = LDB_SUCCESS;
633		break;
634
635	case LDB_REPLY_DONE:
636		talloc_free(ares);
637
638		/* found or not found, go on */
639		ret = samldb_next_step(ac);
640		break;
641	}
642
643done:
644	if (ret != LDB_SUCCESS) {
645		return ldb_module_done(ac->req, NULL, NULL, ret);
646	}
647
648	return LDB_SUCCESS;
649}
650
651/* Finds the DN "res_dn" of an object with a given SID "sid" */
652static int samldb_dn_from_sid(struct samldb_ctx *ac)
653{
654	struct ldb_context *ldb;
655	static const char * const attrs[] = { NULL };
656	struct ldb_request *req;
657	char *filter;
658	int ret;
659
660	ldb = ldb_module_get_ctx(ac->module);
661
662	if (ac->sid == NULL)
663		return LDB_ERR_OPERATIONS_ERROR;
664
665	filter = talloc_asprintf(ac, "(objectSid=%s)",
666		ldap_encode_ndr_dom_sid(ac, ac->sid));
667	if (filter == NULL)
668		return LDB_ERR_OPERATIONS_ERROR;
669
670	ret = ldb_build_search_req(&req, ldb, ac,
671				ldb_get_default_basedn(ldb),
672				LDB_SCOPE_SUBTREE,
673				filter, attrs,
674				NULL,
675				ac, samldb_dn_from_sid_callback,
676				ac->req);
677	if (ret != LDB_SUCCESS)
678		return ret;
679
680	return ldb_next_request(ac->module, req);
681}
682
683
684static int samldb_check_primaryGroupID_1(struct samldb_ctx *ac)
685{
686	struct ldb_context *ldb;
687	uint32_t rid;
688
689	ldb = ldb_module_get_ctx(ac->module);
690
691	rid = samdb_result_uint(ac->msg, "primaryGroupID", ~0);
692	ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
693	if (ac->sid == NULL)
694		return LDB_ERR_OPERATIONS_ERROR;
695	ac->res_dn = NULL;
696
697	return samldb_next_step(ac);
698}
699
700static int samldb_check_primaryGroupID_2(struct samldb_ctx *ac)
701{
702	if (ac->res_dn == NULL)
703		return LDB_ERR_UNWILLING_TO_PERFORM;
704
705	return samldb_next_step(ac);
706}
707
708
709static bool samldb_msg_add_sid(struct ldb_message *msg,
710				const char *name,
711				const struct dom_sid *sid)
712{
713	struct ldb_val v;
714	enum ndr_err_code ndr_err;
715
716	ndr_err = ndr_push_struct_blob(&v, msg, NULL, sid,
717				       (ndr_push_flags_fn_t)ndr_push_dom_sid);
718	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
719		return false;
720	}
721	return (ldb_msg_add_value(msg, name, &v, NULL) == 0);
722}
723
724static int samldb_new_sid(struct samldb_ctx *ac)
725{
726
727	if (ac->domain_sid == NULL || ac->next_rid == 0) {
728		return LDB_ERR_OPERATIONS_ERROR;
729	}
730
731	ac->sid = dom_sid_add_rid(ac, ac->domain_sid, ac->next_rid + 1);
732	if (ac->sid == NULL) {
733		return LDB_ERR_OPERATIONS_ERROR;
734	}
735
736	if ( ! samldb_msg_add_sid(ac->msg, "objectSid", ac->sid)) {
737		return LDB_ERR_OPERATIONS_ERROR;
738	}
739
740	return samldb_next_step(ac);
741}
742
743/*
744 * samldb_notice_sid_callback (async)
745 */
746
747static int samldb_notice_sid_callback(struct ldb_request *req,
748					struct ldb_reply *ares)
749{
750	struct ldb_context *ldb;
751	struct samldb_ctx *ac;
752	int ret;
753
754	ac = talloc_get_type(req->context, struct samldb_ctx);
755	ldb = ldb_module_get_ctx(ac->module);
756
757	if (!ares) {
758		ret = LDB_ERR_OPERATIONS_ERROR;
759		goto done;
760	}
761	if (ares->error != LDB_SUCCESS) {
762		return ldb_module_done(ac->req, ares->controls,
763					ares->response, ares->error);
764	}
765	if (ares->type != LDB_REPLY_DONE) {
766		ldb_set_errstring(ldb,
767			"Invalid reply type!\n");
768		ret = LDB_ERR_OPERATIONS_ERROR;
769		goto done;
770	}
771
772	ret = samldb_next_step(ac);
773
774done:
775	if (ret != LDB_SUCCESS) {
776		return ldb_module_done(ac->req, NULL, NULL, ret);
777	}
778
779	return LDB_SUCCESS;
780}
781
782/* If we are adding new users/groups, we need to update the nextRid
783 * attribute to be 'above' the new/incoming RID. Attempt to do it
784 * atomically. */
785static int samldb_notice_sid(struct samldb_ctx *ac)
786{
787	struct ldb_context *ldb;
788	uint32_t old_id, new_id;
789	struct ldb_request *req;
790	struct ldb_message *msg;
791	struct ldb_message_element *els;
792	struct ldb_val *vals;
793	int ret;
794
795	ldb = ldb_module_get_ctx(ac->module);
796	old_id = ac->next_rid;
797	new_id = ac->sid->sub_auths[ac->sid->num_auths - 1];
798
799	if (old_id >= new_id) {
800		/* no need to update the domain nextRid attribute */
801		return samldb_next_step(ac);
802	}
803
804	/* we do a delete and add as a single operation. That prevents
805	   a race, in case we are not actually on a transaction db */
806	msg = ldb_msg_new(ac);
807	if (msg == NULL) {
808		ldb_oom(ldb);
809		return LDB_ERR_OPERATIONS_ERROR;
810	}
811	els = talloc_array(msg, struct ldb_message_element, 2);
812	if (els == NULL) {
813		ldb_oom(ldb);
814		return LDB_ERR_OPERATIONS_ERROR;
815	}
816	vals = talloc_array(msg, struct ldb_val, 2);
817	if (vals == NULL) {
818		ldb_oom(ldb);
819		return LDB_ERR_OPERATIONS_ERROR;
820	}
821	msg->dn = ac->domain_dn;
822	msg->num_elements = 2;
823	msg->elements = els;
824
825	els[0].num_values = 1;
826	els[0].values = &vals[0];
827	els[0].flags = LDB_FLAG_MOD_DELETE;
828	els[0].name = talloc_strdup(msg, "nextRid");
829	if (!els[0].name) {
830		ldb_oom(ldb);
831		return LDB_ERR_OPERATIONS_ERROR;
832	}
833
834	els[1].num_values = 1;
835	els[1].values = &vals[1];
836	els[1].flags = LDB_FLAG_MOD_ADD;
837	els[1].name = els[0].name;
838
839	vals[0].data = (uint8_t *)talloc_asprintf(vals, "%u", old_id);
840	if (!vals[0].data) {
841		ldb_oom(ldb);
842		return LDB_ERR_OPERATIONS_ERROR;
843	}
844	vals[0].length = strlen((char *)vals[0].data);
845
846	vals[1].data = (uint8_t *)talloc_asprintf(vals, "%u", new_id);
847	if (!vals[1].data) {
848		ldb_oom(ldb);
849		return LDB_ERR_OPERATIONS_ERROR;
850	}
851	vals[1].length = strlen((char *)vals[1].data);
852
853	ret = ldb_build_mod_req(&req, ldb, ac,
854				msg, NULL,
855				ac, samldb_notice_sid_callback,
856				ac->req);
857	if (ret != LDB_SUCCESS) {
858		return ret;
859	}
860
861	return ldb_next_request(ac->module, req);
862}
863
864/*
865 * samldb_add_entry (async)
866 */
867
868static int samldb_add_entry_callback(struct ldb_request *req,
869					struct ldb_reply *ares)
870{
871	struct ldb_context *ldb;
872	struct samldb_ctx *ac;
873
874	ac = talloc_get_type(req->context, struct samldb_ctx);
875	ldb = ldb_module_get_ctx(ac->module);
876
877	if (!ares) {
878		return ldb_module_done(ac->req, NULL, NULL,
879					LDB_ERR_OPERATIONS_ERROR);
880	}
881	if (ares->error != LDB_SUCCESS) {
882		return ldb_module_done(ac->req, ares->controls,
883					ares->response, ares->error);
884	}
885	if (ares->type != LDB_REPLY_DONE) {
886		ldb_set_errstring(ldb,
887			"Invalid reply type!\n");
888		return ldb_module_done(ac->req, NULL, NULL,
889					LDB_ERR_OPERATIONS_ERROR);
890	}
891
892	/* we exit the samldb module here */
893	return ldb_module_done(ac->req, ares->controls,
894				ares->response, LDB_SUCCESS);
895}
896
897static int samldb_add_entry(struct samldb_ctx *ac)
898{
899	struct ldb_context *ldb;
900	struct ldb_request *req;
901	int ret;
902
903	ldb = ldb_module_get_ctx(ac->module);
904
905	ret = ldb_build_add_req(&req, ldb, ac,
906				ac->msg,
907				ac->req->controls,
908				ac, samldb_add_entry_callback,
909				ac->req);
910	if (ret != LDB_SUCCESS) {
911		return ret;
912	}
913
914	return ldb_next_request(ac->module, req);
915}
916
917
918static int samldb_fill_object(struct samldb_ctx *ac, const char *type)
919{
920	struct ldb_context *ldb;
921	int ret;
922
923	ldb = ldb_module_get_ctx(ac->module);
924
925	/* search for a parent domain objet */
926	ac->check_dn = ac->req->op.add.message->dn;
927	ret = samldb_add_step(ac, samldb_get_parent_domain);
928	if (ret != LDB_SUCCESS) return ret;
929
930	/* Add informations for the different account types */
931	ac->type = type;
932	if (strcmp(ac->type, "user") == 0) {
933		ret = samdb_find_or_add_attribute(ldb, ac->msg,
934			"userAccountControl", "546");
935		if (ret != LDB_SUCCESS) return ret;
936		ret = samdb_find_or_add_attribute(ldb, ac->msg,
937			"badPwdCount", "0");
938		if (ret != LDB_SUCCESS) return ret;
939		ret = samdb_find_or_add_attribute(ldb, ac->msg,
940			"codePage", "0");
941		if (ret != LDB_SUCCESS) return ret;
942		ret = samdb_find_or_add_attribute(ldb, ac->msg,
943			"countryCode", "0");
944		if (ret != LDB_SUCCESS) return ret;
945		ret = samdb_find_or_add_attribute(ldb, ac->msg,
946			"badPasswordTime", "0");
947		if (ret != LDB_SUCCESS) return ret;
948		ret = samdb_find_or_add_attribute(ldb, ac->msg,
949			"lastLogoff", "0");
950		if (ret != LDB_SUCCESS) return ret;
951		ret = samdb_find_or_add_attribute(ldb, ac->msg,
952			"lastLogon", "0");
953		if (ret != LDB_SUCCESS) return ret;
954		ret = samdb_find_or_add_attribute(ldb, ac->msg,
955			"pwdLastSet", "0");
956		if (ret != LDB_SUCCESS) return ret;
957		ret = samdb_find_or_add_attribute(ldb, ac->msg,
958			"primaryGroupID", "513");
959		if (ret != LDB_SUCCESS) return ret;
960		ret = samdb_find_or_add_attribute(ldb, ac->msg,
961			"accountExpires", "9223372036854775807");
962		if (ret != LDB_SUCCESS) return ret;
963		ret = samdb_find_or_add_attribute(ldb, ac->msg,
964			"logonCount", "0");
965		if (ret != LDB_SUCCESS) return ret;
966	} else if (strcmp(ac->type, "group") == 0) {
967		ret = samdb_find_or_add_attribute(ldb, ac->msg,
968			"groupType", "-2147483646");
969		if (ret != LDB_SUCCESS) return ret;
970	} else {
971		/* we should only have "user" and "group" */
972		ldb_asprintf_errstring(ldb,
973			"Invalid entry type!\n");
974		return LDB_ERR_OPERATIONS_ERROR;
975	}
976
977	/* check if we have a valid samAccountName */
978	ret = samldb_add_step(ac, samldb_check_samAccountName);
979	if (ret != LDB_SUCCESS) return ret;
980
981	/* check account_type/group_type */
982	ret = samldb_add_step(ac, samldb_check_samAccountType);
983	if (ret != LDB_SUCCESS) return ret;
984
985	/* check if we have a valid primary group ID */
986	if (strcmp(ac->type, "user") == 0) {
987		ret = samldb_add_step(ac, samldb_check_primaryGroupID_1);
988		if (ret != LDB_SUCCESS) return ret;
989		ret = samldb_add_step(ac, samldb_dn_from_sid);
990		if (ret != LDB_SUCCESS) return ret;
991		ret = samldb_add_step(ac, samldb_check_primaryGroupID_2);
992		if (ret != LDB_SUCCESS) return ret;
993	}
994
995	/* check if we have a valid SID */
996	ac->sid = samdb_result_dom_sid(ac, ac->msg, "objectSid");
997	if ( ! ac->sid) {
998		ret = samldb_add_step(ac, samldb_new_sid);
999		if (ret != LDB_SUCCESS) return ret;
1000	} else {
1001		ret = samldb_add_step(ac, samldb_get_sid_domain);
1002		if (ret != LDB_SUCCESS) return ret;
1003	}
1004
1005	ret = samldb_add_step(ac, samldb_notice_sid);
1006	if (ret != LDB_SUCCESS) return ret;
1007
1008	/* finally proceed with adding the entry */
1009	ret = samldb_add_step(ac, samldb_add_entry);
1010	if (ret != LDB_SUCCESS) return ret;
1011
1012	return samldb_first_step(ac);
1013}
1014
1015/*
1016 * samldb_foreign_notice_sid (async)
1017 */
1018
1019static int samldb_foreign_notice_sid_callback(struct ldb_request *req,
1020						struct ldb_reply *ares)
1021{
1022	struct ldb_context *ldb;
1023	struct samldb_ctx *ac;
1024	const char *nextRid;
1025	const char *name;
1026	int ret;
1027
1028	ac = talloc_get_type(req->context, struct samldb_ctx);
1029	ldb = ldb_module_get_ctx(ac->module);
1030
1031	if (!ares) {
1032		ret = LDB_ERR_OPERATIONS_ERROR;
1033		goto done;
1034	}
1035	if (ares->error != LDB_SUCCESS) {
1036		return ldb_module_done(ac->req, ares->controls,
1037					ares->response, ares->error);
1038	}
1039
1040	switch (ares->type) {
1041	case LDB_REPLY_ENTRY:
1042		/* save entry */
1043		if (ac->next_rid != 0) {
1044			/* one too many! */
1045			ldb_set_errstring(ldb,
1046				"Invalid number of results while searching "
1047				"for domain object!");
1048			ret = LDB_ERR_OPERATIONS_ERROR;
1049			break;
1050		}
1051
1052		nextRid = ldb_msg_find_attr_as_string(ares->message,
1053							"nextRid", NULL);
1054		if (nextRid == NULL) {
1055			ldb_asprintf_errstring(ldb,
1056				"while looking for forign sid %s attribute nextRid not found in %s\n",
1057				dom_sid_string(ares, ac->sid),
1058					ldb_dn_get_linearized(ares->message->dn));
1059			ret = LDB_ERR_OPERATIONS_ERROR;
1060			break;
1061		}
1062
1063		ac->next_rid = strtol(nextRid, NULL, 0);
1064
1065		ac->domain_dn = ldb_dn_copy(ac, ares->message->dn);
1066
1067		name = samdb_result_string(ares->message, "name", NULL);
1068		ldb_debug(ldb, LDB_DEBUG_TRACE,
1069			 "NOTE (strange but valid): Adding foreign SID "
1070			 "record with SID %s, but this domain (%s) is "
1071			 "not foreign in the database",
1072			 dom_sid_string(ares, ac->sid), name);
1073
1074		talloc_free(ares);
1075		ret = LDB_SUCCESS;
1076		break;
1077
1078	case LDB_REPLY_REFERRAL:
1079		/* ignore */
1080		talloc_free(ares);
1081		ret = LDB_SUCCESS;
1082		break;
1083
1084	case LDB_REPLY_DONE:
1085		talloc_free(ares);
1086
1087		/* if this is a fake foreign SID, notice the SID */
1088		if (ac->domain_dn) {
1089			ret = samldb_notice_sid(ac);
1090			break;
1091		}
1092
1093		/* found, go on */
1094		ret = samldb_next_step(ac);
1095		break;
1096	}
1097
1098done:
1099	if (ret != LDB_SUCCESS) {
1100		return ldb_module_done(ac->req, NULL, NULL, ret);
1101	}
1102
1103	return LDB_SUCCESS;
1104}
1105
1106/* Find a domain object in the parents of a particular DN. */
1107static int samldb_foreign_notice_sid(struct samldb_ctx *ac)
1108{
1109	struct ldb_context *ldb;
1110	static const char * const attrs[3] = { "nextRid", "name", NULL };
1111	struct ldb_request *req;
1112	NTSTATUS status;
1113	char *filter;
1114	int ret;
1115
1116	ldb = ldb_module_get_ctx(ac->module);
1117
1118	if (ac->sid == NULL) {
1119		return LDB_ERR_OPERATIONS_ERROR;
1120	}
1121
1122	status = dom_sid_split_rid(ac, ac->sid, &ac->domain_sid, NULL);
1123	if (!NT_STATUS_IS_OK(status)) {
1124		return LDB_ERR_OPERATIONS_ERROR;
1125	}
1126
1127	filter = talloc_asprintf(ac, "(&(objectSid=%s)(objectclass=domain))",
1128				 ldap_encode_ndr_dom_sid(ac, ac->domain_sid));
1129	if (filter == NULL) {
1130		return LDB_ERR_OPERATIONS_ERROR;
1131	}
1132
1133	ret = ldb_build_search_req(&req, ldb, ac,
1134				   ldb_get_default_basedn(ldb),
1135				   LDB_SCOPE_SUBTREE,
1136				   filter, attrs,
1137				   NULL,
1138				   ac, samldb_foreign_notice_sid_callback,
1139				   ac->req);
1140
1141	if (ret != LDB_SUCCESS) {
1142		return ret;
1143	}
1144
1145	return ldb_next_request(ac->module, req);
1146}
1147
1148
1149static int samldb_fill_foreignSecurityPrincipal_object(struct samldb_ctx *ac)
1150{
1151	struct ldb_context *ldb;
1152	int ret;
1153
1154	ldb = ldb_module_get_ctx(ac->module);
1155
1156	ac->next_rid = 0;
1157
1158	ac->sid = samdb_result_dom_sid(ac->msg, ac->msg, "objectSid");
1159	if (ac->sid == NULL) {
1160		ac->sid = dom_sid_parse_talloc(ac->msg,
1161			   (const char *)ldb_dn_get_rdn_val(ac->msg->dn)->data);
1162		if (!ac->sid) {
1163			ldb_set_errstring(ldb,
1164					"No valid SID found in "
1165					"ForeignSecurityPrincipal CN!");
1166			talloc_free(ac);
1167			return LDB_ERR_CONSTRAINT_VIOLATION;
1168		}
1169		if ( ! samldb_msg_add_sid(ac->msg, "objectSid", ac->sid)) {
1170			talloc_free(ac);
1171			return LDB_ERR_OPERATIONS_ERROR;
1172		}
1173	}
1174
1175	/* check if we need to notice this SID */
1176	ret = samldb_add_step(ac, samldb_foreign_notice_sid);
1177	if (ret != LDB_SUCCESS) return ret;
1178
1179	/* finally proceed with adding the entry */
1180	ret = samldb_add_step(ac, samldb_add_entry);
1181	if (ret != LDB_SUCCESS) return ret;
1182
1183	return samldb_first_step(ac);
1184}
1185
1186static int samldb_check_rdn(struct ldb_module *module, struct ldb_dn *dn)
1187{
1188	struct ldb_context *ldb;
1189	const char *rdn_name;
1190
1191	ldb = ldb_module_get_ctx(module);
1192	rdn_name = ldb_dn_get_rdn_name(dn);
1193
1194	if (strcasecmp(rdn_name, "cn") != 0) {
1195		ldb_asprintf_errstring(ldb,
1196					"Bad RDN (%s=) for samldb object, "
1197					"should be CN=!\n", rdn_name);
1198		return LDB_ERR_CONSTRAINT_VIOLATION;
1199	}
1200
1201	return LDB_SUCCESS;
1202}
1203
1204/*
1205 * samldb_sid_from_dn (async)
1206 */
1207
1208static int samldb_sid_from_dn(struct samldb_ctx *ac);
1209
1210static int samldb_sid_from_dn_callback(struct ldb_request *req,
1211	struct ldb_reply *ares)
1212{
1213	struct ldb_context *ldb;
1214	struct samldb_ctx *ac;
1215	int ret;
1216
1217	ac = talloc_get_type(req->context, struct samldb_ctx);
1218	ldb = ldb_module_get_ctx(ac->module);
1219
1220	if (!ares) {
1221		ret = LDB_ERR_OPERATIONS_ERROR;
1222		goto done;
1223	}
1224	if (ares->error != LDB_SUCCESS) {
1225		return ldb_module_done(ac->req, ares->controls,
1226					ares->response, ares->error);
1227	}
1228
1229	switch (ares->type) {
1230	case LDB_REPLY_ENTRY:
1231		/* save entry */
1232		if (ac->res_sid != NULL) {
1233			/* one too many! */
1234			ldb_set_errstring(ldb,
1235				"Invalid number of results while searching "
1236				"for domain objects!");
1237			ret = LDB_ERR_OPERATIONS_ERROR;
1238			break;
1239		}
1240		ac->res_sid = samdb_result_dom_sid(ac, ares->message,
1241			"objectSid");
1242
1243		talloc_free(ares);
1244		ret = LDB_SUCCESS;
1245		break;
1246
1247	case LDB_REPLY_REFERRAL:
1248		/* ignore */
1249		talloc_free(ares);
1250		ret = LDB_SUCCESS;
1251		break;
1252
1253	case LDB_REPLY_DONE:
1254		talloc_free(ares);
1255
1256		/* found or not found, go on */
1257		ret = samldb_next_step(ac);
1258		break;
1259	}
1260
1261done:
1262	if (ret != LDB_SUCCESS) {
1263		return ldb_module_done(ac->req, NULL, NULL, ret);
1264	}
1265
1266	return LDB_SUCCESS;
1267}
1268
1269/* Finds the SID "res_sid" of an object with a given DN "dn" */
1270static int samldb_sid_from_dn(struct samldb_ctx *ac)
1271{
1272	struct ldb_context *ldb;
1273	static const char * const attrs[] = { "objectSid" };
1274	struct ldb_request *req;
1275	int ret;
1276
1277	ldb = ldb_module_get_ctx(ac->module);
1278
1279	if (ac->dn == NULL)
1280		return LDB_ERR_OPERATIONS_ERROR;
1281
1282	ret = ldb_build_search_req(&req, ldb, ac,
1283				ac->dn,
1284				LDB_SCOPE_BASE,
1285				NULL, attrs,
1286				NULL,
1287				ac, samldb_sid_from_dn_callback,
1288				ac->req);
1289	if (ret != LDB_SUCCESS)
1290		return ret;
1291
1292	return ldb_next_request(ac->module, req);
1293}
1294
1295/*
1296 * samldb_user_dn_to_prim_group_rid (async)
1297 */
1298
1299static int samldb_user_dn_to_prim_group_rid(struct samldb_ctx *ac);
1300
1301static int samldb_user_dn_to_prim_group_rid_callback(struct ldb_request *req,
1302	struct ldb_reply *ares)
1303{
1304	struct ldb_context *ldb;
1305	struct samldb_ctx *ac;
1306	int ret;
1307
1308	ac = talloc_get_type(req->context, struct samldb_ctx);
1309	ldb = ldb_module_get_ctx(ac->module);
1310
1311	if (!ares) {
1312		ret = LDB_ERR_OPERATIONS_ERROR;
1313		goto done;
1314	}
1315	if (ares->error != LDB_SUCCESS) {
1316		return ldb_module_done(ac->req, ares->controls,
1317					ares->response, ares->error);
1318	}
1319
1320	switch (ares->type) {
1321	case LDB_REPLY_ENTRY:
1322		/* save entry */
1323		if (ac->prim_group_rid != 0) {
1324			/* one too many! */
1325			ldb_set_errstring(ldb,
1326				"Invalid number of results while searching "
1327				"for domain objects!");
1328			ret = LDB_ERR_OPERATIONS_ERROR;
1329			break;
1330		}
1331		ac->prim_group_rid = samdb_result_uint(ares->message,
1332			"primaryGroupID", ~0);
1333
1334		talloc_free(ares);
1335		ret = LDB_SUCCESS;
1336		break;
1337
1338	case LDB_REPLY_REFERRAL:
1339		/* ignore */
1340		talloc_free(ares);
1341		ret = LDB_SUCCESS;
1342		break;
1343
1344	case LDB_REPLY_DONE:
1345		talloc_free(ares);
1346		if (ac->prim_group_rid == 0) {
1347			ldb_asprintf_errstring(ldb,
1348				"Unable to get the primary group RID!\n");
1349			ret = LDB_ERR_OPERATIONS_ERROR;
1350			break;
1351		}
1352
1353		/* found, go on */
1354		ret = samldb_next_step(ac);
1355		break;
1356	}
1357
1358done:
1359	if (ret != LDB_SUCCESS) {
1360		return ldb_module_done(ac->req, NULL, NULL, ret);
1361	}
1362
1363	return LDB_SUCCESS;
1364}
1365
1366/* Locates the "primaryGroupID" attribute from a certain user specified as
1367 * "user_dn". Saves the result in "prim_group_rid". */
1368static int samldb_user_dn_to_prim_group_rid(struct samldb_ctx *ac)
1369{
1370	struct ldb_context *ldb;
1371	static const char * const attrs[] = { "primaryGroupID", NULL };
1372	struct ldb_request *req;
1373	int ret;
1374
1375	ldb = ldb_module_get_ctx(ac->module);
1376
1377	if (ac->user_dn == NULL)
1378		return LDB_ERR_OPERATIONS_ERROR;
1379
1380	ret = ldb_build_search_req(&req, ldb, ac,
1381				ac->user_dn,
1382				LDB_SCOPE_BASE,
1383				NULL, attrs,
1384				NULL,
1385				ac, samldb_user_dn_to_prim_group_rid_callback,
1386				ac->req);
1387	if (ret != LDB_SUCCESS)
1388		return ret;
1389
1390	return ldb_next_request(ac->module, req);
1391}
1392
1393/*
1394 * samldb_prim_group_rid_to_users_cnt (async)
1395 */
1396
1397static int samldb_prim_group_rid_to_users_cnt(struct samldb_ctx *ac);
1398
1399static int samldb_prim_group_rid_to_users_cnt_callback(struct ldb_request *req,
1400	struct ldb_reply *ares)
1401{
1402	struct ldb_context *ldb;
1403	struct samldb_ctx *ac;
1404	int ret;
1405
1406	ac = talloc_get_type(req->context, struct samldb_ctx);
1407	ldb = ldb_module_get_ctx(ac->module);
1408
1409	if (!ares) {
1410		ret = LDB_ERR_OPERATIONS_ERROR;
1411		goto done;
1412	}
1413	if (ares->error != LDB_SUCCESS) {
1414		return ldb_module_done(ac->req, ares->controls,
1415					ares->response, ares->error);
1416	}
1417
1418	switch (ares->type) {
1419	case LDB_REPLY_ENTRY:
1420		/* save entry */
1421		++(ac->users_cnt);
1422
1423		talloc_free(ares);
1424		ret = LDB_SUCCESS;
1425		break;
1426
1427	case LDB_REPLY_REFERRAL:
1428		/* ignore */
1429		talloc_free(ares);
1430		ret = LDB_SUCCESS;
1431		break;
1432
1433	case LDB_REPLY_DONE:
1434		talloc_free(ares);
1435
1436		/* found or not found, go on */
1437		ret = samldb_next_step(ac);
1438		break;
1439	}
1440
1441done:
1442	if (ret != LDB_SUCCESS) {
1443		return ldb_module_done(ac->req, NULL, NULL, ret);
1444	}
1445
1446	return LDB_SUCCESS;
1447}
1448
1449/* Finds the amount of users which have the primary group "prim_group_rid" and
1450 * save the result in "users_cnt" */
1451static int samldb_prim_group_rid_to_users_cnt(struct samldb_ctx *ac)
1452{
1453	struct ldb_context *ldb;
1454	static const char * const attrs[] = { NULL };
1455	struct ldb_request *req;
1456	char *filter;
1457	int ret;
1458
1459	ldb = ldb_module_get_ctx(ac->module);
1460
1461	if ((ac->prim_group_rid == 0) || (ac->users_cnt != 0))
1462		return LDB_ERR_OPERATIONS_ERROR;
1463
1464	filter = talloc_asprintf(ac, "(&(primaryGroupID=%u)(objectclass=user))",
1465		ac->prim_group_rid);
1466	if (filter == NULL)
1467		return LDB_ERR_OPERATIONS_ERROR;
1468
1469	ret = ldb_build_search_req(&req, ldb, ac,
1470				ldb_get_default_basedn(ldb),
1471				LDB_SCOPE_SUBTREE,
1472				filter, attrs,
1473				NULL,
1474				ac,
1475				samldb_prim_group_rid_to_users_cnt_callback,
1476				ac->req);
1477	if (ret != LDB_SUCCESS)
1478		return ret;
1479
1480	return ldb_next_request(ac->module, req);
1481}
1482
1483/*
1484 * samldb_group_add_member (async)
1485 * samldb_group_del_member (async)
1486 */
1487
1488static int samldb_group_add_del_member_callback(struct ldb_request *req,
1489	struct ldb_reply *ares)
1490{
1491	struct ldb_context *ldb;
1492	struct samldb_ctx *ac;
1493	int ret;
1494
1495	ac = talloc_get_type(req->context, struct samldb_ctx);
1496	ldb = ldb_module_get_ctx(ac->module);
1497
1498	if (!ares) {
1499		ret = LDB_ERR_OPERATIONS_ERROR;
1500		goto done;
1501	}
1502	if (ares->error != LDB_SUCCESS) {
1503		if (ares->error == LDB_ERR_NO_SUCH_ATTRIBUTE) {
1504			/* On error "NO_SUCH_ATTRIBUTE" (delete of an invalid
1505			 * "member" attribute) return "UNWILLING_TO_PERFORM" */
1506			ares->error = LDB_ERR_UNWILLING_TO_PERFORM;
1507		}
1508		return ldb_module_done(ac->req, ares->controls,
1509					ares->response, ares->error);
1510	}
1511	if (ares->type != LDB_REPLY_DONE) {
1512		ldb_set_errstring(ldb,
1513			"Invalid reply type!\n");
1514		ret = LDB_ERR_OPERATIONS_ERROR;
1515		goto done;
1516	}
1517
1518	ret = samldb_next_step(ac);
1519
1520done:
1521	if (ret != LDB_SUCCESS) {
1522		return ldb_module_done(ac->req, NULL, NULL, ret);
1523	}
1524
1525	return LDB_SUCCESS;
1526}
1527
1528/* Adds a member with DN "member_dn" to a group with DN "group_dn" */
1529static int samldb_group_add_member(struct samldb_ctx *ac)
1530{
1531	struct ldb_context *ldb;
1532	struct ldb_request *req;
1533	struct ldb_message *msg;
1534	int ret;
1535
1536	ldb = ldb_module_get_ctx(ac->module);
1537
1538	if ((ac->group_dn == NULL) || (ac->member_dn == NULL))
1539		return LDB_ERR_OPERATIONS_ERROR;
1540
1541	msg = ldb_msg_new(ac);
1542	msg->dn = ac->group_dn;
1543	samdb_msg_add_addval(ldb, ac, msg, "member",
1544		ldb_dn_get_linearized(ac->member_dn));
1545
1546	ret = ldb_build_mod_req(&req, ldb, ac,
1547				msg, NULL,
1548				ac, samldb_group_add_del_member_callback,
1549				ac->req);
1550	if (ret != LDB_SUCCESS)
1551		return ret;
1552
1553	return ldb_next_request(ac->module, req);
1554}
1555
1556/* Removes a member with DN "member_dn" from a group with DN "group_dn" */
1557static int samldb_group_del_member(struct samldb_ctx *ac)
1558{
1559	struct ldb_context *ldb;
1560	struct ldb_request *req;
1561	struct ldb_message *msg;
1562	int ret;
1563
1564	ldb = ldb_module_get_ctx(ac->module);
1565
1566	if ((ac->group_dn == NULL) || (ac->member_dn == NULL))
1567		return LDB_ERR_OPERATIONS_ERROR;
1568
1569	msg = ldb_msg_new(ac);
1570	msg->dn = ac->group_dn;
1571	samdb_msg_add_delval(ldb, ac, msg, "member",
1572		ldb_dn_get_linearized(ac->member_dn));
1573
1574	ret = ldb_build_mod_req(&req, ldb, ac,
1575				msg, NULL,
1576				ac, samldb_group_add_del_member_callback,
1577				ac->req);
1578	if (ret != LDB_SUCCESS)
1579		return ret;
1580
1581	return ldb_next_request(ac->module, req);
1582}
1583
1584
1585static int samldb_prim_group_change_1(struct samldb_ctx *ac)
1586{
1587	struct ldb_context *ldb;
1588	uint32_t rid;
1589
1590	ldb = ldb_module_get_ctx(ac->module);
1591
1592	ac->user_dn = ac->msg->dn;
1593
1594	rid = samdb_result_uint(ac->msg, "primaryGroupID", ~0);
1595	ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
1596	if (ac->sid == NULL)
1597		return LDB_ERR_OPERATIONS_ERROR;
1598	ac->res_dn = NULL;
1599
1600	ac->prim_group_rid = 0;
1601
1602	return samldb_next_step(ac);
1603}
1604
1605static int samldb_prim_group_change_2(struct samldb_ctx *ac)
1606{
1607	struct ldb_context *ldb;
1608
1609	ldb = ldb_module_get_ctx(ac->module);
1610
1611	if (ac->res_dn != NULL)
1612		ac->new_prim_group_dn = ac->res_dn;
1613	else
1614		return LDB_ERR_UNWILLING_TO_PERFORM;
1615
1616	ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb),
1617		ac->prim_group_rid);
1618	if (ac->sid == NULL)
1619		return LDB_ERR_OPERATIONS_ERROR;
1620	ac->res_dn = NULL;
1621
1622	return samldb_next_step(ac);
1623}
1624
1625static int samldb_prim_group_change_4(struct samldb_ctx *ac);
1626static int samldb_prim_group_change_5(struct samldb_ctx *ac);
1627static int samldb_prim_group_change_6(struct samldb_ctx *ac);
1628
1629static int samldb_prim_group_change_3(struct samldb_ctx *ac)
1630{
1631	int ret;
1632
1633	if (ac->res_dn != NULL)
1634		ac->old_prim_group_dn = ac->res_dn;
1635	else
1636		return LDB_ERR_UNWILLING_TO_PERFORM;
1637
1638	/* Only update when the primary group changed */
1639	if (ldb_dn_compare(ac->old_prim_group_dn, ac->new_prim_group_dn) != 0) {
1640		ac->member_dn = ac->user_dn;
1641		/* Remove the "member" attribute of the actual (new) primary
1642		 * group */
1643
1644		ret = samldb_add_step(ac, samldb_prim_group_change_4);
1645		if (ret != LDB_SUCCESS) return ret;
1646
1647		ret = samldb_add_step(ac, samldb_group_del_member);
1648		if (ret != LDB_SUCCESS) return ret;
1649
1650		/* Add a "member" attribute for the previous primary group */
1651
1652		ret = samldb_add_step(ac, samldb_prim_group_change_5);
1653		if (ret != LDB_SUCCESS) return ret;
1654
1655		ret = samldb_add_step(ac, samldb_group_add_member);
1656		if (ret != LDB_SUCCESS) return ret;
1657	}
1658
1659	ret = samldb_add_step(ac, samldb_prim_group_change_6);
1660	if (ret != LDB_SUCCESS) return ret;
1661
1662	return samldb_next_step(ac);
1663}
1664
1665static int samldb_prim_group_change_4(struct samldb_ctx *ac)
1666{
1667	ac->group_dn = ac->new_prim_group_dn;
1668
1669	return samldb_next_step(ac);
1670}
1671
1672static int samldb_prim_group_change_5(struct samldb_ctx *ac)
1673{
1674	ac->group_dn = ac->old_prim_group_dn;
1675
1676	return samldb_next_step(ac);
1677}
1678
1679static int samldb_prim_group_change_6(struct samldb_ctx *ac)
1680{
1681	return ldb_next_request(ac->module, ac->req);
1682}
1683
1684static int samldb_prim_group_change(struct samldb_ctx *ac)
1685{
1686	int ret;
1687
1688	/* Finds out the DN of the new primary group */
1689
1690	ret = samldb_add_step(ac, samldb_prim_group_change_1);
1691	if (ret != LDB_SUCCESS) return ret;
1692
1693	ret = samldb_add_step(ac, samldb_dn_from_sid);
1694	if (ret != LDB_SUCCESS) return ret;
1695
1696	ret = samldb_add_step(ac, samldb_user_dn_to_prim_group_rid);
1697	if (ret != LDB_SUCCESS) return ret;
1698
1699	/* Finds out the DN of the old primary group */
1700
1701	ret = samldb_add_step(ac, samldb_prim_group_change_2);
1702	if (ret != LDB_SUCCESS) return ret;
1703
1704	ret = samldb_add_step(ac, samldb_dn_from_sid);
1705	if (ret != LDB_SUCCESS) return ret;
1706
1707	ret = samldb_add_step(ac, samldb_prim_group_change_3);
1708	if (ret != LDB_SUCCESS) return ret;
1709
1710	return samldb_first_step(ac);
1711}
1712
1713
1714static int samldb_member_check_1(struct samldb_ctx *ac)
1715{
1716	struct ldb_context *ldb;
1717	struct ldb_message_element *el;
1718
1719	ldb = ldb_module_get_ctx(ac->module);
1720
1721	el = ldb_msg_find_element(ac->msg, "member");
1722
1723	ac->user_dn = ldb_dn_from_ldb_val(ac, ldb, &el->values[ac->cnt]);
1724	if (!ldb_dn_validate(ac->user_dn))
1725		return LDB_ERR_OPERATIONS_ERROR;
1726	ac->prim_group_rid = 0;
1727
1728	return samldb_next_step(ac);
1729}
1730
1731static int samldb_member_check_2(struct samldb_ctx *ac)
1732{
1733	struct ldb_context *ldb;
1734
1735	ldb = ldb_module_get_ctx(ac->module);
1736
1737	ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb),
1738		ac->prim_group_rid);
1739	if (ac->sid == NULL)
1740		return LDB_ERR_OPERATIONS_ERROR;
1741	ac->res_dn = NULL;
1742
1743	return samldb_next_step(ac);
1744}
1745
1746static int samldb_member_check_3(struct samldb_ctx *ac)
1747{
1748	if (ldb_dn_compare(ac->res_dn, ac->msg->dn) == 0)
1749		return LDB_ERR_ENTRY_ALREADY_EXISTS;
1750
1751	++(ac->cnt);
1752
1753	return samldb_next_step(ac);
1754}
1755
1756static int samldb_member_check_4(struct samldb_ctx *ac)
1757{
1758	return ldb_next_request(ac->module, ac->req);
1759}
1760
1761static int samldb_member_check(struct samldb_ctx *ac)
1762{
1763	struct ldb_message_element *el;
1764	int i, ret;
1765
1766	el = ldb_msg_find_element(ac->msg, "member");
1767	ac->cnt = 0;
1768	for (i = 0; i < el->num_values; i++) {
1769		/* Denies to add "member"s to groups which are primary ones
1770		 * for them */
1771		ret = samldb_add_step(ac, samldb_member_check_1);
1772		if (ret != LDB_SUCCESS) return ret;
1773
1774		ret = samldb_add_step(ac, samldb_user_dn_to_prim_group_rid);
1775		if (ret != LDB_SUCCESS) return ret;
1776
1777		ret = samldb_add_step(ac, samldb_member_check_2);
1778		if (ret != LDB_SUCCESS) return ret;
1779
1780		ret = samldb_add_step(ac, samldb_dn_from_sid);
1781		if (ret != LDB_SUCCESS) return ret;
1782
1783		ret = samldb_add_step(ac, samldb_member_check_3);
1784		if (ret != LDB_SUCCESS) return ret;
1785	}
1786
1787	ret = samldb_add_step(ac, samldb_member_check_4);
1788	if (ret != LDB_SUCCESS) return ret;
1789
1790	return samldb_first_step(ac);
1791}
1792
1793
1794static int samldb_prim_group_users_check_1(struct samldb_ctx *ac)
1795{
1796	ac->dn = ac->req->op.del.dn;
1797	ac->res_sid = NULL;
1798
1799	return samldb_next_step(ac);
1800}
1801
1802static int samldb_prim_group_users_check_2(struct samldb_ctx *ac)
1803{
1804	NTSTATUS status;
1805	uint32_t rid;
1806
1807	if (ac->res_sid == NULL) {
1808		/* No SID - therefore ok here */
1809		return ldb_next_request(ac->module, ac->req);
1810	}
1811	status = dom_sid_split_rid(ac, ac->res_sid, NULL, &rid);
1812	if (!NT_STATUS_IS_OK(status))
1813		return LDB_ERR_OPERATIONS_ERROR;
1814
1815	if (rid == 0) {
1816		/* Special object (security principal?) */
1817		return ldb_next_request(ac->module, ac->req);
1818	}
1819
1820	ac->prim_group_rid = rid;
1821	ac->users_cnt = 0;
1822
1823	return samldb_next_step(ac);
1824}
1825
1826static int samldb_prim_group_users_check_3(struct samldb_ctx *ac)
1827{
1828	if (ac->users_cnt > 0)
1829		return LDB_ERR_ENTRY_ALREADY_EXISTS;
1830
1831	return ldb_next_request(ac->module, ac->req);
1832}
1833
1834static int samldb_prim_group_users_check(struct samldb_ctx *ac)
1835{
1836	int ret;
1837
1838	/* Finds out the SID/RID of the domain object */
1839
1840	ret = samldb_add_step(ac, samldb_prim_group_users_check_1);
1841	if (ret != LDB_SUCCESS) return ret;
1842
1843	ret = samldb_add_step(ac, samldb_sid_from_dn);
1844	if (ret != LDB_SUCCESS) return ret;
1845
1846	/* Deny delete requests from groups which are primary ones */
1847
1848	ret = samldb_add_step(ac, samldb_prim_group_users_check_2);
1849	if (ret != LDB_SUCCESS) return ret;
1850
1851	ret = samldb_add_step(ac, samldb_prim_group_rid_to_users_cnt);
1852	if (ret != LDB_SUCCESS) return ret;
1853
1854	ret = samldb_add_step(ac, samldb_prim_group_users_check_3);
1855	if (ret != LDB_SUCCESS) return ret;
1856
1857	return samldb_first_step(ac);
1858}
1859
1860
1861/* add */
1862static int samldb_add(struct ldb_module *module, struct ldb_request *req)
1863{
1864	struct ldb_context *ldb;
1865	struct samldb_ctx *ac;
1866	int ret;
1867
1868	ldb = ldb_module_get_ctx(module);
1869	ldb_debug(ldb, LDB_DEBUG_TRACE, "samldb_add_record\n");
1870
1871	/* do not manipulate our control entries */
1872	if (ldb_dn_is_special(req->op.add.message->dn)) {
1873		return ldb_next_request(module, req);
1874	}
1875
1876	ac = samldb_ctx_init(module, req);
1877	if (ac == NULL) {
1878		return LDB_ERR_OPERATIONS_ERROR;
1879	}
1880
1881	/* build the new msg */
1882	ac->msg = ldb_msg_copy(ac, ac->req->op.add.message);
1883	if (!ac->msg) {
1884		talloc_free(ac);
1885		ldb_debug(ldb, LDB_DEBUG_FATAL,
1886			  "samldb_add: ldb_msg_copy failed!\n");
1887		return LDB_ERR_OPERATIONS_ERROR;
1888	}
1889
1890	if (samdb_find_attribute(ldb, ac->msg,
1891				 "objectclass", "computer") != NULL) {
1892
1893		/* make sure the computer object also has the 'user'
1894		 * objectclass so it will be handled by the next call */
1895		ret = samdb_find_or_add_value(ldb, ac->msg,
1896						"objectclass", "user");
1897		if (ret != LDB_SUCCESS) {
1898			talloc_free(ac);
1899			return ret;
1900		}
1901	}
1902
1903	if (samdb_find_attribute(ldb, ac->msg,
1904				 "objectclass", "user") != NULL) {
1905
1906		ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
1907		if (ret != LDB_SUCCESS) {
1908			talloc_free(ac);
1909			return ret;
1910		}
1911
1912		return samldb_fill_object(ac, "user");
1913	}
1914
1915	if (samdb_find_attribute(ldb, ac->msg,
1916				 "objectclass", "group") != NULL) {
1917
1918		ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
1919		if (ret != LDB_SUCCESS) {
1920			talloc_free(ac);
1921			return ret;
1922		}
1923
1924		return samldb_fill_object(ac, "group");
1925	}
1926
1927	/* perhaps a foreignSecurityPrincipal? */
1928	if (samdb_find_attribute(ldb, ac->msg,
1929				 "objectclass",
1930				 "foreignSecurityPrincipal") != NULL) {
1931
1932		ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
1933		if (ret != LDB_SUCCESS) {
1934			talloc_free(ac);
1935			return ret;
1936		}
1937
1938		return samldb_fill_foreignSecurityPrincipal_object(ac);
1939	}
1940
1941	talloc_free(ac);
1942
1943	/* nothing matched, go on */
1944	return ldb_next_request(module, req);
1945}
1946
1947/* modify */
1948static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
1949{
1950	struct ldb_context *ldb;
1951	struct ldb_message *msg;
1952	struct ldb_message_element *el, *el2;
1953	int ret;
1954	uint32_t account_type;
1955
1956	if (ldb_dn_is_special(req->op.mod.message->dn)) {
1957		/* do not manipulate our control entries */
1958		return ldb_next_request(module, req);
1959	}
1960
1961	ldb = ldb_module_get_ctx(module);
1962
1963	if (ldb_msg_find_element(req->op.mod.message, "sAMAccountType") != NULL) {
1964		ldb_asprintf_errstring(ldb,
1965			"sAMAccountType must not be specified!");
1966		return LDB_ERR_UNWILLING_TO_PERFORM;
1967	}
1968
1969	/* TODO: do not modify original request, create a new one */
1970
1971	el = ldb_msg_find_element(req->op.mod.message, "groupType");
1972	if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
1973		uint32_t group_type;
1974
1975		req->op.mod.message = msg = ldb_msg_copy_shallow(req,
1976			req->op.mod.message);
1977
1978		group_type = strtoul((const char *)el->values[0].data, NULL, 0);
1979		account_type =  ds_gtype2atype(group_type);
1980		ret = samdb_msg_add_uint(ldb, msg, msg,
1981					 "sAMAccountType",
1982					 account_type);
1983		if (ret != LDB_SUCCESS) {
1984			return ret;
1985		}
1986		el2 = ldb_msg_find_element(msg, "sAMAccountType");
1987		el2->flags = LDB_FLAG_MOD_REPLACE;
1988	}
1989
1990	el = ldb_msg_find_element(req->op.mod.message, "userAccountControl");
1991	if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
1992		uint32_t user_account_control;
1993
1994		req->op.mod.message = msg = ldb_msg_copy_shallow(req,
1995			req->op.mod.message);
1996
1997		user_account_control = strtoul((const char *)el->values[0].data,
1998			NULL, 0);
1999		account_type = ds_uf2atype(user_account_control);
2000		ret = samdb_msg_add_uint(ldb, msg, msg,
2001					 "sAMAccountType",
2002					 account_type);
2003		if (ret != LDB_SUCCESS) {
2004			return ret;
2005		}
2006		el2 = ldb_msg_find_element(msg, "sAMAccountType");
2007		el2->flags = LDB_FLAG_MOD_REPLACE;
2008
2009		if (user_account_control & UF_SERVER_TRUST_ACCOUNT) {
2010			ret = samdb_msg_add_string(ldb, msg, msg,
2011						   "isCriticalSystemObject", "TRUE");
2012			if (ret != LDB_SUCCESS) {
2013				return ret;
2014			}
2015			el2 = ldb_msg_find_element(msg, "isCriticalSystemObject");
2016			el2->flags = LDB_FLAG_MOD_REPLACE;
2017		}
2018	}
2019
2020	el = ldb_msg_find_element(req->op.mod.message, "primaryGroupID");
2021	if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
2022		struct samldb_ctx *ac;
2023
2024		ac = samldb_ctx_init(module, req);
2025		if (ac == NULL)
2026			return LDB_ERR_OPERATIONS_ERROR;
2027
2028		req->op.mod.message = ac->msg = ldb_msg_copy_shallow(req,
2029			req->op.mod.message);
2030
2031		return samldb_prim_group_change(ac);
2032	}
2033
2034	el = ldb_msg_find_element(req->op.mod.message, "member");
2035	if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
2036		struct samldb_ctx *ac;
2037
2038		ac = samldb_ctx_init(module, req);
2039		if (ac == NULL)
2040			return LDB_ERR_OPERATIONS_ERROR;
2041
2042		req->op.mod.message = ac->msg = ldb_msg_copy_shallow(req,
2043			req->op.mod.message);
2044
2045		return samldb_member_check(ac);
2046	}
2047
2048	/* nothing matched, go on */
2049	return ldb_next_request(module, req);
2050}
2051
2052/* delete */
2053static int samldb_delete(struct ldb_module *module, struct ldb_request *req)
2054{
2055	struct samldb_ctx *ac;
2056
2057	if (ldb_dn_is_special(req->op.del.dn)) {
2058		/* do not manipulate our control entries */
2059		return ldb_next_request(module, req);
2060	}
2061
2062	ac = samldb_ctx_init(module, req);
2063	if (ac == NULL)
2064		return LDB_ERR_OPERATIONS_ERROR;
2065
2066	return samldb_prim_group_users_check(ac);
2067}
2068
2069
2070static int samldb_init(struct ldb_module *module)
2071{
2072	return ldb_next_init(module);
2073}
2074
2075_PUBLIC_ const struct ldb_module_ops ldb_samldb_module_ops = {
2076	.name          = "samldb",
2077	.init_context  = samldb_init,
2078	.add           = samldb_add,
2079	.modify        = samldb_modify,
2080	.del           = samldb_delete
2081};
2082