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