Revert "s4:prefer "samdb_*_dn" basedn calls over the "ldb_get_*_dn" functions"
[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 static int samldb_fill_object(struct samldb_ctx *ac, const char *type)
831 {
832         struct ldb_context *ldb;
833         struct loadparm_context *lp_ctx;
834         enum sid_generator sid_generator;
835         int ret;
836
837         ldb = ldb_module_get_ctx(ac->module);
838
839         /* Add informations for the different account types */
840         ac->type = type;
841         if (strcmp(ac->type, "user") == 0) {
842                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
843                         "userAccountControl", "546");
844                 if (ret != LDB_SUCCESS) return ret;
845                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
846                         "badPwdCount", "0");
847                 if (ret != LDB_SUCCESS) return ret;
848                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
849                         "codePage", "0");
850                 if (ret != LDB_SUCCESS) return ret;
851                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
852                         "countryCode", "0");
853                 if (ret != LDB_SUCCESS) return ret;
854                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
855                         "badPasswordTime", "0");
856                 if (ret != LDB_SUCCESS) return ret;
857                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
858                         "lastLogoff", "0");
859                 if (ret != LDB_SUCCESS) return ret;
860                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
861                         "lastLogon", "0");
862                 if (ret != LDB_SUCCESS) return ret;
863                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
864                         "pwdLastSet", "0");
865                 if (ret != LDB_SUCCESS) return ret;
866                 if (!ldb_msg_find_element(ac->msg, "primaryGroupID")) {
867                         ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
868                                                  "primaryGroupID", DOMAIN_RID_USERS);
869                         if (ret != LDB_SUCCESS) return ret;
870                 }
871                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
872                         "accountExpires", "9223372036854775807");
873                 if (ret != LDB_SUCCESS) return ret;
874                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
875                         "logonCount", "0");
876                 if (ret != LDB_SUCCESS) return ret;
877         } else if (strcmp(ac->type, "group") == 0) {
878                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
879                         "groupType", "-2147483646");
880                 if (ret != LDB_SUCCESS) return ret;
881         } else if (strcmp(ac->type, "classSchema") == 0) {
882                 const struct ldb_val *rdn_value;
883
884                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
885                                                   "rdnAttId", "cn");
886                 if (ret != LDB_SUCCESS) return ret;
887
888                 rdn_value = ldb_dn_get_rdn_val(ac->msg->dn);
889                 if (!ldb_msg_find_element(ac->msg, "lDAPDisplayName")) {
890                         /* the RDN has prefix "CN" */
891                         ret = ldb_msg_add_string(ac->msg, "lDAPDisplayName",
892                                 samdb_cn_to_lDAPDisplayName(ac,
893                                         (const char *) rdn_value->data));
894                         if (ret != LDB_SUCCESS) {
895                                 ldb_oom(ldb);
896                                 return ret;
897                         }
898                 }
899
900                 if (!ldb_msg_find_element(ac->msg, "schemaIDGUID")) {
901                         struct GUID guid;
902                         /* a new GUID */
903                         guid = GUID_random();
904                         ret = dsdb_msg_add_guid(ac->msg, &guid, "schemaIDGUID");
905                         if (ret != LDB_SUCCESS) {
906                                 ldb_oom(ldb);
907                                 return ret;
908                         }
909                 }
910
911                 ret = samldb_add_step(ac, samldb_add_entry);
912                 if (ret != LDB_SUCCESS) return ret;
913
914                 ret = samldb_add_step(ac, samldb_find_for_defaultObjectCategory);
915                 if (ret != LDB_SUCCESS) return ret;
916
917                 ret = samldb_add_step(ac, samldb_set_defaultObjectCategory);
918                 if (ret != LDB_SUCCESS) return ret;
919
920                 return samldb_first_step(ac);
921         } else if (strcmp(ac->type, "attributeSchema") == 0) {
922                 const struct ldb_val *rdn_value;
923                 rdn_value = ldb_dn_get_rdn_val(ac->msg->dn);
924                 if (!ldb_msg_find_element(ac->msg, "lDAPDisplayName")) {
925                         /* the RDN has prefix "CN" */
926                         ret = ldb_msg_add_string(ac->msg, "lDAPDisplayName",
927                                 samdb_cn_to_lDAPDisplayName(ac,
928                                         (const char *) rdn_value->data));
929                         if (ret != LDB_SUCCESS) {
930                                 ldb_oom(ldb);
931                                 return ret;
932                         }
933                 }
934
935                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
936                                                   "isSingleValued", "FALSE");
937                 if (ret != LDB_SUCCESS) return ret;
938
939                 if (!ldb_msg_find_element(ac->msg, "schemaIDGUID")) {
940                         struct GUID guid;
941                         /* a new GUID */
942                         guid = GUID_random();
943                         ret = dsdb_msg_add_guid(ac->msg, &guid, "schemaIDGUID");
944                         if (ret != LDB_SUCCESS) {
945                                 ldb_oom(ldb);
946                                 return ret;
947                         }
948                 }
949
950                 /* handle msDS-IntID attribute */
951                 ret = samldb_add_handle_msDS_IntId(ac);
952                 if (ret != LDB_SUCCESS) return ret;
953
954                 ret = samldb_add_step(ac, samldb_add_entry);
955                 if (ret != LDB_SUCCESS) return ret;
956
957                 return samldb_first_step(ac);
958         } else {
959                 ldb_asprintf_errstring(ldb,
960                         "Invalid entry type!");
961                 return LDB_ERR_OPERATIONS_ERROR;
962         }
963
964         /* check if we have a valid samAccountName */
965         ret = samldb_add_step(ac, samldb_check_samAccountName);
966         if (ret != LDB_SUCCESS) return ret;
967
968         /* check account_type/group_type */
969         ret = samldb_add_step(ac, samldb_check_samAccountType);
970         if (ret != LDB_SUCCESS) return ret;
971
972         /* check if we have a valid primary group ID */
973         if (strcmp(ac->type, "user") == 0) {
974                 ret = samldb_add_step(ac, samldb_check_primaryGroupID_1);
975                 if (ret != LDB_SUCCESS) return ret;
976                 ret = samldb_add_step(ac, samldb_dn_from_sid);
977                 if (ret != LDB_SUCCESS) return ret;
978                 ret = samldb_add_step(ac, samldb_check_primaryGroupID_2);
979                 if (ret != LDB_SUCCESS) return ret;
980         }
981
982         lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
983                  struct loadparm_context);
984
985         /* don't allow objectSID to be specified without the RELAX control */
986         ac->sid = samdb_result_dom_sid(ac, ac->msg, "objectSid");
987         if (ac->sid && !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) &&
988             !dsdb_module_am_system(ac->module)) {
989                 ldb_asprintf_errstring(ldb, "No SID may be specified in user/group creation for %s",
990                                        ldb_dn_get_linearized(ac->msg->dn));
991                 return LDB_ERR_UNWILLING_TO_PERFORM;
992         }
993
994         if ( ! ac->sid) {
995                 sid_generator = lp_sid_generator(lp_ctx);
996                 if (sid_generator == SID_GENERATOR_INTERNAL) {
997                         ret = samldb_add_step(ac, samldb_allocate_sid);
998                         if (ret != LDB_SUCCESS) return ret;
999                 }
1000         }
1001
1002         /* finally proceed with adding the entry */
1003         ret = samldb_add_step(ac, samldb_add_entry);
1004         if (ret != LDB_SUCCESS) return ret;
1005
1006         return samldb_first_step(ac);
1007 }
1008
1009 static int samldb_fill_foreignSecurityPrincipal_object(struct samldb_ctx *ac)
1010 {
1011         struct ldb_context *ldb;
1012         int ret;
1013
1014         ldb = ldb_module_get_ctx(ac->module);
1015
1016         ac->sid = samdb_result_dom_sid(ac->msg, ac->msg, "objectSid");
1017         if (ac->sid == NULL) {
1018                 ac->sid = dom_sid_parse_talloc(ac->msg,
1019                            (const char *)ldb_dn_get_rdn_val(ac->msg->dn)->data);
1020                 if (!ac->sid) {
1021                         ldb_set_errstring(ldb,
1022                                         "No valid SID found in "
1023                                         "ForeignSecurityPrincipal CN!");
1024                         talloc_free(ac);
1025                         return LDB_ERR_CONSTRAINT_VIOLATION;
1026                 }
1027                 if ( ! samldb_msg_add_sid(ac->msg, "objectSid", ac->sid)) {
1028                         talloc_free(ac);
1029                         return LDB_ERR_OPERATIONS_ERROR;
1030                 }
1031         }
1032
1033         /* finally proceed with adding the entry */
1034         ret = samldb_add_step(ac, samldb_add_entry);
1035         if (ret != LDB_SUCCESS) return ret;
1036
1037         return samldb_first_step(ac);
1038 }
1039
1040 static int samldb_check_rdn(struct ldb_module *module, struct ldb_dn *dn)
1041 {
1042         struct ldb_context *ldb;
1043         const char *rdn_name;
1044
1045         ldb = ldb_module_get_ctx(module);
1046         rdn_name = ldb_dn_get_rdn_name(dn);
1047
1048         if (strcasecmp(rdn_name, "cn") != 0) {
1049                 ldb_asprintf_errstring(ldb,
1050                                         "Bad RDN (%s=) for samldb object, "
1051                                         "should be CN=!", rdn_name);
1052                 return LDB_ERR_CONSTRAINT_VIOLATION;
1053         }
1054
1055         return LDB_SUCCESS;
1056 }
1057
1058 static int samldb_schema_info_update(struct samldb_ctx *ac)
1059 {
1060         WERROR werr;
1061         struct ldb_context *ldb;
1062         struct dsdb_schema *schema;
1063
1064         /* replicated update should always go through */
1065         if (ldb_request_get_control(ac->req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
1066                 return LDB_SUCCESS;
1067         }
1068
1069         /* do not update schemaInfo during provisioning */
1070         if (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
1071                 return LDB_SUCCESS;
1072         }
1073
1074         ldb = ldb_module_get_ctx(ac->module);
1075         schema = dsdb_get_schema(ldb, NULL);
1076         if (!schema) {
1077                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
1078                               "samldb_schema_info_update: no dsdb_schema loaded");
1079                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
1080                 return LDB_ERR_OPERATIONS_ERROR;
1081         }
1082
1083         werr = dsdb_module_schema_info_update(ac->module, schema, 0);
1084         if (!W_ERROR_IS_OK(werr)) {
1085                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
1086                               "samldb_schema_info_update: "
1087                               "dsdb_module_schema_info_update failed with %s",
1088                               win_errstr(werr));
1089                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
1090                 return LDB_ERR_OPERATIONS_ERROR;
1091         }
1092
1093         return LDB_SUCCESS;
1094 }
1095
1096 /*
1097  * samldb_sid_from_dn (async)
1098  */
1099
1100 static int samldb_sid_from_dn(struct samldb_ctx *ac);
1101
1102 static int samldb_sid_from_dn_callback(struct ldb_request *req,
1103         struct ldb_reply *ares)
1104 {
1105         struct ldb_context *ldb;
1106         struct samldb_ctx *ac;
1107         int ret;
1108
1109         ac = talloc_get_type(req->context, struct samldb_ctx);
1110         ldb = ldb_module_get_ctx(ac->module);
1111
1112         if (!ares) {
1113                 ret = LDB_ERR_OPERATIONS_ERROR;
1114                 goto done;
1115         }
1116         if (ares->error != LDB_SUCCESS) {
1117                 return ldb_module_done(ac->req, ares->controls,
1118                                         ares->response, ares->error);
1119         }
1120
1121         switch (ares->type) {
1122         case LDB_REPLY_ENTRY:
1123                 /* save entry */
1124                 if (ac->res_sid != NULL) {
1125                         /* one too many! */
1126                         ldb_set_errstring(ldb,
1127                                 "Invalid number of results while searching "
1128                                 "for domain objects!");
1129                         ret = LDB_ERR_OPERATIONS_ERROR;
1130                         break;
1131                 }
1132                 ac->res_sid = samdb_result_dom_sid(ac, ares->message,
1133                         "objectSid");
1134
1135                 talloc_free(ares);
1136                 ret = LDB_SUCCESS;
1137                 break;
1138
1139         case LDB_REPLY_REFERRAL:
1140                 /* ignore */
1141                 talloc_free(ares);
1142                 ret = LDB_SUCCESS;
1143                 break;
1144
1145         case LDB_REPLY_DONE:
1146                 talloc_free(ares);
1147
1148                 /* found or not found, go on */
1149                 ret = samldb_next_step(ac);
1150                 break;
1151         }
1152
1153 done:
1154         if (ret != LDB_SUCCESS) {
1155                 return ldb_module_done(ac->req, NULL, NULL, ret);
1156         }
1157
1158         return LDB_SUCCESS;
1159 }
1160
1161 /* Finds the SID "res_sid" of an object with a given DN "dn" */
1162 static int samldb_sid_from_dn(struct samldb_ctx *ac)
1163 {
1164         struct ldb_context *ldb;
1165         static const char * const attrs[] = { "objectSid", NULL };
1166         struct ldb_request *req;
1167         int ret;
1168
1169         ldb = ldb_module_get_ctx(ac->module);
1170
1171         if (ac->dn == NULL)
1172                 return LDB_ERR_OPERATIONS_ERROR;
1173
1174         ret = ldb_build_search_req(&req, ldb, ac,
1175                                 ac->dn,
1176                                 LDB_SCOPE_BASE,
1177                                 NULL, attrs,
1178                                 NULL,
1179                                 ac, samldb_sid_from_dn_callback,
1180                                 ac->req);
1181         if (ret != LDB_SUCCESS)
1182                 return ret;
1183
1184         return ldb_next_request(ac->module, req);
1185 }
1186
1187 /*
1188  * samldb_user_dn_to_prim_group_rid (async)
1189  */
1190
1191 static int samldb_user_dn_to_prim_group_rid(struct samldb_ctx *ac);
1192
1193 static int samldb_user_dn_to_prim_group_rid_callback(struct ldb_request *req,
1194         struct ldb_reply *ares)
1195 {
1196         struct ldb_context *ldb;
1197         struct samldb_ctx *ac;
1198         int ret;
1199
1200         ac = talloc_get_type(req->context, struct samldb_ctx);
1201         ldb = ldb_module_get_ctx(ac->module);
1202
1203         if (!ares) {
1204                 ret = LDB_ERR_OPERATIONS_ERROR;
1205                 goto done;
1206         }
1207         if (ares->error != LDB_SUCCESS) {
1208                 return ldb_module_done(ac->req, ares->controls,
1209                                         ares->response, ares->error);
1210         }
1211
1212         switch (ares->type) {
1213         case LDB_REPLY_ENTRY:
1214                 /* save entry */
1215                 if (ac->prim_group_rid != 0) {
1216                         /* one too many! */
1217                         ldb_set_errstring(ldb,
1218                                 "Invalid number of results while searching "
1219                                 "for domain objects!");
1220                         ret = LDB_ERR_OPERATIONS_ERROR;
1221                         break;
1222                 }
1223                 ac->prim_group_rid = samdb_result_uint(ares->message,
1224                         "primaryGroupID", ~0);
1225
1226                 talloc_free(ares);
1227                 ret = LDB_SUCCESS;
1228                 break;
1229
1230         case LDB_REPLY_REFERRAL:
1231                 /* ignore */
1232                 talloc_free(ares);
1233                 ret = LDB_SUCCESS;
1234                 break;
1235
1236         case LDB_REPLY_DONE:
1237                 talloc_free(ares);
1238                 if (ac->prim_group_rid == 0) {
1239                         ldb_asprintf_errstring(ldb,
1240                                 "Unable to get the primary group RID!");
1241                         ret = LDB_ERR_OPERATIONS_ERROR;
1242                         break;
1243                 }
1244
1245                 /* found, go on */
1246                 ret = samldb_next_step(ac);
1247                 break;
1248         }
1249
1250 done:
1251         if (ret != LDB_SUCCESS) {
1252                 return ldb_module_done(ac->req, NULL, NULL, ret);
1253         }
1254
1255         return LDB_SUCCESS;
1256 }
1257
1258 /* Locates the "primaryGroupID" attribute from a certain user specified as
1259  * "user_dn". Saves the result in "prim_group_rid". */
1260 static int samldb_user_dn_to_prim_group_rid(struct samldb_ctx *ac)
1261 {
1262         struct ldb_context *ldb;
1263         static const char * const attrs[] = { "primaryGroupID", NULL };
1264         struct ldb_request *req;
1265         int ret;
1266
1267         ldb = ldb_module_get_ctx(ac->module);
1268
1269         if (ac->user_dn == NULL)
1270                 return LDB_ERR_OPERATIONS_ERROR;
1271
1272         ret = ldb_build_search_req(&req, ldb, ac,
1273                                 ac->user_dn,
1274                                 LDB_SCOPE_BASE,
1275                                 NULL, attrs,
1276                                 NULL,
1277                                 ac, samldb_user_dn_to_prim_group_rid_callback,
1278                                 ac->req);
1279         if (ret != LDB_SUCCESS)
1280                 return ret;
1281
1282         return ldb_next_request(ac->module, req);
1283 }
1284
1285 /*
1286  * samldb_prim_group_rid_to_users_cnt (async)
1287  */
1288
1289 static int samldb_prim_group_rid_to_users_cnt(struct samldb_ctx *ac);
1290
1291 static int samldb_prim_group_rid_to_users_cnt_callback(struct ldb_request *req,
1292         struct ldb_reply *ares)
1293 {
1294         struct ldb_context *ldb;
1295         struct samldb_ctx *ac;
1296         int ret;
1297
1298         ac = talloc_get_type(req->context, struct samldb_ctx);
1299         ldb = ldb_module_get_ctx(ac->module);
1300
1301         if (!ares) {
1302                 ret = LDB_ERR_OPERATIONS_ERROR;
1303                 goto done;
1304         }
1305         if (ares->error != LDB_SUCCESS) {
1306                 return ldb_module_done(ac->req, ares->controls,
1307                                         ares->response, ares->error);
1308         }
1309
1310         switch (ares->type) {
1311         case LDB_REPLY_ENTRY:
1312                 /* save entry */
1313                 ++(ac->users_cnt);
1314
1315                 talloc_free(ares);
1316                 ret = LDB_SUCCESS;
1317                 break;
1318
1319         case LDB_REPLY_REFERRAL:
1320                 /* ignore */
1321                 talloc_free(ares);
1322                 ret = LDB_SUCCESS;
1323                 break;
1324
1325         case LDB_REPLY_DONE:
1326                 talloc_free(ares);
1327
1328                 /* found or not found, go on */
1329                 ret = samldb_next_step(ac);
1330                 break;
1331         }
1332
1333 done:
1334         if (ret != LDB_SUCCESS) {
1335                 return ldb_module_done(ac->req, NULL, NULL, ret);
1336         }
1337
1338         return LDB_SUCCESS;
1339 }
1340
1341 /* Finds the amount of users which have the primary group "prim_group_rid" and
1342  * save the result in "users_cnt" */
1343 static int samldb_prim_group_rid_to_users_cnt(struct samldb_ctx *ac)
1344 {
1345         struct ldb_context *ldb;
1346         static const char * const attrs[] = { NULL };
1347         struct ldb_request *req;
1348         char *filter;
1349         int ret;
1350
1351         ldb = ldb_module_get_ctx(ac->module);
1352
1353         if ((ac->prim_group_rid == 0) || (ac->users_cnt != 0))
1354                 return LDB_ERR_OPERATIONS_ERROR;
1355
1356         filter = talloc_asprintf(ac, "(&(primaryGroupID=%u)(objectclass=user))",
1357                 ac->prim_group_rid);
1358         if (filter == NULL)
1359                 return LDB_ERR_OPERATIONS_ERROR;
1360
1361         ret = ldb_build_search_req(&req, ldb, ac,
1362                                 ldb_get_default_basedn(ldb),
1363                                 LDB_SCOPE_SUBTREE,
1364                                 filter, attrs,
1365                                 NULL,
1366                                 ac,
1367                                 samldb_prim_group_rid_to_users_cnt_callback,
1368                                 ac->req);
1369         if (ret != LDB_SUCCESS)
1370                 return ret;
1371
1372         return ldb_next_request(ac->module, req);
1373 }
1374
1375 /*
1376  * samldb_group_add_member (async)
1377  * samldb_group_del_member (async)
1378  */
1379
1380 static int samldb_group_add_del_member_callback(struct ldb_request *req,
1381         struct ldb_reply *ares)
1382 {
1383         struct ldb_context *ldb;
1384         struct samldb_ctx *ac;
1385         int ret;
1386
1387         ac = talloc_get_type(req->context, struct samldb_ctx);
1388         ldb = ldb_module_get_ctx(ac->module);
1389
1390         if (!ares) {
1391                 ret = LDB_ERR_OPERATIONS_ERROR;
1392                 goto done;
1393         }
1394         if (ares->error != LDB_SUCCESS) {
1395                 if (ares->error == LDB_ERR_NO_SUCH_ATTRIBUTE) {
1396                         /* On error "NO_SUCH_ATTRIBUTE" (delete of an invalid
1397                          * "member" attribute) return "UNWILLING_TO_PERFORM" */
1398                         ares->error = LDB_ERR_UNWILLING_TO_PERFORM;
1399                 }
1400                 return ldb_module_done(ac->req, ares->controls,
1401                                         ares->response, ares->error);
1402         }
1403         if (ares->type != LDB_REPLY_DONE) {
1404                 ldb_set_errstring(ldb,
1405                         "Invalid reply type!");
1406                 ret = LDB_ERR_OPERATIONS_ERROR;
1407                 goto done;
1408         }
1409
1410         ret = samldb_next_step(ac);
1411
1412 done:
1413         if (ret != LDB_SUCCESS) {
1414                 return ldb_module_done(ac->req, NULL, NULL, ret);
1415         }
1416
1417         return LDB_SUCCESS;
1418 }
1419
1420 /* Adds a member with DN "member_dn" to a group with DN "group_dn" */
1421 static int samldb_group_add_member(struct samldb_ctx *ac)
1422 {
1423         struct ldb_context *ldb;
1424         struct ldb_request *req;
1425         struct ldb_message *msg;
1426         int ret;
1427
1428         ldb = ldb_module_get_ctx(ac->module);
1429
1430         if ((ac->group_dn == NULL) || (ac->member_dn == NULL))
1431                 return LDB_ERR_OPERATIONS_ERROR;
1432
1433         msg = ldb_msg_new(ac);
1434         msg->dn = ac->group_dn;
1435         samdb_msg_add_addval(ldb, ac, msg, "member",
1436                 ldb_dn_get_linearized(ac->member_dn));
1437
1438         ret = ldb_build_mod_req(&req, ldb, ac,
1439                                 msg, NULL,
1440                                 ac, samldb_group_add_del_member_callback,
1441                                 ac->req);
1442         if (ret != LDB_SUCCESS)
1443                 return ret;
1444
1445         return ldb_next_request(ac->module, req);
1446 }
1447
1448 /* Removes a member with DN "member_dn" from a group with DN "group_dn" */
1449 static int samldb_group_del_member(struct samldb_ctx *ac)
1450 {
1451         struct ldb_context *ldb;
1452         struct ldb_request *req;
1453         struct ldb_message *msg;
1454         int ret;
1455
1456         ldb = ldb_module_get_ctx(ac->module);
1457
1458         if ((ac->group_dn == NULL) || (ac->member_dn == NULL))
1459                 return LDB_ERR_OPERATIONS_ERROR;
1460
1461         msg = ldb_msg_new(ac);
1462         msg->dn = ac->group_dn;
1463         samdb_msg_add_delval(ldb, ac, msg, "member",
1464                 ldb_dn_get_linearized(ac->member_dn));
1465
1466         ret = ldb_build_mod_req(&req, ldb, ac,
1467                                 msg, NULL,
1468                                 ac, samldb_group_add_del_member_callback,
1469                                 ac->req);
1470         if (ret != LDB_SUCCESS)
1471                 return ret;
1472
1473         return ldb_next_request(ac->module, req);
1474 }
1475
1476
1477 static int samldb_prim_group_change_1(struct samldb_ctx *ac)
1478 {
1479         struct ldb_context *ldb;
1480         uint32_t rid;
1481
1482         ldb = ldb_module_get_ctx(ac->module);
1483
1484         ac->user_dn = ac->msg->dn;
1485
1486         rid = samdb_result_uint(ac->msg, "primaryGroupID", ~0);
1487         ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
1488         if (ac->sid == NULL)
1489                 return LDB_ERR_OPERATIONS_ERROR;
1490         ac->res_dn = NULL;
1491
1492         ac->prim_group_rid = 0;
1493
1494         return samldb_next_step(ac);
1495 }
1496
1497 static int samldb_prim_group_change_2(struct samldb_ctx *ac)
1498 {
1499         struct ldb_context *ldb;
1500
1501         ldb = ldb_module_get_ctx(ac->module);
1502
1503         if (ac->res_dn != NULL)
1504                 ac->new_prim_group_dn = ac->res_dn;
1505         else
1506                 return LDB_ERR_UNWILLING_TO_PERFORM;
1507
1508         ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb),
1509                 ac->prim_group_rid);
1510         if (ac->sid == NULL)
1511                 return LDB_ERR_OPERATIONS_ERROR;
1512         ac->res_dn = NULL;
1513
1514         return samldb_next_step(ac);
1515 }
1516
1517 static int samldb_prim_group_change_4(struct samldb_ctx *ac);
1518 static int samldb_prim_group_change_5(struct samldb_ctx *ac);
1519 static int samldb_prim_group_change_6(struct samldb_ctx *ac);
1520
1521 static int samldb_prim_group_change_3(struct samldb_ctx *ac)
1522 {
1523         int ret;
1524
1525         if (ac->res_dn != NULL)
1526                 ac->old_prim_group_dn = ac->res_dn;
1527         else
1528                 return LDB_ERR_UNWILLING_TO_PERFORM;
1529
1530         /* Only update when the primary group changed */
1531         if (ldb_dn_compare(ac->old_prim_group_dn, ac->new_prim_group_dn) != 0) {
1532                 ac->member_dn = ac->user_dn;
1533                 /* Remove the "member" attribute of the actual (new) primary
1534                  * group */
1535
1536                 ret = samldb_add_step(ac, samldb_prim_group_change_4);
1537                 if (ret != LDB_SUCCESS) return ret;
1538
1539                 ret = samldb_add_step(ac, samldb_group_del_member);
1540                 if (ret != LDB_SUCCESS) return ret;
1541
1542                 /* Add a "member" attribute for the previous primary group */
1543
1544                 ret = samldb_add_step(ac, samldb_prim_group_change_5);
1545                 if (ret != LDB_SUCCESS) return ret;
1546
1547                 ret = samldb_add_step(ac, samldb_group_add_member);
1548                 if (ret != LDB_SUCCESS) return ret;
1549         }
1550
1551         ret = samldb_add_step(ac, samldb_prim_group_change_6);
1552         if (ret != LDB_SUCCESS) return ret;
1553
1554         return samldb_next_step(ac);
1555 }
1556
1557 static int samldb_prim_group_change_4(struct samldb_ctx *ac)
1558 {
1559         ac->group_dn = ac->new_prim_group_dn;
1560
1561         return samldb_next_step(ac);
1562 }
1563
1564 static int samldb_prim_group_change_5(struct samldb_ctx *ac)
1565 {
1566         ac->group_dn = ac->old_prim_group_dn;
1567
1568         return samldb_next_step(ac);
1569 }
1570
1571 static int samldb_prim_group_change_6(struct samldb_ctx *ac)
1572 {
1573         return ldb_next_request(ac->module, ac->req);
1574 }
1575
1576 static int samldb_prim_group_change(struct samldb_ctx *ac)
1577 {
1578         int ret;
1579
1580         /* Finds out the DN of the new primary group */
1581
1582         ret = samldb_add_step(ac, samldb_prim_group_change_1);
1583         if (ret != LDB_SUCCESS) return ret;
1584
1585         ret = samldb_add_step(ac, samldb_dn_from_sid);
1586         if (ret != LDB_SUCCESS) return ret;
1587
1588         ret = samldb_add_step(ac, samldb_user_dn_to_prim_group_rid);
1589         if (ret != LDB_SUCCESS) return ret;
1590
1591         /* Finds out the DN of the old primary group */
1592
1593         ret = samldb_add_step(ac, samldb_prim_group_change_2);
1594         if (ret != LDB_SUCCESS) return ret;
1595
1596         ret = samldb_add_step(ac, samldb_dn_from_sid);
1597         if (ret != LDB_SUCCESS) return ret;
1598
1599         ret = samldb_add_step(ac, samldb_prim_group_change_3);
1600         if (ret != LDB_SUCCESS) return ret;
1601
1602         return samldb_first_step(ac);
1603 }
1604
1605
1606 static int samldb_member_check_1(struct samldb_ctx *ac)
1607 {
1608         struct ldb_context *ldb;
1609         struct ldb_message_element *el;
1610
1611         ldb = ldb_module_get_ctx(ac->module);
1612
1613         el = ldb_msg_find_element(ac->msg, "member");
1614
1615         ac->user_dn = ldb_dn_from_ldb_val(ac, ldb, &el->values[ac->cnt]);
1616         if (!ldb_dn_validate(ac->user_dn))
1617                 return LDB_ERR_OPERATIONS_ERROR;
1618         ac->prim_group_rid = 0;
1619
1620         return samldb_next_step(ac);
1621 }
1622
1623 static int samldb_member_check_2(struct samldb_ctx *ac)
1624 {
1625         struct ldb_context *ldb;
1626
1627         ldb = ldb_module_get_ctx(ac->module);
1628
1629         ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb),
1630                 ac->prim_group_rid);
1631         if (ac->sid == NULL)
1632                 return LDB_ERR_OPERATIONS_ERROR;
1633         ac->res_dn = NULL;
1634
1635         return samldb_next_step(ac);
1636 }
1637
1638 static int samldb_member_check_3(struct samldb_ctx *ac)
1639 {
1640         if (ldb_dn_compare(ac->res_dn, ac->msg->dn) == 0)
1641                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
1642
1643         ++(ac->cnt);
1644
1645         return samldb_next_step(ac);
1646 }
1647
1648 static int samldb_member_check_4(struct samldb_ctx *ac)
1649 {
1650         return ldb_next_request(ac->module, ac->req);
1651 }
1652
1653 static int samldb_member_check(struct samldb_ctx *ac)
1654 {
1655         struct ldb_message_element *el;
1656         int i, ret;
1657
1658         el = ldb_msg_find_element(ac->msg, "member");
1659         ac->cnt = 0;
1660         for (i = 0; i < el->num_values; i++) {
1661                 /* Denies to add "member"s to groups which are primary ones
1662                  * for them */
1663                 ret = samldb_add_step(ac, samldb_member_check_1);
1664                 if (ret != LDB_SUCCESS) return ret;
1665
1666                 ret = samldb_add_step(ac, samldb_user_dn_to_prim_group_rid);
1667                 if (ret != LDB_SUCCESS) return ret;
1668
1669                 ret = samldb_add_step(ac, samldb_member_check_2);
1670                 if (ret != LDB_SUCCESS) return ret;
1671
1672                 ret = samldb_add_step(ac, samldb_dn_from_sid);
1673                 if (ret != LDB_SUCCESS) return ret;
1674
1675                 ret = samldb_add_step(ac, samldb_member_check_3);
1676                 if (ret != LDB_SUCCESS) return ret;
1677         }
1678
1679         ret = samldb_add_step(ac, samldb_member_check_4);
1680         if (ret != LDB_SUCCESS) return ret;
1681
1682         return samldb_first_step(ac);
1683 }
1684
1685
1686 static int samldb_prim_group_users_check_1(struct samldb_ctx *ac)
1687 {
1688         ac->dn = ac->req->op.del.dn;
1689         ac->res_sid = NULL;
1690
1691         return samldb_next_step(ac);
1692 }
1693
1694 static int samldb_prim_group_users_check_2(struct samldb_ctx *ac)
1695 {
1696         NTSTATUS status;
1697         uint32_t rid;
1698
1699         if (ac->res_sid == NULL) {
1700                 /* No SID - therefore ok here */
1701                 return ldb_next_request(ac->module, ac->req);
1702         }
1703         status = dom_sid_split_rid(ac, ac->res_sid, NULL, &rid);
1704         if (!NT_STATUS_IS_OK(status))
1705                 return LDB_ERR_OPERATIONS_ERROR;
1706
1707         if (rid == 0) {
1708                 /* Special object (security principal?) */
1709                 return ldb_next_request(ac->module, ac->req);
1710         }
1711
1712         ac->prim_group_rid = rid;
1713         ac->users_cnt = 0;
1714
1715         return samldb_next_step(ac);
1716 }
1717
1718 static int samldb_prim_group_users_check_3(struct samldb_ctx *ac)
1719 {
1720         if (ac->users_cnt > 0)
1721                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
1722
1723         return ldb_next_request(ac->module, ac->req);
1724 }
1725
1726 static int samldb_prim_group_users_check(struct samldb_ctx *ac)
1727 {
1728         int ret;
1729
1730         /* Finds out the SID/RID of the domain object */
1731
1732         ret = samldb_add_step(ac, samldb_prim_group_users_check_1);
1733         if (ret != LDB_SUCCESS) return ret;
1734
1735         ret = samldb_add_step(ac, samldb_sid_from_dn);
1736         if (ret != LDB_SUCCESS) return ret;
1737
1738         /* Deny delete requests from groups which are primary ones */
1739
1740         ret = samldb_add_step(ac, samldb_prim_group_users_check_2);
1741         if (ret != LDB_SUCCESS) return ret;
1742
1743         ret = samldb_add_step(ac, samldb_prim_group_rid_to_users_cnt);
1744         if (ret != LDB_SUCCESS) return ret;
1745
1746         ret = samldb_add_step(ac, samldb_prim_group_users_check_3);
1747         if (ret != LDB_SUCCESS) return ret;
1748
1749         return samldb_first_step(ac);
1750 }
1751
1752
1753 /* add */
1754 static int samldb_add(struct ldb_module *module, struct ldb_request *req)
1755 {
1756         struct ldb_context *ldb;
1757         struct samldb_ctx *ac;
1758         int ret;
1759
1760         ldb = ldb_module_get_ctx(module);
1761         ldb_debug(ldb, LDB_DEBUG_TRACE, "samldb_add\n");
1762
1763         /* do not manipulate our control entries */
1764         if (ldb_dn_is_special(req->op.add.message->dn)) {
1765                 return ldb_next_request(module, req);
1766         }
1767
1768         ac = samldb_ctx_init(module, req);
1769         if (ac == NULL) {
1770                 return LDB_ERR_OPERATIONS_ERROR;
1771         }
1772
1773         /* build the new msg */
1774         ac->msg = ldb_msg_copy(ac, ac->req->op.add.message);
1775         if (!ac->msg) {
1776                 talloc_free(ac);
1777                 ldb_debug(ldb, LDB_DEBUG_FATAL,
1778                           "samldb_add: ldb_msg_copy failed!\n");
1779                 return LDB_ERR_OPERATIONS_ERROR;
1780         }
1781
1782         if (samdb_find_attribute(ldb, ac->msg,
1783                                  "objectclass", "computer") != NULL) {
1784
1785                 /* make sure the computer object also has the 'user'
1786                  * objectclass so it will be handled by the next call */
1787                 ret = samdb_find_or_add_value(ldb, ac->msg,
1788                                                 "objectclass", "user");
1789                 if (ret != LDB_SUCCESS) {
1790                         talloc_free(ac);
1791                         return ret;
1792                 }
1793         }
1794
1795         if (samdb_find_attribute(ldb, ac->msg,
1796                                  "objectclass", "user") != NULL) {
1797
1798                 ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
1799                 if (ret != LDB_SUCCESS) {
1800                         talloc_free(ac);
1801                         return ret;
1802                 }
1803
1804                 return samldb_fill_object(ac, "user");
1805         }
1806
1807         if (samdb_find_attribute(ldb, ac->msg,
1808                                  "objectclass", "group") != NULL) {
1809
1810                 ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
1811                 if (ret != LDB_SUCCESS) {
1812                         talloc_free(ac);
1813                         return ret;
1814                 }
1815
1816                 return samldb_fill_object(ac, "group");
1817         }
1818
1819         /* perhaps a foreignSecurityPrincipal? */
1820         if (samdb_find_attribute(ldb, ac->msg,
1821                                  "objectclass",
1822                                  "foreignSecurityPrincipal") != NULL) {
1823
1824                 ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
1825                 if (ret != LDB_SUCCESS) {
1826                         talloc_free(ac);
1827                         return ret;
1828                 }
1829
1830                 return samldb_fill_foreignSecurityPrincipal_object(ac);
1831         }
1832
1833         if (samdb_find_attribute(ldb, ac->msg,
1834                                  "objectclass", "classSchema") != NULL) {
1835
1836                 ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
1837                 if (ret != LDB_SUCCESS) {
1838                         talloc_free(ac);
1839                         return ret;
1840                 }
1841
1842                 ret = samldb_schema_info_update(ac);
1843                 if (ret != LDB_SUCCESS) {
1844                         talloc_free(ac);
1845                         return ret;
1846                 }
1847
1848                 return samldb_fill_object(ac, "classSchema");
1849         }
1850
1851         if (samdb_find_attribute(ldb, ac->msg,
1852                                  "objectclass", "attributeSchema") != NULL) {
1853
1854                 ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
1855                 if (ret != LDB_SUCCESS) {
1856                         talloc_free(ac);
1857                         return ret;
1858                 }
1859
1860                 ret = samldb_schema_info_update(ac);
1861                 if (ret != LDB_SUCCESS) {
1862                         talloc_free(ac);
1863                         return ret;
1864                 }
1865
1866                 return samldb_fill_object(ac, "attributeSchema");
1867         }
1868
1869         talloc_free(ac);
1870
1871         /* nothing matched, go on */
1872         return ldb_next_request(module, req);
1873 }
1874
1875 /* modify */
1876 static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
1877 {
1878         struct ldb_context *ldb;
1879         struct ldb_message *msg;
1880         struct ldb_message_element *el, *el2;
1881         int ret;
1882         uint32_t account_type;
1883
1884         if (ldb_dn_is_special(req->op.mod.message->dn)) {
1885                 /* do not manipulate our control entries */
1886                 return ldb_next_request(module, req);
1887         }
1888
1889         ldb = ldb_module_get_ctx(module);
1890
1891         if (ldb_msg_find_element(req->op.mod.message, "sAMAccountType") != NULL) {
1892                 ldb_asprintf_errstring(ldb,
1893                         "sAMAccountType must not be specified!");
1894                 return LDB_ERR_UNWILLING_TO_PERFORM;
1895         }
1896
1897         /* msDS-IntId is not allowed to be modified
1898          * except when modification comes from replication */
1899         if (ldb_msg_find_element(req->op.mod.message, "msDS-IntId")) {
1900                 if (!ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
1901                         return LDB_ERR_CONSTRAINT_VIOLATION;
1902                 }
1903         }
1904
1905         /* TODO: do not modify original request, create a new one */
1906
1907         el = ldb_msg_find_element(req->op.mod.message, "groupType");
1908         if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
1909                 uint32_t group_type;
1910
1911                 req->op.mod.message = msg = ldb_msg_copy_shallow(req,
1912                         req->op.mod.message);
1913
1914                 group_type = strtoul((const char *)el->values[0].data, NULL, 0);
1915                 account_type =  ds_gtype2atype(group_type);
1916                 ret = samdb_msg_add_uint(ldb, msg, msg,
1917                                          "sAMAccountType",
1918                                          account_type);
1919                 if (ret != LDB_SUCCESS) {
1920                         return ret;
1921                 }
1922                 el2 = ldb_msg_find_element(msg, "sAMAccountType");
1923                 el2->flags = LDB_FLAG_MOD_REPLACE;
1924         }
1925
1926         el = ldb_msg_find_element(req->op.mod.message, "primaryGroupID");
1927         if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
1928                 struct samldb_ctx *ac;
1929
1930                 ac = samldb_ctx_init(module, req);
1931                 if (ac == NULL)
1932                         return LDB_ERR_OPERATIONS_ERROR;
1933
1934                 req->op.mod.message = ac->msg = ldb_msg_copy_shallow(req,
1935                         req->op.mod.message);
1936
1937                 return samldb_prim_group_change(ac);
1938         }
1939
1940         el = ldb_msg_find_element(req->op.mod.message, "userAccountControl");
1941         if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
1942                 uint32_t user_account_control;
1943
1944                 req->op.mod.message = msg = ldb_msg_copy_shallow(req,
1945                         req->op.mod.message);
1946
1947                 user_account_control = strtoul((const char *)el->values[0].data,
1948                         NULL, 0);
1949                 account_type = ds_uf2atype(user_account_control);
1950                 ret = samdb_msg_add_uint(ldb, msg, msg,
1951                                          "sAMAccountType",
1952                                          account_type);
1953                 if (ret != LDB_SUCCESS) {
1954                         return ret;
1955                 }
1956                 el2 = ldb_msg_find_element(msg, "sAMAccountType");
1957                 el2->flags = LDB_FLAG_MOD_REPLACE;
1958
1959                 if (user_account_control & UF_SERVER_TRUST_ACCOUNT) {
1960                         ret = samdb_msg_add_string(ldb, msg, msg,
1961                                                    "isCriticalSystemObject", "TRUE");
1962                         if (ret != LDB_SUCCESS) {
1963                                 return ret;
1964                         }
1965                         el2 = ldb_msg_find_element(msg, "isCriticalSystemObject");
1966                         el2->flags = LDB_FLAG_MOD_REPLACE;
1967
1968                         /* DCs have primaryGroupID of DOMAIN_RID_DCS */
1969                         if (!ldb_msg_find_element(msg, "primaryGroupID")) {
1970                                 ret = samdb_msg_add_uint(ldb, msg, msg,
1971                                                          "primaryGroupID", DOMAIN_RID_DCS);
1972                                 if (ret != LDB_SUCCESS) {
1973                                         return ret;
1974                                 }
1975                                 el2 = ldb_msg_find_element(msg, "primaryGroupID");
1976                                 el2->flags = LDB_FLAG_MOD_REPLACE;
1977                         }
1978                 }
1979         }
1980
1981         el = ldb_msg_find_element(req->op.mod.message, "member");
1982         if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
1983                 struct samldb_ctx *ac;
1984
1985                 ac = samldb_ctx_init(module, req);
1986                 if (ac == NULL)
1987                         return LDB_ERR_OPERATIONS_ERROR;
1988
1989                 req->op.mod.message = ac->msg = ldb_msg_copy_shallow(req,
1990                         req->op.mod.message);
1991
1992                 return samldb_member_check(ac);
1993         }
1994
1995         /* nothing matched, go on */
1996         return ldb_next_request(module, req);
1997 }
1998
1999 /* delete */
2000 static int samldb_delete(struct ldb_module *module, struct ldb_request *req)
2001 {
2002         struct samldb_ctx *ac;
2003
2004         if (ldb_dn_is_special(req->op.del.dn)) {
2005                 /* do not manipulate our control entries */
2006                 return ldb_next_request(module, req);
2007         }
2008
2009         ac = samldb_ctx_init(module, req);
2010         if (ac == NULL)
2011                 return LDB_ERR_OPERATIONS_ERROR;
2012
2013         return samldb_prim_group_users_check(ac);
2014 }
2015
2016 static int samldb_extended_allocate_rid_pool(struct ldb_module *module, struct ldb_request *req)
2017 {
2018         struct ldb_context *ldb = ldb_module_get_ctx(module);
2019         struct dsdb_fsmo_extended_op *exop;
2020         int ret;
2021
2022         exop = talloc_get_type(req->op.extended.data, struct dsdb_fsmo_extended_op);
2023         if (!exop) {
2024                 ldb_debug(ldb, LDB_DEBUG_FATAL, "samldb_extended_allocate_rid_pool: invalid extended data\n");
2025                 return LDB_ERR_PROTOCOL_ERROR;
2026         }
2027
2028         ret = ridalloc_allocate_rid_pool_fsmo(module, exop);
2029         if (ret != LDB_SUCCESS) {
2030                 return ret;
2031         }
2032
2033         return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
2034 }
2035
2036 static int samldb_extended(struct ldb_module *module, struct ldb_request *req)
2037 {
2038         if (strcmp(req->op.extended.oid, DSDB_EXTENDED_ALLOCATE_RID_POOL) == 0) {
2039                 return samldb_extended_allocate_rid_pool(module, req);
2040         }
2041
2042         return ldb_next_request(module, req);
2043 }
2044
2045
2046 _PUBLIC_ const struct ldb_module_ops ldb_samldb_module_ops = {
2047         .name          = "samldb",
2048         .add           = samldb_add,
2049         .modify        = samldb_modify,
2050         .del           = samldb_delete,
2051         .extended      = samldb_extended
2052 };
2053