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