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