s4:SAMLDB DSDB module - Add "\n"s on debug messages
[samba.git] / source4 / dsdb / samdb / ldb_modules / samldb.c
1 /*
2    SAM ldb module
3
4    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
5    Copyright (C) Simo Sorce  2004-2008
6    Copyright (C) Matthias Dieter Wallnöfer 2009
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 /*
23  *  Name: ldb
24  *
25  *  Component: ldb samldb module
26  *
27  *  Description: add embedded user/group creation functionality
28  *
29  *  Author: Simo Sorce
30  */
31
32 #include "includes.h"
33 #include "libcli/ldap/ldap_ndr.h"
34 #include "ldb_module.h"
35 #include "dsdb/samdb/samdb.h"
36 #include "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                         enum ndr_err_code ndr_err;
1165                         struct ldb_val guid_value;
1166                         struct GUID guid;
1167                         /* a new GUID */
1168                         guid = GUID_random();
1169                         /* generated NDR encoded values */
1170                         ndr_err = ndr_push_struct_blob(&guid_value, ac->msg,
1171                                                        NULL,
1172                                                        &guid,
1173                                                        (ndr_push_flags_fn_t)ndr_push_GUID);
1174                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1175                                 ldb_oom(ldb);
1176                                 return LDB_ERR_OPERATIONS_ERROR;
1177                         }
1178                         ret = ldb_msg_add_value(ac->msg, "schemaIDGUID", &guid_value, NULL);
1179                         if (ret != LDB_SUCCESS) {
1180                                 ldb_oom(ldb);
1181                                 return ret;
1182                         }
1183                 }
1184
1185                 ret = samldb_add_step(ac, samldb_add_entry);
1186                 if (ret != LDB_SUCCESS) return ret;
1187
1188                 ret = samldb_add_step(ac, samldb_find_for_defaultObjectCategory);
1189                 if (ret != LDB_SUCCESS) return ret;
1190
1191                 ret = samldb_add_step(ac, samldb_set_defaultObjectCategory);
1192                 if (ret != LDB_SUCCESS) return ret;
1193
1194                 return samldb_first_step(ac);
1195         } else if (strcmp(ac->type, "attributeSchema") == 0) {
1196                 const struct ldb_val *rdn_value;
1197                 rdn_value = ldb_dn_get_rdn_val(ac->msg->dn);
1198                 if (!ldb_msg_find_element(ac->msg, "lDAPDisplayName")) {
1199                         /* the RDN has prefix "CN" */
1200                         ret = ldb_msg_add_string(ac->msg, "lDAPDisplayName",
1201                                 samdb_cn_to_lDAPDisplayName(ac,
1202                                         (const char *) rdn_value->data));
1203                         if (ret != LDB_SUCCESS) {
1204                                 ldb_oom(ldb);
1205                                 return ret;
1206                         }
1207                 }
1208
1209                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
1210                                                   "isSingleValued", "FALSE");
1211                 if (ret != LDB_SUCCESS) return ret;
1212
1213                 if (!ldb_msg_find_element(ac->msg, "schemaIDGUID")) {
1214                         enum ndr_err_code ndr_err;
1215                         struct ldb_val guid_value;
1216                         struct GUID guid;
1217                         /* a new GUID */
1218                         guid = GUID_random();
1219                         /* generated NDR encoded values */
1220                         ndr_err = ndr_push_struct_blob(&guid_value, ac->msg,
1221                                                        NULL,
1222                                                        &guid,
1223                                                        (ndr_push_flags_fn_t)ndr_push_GUID);
1224                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1225                                 ldb_oom(ldb);
1226                                 return LDB_ERR_OPERATIONS_ERROR;
1227                         }
1228                         ret = ldb_msg_add_value(ac->msg, "schemaIDGUID", &guid_value, NULL);
1229                         if (ret != LDB_SUCCESS) {
1230                                 ldb_oom(ldb);
1231                                 return ret;
1232                         }
1233                 }
1234
1235                 ret = samldb_add_step(ac, samldb_add_entry);
1236                 if (ret != LDB_SUCCESS) return ret;
1237
1238                 return samldb_first_step(ac);
1239         } else {
1240                 ldb_asprintf_errstring(ldb,
1241                         "Invalid entry type!");
1242                 return LDB_ERR_OPERATIONS_ERROR;
1243         }
1244
1245         /* check if we have a valid samAccountName */
1246         ret = samldb_add_step(ac, samldb_check_samAccountName);
1247         if (ret != LDB_SUCCESS) return ret;
1248
1249         /* check account_type/group_type */
1250         ret = samldb_add_step(ac, samldb_check_samAccountType);
1251         if (ret != LDB_SUCCESS) return ret;
1252
1253         /* check if we have a valid primary group ID */
1254         if (strcmp(ac->type, "user") == 0) {
1255                 ret = samldb_add_step(ac, samldb_check_primaryGroupID_1);
1256                 if (ret != LDB_SUCCESS) return ret;
1257                 ret = samldb_add_step(ac, samldb_dn_from_sid);
1258                 if (ret != LDB_SUCCESS) return ret;
1259                 ret = samldb_add_step(ac, samldb_check_primaryGroupID_2);
1260                 if (ret != LDB_SUCCESS) return ret;
1261         }
1262
1263         lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
1264                  struct loadparm_context);
1265
1266         sid_generator = lp_sid_generator(lp_ctx);
1267         if (sid_generator == SID_GENERATOR_INTERNAL) {
1268                 /* check if we have a valid SID */
1269                 ac->sid = samdb_result_dom_sid(ac, ac->msg, "objectSid");
1270                 if ( ! ac->sid) {
1271                         ret = samldb_add_step(ac, samldb_new_sid);
1272                         if (ret != LDB_SUCCESS) return ret;
1273                 } else {
1274                         ret = samldb_add_step(ac, samldb_get_sid_domain);
1275                         if (ret != LDB_SUCCESS) return ret;
1276                 }
1277
1278                 ret = samldb_add_step(ac, samldb_notice_sid);
1279                 if (ret != LDB_SUCCESS) return ret;
1280         }
1281
1282         /* finally proceed with adding the entry */
1283         ret = samldb_add_step(ac, samldb_add_entry);
1284         if (ret != LDB_SUCCESS) return ret;
1285
1286         return samldb_first_step(ac);
1287 }
1288
1289 /*
1290  * samldb_foreign_notice_sid (async)
1291  */
1292
1293 static int samldb_foreign_notice_sid_callback(struct ldb_request *req,
1294                                                 struct ldb_reply *ares)
1295 {
1296         struct ldb_context *ldb;
1297         struct samldb_ctx *ac;
1298         const char *nextRid;
1299         const char *name;
1300         int ret;
1301
1302         ac = talloc_get_type(req->context, struct samldb_ctx);
1303         ldb = ldb_module_get_ctx(ac->module);
1304
1305         if (!ares) {
1306                 ret = LDB_ERR_OPERATIONS_ERROR;
1307                 goto done;
1308         }
1309         if (ares->error != LDB_SUCCESS) {
1310                 return ldb_module_done(ac->req, ares->controls,
1311                                         ares->response, ares->error);
1312         }
1313
1314         switch (ares->type) {
1315         case LDB_REPLY_ENTRY:
1316                 /* save entry */
1317                 if (ac->next_rid != 0) {
1318                         /* one too many! */
1319                         ldb_set_errstring(ldb,
1320                                 "Invalid number of results while searching "
1321                                 "for domain object!");
1322                         ret = LDB_ERR_OPERATIONS_ERROR;
1323                         break;
1324                 }
1325
1326                 nextRid = ldb_msg_find_attr_as_string(ares->message,
1327                                                         "nextRid", NULL);
1328                 if (nextRid == NULL) {
1329                         ldb_asprintf_errstring(ldb,
1330                                 "While looking for foreign SID %s attribute nextRid not found in %s",
1331                                 dom_sid_string(ares, ac->sid),
1332                                         ldb_dn_get_linearized(ares->message->dn));
1333                         ret = LDB_ERR_OPERATIONS_ERROR;
1334                         break;
1335                 }
1336
1337                 ac->next_rid = strtol(nextRid, NULL, 0);
1338
1339                 ac->domain_dn = ldb_dn_copy(ac, ares->message->dn);
1340
1341                 name = samdb_result_string(ares->message, "name", NULL);
1342                 ldb_debug(ldb, LDB_DEBUG_TRACE,
1343                          "NOTE (strange but valid): Adding foreign SID "
1344                          "record with SID %s, but this domain (%s) is "
1345                          "not foreign in the database\n",
1346                          dom_sid_string(ares, ac->sid), name);
1347
1348                 talloc_free(ares);
1349                 ret = LDB_SUCCESS;
1350                 break;
1351
1352         case LDB_REPLY_REFERRAL:
1353                 /* ignore */
1354                 talloc_free(ares);
1355                 ret = LDB_SUCCESS;
1356                 break;
1357
1358         case LDB_REPLY_DONE:
1359                 talloc_free(ares);
1360
1361                 /* if this is a fake foreign SID, notice the SID */
1362                 if (ac->domain_dn) {
1363                         ret = samldb_notice_sid(ac);
1364                         break;
1365                 }
1366
1367                 /* found, go on */
1368                 ret = samldb_next_step(ac);
1369                 break;
1370         }
1371
1372 done:
1373         if (ret != LDB_SUCCESS) {
1374                 return ldb_module_done(ac->req, NULL, NULL, ret);
1375         }
1376
1377         return LDB_SUCCESS;
1378 }
1379
1380 /* Find a domain object in the parents of a particular DN. */
1381 static int samldb_foreign_notice_sid(struct samldb_ctx *ac)
1382 {
1383         struct ldb_context *ldb;
1384         static const char * const attrs[3] = { "nextRid", "name", NULL };
1385         struct ldb_request *req;
1386         NTSTATUS status;
1387         char *filter;
1388         int ret;
1389
1390         ldb = ldb_module_get_ctx(ac->module);
1391
1392         if (ac->sid == NULL) {
1393                 return LDB_ERR_OPERATIONS_ERROR;
1394         }
1395
1396         status = dom_sid_split_rid(ac, ac->sid, &ac->domain_sid, NULL);
1397         if (!NT_STATUS_IS_OK(status)) {
1398                 return LDB_ERR_OPERATIONS_ERROR;
1399         }
1400
1401
1402         filter = talloc_asprintf(ac, 
1403                                  "(&(objectSid=%s)"
1404                                  "(|(objectClass=domain)"
1405                                  "(objectClass=builtinDomain)))",
1406                                  ldap_encode_ndr_dom_sid(ac, ac->domain_sid));
1407         if (filter == NULL) {
1408                 return LDB_ERR_OPERATIONS_ERROR;
1409         }
1410
1411         ret = ldb_build_search_req(&req, ldb, ac,
1412                                    ldb_get_default_basedn(ldb),
1413                                    LDB_SCOPE_SUBTREE,
1414                                    filter, attrs,
1415                                    NULL,
1416                                    ac, samldb_foreign_notice_sid_callback,
1417                                    ac->req);
1418
1419         if (ret != LDB_SUCCESS) {
1420                 return ret;
1421         }
1422
1423         return ldb_next_request(ac->module, req);
1424 }
1425
1426
1427 static int samldb_fill_foreignSecurityPrincipal_object(struct samldb_ctx *ac)
1428 {
1429         struct ldb_context *ldb;
1430         int ret;
1431
1432         ldb = ldb_module_get_ctx(ac->module);
1433
1434         ac->next_rid = 0;
1435
1436         ac->sid = samdb_result_dom_sid(ac->msg, ac->msg, "objectSid");
1437         if (ac->sid == NULL) {
1438                 ac->sid = dom_sid_parse_talloc(ac->msg,
1439                            (const char *)ldb_dn_get_rdn_val(ac->msg->dn)->data);
1440                 if (!ac->sid) {
1441                         ldb_set_errstring(ldb,
1442                                         "No valid SID found in "
1443                                         "ForeignSecurityPrincipal CN!");
1444                         talloc_free(ac);
1445                         return LDB_ERR_CONSTRAINT_VIOLATION;
1446                 }
1447                 if ( ! samldb_msg_add_sid(ac->msg, "objectSid", ac->sid)) {
1448                         talloc_free(ac);
1449                         return LDB_ERR_OPERATIONS_ERROR;
1450                 }
1451         }
1452
1453         /* check if we need to notice this SID */
1454         ret = samldb_add_step(ac, samldb_foreign_notice_sid);
1455         if (ret != LDB_SUCCESS) return ret;
1456
1457         /* finally proceed with adding the entry */
1458         ret = samldb_add_step(ac, samldb_add_entry);
1459         if (ret != LDB_SUCCESS) return ret;
1460
1461         return samldb_first_step(ac);
1462 }
1463
1464 static int samldb_check_rdn(struct ldb_module *module, struct ldb_dn *dn)
1465 {
1466         struct ldb_context *ldb;
1467         const char *rdn_name;
1468
1469         ldb = ldb_module_get_ctx(module);
1470         rdn_name = ldb_dn_get_rdn_name(dn);
1471
1472         if (strcasecmp(rdn_name, "cn") != 0) {
1473                 ldb_asprintf_errstring(ldb,
1474                                         "Bad RDN (%s=) for samldb object, "
1475                                         "should be CN=!", rdn_name);
1476                 return LDB_ERR_CONSTRAINT_VIOLATION;
1477         }
1478
1479         return LDB_SUCCESS;
1480 }
1481
1482 /*
1483  * samldb_sid_from_dn (async)
1484  */
1485
1486 static int samldb_sid_from_dn(struct samldb_ctx *ac);
1487
1488 static int samldb_sid_from_dn_callback(struct ldb_request *req,
1489         struct ldb_reply *ares)
1490 {
1491         struct ldb_context *ldb;
1492         struct samldb_ctx *ac;
1493         int ret;
1494
1495         ac = talloc_get_type(req->context, struct samldb_ctx);
1496         ldb = ldb_module_get_ctx(ac->module);
1497
1498         if (!ares) {
1499                 ret = LDB_ERR_OPERATIONS_ERROR;
1500                 goto done;
1501         }
1502         if (ares->error != LDB_SUCCESS) {
1503                 return ldb_module_done(ac->req, ares->controls,
1504                                         ares->response, ares->error);
1505         }
1506
1507         switch (ares->type) {
1508         case LDB_REPLY_ENTRY:
1509                 /* save entry */
1510                 if (ac->res_sid != NULL) {
1511                         /* one too many! */
1512                         ldb_set_errstring(ldb,
1513                                 "Invalid number of results while searching "
1514                                 "for domain objects!");
1515                         ret = LDB_ERR_OPERATIONS_ERROR;
1516                         break;
1517                 }
1518                 ac->res_sid = samdb_result_dom_sid(ac, ares->message,
1519                         "objectSid");
1520
1521                 talloc_free(ares);
1522                 ret = LDB_SUCCESS;
1523                 break;
1524
1525         case LDB_REPLY_REFERRAL:
1526                 /* ignore */
1527                 talloc_free(ares);
1528                 ret = LDB_SUCCESS;
1529                 break;
1530
1531         case LDB_REPLY_DONE:
1532                 talloc_free(ares);
1533
1534                 /* found or not found, go on */
1535                 ret = samldb_next_step(ac);
1536                 break;
1537         }
1538
1539 done:
1540         if (ret != LDB_SUCCESS) {
1541                 return ldb_module_done(ac->req, NULL, NULL, ret);
1542         }
1543
1544         return LDB_SUCCESS;
1545 }
1546
1547 /* Finds the SID "res_sid" of an object with a given DN "dn" */
1548 static int samldb_sid_from_dn(struct samldb_ctx *ac)
1549 {
1550         struct ldb_context *ldb;
1551         static const char * const attrs[] = { "objectSid", NULL };
1552         struct ldb_request *req;
1553         int ret;
1554
1555         ldb = ldb_module_get_ctx(ac->module);
1556
1557         if (ac->dn == NULL)
1558                 return LDB_ERR_OPERATIONS_ERROR;
1559
1560         ret = ldb_build_search_req(&req, ldb, ac,
1561                                 ac->dn,
1562                                 LDB_SCOPE_BASE,
1563                                 NULL, attrs,
1564                                 NULL,
1565                                 ac, samldb_sid_from_dn_callback,
1566                                 ac->req);
1567         if (ret != LDB_SUCCESS)
1568                 return ret;
1569
1570         return ldb_next_request(ac->module, req);
1571 }
1572
1573 /*
1574  * samldb_user_dn_to_prim_group_rid (async)
1575  */
1576
1577 static int samldb_user_dn_to_prim_group_rid(struct samldb_ctx *ac);
1578
1579 static int samldb_user_dn_to_prim_group_rid_callback(struct ldb_request *req,
1580         struct ldb_reply *ares)
1581 {
1582         struct ldb_context *ldb;
1583         struct samldb_ctx *ac;
1584         int ret;
1585
1586         ac = talloc_get_type(req->context, struct samldb_ctx);
1587         ldb = ldb_module_get_ctx(ac->module);
1588
1589         if (!ares) {
1590                 ret = LDB_ERR_OPERATIONS_ERROR;
1591                 goto done;
1592         }
1593         if (ares->error != LDB_SUCCESS) {
1594                 return ldb_module_done(ac->req, ares->controls,
1595                                         ares->response, ares->error);
1596         }
1597
1598         switch (ares->type) {
1599         case LDB_REPLY_ENTRY:
1600                 /* save entry */
1601                 if (ac->prim_group_rid != 0) {
1602                         /* one too many! */
1603                         ldb_set_errstring(ldb,
1604                                 "Invalid number of results while searching "
1605                                 "for domain objects!");
1606                         ret = LDB_ERR_OPERATIONS_ERROR;
1607                         break;
1608                 }
1609                 ac->prim_group_rid = samdb_result_uint(ares->message,
1610                         "primaryGroupID", ~0);
1611
1612                 talloc_free(ares);
1613                 ret = LDB_SUCCESS;
1614                 break;
1615
1616         case LDB_REPLY_REFERRAL:
1617                 /* ignore */
1618                 talloc_free(ares);
1619                 ret = LDB_SUCCESS;
1620                 break;
1621
1622         case LDB_REPLY_DONE:
1623                 talloc_free(ares);
1624                 if (ac->prim_group_rid == 0) {
1625                         ldb_asprintf_errstring(ldb,
1626                                 "Unable to get the primary group RID!");
1627                         ret = LDB_ERR_OPERATIONS_ERROR;
1628                         break;
1629                 }
1630
1631                 /* found, go on */
1632                 ret = samldb_next_step(ac);
1633                 break;
1634         }
1635
1636 done:
1637         if (ret != LDB_SUCCESS) {
1638                 return ldb_module_done(ac->req, NULL, NULL, ret);
1639         }
1640
1641         return LDB_SUCCESS;
1642 }
1643
1644 /* Locates the "primaryGroupID" attribute from a certain user specified as
1645  * "user_dn". Saves the result in "prim_group_rid". */
1646 static int samldb_user_dn_to_prim_group_rid(struct samldb_ctx *ac)
1647 {
1648         struct ldb_context *ldb;
1649         static const char * const attrs[] = { "primaryGroupID", NULL };
1650         struct ldb_request *req;
1651         int ret;
1652
1653         ldb = ldb_module_get_ctx(ac->module);
1654
1655         if (ac->user_dn == NULL)
1656                 return LDB_ERR_OPERATIONS_ERROR;
1657
1658         ret = ldb_build_search_req(&req, ldb, ac,
1659                                 ac->user_dn,
1660                                 LDB_SCOPE_BASE,
1661                                 NULL, attrs,
1662                                 NULL,
1663                                 ac, samldb_user_dn_to_prim_group_rid_callback,
1664                                 ac->req);
1665         if (ret != LDB_SUCCESS)
1666                 return ret;
1667
1668         return ldb_next_request(ac->module, req);
1669 }
1670
1671 /*
1672  * samldb_prim_group_rid_to_users_cnt (async)
1673  */
1674
1675 static int samldb_prim_group_rid_to_users_cnt(struct samldb_ctx *ac);
1676
1677 static int samldb_prim_group_rid_to_users_cnt_callback(struct ldb_request *req,
1678         struct ldb_reply *ares)
1679 {
1680         struct ldb_context *ldb;
1681         struct samldb_ctx *ac;
1682         int ret;
1683
1684         ac = talloc_get_type(req->context, struct samldb_ctx);
1685         ldb = ldb_module_get_ctx(ac->module);
1686
1687         if (!ares) {
1688                 ret = LDB_ERR_OPERATIONS_ERROR;
1689                 goto done;
1690         }
1691         if (ares->error != LDB_SUCCESS) {
1692                 return ldb_module_done(ac->req, ares->controls,
1693                                         ares->response, ares->error);
1694         }
1695
1696         switch (ares->type) {
1697         case LDB_REPLY_ENTRY:
1698                 /* save entry */
1699                 ++(ac->users_cnt);
1700
1701                 talloc_free(ares);
1702                 ret = LDB_SUCCESS;
1703                 break;
1704
1705         case LDB_REPLY_REFERRAL:
1706                 /* ignore */
1707                 talloc_free(ares);
1708                 ret = LDB_SUCCESS;
1709                 break;
1710
1711         case LDB_REPLY_DONE:
1712                 talloc_free(ares);
1713
1714                 /* found or not found, go on */
1715                 ret = samldb_next_step(ac);
1716                 break;
1717         }
1718
1719 done:
1720         if (ret != LDB_SUCCESS) {
1721                 return ldb_module_done(ac->req, NULL, NULL, ret);
1722         }
1723
1724         return LDB_SUCCESS;
1725 }
1726
1727 /* Finds the amount of users which have the primary group "prim_group_rid" and
1728  * save the result in "users_cnt" */
1729 static int samldb_prim_group_rid_to_users_cnt(struct samldb_ctx *ac)
1730 {
1731         struct ldb_context *ldb;
1732         static const char * const attrs[] = { NULL };
1733         struct ldb_request *req;
1734         char *filter;
1735         int ret;
1736
1737         ldb = ldb_module_get_ctx(ac->module);
1738
1739         if ((ac->prim_group_rid == 0) || (ac->users_cnt != 0))
1740                 return LDB_ERR_OPERATIONS_ERROR;
1741
1742         filter = talloc_asprintf(ac, "(&(primaryGroupID=%u)(objectclass=user))",
1743                 ac->prim_group_rid);
1744         if (filter == NULL)
1745                 return LDB_ERR_OPERATIONS_ERROR;
1746
1747         ret = ldb_build_search_req(&req, ldb, ac,
1748                                 ldb_get_default_basedn(ldb),
1749                                 LDB_SCOPE_SUBTREE,
1750                                 filter, attrs,
1751                                 NULL,
1752                                 ac,
1753                                 samldb_prim_group_rid_to_users_cnt_callback,
1754                                 ac->req);
1755         if (ret != LDB_SUCCESS)
1756                 return ret;
1757
1758         return ldb_next_request(ac->module, req);
1759 }
1760
1761 /*
1762  * samldb_group_add_member (async)
1763  * samldb_group_del_member (async)
1764  */
1765
1766 static int samldb_group_add_del_member_callback(struct ldb_request *req,
1767         struct ldb_reply *ares)
1768 {
1769         struct ldb_context *ldb;
1770         struct samldb_ctx *ac;
1771         int ret;
1772
1773         ac = talloc_get_type(req->context, struct samldb_ctx);
1774         ldb = ldb_module_get_ctx(ac->module);
1775
1776         if (!ares) {
1777                 ret = LDB_ERR_OPERATIONS_ERROR;
1778                 goto done;
1779         }
1780         if (ares->error != LDB_SUCCESS) {
1781                 if (ares->error == LDB_ERR_NO_SUCH_ATTRIBUTE) {
1782                         /* On error "NO_SUCH_ATTRIBUTE" (delete of an invalid
1783                          * "member" attribute) return "UNWILLING_TO_PERFORM" */
1784                         ares->error = LDB_ERR_UNWILLING_TO_PERFORM;
1785                 }
1786                 return ldb_module_done(ac->req, ares->controls,
1787                                         ares->response, ares->error);
1788         }
1789         if (ares->type != LDB_REPLY_DONE) {
1790                 ldb_set_errstring(ldb,
1791                         "Invalid reply type!");
1792                 ret = LDB_ERR_OPERATIONS_ERROR;
1793                 goto done;
1794         }
1795
1796         ret = samldb_next_step(ac);
1797
1798 done:
1799         if (ret != LDB_SUCCESS) {
1800                 return ldb_module_done(ac->req, NULL, NULL, ret);
1801         }
1802
1803         return LDB_SUCCESS;
1804 }
1805
1806 /* Adds a member with DN "member_dn" to a group with DN "group_dn" */
1807 static int samldb_group_add_member(struct samldb_ctx *ac)
1808 {
1809         struct ldb_context *ldb;
1810         struct ldb_request *req;
1811         struct ldb_message *msg;
1812         int ret;
1813
1814         ldb = ldb_module_get_ctx(ac->module);
1815
1816         if ((ac->group_dn == NULL) || (ac->member_dn == NULL))
1817                 return LDB_ERR_OPERATIONS_ERROR;
1818
1819         msg = ldb_msg_new(ac);
1820         msg->dn = ac->group_dn;
1821         samdb_msg_add_addval(ldb, ac, msg, "member",
1822                 ldb_dn_get_linearized(ac->member_dn));
1823
1824         ret = ldb_build_mod_req(&req, ldb, ac,
1825                                 msg, NULL,
1826                                 ac, samldb_group_add_del_member_callback,
1827                                 ac->req);
1828         if (ret != LDB_SUCCESS)
1829                 return ret;
1830
1831         return ldb_next_request(ac->module, req);
1832 }
1833
1834 /* Removes a member with DN "member_dn" from a group with DN "group_dn" */
1835 static int samldb_group_del_member(struct samldb_ctx *ac)
1836 {
1837         struct ldb_context *ldb;
1838         struct ldb_request *req;
1839         struct ldb_message *msg;
1840         int ret;
1841
1842         ldb = ldb_module_get_ctx(ac->module);
1843
1844         if ((ac->group_dn == NULL) || (ac->member_dn == NULL))
1845                 return LDB_ERR_OPERATIONS_ERROR;
1846
1847         msg = ldb_msg_new(ac);
1848         msg->dn = ac->group_dn;
1849         samdb_msg_add_delval(ldb, ac, msg, "member",
1850                 ldb_dn_get_linearized(ac->member_dn));
1851
1852         ret = ldb_build_mod_req(&req, ldb, ac,
1853                                 msg, NULL,
1854                                 ac, samldb_group_add_del_member_callback,
1855                                 ac->req);
1856         if (ret != LDB_SUCCESS)
1857                 return ret;
1858
1859         return ldb_next_request(ac->module, req);
1860 }
1861
1862
1863 static int samldb_prim_group_change_1(struct samldb_ctx *ac)
1864 {
1865         struct ldb_context *ldb;
1866         uint32_t rid;
1867
1868         ldb = ldb_module_get_ctx(ac->module);
1869
1870         ac->user_dn = ac->msg->dn;
1871
1872         rid = samdb_result_uint(ac->msg, "primaryGroupID", ~0);
1873         ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
1874         if (ac->sid == NULL)
1875                 return LDB_ERR_OPERATIONS_ERROR;
1876         ac->res_dn = NULL;
1877
1878         ac->prim_group_rid = 0;
1879
1880         return samldb_next_step(ac);
1881 }
1882
1883 static int samldb_prim_group_change_2(struct samldb_ctx *ac)
1884 {
1885         struct ldb_context *ldb;
1886
1887         ldb = ldb_module_get_ctx(ac->module);
1888
1889         if (ac->res_dn != NULL)
1890                 ac->new_prim_group_dn = ac->res_dn;
1891         else
1892                 return LDB_ERR_UNWILLING_TO_PERFORM;
1893
1894         ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb),
1895                 ac->prim_group_rid);
1896         if (ac->sid == NULL)
1897                 return LDB_ERR_OPERATIONS_ERROR;
1898         ac->res_dn = NULL;
1899
1900         return samldb_next_step(ac);
1901 }
1902
1903 static int samldb_prim_group_change_4(struct samldb_ctx *ac);
1904 static int samldb_prim_group_change_5(struct samldb_ctx *ac);
1905 static int samldb_prim_group_change_6(struct samldb_ctx *ac);
1906
1907 static int samldb_prim_group_change_3(struct samldb_ctx *ac)
1908 {
1909         int ret;
1910
1911         if (ac->res_dn != NULL)
1912                 ac->old_prim_group_dn = ac->res_dn;
1913         else
1914                 return LDB_ERR_UNWILLING_TO_PERFORM;
1915
1916         /* Only update when the primary group changed */
1917         if (ldb_dn_compare(ac->old_prim_group_dn, ac->new_prim_group_dn) != 0) {
1918                 ac->member_dn = ac->user_dn;
1919                 /* Remove the "member" attribute of the actual (new) primary
1920                  * group */
1921
1922                 ret = samldb_add_step(ac, samldb_prim_group_change_4);
1923                 if (ret != LDB_SUCCESS) return ret;
1924
1925                 ret = samldb_add_step(ac, samldb_group_del_member);
1926                 if (ret != LDB_SUCCESS) return ret;
1927
1928                 /* Add a "member" attribute for the previous primary group */
1929
1930                 ret = samldb_add_step(ac, samldb_prim_group_change_5);
1931                 if (ret != LDB_SUCCESS) return ret;
1932
1933                 ret = samldb_add_step(ac, samldb_group_add_member);
1934                 if (ret != LDB_SUCCESS) return ret;
1935         }
1936
1937         ret = samldb_add_step(ac, samldb_prim_group_change_6);
1938         if (ret != LDB_SUCCESS) return ret;
1939
1940         return samldb_next_step(ac);
1941 }
1942
1943 static int samldb_prim_group_change_4(struct samldb_ctx *ac)
1944 {
1945         ac->group_dn = ac->new_prim_group_dn;
1946
1947         return samldb_next_step(ac);
1948 }
1949
1950 static int samldb_prim_group_change_5(struct samldb_ctx *ac)
1951 {
1952         ac->group_dn = ac->old_prim_group_dn;
1953
1954         return samldb_next_step(ac);
1955 }
1956
1957 static int samldb_prim_group_change_6(struct samldb_ctx *ac)
1958 {
1959         return ldb_next_request(ac->module, ac->req);
1960 }
1961
1962 static int samldb_prim_group_change(struct samldb_ctx *ac)
1963 {
1964         int ret;
1965
1966         /* Finds out the DN of the new primary group */
1967
1968         ret = samldb_add_step(ac, samldb_prim_group_change_1);
1969         if (ret != LDB_SUCCESS) return ret;
1970
1971         ret = samldb_add_step(ac, samldb_dn_from_sid);
1972         if (ret != LDB_SUCCESS) return ret;
1973
1974         ret = samldb_add_step(ac, samldb_user_dn_to_prim_group_rid);
1975         if (ret != LDB_SUCCESS) return ret;
1976
1977         /* Finds out the DN of the old primary group */
1978
1979         ret = samldb_add_step(ac, samldb_prim_group_change_2);
1980         if (ret != LDB_SUCCESS) return ret;
1981
1982         ret = samldb_add_step(ac, samldb_dn_from_sid);
1983         if (ret != LDB_SUCCESS) return ret;
1984
1985         ret = samldb_add_step(ac, samldb_prim_group_change_3);
1986         if (ret != LDB_SUCCESS) return ret;
1987
1988         return samldb_first_step(ac);
1989 }
1990
1991
1992 static int samldb_member_check_1(struct samldb_ctx *ac)
1993 {
1994         struct ldb_context *ldb;
1995         struct ldb_message_element *el;
1996
1997         ldb = ldb_module_get_ctx(ac->module);
1998
1999         el = ldb_msg_find_element(ac->msg, "member");
2000
2001         ac->user_dn = ldb_dn_from_ldb_val(ac, ldb, &el->values[ac->cnt]);
2002         if (!ldb_dn_validate(ac->user_dn))
2003                 return LDB_ERR_OPERATIONS_ERROR;
2004         ac->prim_group_rid = 0;
2005
2006         return samldb_next_step(ac);
2007 }
2008
2009 static int samldb_member_check_2(struct samldb_ctx *ac)
2010 {
2011         struct ldb_context *ldb;
2012
2013         ldb = ldb_module_get_ctx(ac->module);
2014
2015         ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb),
2016                 ac->prim_group_rid);
2017         if (ac->sid == NULL)
2018                 return LDB_ERR_OPERATIONS_ERROR;
2019         ac->res_dn = NULL;
2020
2021         return samldb_next_step(ac);
2022 }
2023
2024 static int samldb_member_check_3(struct samldb_ctx *ac)
2025 {
2026         if (ldb_dn_compare(ac->res_dn, ac->msg->dn) == 0)
2027                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
2028
2029         ++(ac->cnt);
2030
2031         return samldb_next_step(ac);
2032 }
2033
2034 static int samldb_member_check_4(struct samldb_ctx *ac)
2035 {
2036         return ldb_next_request(ac->module, ac->req);
2037 }
2038
2039 static int samldb_member_check(struct samldb_ctx *ac)
2040 {
2041         struct ldb_message_element *el;
2042         int i, ret;
2043
2044         el = ldb_msg_find_element(ac->msg, "member");
2045         ac->cnt = 0;
2046         for (i = 0; i < el->num_values; i++) {
2047                 /* Denies to add "member"s to groups which are primary ones
2048                  * for them */
2049                 ret = samldb_add_step(ac, samldb_member_check_1);
2050                 if (ret != LDB_SUCCESS) return ret;
2051
2052                 ret = samldb_add_step(ac, samldb_user_dn_to_prim_group_rid);
2053                 if (ret != LDB_SUCCESS) return ret;
2054
2055                 ret = samldb_add_step(ac, samldb_member_check_2);
2056                 if (ret != LDB_SUCCESS) return ret;
2057
2058                 ret = samldb_add_step(ac, samldb_dn_from_sid);
2059                 if (ret != LDB_SUCCESS) return ret;
2060
2061                 ret = samldb_add_step(ac, samldb_member_check_3);
2062                 if (ret != LDB_SUCCESS) return ret;
2063         }
2064
2065         ret = samldb_add_step(ac, samldb_member_check_4);
2066         if (ret != LDB_SUCCESS) return ret;
2067
2068         return samldb_first_step(ac);
2069 }
2070
2071
2072 static int samldb_prim_group_users_check_1(struct samldb_ctx *ac)
2073 {
2074         ac->dn = ac->req->op.del.dn;
2075         ac->res_sid = NULL;
2076
2077         return samldb_next_step(ac);
2078 }
2079
2080 static int samldb_prim_group_users_check_2(struct samldb_ctx *ac)
2081 {
2082         NTSTATUS status;
2083         uint32_t rid;
2084
2085         if (ac->res_sid == NULL) {
2086                 /* No SID - therefore ok here */
2087                 return ldb_next_request(ac->module, ac->req);
2088         }
2089         status = dom_sid_split_rid(ac, ac->res_sid, NULL, &rid);
2090         if (!NT_STATUS_IS_OK(status))
2091                 return LDB_ERR_OPERATIONS_ERROR;
2092
2093         if (rid == 0) {
2094                 /* Special object (security principal?) */
2095                 return ldb_next_request(ac->module, ac->req);
2096         }
2097
2098         ac->prim_group_rid = rid;
2099         ac->users_cnt = 0;
2100
2101         return samldb_next_step(ac);
2102 }
2103
2104 static int samldb_prim_group_users_check_3(struct samldb_ctx *ac)
2105 {
2106         if (ac->users_cnt > 0)
2107                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
2108
2109         return ldb_next_request(ac->module, ac->req);
2110 }
2111
2112 static int samldb_prim_group_users_check(struct samldb_ctx *ac)
2113 {
2114         int ret;
2115
2116         /* Finds out the SID/RID of the domain object */
2117
2118         ret = samldb_add_step(ac, samldb_prim_group_users_check_1);
2119         if (ret != LDB_SUCCESS) return ret;
2120
2121         ret = samldb_add_step(ac, samldb_sid_from_dn);
2122         if (ret != LDB_SUCCESS) return ret;
2123
2124         /* Deny delete requests from groups which are primary ones */
2125
2126         ret = samldb_add_step(ac, samldb_prim_group_users_check_2);
2127         if (ret != LDB_SUCCESS) return ret;
2128
2129         ret = samldb_add_step(ac, samldb_prim_group_rid_to_users_cnt);
2130         if (ret != LDB_SUCCESS) return ret;
2131
2132         ret = samldb_add_step(ac, samldb_prim_group_users_check_3);
2133         if (ret != LDB_SUCCESS) return ret;
2134
2135         return samldb_first_step(ac);
2136 }
2137
2138
2139 /* add */
2140 static int samldb_add(struct ldb_module *module, struct ldb_request *req)
2141 {
2142         struct ldb_context *ldb;
2143         struct samldb_ctx *ac;
2144         int ret;
2145
2146         ldb = ldb_module_get_ctx(module);
2147         ldb_debug(ldb, LDB_DEBUG_TRACE, "samldb_add\n");
2148
2149         /* do not manipulate our control entries */
2150         if (ldb_dn_is_special(req->op.add.message->dn)) {
2151                 return ldb_next_request(module, req);
2152         }
2153
2154         ac = samldb_ctx_init(module, req);
2155         if (ac == NULL) {
2156                 return LDB_ERR_OPERATIONS_ERROR;
2157         }
2158
2159         /* build the new msg */
2160         ac->msg = ldb_msg_copy(ac, ac->req->op.add.message);
2161         if (!ac->msg) {
2162                 talloc_free(ac);
2163                 ldb_debug(ldb, LDB_DEBUG_FATAL,
2164                           "samldb_add: ldb_msg_copy failed!\n");
2165                 return LDB_ERR_OPERATIONS_ERROR;
2166         }
2167
2168         if (samdb_find_attribute(ldb, ac->msg,
2169                                  "objectclass", "computer") != NULL) {
2170
2171                 /* make sure the computer object also has the 'user'
2172                  * objectclass so it will be handled by the next call */
2173                 ret = samdb_find_or_add_value(ldb, ac->msg,
2174                                                 "objectclass", "user");
2175                 if (ret != LDB_SUCCESS) {
2176                         talloc_free(ac);
2177                         return ret;
2178                 }
2179         }
2180
2181         if (samdb_find_attribute(ldb, ac->msg,
2182                                  "objectclass", "user") != NULL) {
2183
2184                 ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
2185                 if (ret != LDB_SUCCESS) {
2186                         talloc_free(ac);
2187                         return ret;
2188                 }
2189
2190                 return samldb_fill_object(ac, "user");
2191         }
2192
2193         if (samdb_find_attribute(ldb, ac->msg,
2194                                  "objectclass", "group") != NULL) {
2195
2196                 ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
2197                 if (ret != LDB_SUCCESS) {
2198                         talloc_free(ac);
2199                         return ret;
2200                 }
2201
2202                 return samldb_fill_object(ac, "group");
2203         }
2204
2205         /* perhaps a foreignSecurityPrincipal? */
2206         if (samdb_find_attribute(ldb, ac->msg,
2207                                  "objectclass",
2208                                  "foreignSecurityPrincipal") != NULL) {
2209
2210                 ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
2211                 if (ret != LDB_SUCCESS) {
2212                         talloc_free(ac);
2213                         return ret;
2214                 }
2215
2216                 return samldb_fill_foreignSecurityPrincipal_object(ac);
2217         }
2218
2219         if (samdb_find_attribute(ldb, ac->msg,
2220                                  "objectclass", "classSchema") != NULL) {
2221
2222                 ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
2223                 if (ret != LDB_SUCCESS) {
2224                         talloc_free(ac);
2225                         return ret;
2226                 }
2227
2228                 return samldb_fill_object(ac, "classSchema");
2229         }
2230
2231         if (samdb_find_attribute(ldb, ac->msg,
2232                                  "objectclass", "attributeSchema") != NULL) {
2233
2234                 ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
2235                 if (ret != LDB_SUCCESS) {
2236                         talloc_free(ac);
2237                         return ret;
2238                 }
2239
2240                 return samldb_fill_object(ac, "attributeSchema");
2241         }
2242
2243         talloc_free(ac);
2244
2245         /* nothing matched, go on */
2246         return ldb_next_request(module, req);
2247 }
2248
2249 /* modify */
2250 static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
2251 {
2252         struct ldb_context *ldb;
2253         struct ldb_message *msg;
2254         struct ldb_message_element *el, *el2;
2255         int ret;
2256         uint32_t account_type;
2257
2258         if (ldb_dn_is_special(req->op.mod.message->dn)) {
2259                 /* do not manipulate our control entries */
2260                 return ldb_next_request(module, req);
2261         }
2262
2263         ldb = ldb_module_get_ctx(module);
2264
2265         if (ldb_msg_find_element(req->op.mod.message, "sAMAccountType") != NULL) {
2266                 ldb_asprintf_errstring(ldb,
2267                         "sAMAccountType must not be specified!");
2268                 return LDB_ERR_UNWILLING_TO_PERFORM;
2269         }
2270
2271         /* TODO: do not modify original request, create a new one */
2272
2273         el = ldb_msg_find_element(req->op.mod.message, "groupType");
2274         if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
2275                 uint32_t group_type;
2276
2277                 req->op.mod.message = msg = ldb_msg_copy_shallow(req,
2278                         req->op.mod.message);
2279
2280                 group_type = strtoul((const char *)el->values[0].data, NULL, 0);
2281                 account_type =  ds_gtype2atype(group_type);
2282                 ret = samdb_msg_add_uint(ldb, msg, msg,
2283                                          "sAMAccountType",
2284                                          account_type);
2285                 if (ret != LDB_SUCCESS) {
2286                         return ret;
2287                 }
2288                 el2 = ldb_msg_find_element(msg, "sAMAccountType");
2289                 el2->flags = LDB_FLAG_MOD_REPLACE;
2290         }
2291
2292         el = ldb_msg_find_element(req->op.mod.message, "userAccountControl");
2293         if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
2294                 uint32_t user_account_control;
2295
2296                 req->op.mod.message = msg = ldb_msg_copy_shallow(req,
2297                         req->op.mod.message);
2298
2299                 user_account_control = strtoul((const char *)el->values[0].data,
2300                         NULL, 0);
2301                 account_type = ds_uf2atype(user_account_control);
2302                 ret = samdb_msg_add_uint(ldb, msg, msg,
2303                                          "sAMAccountType",
2304                                          account_type);
2305                 if (ret != LDB_SUCCESS) {
2306                         return ret;
2307                 }
2308                 el2 = ldb_msg_find_element(msg, "sAMAccountType");
2309                 el2->flags = LDB_FLAG_MOD_REPLACE;
2310
2311                 if (user_account_control & UF_SERVER_TRUST_ACCOUNT) {
2312                         ret = samdb_msg_add_string(ldb, msg, msg,
2313                                                    "isCriticalSystemObject", "TRUE");
2314                         if (ret != LDB_SUCCESS) {
2315                                 return ret;
2316                         }
2317                         el2 = ldb_msg_find_element(msg, "isCriticalSystemObject");
2318                         el2->flags = LDB_FLAG_MOD_REPLACE;
2319                 }
2320         }
2321
2322         el = ldb_msg_find_element(req->op.mod.message, "primaryGroupID");
2323         if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
2324                 struct samldb_ctx *ac;
2325
2326                 ac = samldb_ctx_init(module, req);
2327                 if (ac == NULL)
2328                         return LDB_ERR_OPERATIONS_ERROR;
2329
2330                 req->op.mod.message = ac->msg = ldb_msg_copy_shallow(req,
2331                         req->op.mod.message);
2332
2333                 return samldb_prim_group_change(ac);
2334         }
2335
2336         el = ldb_msg_find_element(req->op.mod.message, "member");
2337         if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
2338                 struct samldb_ctx *ac;
2339
2340                 ac = samldb_ctx_init(module, req);
2341                 if (ac == NULL)
2342                         return LDB_ERR_OPERATIONS_ERROR;
2343
2344                 req->op.mod.message = ac->msg = ldb_msg_copy_shallow(req,
2345                         req->op.mod.message);
2346
2347                 return samldb_member_check(ac);
2348         }
2349
2350         /* nothing matched, go on */
2351         return ldb_next_request(module, req);
2352 }
2353
2354 /* delete */
2355 static int samldb_delete(struct ldb_module *module, struct ldb_request *req)
2356 {
2357         struct samldb_ctx *ac;
2358
2359         if (ldb_dn_is_special(req->op.del.dn)) {
2360                 /* do not manipulate our control entries */
2361                 return ldb_next_request(module, req);
2362         }
2363
2364         ac = samldb_ctx_init(module, req);
2365         if (ac == NULL)
2366                 return LDB_ERR_OPERATIONS_ERROR;
2367
2368         return samldb_prim_group_users_check(ac);
2369 }
2370
2371
2372 static int samldb_init(struct ldb_module *module)
2373 {
2374         return ldb_next_init(module);
2375 }
2376
2377 _PUBLIC_ const struct ldb_module_ops ldb_samldb_module_ops = {
2378         .name          = "samldb",
2379         .init_context  = samldb_init,
2380         .add           = samldb_add,
2381         .modify        = samldb_modify,
2382         .del           = samldb_delete
2383 };
2384