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