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