s4:SAMLDB LDB module - Fix trailing whitespaces
[ira/wip.git] / source4 / dsdb / samdb / ldb_modules / samldb.c
1 /*
2    SAM ldb module
3
4    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
5    Copyright (C) Simo Sorce  2004-2008
6    Copyright (C) Matthias Dieter Wallnöfer 2009
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 /*
23  *  Name: ldb
24  *
25  *  Component: ldb samldb module
26  *
27  *  Description: add embedded user/group creation functionality
28  *
29  *  Author: Simo Sorce
30  */
31
32 #include "includes.h"
33 #include "libcli/ldap/ldap_ndr.h"
34 #include "ldb_module.h"
35 #include "dsdb/samdb/samdb.h"
36 #include "dsdb/samdb/ldb_modules/util.h"
37 #include "libcli/security/security.h"
38 #include "librpc/gen_ndr/ndr_security.h"
39 #include "../lib/util/util_ldb.h"
40 #include "ldb_wrap.h"
41 #include "param/param.h"
42
43 struct samldb_ctx;
44
45 typedef int (*samldb_step_fn_t)(struct samldb_ctx *);
46
47 struct samldb_step {
48         struct samldb_step *next;
49         samldb_step_fn_t fn;
50 };
51
52 struct samldb_ctx {
53         struct ldb_module *module;
54         struct ldb_request *req;
55
56         /* used for add operations */
57         const char *type;
58
59         /* the resulting message */
60         struct ldb_message *msg;
61
62         /* used to find parent domain */
63         struct ldb_dn *check_dn;
64         struct ldb_dn *domain_dn;
65         struct dom_sid *domain_sid;
66         uint32_t next_rid;
67
68         /* holds the entry SID */
69         struct dom_sid *sid;
70
71         /* holds a generic dn */
72         struct ldb_dn *dn;
73
74         /* used in conjunction with "sid" in "samldb_dn_from_sid" */
75         struct ldb_dn *res_dn;
76
77         /* used in conjunction with "dn" in "samldb_sid_from_dn" */
78         struct dom_sid *res_sid;
79
80         /* used in "samldb_user_dn_to_prim_group_rid" */
81         uint32_t prim_group_rid;
82
83         /* used in conjunction with "prim_group_rid" in
84          * "samldb_prim_group_rid_to_users_cnt" */
85         unsigned int users_cnt;
86
87         /* used in "samldb_group_add_member" and "samldb_group_del_member" */
88         struct ldb_dn *group_dn;
89         struct ldb_dn *member_dn;
90
91         /* used in "samldb_primary_group_change" */
92         struct ldb_dn *user_dn;
93         struct ldb_dn *old_prim_group_dn, *new_prim_group_dn;
94
95         /* generic counter - used in "samldb_member_check" */
96         unsigned int cnt;
97
98         /* all the async steps necessary to complete the operation */
99         struct samldb_step *steps;
100         struct samldb_step *curstep;
101
102         /* If someone set an ares to forward controls and response back to the caller */
103         struct ldb_reply *ares;
104 };
105
106 static struct samldb_ctx *samldb_ctx_init(struct ldb_module *module,
107                                           struct ldb_request *req)
108 {
109         struct ldb_context *ldb;
110         struct samldb_ctx *ac;
111
112         ldb = ldb_module_get_ctx(module);
113
114         ac = talloc_zero(req, struct samldb_ctx);
115         if (ac == NULL) {
116                 ldb_oom(ldb);
117                 return NULL;
118         }
119
120         ac->module = module;
121         ac->req = req;
122
123         return ac;
124 }
125
126 static int samldb_add_step(struct samldb_ctx *ac, samldb_step_fn_t fn)
127 {
128         struct samldb_step *step, *stepper;
129
130         step = talloc_zero(ac, struct samldb_step);
131         if (step == NULL) {
132                 return LDB_ERR_OPERATIONS_ERROR;
133         }
134
135         step->fn = fn;
136
137         if (ac->steps == NULL) {
138                 ac->steps = step;
139                 ac->curstep = step;
140         } else {
141                 if (ac->curstep == NULL)
142                         return LDB_ERR_OPERATIONS_ERROR;
143                 for (stepper = ac->curstep; stepper->next != NULL;
144                         stepper = stepper->next);
145                 stepper->next = step;
146         }
147
148         return LDB_SUCCESS;
149 }
150
151 static int samldb_first_step(struct samldb_ctx *ac)
152 {
153         if (ac->steps == NULL) {
154                 return LDB_ERR_OPERATIONS_ERROR;
155         }
156
157         ac->curstep = ac->steps;
158         return ac->curstep->fn(ac);
159 }
160
161 static int samldb_next_step(struct samldb_ctx *ac)
162 {
163         if (ac->curstep->next) {
164                 ac->curstep = ac->curstep->next;
165                 return ac->curstep->fn(ac);
166         }
167
168         /* we exit the samldb module here */
169         /* If someone set an ares to forward controls and response back to the caller, use them */
170         if (ac->ares) {
171                 return ldb_module_done(ac->req, ac->ares->controls,
172                                        ac->ares->response, LDB_SUCCESS);
173         } else {
174                 return ldb_module_done(ac->req, NULL, NULL, LDB_SUCCESS);
175         }
176 }
177
178 /*
179  * samldb_get_parent_domain (async)
180  */
181
182 static int samldb_get_parent_domain(struct samldb_ctx *ac);
183
184 static int samldb_get_parent_domain_callback(struct ldb_request *req,
185                                              struct ldb_reply *ares)
186 {
187         struct ldb_context *ldb;
188         struct samldb_ctx *ac;
189         const char *nextRid;
190         int ret;
191
192         ac = talloc_get_type(req->context, struct samldb_ctx);
193         ldb = ldb_module_get_ctx(ac->module);
194
195         if (!ares) {
196                 ret = LDB_ERR_OPERATIONS_ERROR;
197                 goto done;
198         }
199         if (ares->error != LDB_SUCCESS) {
200                 return ldb_module_done(ac->req, ares->controls,
201                                         ares->response, ares->error);
202         }
203
204         switch (ares->type) {
205         case LDB_REPLY_ENTRY:
206                 /* save entry */
207                 if ((ac->domain_dn != NULL) || (ac->domain_sid != NULL)) {
208                         /* one too many! */
209                         ldb_set_errstring(ldb,
210                                 "Invalid number of results while searching "
211                                 "for domain object!");
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         struct ldb_context *ldb;
922         struct ldb_message *msg;
923         struct ldb_request *req;
924         int ret;
925
926         ldb = ldb_module_get_ctx(ac->module);
927
928         /* (Re)set the default object category to have it set to the DN in the
929          * storage format */
930         msg = ldb_msg_new(ac);
931         msg->dn = ac->msg->dn;
932         ldb_msg_add_empty(msg, "defaultObjectCategory",
933                           LDB_FLAG_MOD_REPLACE, NULL);
934         ldb_msg_add_steal_string(msg, "defaultObjectCategory",
935                                  ldb_dn_alloc_linearized(msg, ac->dn));
936
937         ret = ldb_build_mod_req(&req, ldb, ac,
938                                 msg, NULL,
939                                 ac,
940                                 samldb_set_defaultObjectCategory_callback,
941                                 ac->req);
942         if (ret != LDB_SUCCESS) {
943                 talloc_free(msg);
944                 return ret;
945         }
946
947         return ldb_next_request(ac->module, req);
948 }
949
950 /*
951  * samldb_find_for_defaultObjectCategory (async)
952  */
953
954 static int samldb_find_for_defaultObjectCategory_callback(struct ldb_request *req,
955                                                           struct ldb_reply *ares)
956 {
957         struct ldb_context *ldb;
958         struct samldb_ctx *ac;
959         int ret;
960
961         ac = talloc_get_type(req->context, struct samldb_ctx);
962         ldb = ldb_module_get_ctx(ac->module);
963
964         if (!ares) {
965                 ret = LDB_ERR_OPERATIONS_ERROR;
966                 goto done;
967         }
968         if (ares->error != LDB_SUCCESS) {
969                 if (ares->error == LDB_ERR_NO_SUCH_OBJECT) {
970                         if (ldb_request_get_control(ac->req,
971                                                     LDB_CONTROL_RELAX_OID) != NULL) {
972                                 /* Don't be pricky when the DN doesn't exist */
973                                 /* if we have the RELAX control specified */
974                                 ac->dn = req->op.search.base;
975                                 return samldb_next_step(ac);
976                         } else {
977                                 ldb_set_errstring(ldb,
978                                         "samldb_find_defaultObjectCategory: "
979                                         "Invalid DN for 'defaultObjectCategory'!");
980                                 ares->error = LDB_ERR_CONSTRAINT_VIOLATION;
981                         }
982                 }
983
984                 return ldb_module_done(ac->req, ares->controls,
985                                        ares->response, ares->error);
986         }
987
988         switch (ares->type) {
989         case LDB_REPLY_ENTRY:
990                 ac->dn = talloc_steal(ac, ares->message->dn);
991
992                 ret = LDB_SUCCESS;
993                 break;
994
995         case LDB_REPLY_REFERRAL:
996                 /* this should not happen */
997                 talloc_free(ares);
998                 ret = LDB_ERR_OPERATIONS_ERROR;
999                 break;
1000
1001         case LDB_REPLY_DONE:
1002                 talloc_free(ares);
1003
1004                 if (ac->dn != NULL) {
1005                         /* when found go on */
1006                         ret = samldb_next_step(ac);
1007                 } else {
1008                         ret = LDB_ERR_OPERATIONS_ERROR;
1009                 }
1010                 break;
1011         }
1012
1013 done:
1014         if (ret != LDB_SUCCESS) {
1015                 return ldb_module_done(ac->req, NULL, NULL, ret);
1016         }
1017
1018         return LDB_SUCCESS;
1019 }
1020
1021 static int samldb_find_for_defaultObjectCategory(struct samldb_ctx *ac)
1022 {
1023         struct ldb_context *ldb;
1024         struct ldb_request *req;
1025         static const char *no_attrs[] = { NULL };
1026         int ret;
1027         const struct ldb_val *val;
1028         struct ldb_dn *def_obj_cat_dn;
1029
1030         ldb = ldb_module_get_ctx(ac->module);
1031
1032         ac->dn = NULL;
1033
1034         val = ldb_msg_find_ldb_val(ac->msg, "defaultObjectCategory");
1035         if (val != NULL) {
1036                 /* "defaultObjectCategory" has been set by the caller. Do some
1037                  * checks for consistency.
1038                  * NOTE: The real constraint check (that 'defaultObjectCategory'
1039                  * is the DN of the new objectclass or any parent of it) is
1040                  * still incomplete.
1041                  * For now we say that 'defaultObjectCategory' is valid if it
1042                  * exists and it is of objectclass "classSchema". */
1043                 def_obj_cat_dn = ldb_dn_from_ldb_val(ac, ldb, val);
1044                 if (def_obj_cat_dn == NULL) {
1045                         ldb_set_errstring(ldb,
1046                                 "samldb_find_defaultObjectCategory: Invalid DN "
1047                                 "for 'defaultObjectCategory'!");
1048                         return LDB_ERR_CONSTRAINT_VIOLATION;
1049                 }
1050         } else {
1051                 /* "defaultObjectCategory" has not been set by the caller. Use
1052                  * the entry DN for it. */
1053                 def_obj_cat_dn = ac->msg->dn;
1054         }
1055
1056         ret = ldb_build_search_req(&req, ldb, ac,
1057                                    def_obj_cat_dn, LDB_SCOPE_BASE,
1058                                    "objectClass=classSchema", no_attrs,
1059                                    NULL,
1060                                    ac, samldb_find_for_defaultObjectCategory_callback,
1061                                    ac->req);
1062         if (ret != LDB_SUCCESS) {
1063                 return ret;
1064         }
1065
1066         ret = dsdb_request_add_controls(ac->module, req,
1067                                         DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT);
1068         if (ret != LDB_SUCCESS) {
1069                 return ret;
1070         }
1071
1072         return ldb_next_request(ac->module, req);
1073 }
1074
1075
1076 /*
1077  * samldb_add_entry (async)
1078  */
1079
1080 static int samldb_add_entry_callback(struct ldb_request *req,
1081                                         struct ldb_reply *ares)
1082 {
1083         struct ldb_context *ldb;
1084         struct samldb_ctx *ac;
1085         int ret;
1086
1087         ac = talloc_get_type(req->context, struct samldb_ctx);
1088         ldb = ldb_module_get_ctx(ac->module);
1089
1090         if (!ares) {
1091                 return ldb_module_done(ac->req, NULL, NULL,
1092                                         LDB_ERR_OPERATIONS_ERROR);
1093         }
1094         if (ares->error != LDB_SUCCESS) {
1095                 return ldb_module_done(ac->req, ares->controls,
1096                                         ares->response, ares->error);
1097         }
1098         if (ares->type != LDB_REPLY_DONE) {
1099                 ldb_set_errstring(ldb,
1100                         "Invalid reply type!\n");
1101                 return ldb_module_done(ac->req, NULL, NULL,
1102                                         LDB_ERR_OPERATIONS_ERROR);
1103         }
1104
1105         /* The caller may wish to get controls back from the add */
1106         ac->ares = talloc_steal(ac, ares);
1107
1108         ret = samldb_next_step(ac);
1109         if (ret != LDB_SUCCESS) {
1110                 return ldb_module_done(ac->req, NULL, NULL, ret);
1111         }
1112         return ret;
1113 }
1114
1115 static int samldb_add_entry(struct samldb_ctx *ac)
1116 {
1117         struct ldb_context *ldb;
1118         struct ldb_request *req;
1119         int ret;
1120
1121         ldb = ldb_module_get_ctx(ac->module);
1122
1123         ret = ldb_build_add_req(&req, ldb, ac,
1124                                 ac->msg,
1125                                 ac->req->controls,
1126                                 ac, samldb_add_entry_callback,
1127                                 ac->req);
1128         if (ret != LDB_SUCCESS) {
1129                 return ret;
1130         }
1131
1132         return ldb_next_request(ac->module, req);
1133 }
1134
1135
1136 static int samldb_fill_object(struct samldb_ctx *ac, const char *type)
1137 {
1138         struct ldb_context *ldb;
1139         struct loadparm_context *lp_ctx;
1140         enum sid_generator sid_generator;
1141         int ret;
1142
1143         ldb = ldb_module_get_ctx(ac->module);
1144
1145         /* search for a parent domain objet */
1146         ac->check_dn = ac->req->op.add.message->dn;
1147         ret = samldb_add_step(ac, samldb_get_parent_domain);
1148         if (ret != LDB_SUCCESS) return ret;
1149
1150         /* Add informations for the different account types */
1151         ac->type = type;
1152         if (strcmp(ac->type, "user") == 0) {
1153                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
1154                         "userAccountControl", "546");
1155                 if (ret != LDB_SUCCESS) return ret;
1156                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
1157                         "badPwdCount", "0");
1158                 if (ret != LDB_SUCCESS) return ret;
1159                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
1160                         "codePage", "0");
1161                 if (ret != LDB_SUCCESS) return ret;
1162                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
1163                         "countryCode", "0");
1164                 if (ret != LDB_SUCCESS) return ret;
1165                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
1166                         "badPasswordTime", "0");
1167                 if (ret != LDB_SUCCESS) return ret;
1168                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
1169                         "lastLogoff", "0");
1170                 if (ret != LDB_SUCCESS) return ret;
1171                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
1172                         "lastLogon", "0");
1173                 if (ret != LDB_SUCCESS) return ret;
1174                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
1175                         "pwdLastSet", "0");
1176                 if (ret != LDB_SUCCESS) return ret;
1177                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
1178                         "primaryGroupID", "513");
1179                 if (ret != LDB_SUCCESS) return ret;
1180                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
1181                         "accountExpires", "9223372036854775807");
1182                 if (ret != LDB_SUCCESS) return ret;
1183                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
1184                         "logonCount", "0");
1185                 if (ret != LDB_SUCCESS) return ret;
1186         } else if (strcmp(ac->type, "group") == 0) {
1187                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
1188                         "groupType", "-2147483646");
1189                 if (ret != LDB_SUCCESS) return ret;
1190         } else if (strcmp(ac->type, "classSchema") == 0) {
1191                 const struct ldb_val *rdn_value;
1192
1193                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
1194                                                   "rdnAttId", "cn");
1195                 if (ret != LDB_SUCCESS) return ret;
1196
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                 if (!ldb_msg_find_element(ac->msg, "schemaIDGUID")) {
1210                         struct GUID guid;
1211                         /* a new GUID */
1212                         guid = GUID_random();
1213                         ret = dsdb_msg_add_guid(ac->msg, &guid, "schemaIDGUID");
1214                         if (ret != LDB_SUCCESS) {
1215                                 ldb_oom(ldb);
1216                                 return ret;
1217                         }
1218                 }
1219
1220                 ret = samldb_add_step(ac, samldb_add_entry);
1221                 if (ret != LDB_SUCCESS) return ret;
1222
1223                 ret = samldb_add_step(ac, samldb_find_for_defaultObjectCategory);
1224                 if (ret != LDB_SUCCESS) return ret;
1225
1226                 ret = samldb_add_step(ac, samldb_set_defaultObjectCategory);
1227                 if (ret != LDB_SUCCESS) return ret;
1228
1229                 return samldb_first_step(ac);
1230         } else if (strcmp(ac->type, "attributeSchema") == 0) {
1231                 const struct ldb_val *rdn_value;
1232                 rdn_value = ldb_dn_get_rdn_val(ac->msg->dn);
1233                 if (!ldb_msg_find_element(ac->msg, "lDAPDisplayName")) {
1234                         /* the RDN has prefix "CN" */
1235                         ret = ldb_msg_add_string(ac->msg, "lDAPDisplayName",
1236                                 samdb_cn_to_lDAPDisplayName(ac,
1237                                         (const char *) rdn_value->data));
1238                         if (ret != LDB_SUCCESS) {
1239                                 ldb_oom(ldb);
1240                                 return ret;
1241                         }
1242                 }
1243
1244                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
1245                                                   "isSingleValued", "FALSE");
1246                 if (ret != LDB_SUCCESS) return ret;
1247
1248                 if (!ldb_msg_find_element(ac->msg, "schemaIDGUID")) {
1249                         struct GUID guid;
1250                         /* a new GUID */
1251                         guid = GUID_random();
1252                         ret = dsdb_msg_add_guid(ac->msg, &guid, "schemaIDGUID");
1253                         if (ret != LDB_SUCCESS) {
1254                                 ldb_oom(ldb);
1255                                 return ret;
1256                         }
1257                 }
1258
1259                 ret = samldb_add_step(ac, samldb_add_entry);
1260                 if (ret != LDB_SUCCESS) return ret;
1261
1262                 return samldb_first_step(ac);
1263         } else {
1264                 ldb_asprintf_errstring(ldb,
1265                         "Invalid entry type!");
1266                 return LDB_ERR_OPERATIONS_ERROR;
1267         }
1268
1269         /* check if we have a valid samAccountName */
1270         ret = samldb_add_step(ac, samldb_check_samAccountName);
1271         if (ret != LDB_SUCCESS) return ret;
1272
1273         /* check account_type/group_type */
1274         ret = samldb_add_step(ac, samldb_check_samAccountType);
1275         if (ret != LDB_SUCCESS) return ret;
1276
1277         /* check if we have a valid primary group ID */
1278         if (strcmp(ac->type, "user") == 0) {
1279                 ret = samldb_add_step(ac, samldb_check_primaryGroupID_1);
1280                 if (ret != LDB_SUCCESS) return ret;
1281                 ret = samldb_add_step(ac, samldb_dn_from_sid);
1282                 if (ret != LDB_SUCCESS) return ret;
1283                 ret = samldb_add_step(ac, samldb_check_primaryGroupID_2);
1284                 if (ret != LDB_SUCCESS) return ret;
1285         }
1286
1287         lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
1288                  struct loadparm_context);
1289
1290         sid_generator = lp_sid_generator(lp_ctx);
1291         if (sid_generator == SID_GENERATOR_INTERNAL) {
1292                 /* check if we have a valid SID */
1293                 ac->sid = samdb_result_dom_sid(ac, ac->msg, "objectSid");
1294                 if ( ! ac->sid) {
1295                         ret = samldb_add_step(ac, samldb_new_sid);
1296                         if (ret != LDB_SUCCESS) return ret;
1297                 } else {
1298                         ret = samldb_add_step(ac, samldb_get_sid_domain);
1299                         if (ret != LDB_SUCCESS) return ret;
1300                 }
1301
1302                 ret = samldb_add_step(ac, samldb_notice_sid);
1303                 if (ret != LDB_SUCCESS) return ret;
1304         }
1305
1306         /* finally proceed with adding the entry */
1307         ret = samldb_add_step(ac, samldb_add_entry);
1308         if (ret != LDB_SUCCESS) return ret;
1309
1310         return samldb_first_step(ac);
1311 }
1312
1313 /*
1314  * samldb_foreign_notice_sid (async)
1315  */
1316
1317 static int samldb_foreign_notice_sid_callback(struct ldb_request *req,
1318                                                 struct ldb_reply *ares)
1319 {
1320         struct ldb_context *ldb;
1321         struct samldb_ctx *ac;
1322         const char *nextRid;
1323         const char *name;
1324         int ret;
1325
1326         ac = talloc_get_type(req->context, struct samldb_ctx);
1327         ldb = ldb_module_get_ctx(ac->module);
1328
1329         if (!ares) {
1330                 ret = LDB_ERR_OPERATIONS_ERROR;
1331                 goto done;
1332         }
1333         if (ares->error != LDB_SUCCESS) {
1334                 return ldb_module_done(ac->req, ares->controls,
1335                                         ares->response, ares->error);
1336         }
1337
1338         switch (ares->type) {
1339         case LDB_REPLY_ENTRY:
1340                 /* save entry */
1341                 if (ac->next_rid != 0) {
1342                         /* one too many! */
1343                         ldb_set_errstring(ldb,
1344                                 "Invalid number of results while searching "
1345                                 "for domain object!");
1346                         ret = LDB_ERR_OPERATIONS_ERROR;
1347                         break;
1348                 }
1349
1350                 nextRid = ldb_msg_find_attr_as_string(ares->message,
1351                                                         "nextRid", NULL);
1352                 if (nextRid == NULL) {
1353                         ldb_asprintf_errstring(ldb,
1354                                 "While looking for foreign SID %s attribute nextRid not found in %s",
1355                                 dom_sid_string(ares, ac->sid),
1356                                         ldb_dn_get_linearized(ares->message->dn));
1357                         ret = LDB_ERR_OPERATIONS_ERROR;
1358                         break;
1359                 }
1360
1361                 ac->next_rid = strtol(nextRid, NULL, 0);
1362
1363                 ac->domain_dn = ldb_dn_copy(ac, ares->message->dn);
1364
1365                 name = samdb_result_string(ares->message, "name", NULL);
1366                 ldb_debug(ldb, LDB_DEBUG_TRACE,
1367                          "NOTE (strange but valid): Adding foreign SID "
1368                          "record with SID %s, but this domain (%s) is "
1369                          "not foreign in the database\n",
1370                          dom_sid_string(ares, ac->sid), name);
1371
1372                 talloc_free(ares);
1373                 ret = LDB_SUCCESS;
1374                 break;
1375
1376         case LDB_REPLY_REFERRAL:
1377                 /* ignore */
1378                 talloc_free(ares);
1379                 ret = LDB_SUCCESS;
1380                 break;
1381
1382         case LDB_REPLY_DONE:
1383                 talloc_free(ares);
1384
1385                 /* if this is a fake foreign SID, notice the SID */
1386                 if (ac->domain_dn) {
1387                         ret = samldb_notice_sid(ac);
1388                         break;
1389                 }
1390
1391                 /* found, go on */
1392                 ret = samldb_next_step(ac);
1393                 break;
1394         }
1395
1396 done:
1397         if (ret != LDB_SUCCESS) {
1398                 return ldb_module_done(ac->req, NULL, NULL, ret);
1399         }
1400
1401         return LDB_SUCCESS;
1402 }
1403
1404 /* Find a domain object in the parents of a particular DN. */
1405 static int samldb_foreign_notice_sid(struct samldb_ctx *ac)
1406 {
1407         struct ldb_context *ldb;
1408         static const char * const attrs[3] = { "nextRid", "name", NULL };
1409         struct ldb_request *req;
1410         NTSTATUS status;
1411         char *filter;
1412         int ret;
1413
1414         ldb = ldb_module_get_ctx(ac->module);
1415
1416         if (ac->sid == NULL) {
1417                 return LDB_ERR_OPERATIONS_ERROR;
1418         }
1419
1420         status = dom_sid_split_rid(ac, ac->sid, &ac->domain_sid, NULL);
1421         if (!NT_STATUS_IS_OK(status)) {
1422                 return LDB_ERR_OPERATIONS_ERROR;
1423         }
1424
1425
1426         filter = talloc_asprintf(ac,
1427                                  "(&(objectSid=%s)"
1428                                  "(|(objectClass=domain)"
1429                                  "(objectClass=builtinDomain)))",
1430                                  ldap_encode_ndr_dom_sid(ac, ac->domain_sid));
1431         if (filter == NULL) {
1432                 return LDB_ERR_OPERATIONS_ERROR;
1433         }
1434
1435         ret = ldb_build_search_req(&req, ldb, ac,
1436                                    ldb_get_default_basedn(ldb),
1437                                    LDB_SCOPE_SUBTREE,
1438                                    filter, attrs,
1439                                    NULL,
1440                                    ac, samldb_foreign_notice_sid_callback,
1441                                    ac->req);
1442
1443         if (ret != LDB_SUCCESS) {
1444                 return ret;
1445         }
1446
1447         return ldb_next_request(ac->module, req);
1448 }
1449
1450
1451 static int samldb_fill_foreignSecurityPrincipal_object(struct samldb_ctx *ac)
1452 {
1453         struct ldb_context *ldb;
1454         int ret;
1455
1456         ldb = ldb_module_get_ctx(ac->module);
1457
1458         ac->next_rid = 0;
1459
1460         ac->sid = samdb_result_dom_sid(ac->msg, ac->msg, "objectSid");
1461         if (ac->sid == NULL) {
1462                 ac->sid = dom_sid_parse_talloc(ac->msg,
1463                            (const char *)ldb_dn_get_rdn_val(ac->msg->dn)->data);
1464                 if (!ac->sid) {
1465                         ldb_set_errstring(ldb,
1466                                         "No valid SID found in "
1467                                         "ForeignSecurityPrincipal CN!");
1468                         talloc_free(ac);
1469                         return LDB_ERR_CONSTRAINT_VIOLATION;
1470                 }
1471                 if ( ! samldb_msg_add_sid(ac->msg, "objectSid", ac->sid)) {
1472                         talloc_free(ac);
1473                         return LDB_ERR_OPERATIONS_ERROR;
1474                 }
1475         }
1476
1477         /* check if we need to notice this SID */
1478         ret = samldb_add_step(ac, samldb_foreign_notice_sid);
1479         if (ret != LDB_SUCCESS) return ret;
1480
1481         /* finally proceed with adding the entry */
1482         ret = samldb_add_step(ac, samldb_add_entry);
1483         if (ret != LDB_SUCCESS) return ret;
1484
1485         return samldb_first_step(ac);
1486 }
1487
1488 static int samldb_check_rdn(struct ldb_module *module, struct ldb_dn *dn)
1489 {
1490         struct ldb_context *ldb;
1491         const char *rdn_name;
1492
1493         ldb = ldb_module_get_ctx(module);
1494         rdn_name = ldb_dn_get_rdn_name(dn);
1495
1496         if (strcasecmp(rdn_name, "cn") != 0) {
1497                 ldb_asprintf_errstring(ldb,
1498                                         "Bad RDN (%s=) for samldb object, "
1499                                         "should be CN=!", rdn_name);
1500                 return LDB_ERR_CONSTRAINT_VIOLATION;
1501         }
1502
1503         return LDB_SUCCESS;
1504 }
1505
1506 /*
1507  * samldb_sid_from_dn (async)
1508  */
1509
1510 static int samldb_sid_from_dn(struct samldb_ctx *ac);
1511
1512 static int samldb_sid_from_dn_callback(struct ldb_request *req,
1513         struct ldb_reply *ares)
1514 {
1515         struct ldb_context *ldb;
1516         struct samldb_ctx *ac;
1517         int ret;
1518
1519         ac = talloc_get_type(req->context, struct samldb_ctx);
1520         ldb = ldb_module_get_ctx(ac->module);
1521
1522         if (!ares) {
1523                 ret = LDB_ERR_OPERATIONS_ERROR;
1524                 goto done;
1525         }
1526         if (ares->error != LDB_SUCCESS) {
1527                 return ldb_module_done(ac->req, ares->controls,
1528                                         ares->response, ares->error);
1529         }
1530
1531         switch (ares->type) {
1532         case LDB_REPLY_ENTRY:
1533                 /* save entry */
1534                 if (ac->res_sid != NULL) {
1535                         /* one too many! */
1536                         ldb_set_errstring(ldb,
1537                                 "Invalid number of results while searching "
1538                                 "for domain objects!");
1539                         ret = LDB_ERR_OPERATIONS_ERROR;
1540                         break;
1541                 }
1542                 ac->res_sid = samdb_result_dom_sid(ac, ares->message,
1543                         "objectSid");
1544
1545                 talloc_free(ares);
1546                 ret = LDB_SUCCESS;
1547                 break;
1548
1549         case LDB_REPLY_REFERRAL:
1550                 /* ignore */
1551                 talloc_free(ares);
1552                 ret = LDB_SUCCESS;
1553                 break;
1554
1555         case LDB_REPLY_DONE:
1556                 talloc_free(ares);
1557
1558                 /* found or not found, go on */
1559                 ret = samldb_next_step(ac);
1560                 break;
1561         }
1562
1563 done:
1564         if (ret != LDB_SUCCESS) {
1565                 return ldb_module_done(ac->req, NULL, NULL, ret);
1566         }
1567
1568         return LDB_SUCCESS;
1569 }
1570
1571 /* Finds the SID "res_sid" of an object with a given DN "dn" */
1572 static int samldb_sid_from_dn(struct samldb_ctx *ac)
1573 {
1574         struct ldb_context *ldb;
1575         static const char * const attrs[] = { "objectSid", NULL };
1576         struct ldb_request *req;
1577         int ret;
1578
1579         ldb = ldb_module_get_ctx(ac->module);
1580
1581         if (ac->dn == NULL)
1582                 return LDB_ERR_OPERATIONS_ERROR;
1583
1584         ret = ldb_build_search_req(&req, ldb, ac,
1585                                 ac->dn,
1586                                 LDB_SCOPE_BASE,
1587                                 NULL, attrs,
1588                                 NULL,
1589                                 ac, samldb_sid_from_dn_callback,
1590                                 ac->req);
1591         if (ret != LDB_SUCCESS)
1592                 return ret;
1593
1594         return ldb_next_request(ac->module, req);
1595 }
1596
1597 /*
1598  * samldb_user_dn_to_prim_group_rid (async)
1599  */
1600
1601 static int samldb_user_dn_to_prim_group_rid(struct samldb_ctx *ac);
1602
1603 static int samldb_user_dn_to_prim_group_rid_callback(struct ldb_request *req,
1604         struct ldb_reply *ares)
1605 {
1606         struct ldb_context *ldb;
1607         struct samldb_ctx *ac;
1608         int ret;
1609
1610         ac = talloc_get_type(req->context, struct samldb_ctx);
1611         ldb = ldb_module_get_ctx(ac->module);
1612
1613         if (!ares) {
1614                 ret = LDB_ERR_OPERATIONS_ERROR;
1615                 goto done;
1616         }
1617         if (ares->error != LDB_SUCCESS) {
1618                 return ldb_module_done(ac->req, ares->controls,
1619                                         ares->response, ares->error);
1620         }
1621
1622         switch (ares->type) {
1623         case LDB_REPLY_ENTRY:
1624                 /* save entry */
1625                 if (ac->prim_group_rid != 0) {
1626                         /* one too many! */
1627                         ldb_set_errstring(ldb,
1628                                 "Invalid number of results while searching "
1629                                 "for domain objects!");
1630                         ret = LDB_ERR_OPERATIONS_ERROR;
1631                         break;
1632                 }
1633                 ac->prim_group_rid = samdb_result_uint(ares->message,
1634                         "primaryGroupID", ~0);
1635
1636                 talloc_free(ares);
1637                 ret = LDB_SUCCESS;
1638                 break;
1639
1640         case LDB_REPLY_REFERRAL:
1641                 /* ignore */
1642                 talloc_free(ares);
1643                 ret = LDB_SUCCESS;
1644                 break;
1645
1646         case LDB_REPLY_DONE:
1647                 talloc_free(ares);
1648                 if (ac->prim_group_rid == 0) {
1649                         ldb_asprintf_errstring(ldb,
1650                                 "Unable to get the primary group RID!");
1651                         ret = LDB_ERR_OPERATIONS_ERROR;
1652                         break;
1653                 }
1654
1655                 /* found, go on */
1656                 ret = samldb_next_step(ac);
1657                 break;
1658         }
1659
1660 done:
1661         if (ret != LDB_SUCCESS) {
1662                 return ldb_module_done(ac->req, NULL, NULL, ret);
1663         }
1664
1665         return LDB_SUCCESS;
1666 }
1667
1668 /* Locates the "primaryGroupID" attribute from a certain user specified as
1669  * "user_dn". Saves the result in "prim_group_rid". */
1670 static int samldb_user_dn_to_prim_group_rid(struct samldb_ctx *ac)
1671 {
1672         struct ldb_context *ldb;
1673         static const char * const attrs[] = { "primaryGroupID", NULL };
1674         struct ldb_request *req;
1675         int ret;
1676
1677         ldb = ldb_module_get_ctx(ac->module);
1678
1679         if (ac->user_dn == NULL)
1680                 return LDB_ERR_OPERATIONS_ERROR;
1681
1682         ret = ldb_build_search_req(&req, ldb, ac,
1683                                 ac->user_dn,
1684                                 LDB_SCOPE_BASE,
1685                                 NULL, attrs,
1686                                 NULL,
1687                                 ac, samldb_user_dn_to_prim_group_rid_callback,
1688                                 ac->req);
1689         if (ret != LDB_SUCCESS)
1690                 return ret;
1691
1692         return ldb_next_request(ac->module, req);
1693 }
1694
1695 /*
1696  * samldb_prim_group_rid_to_users_cnt (async)
1697  */
1698
1699 static int samldb_prim_group_rid_to_users_cnt(struct samldb_ctx *ac);
1700
1701 static int samldb_prim_group_rid_to_users_cnt_callback(struct ldb_request *req,
1702         struct ldb_reply *ares)
1703 {
1704         struct ldb_context *ldb;
1705         struct samldb_ctx *ac;
1706         int ret;
1707
1708         ac = talloc_get_type(req->context, struct samldb_ctx);
1709         ldb = ldb_module_get_ctx(ac->module);
1710
1711         if (!ares) {
1712                 ret = LDB_ERR_OPERATIONS_ERROR;
1713                 goto done;
1714         }
1715         if (ares->error != LDB_SUCCESS) {
1716                 return ldb_module_done(ac->req, ares->controls,
1717                                         ares->response, ares->error);
1718         }
1719
1720         switch (ares->type) {
1721         case LDB_REPLY_ENTRY:
1722                 /* save entry */
1723                 ++(ac->users_cnt);
1724
1725                 talloc_free(ares);
1726                 ret = LDB_SUCCESS;
1727                 break;
1728
1729         case LDB_REPLY_REFERRAL:
1730                 /* ignore */
1731                 talloc_free(ares);
1732                 ret = LDB_SUCCESS;
1733                 break;
1734
1735         case LDB_REPLY_DONE:
1736                 talloc_free(ares);
1737
1738                 /* found or not found, go on */
1739                 ret = samldb_next_step(ac);
1740                 break;
1741         }
1742
1743 done:
1744         if (ret != LDB_SUCCESS) {
1745                 return ldb_module_done(ac->req, NULL, NULL, ret);
1746         }
1747
1748         return LDB_SUCCESS;
1749 }
1750
1751 /* Finds the amount of users which have the primary group "prim_group_rid" and
1752  * save the result in "users_cnt" */
1753 static int samldb_prim_group_rid_to_users_cnt(struct samldb_ctx *ac)
1754 {
1755         struct ldb_context *ldb;
1756         static const char * const attrs[] = { NULL };
1757         struct ldb_request *req;
1758         char *filter;
1759         int ret;
1760
1761         ldb = ldb_module_get_ctx(ac->module);
1762
1763         if ((ac->prim_group_rid == 0) || (ac->users_cnt != 0))
1764                 return LDB_ERR_OPERATIONS_ERROR;
1765
1766         filter = talloc_asprintf(ac, "(&(primaryGroupID=%u)(objectclass=user))",
1767                 ac->prim_group_rid);
1768         if (filter == NULL)
1769                 return LDB_ERR_OPERATIONS_ERROR;
1770
1771         ret = ldb_build_search_req(&req, ldb, ac,
1772                                 ldb_get_default_basedn(ldb),
1773                                 LDB_SCOPE_SUBTREE,
1774                                 filter, attrs,
1775                                 NULL,
1776                                 ac,
1777                                 samldb_prim_group_rid_to_users_cnt_callback,
1778                                 ac->req);
1779         if (ret != LDB_SUCCESS)
1780                 return ret;
1781
1782         return ldb_next_request(ac->module, req);
1783 }
1784
1785 /*
1786  * samldb_group_add_member (async)
1787  * samldb_group_del_member (async)
1788  */
1789
1790 static int samldb_group_add_del_member_callback(struct ldb_request *req,
1791         struct ldb_reply *ares)
1792 {
1793         struct ldb_context *ldb;
1794         struct samldb_ctx *ac;
1795         int ret;
1796
1797         ac = talloc_get_type(req->context, struct samldb_ctx);
1798         ldb = ldb_module_get_ctx(ac->module);
1799
1800         if (!ares) {
1801                 ret = LDB_ERR_OPERATIONS_ERROR;
1802                 goto done;
1803         }
1804         if (ares->error != LDB_SUCCESS) {
1805                 if (ares->error == LDB_ERR_NO_SUCH_ATTRIBUTE) {
1806                         /* On error "NO_SUCH_ATTRIBUTE" (delete of an invalid
1807                          * "member" attribute) return "UNWILLING_TO_PERFORM" */
1808                         ares->error = LDB_ERR_UNWILLING_TO_PERFORM;
1809                 }
1810                 return ldb_module_done(ac->req, ares->controls,
1811                                         ares->response, ares->error);
1812         }
1813         if (ares->type != LDB_REPLY_DONE) {
1814                 ldb_set_errstring(ldb,
1815                         "Invalid reply type!");
1816                 ret = LDB_ERR_OPERATIONS_ERROR;
1817                 goto done;
1818         }
1819
1820         ret = samldb_next_step(ac);
1821
1822 done:
1823         if (ret != LDB_SUCCESS) {
1824                 return ldb_module_done(ac->req, NULL, NULL, ret);
1825         }
1826
1827         return LDB_SUCCESS;
1828 }
1829
1830 /* Adds a member with DN "member_dn" to a group with DN "group_dn" */
1831 static int samldb_group_add_member(struct samldb_ctx *ac)
1832 {
1833         struct ldb_context *ldb;
1834         struct ldb_request *req;
1835         struct ldb_message *msg;
1836         int ret;
1837
1838         ldb = ldb_module_get_ctx(ac->module);
1839
1840         if ((ac->group_dn == NULL) || (ac->member_dn == NULL))
1841                 return LDB_ERR_OPERATIONS_ERROR;
1842
1843         msg = ldb_msg_new(ac);
1844         msg->dn = ac->group_dn;
1845         samdb_msg_add_addval(ldb, ac, msg, "member",
1846                 ldb_dn_get_linearized(ac->member_dn));
1847
1848         ret = ldb_build_mod_req(&req, ldb, ac,
1849                                 msg, NULL,
1850                                 ac, samldb_group_add_del_member_callback,
1851                                 ac->req);
1852         if (ret != LDB_SUCCESS)
1853                 return ret;
1854
1855         return ldb_next_request(ac->module, req);
1856 }
1857
1858 /* Removes a member with DN "member_dn" from a group with DN "group_dn" */
1859 static int samldb_group_del_member(struct samldb_ctx *ac)
1860 {
1861         struct ldb_context *ldb;
1862         struct ldb_request *req;
1863         struct ldb_message *msg;
1864         int ret;
1865
1866         ldb = ldb_module_get_ctx(ac->module);
1867
1868         if ((ac->group_dn == NULL) || (ac->member_dn == NULL))
1869                 return LDB_ERR_OPERATIONS_ERROR;
1870
1871         msg = ldb_msg_new(ac);
1872         msg->dn = ac->group_dn;
1873         samdb_msg_add_delval(ldb, ac, msg, "member",
1874                 ldb_dn_get_linearized(ac->member_dn));
1875
1876         ret = ldb_build_mod_req(&req, ldb, ac,
1877                                 msg, NULL,
1878                                 ac, samldb_group_add_del_member_callback,
1879                                 ac->req);
1880         if (ret != LDB_SUCCESS)
1881                 return ret;
1882
1883         return ldb_next_request(ac->module, req);
1884 }
1885
1886
1887 static int samldb_prim_group_change_1(struct samldb_ctx *ac)
1888 {
1889         struct ldb_context *ldb;
1890         uint32_t rid;
1891
1892         ldb = ldb_module_get_ctx(ac->module);
1893
1894         ac->user_dn = ac->msg->dn;
1895
1896         rid = samdb_result_uint(ac->msg, "primaryGroupID", ~0);
1897         ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
1898         if (ac->sid == NULL)
1899                 return LDB_ERR_OPERATIONS_ERROR;
1900         ac->res_dn = NULL;
1901
1902         ac->prim_group_rid = 0;
1903
1904         return samldb_next_step(ac);
1905 }
1906
1907 static int samldb_prim_group_change_2(struct samldb_ctx *ac)
1908 {
1909         struct ldb_context *ldb;
1910
1911         ldb = ldb_module_get_ctx(ac->module);
1912
1913         if (ac->res_dn != NULL)
1914                 ac->new_prim_group_dn = ac->res_dn;
1915         else
1916                 return LDB_ERR_UNWILLING_TO_PERFORM;
1917
1918         ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb),
1919                 ac->prim_group_rid);
1920         if (ac->sid == NULL)
1921                 return LDB_ERR_OPERATIONS_ERROR;
1922         ac->res_dn = NULL;
1923
1924         return samldb_next_step(ac);
1925 }
1926
1927 static int samldb_prim_group_change_4(struct samldb_ctx *ac);
1928 static int samldb_prim_group_change_5(struct samldb_ctx *ac);
1929 static int samldb_prim_group_change_6(struct samldb_ctx *ac);
1930
1931 static int samldb_prim_group_change_3(struct samldb_ctx *ac)
1932 {
1933         int ret;
1934
1935         if (ac->res_dn != NULL)
1936                 ac->old_prim_group_dn = ac->res_dn;
1937         else
1938                 return LDB_ERR_UNWILLING_TO_PERFORM;
1939
1940         /* Only update when the primary group changed */
1941         if (ldb_dn_compare(ac->old_prim_group_dn, ac->new_prim_group_dn) != 0) {
1942                 ac->member_dn = ac->user_dn;
1943                 /* Remove the "member" attribute of the actual (new) primary
1944                  * group */
1945
1946                 ret = samldb_add_step(ac, samldb_prim_group_change_4);
1947                 if (ret != LDB_SUCCESS) return ret;
1948
1949                 ret = samldb_add_step(ac, samldb_group_del_member);
1950                 if (ret != LDB_SUCCESS) return ret;
1951
1952                 /* Add a "member" attribute for the previous primary group */
1953
1954                 ret = samldb_add_step(ac, samldb_prim_group_change_5);
1955                 if (ret != LDB_SUCCESS) return ret;
1956
1957                 ret = samldb_add_step(ac, samldb_group_add_member);
1958                 if (ret != LDB_SUCCESS) return ret;
1959         }
1960
1961         ret = samldb_add_step(ac, samldb_prim_group_change_6);
1962         if (ret != LDB_SUCCESS) return ret;
1963
1964         return samldb_next_step(ac);
1965 }
1966
1967 static int samldb_prim_group_change_4(struct samldb_ctx *ac)
1968 {
1969         ac->group_dn = ac->new_prim_group_dn;
1970
1971         return samldb_next_step(ac);
1972 }
1973
1974 static int samldb_prim_group_change_5(struct samldb_ctx *ac)
1975 {
1976         ac->group_dn = ac->old_prim_group_dn;
1977
1978         return samldb_next_step(ac);
1979 }
1980
1981 static int samldb_prim_group_change_6(struct samldb_ctx *ac)
1982 {
1983         return ldb_next_request(ac->module, ac->req);
1984 }
1985
1986 static int samldb_prim_group_change(struct samldb_ctx *ac)
1987 {
1988         int ret;
1989
1990         /* Finds out the DN of the new primary group */
1991
1992         ret = samldb_add_step(ac, samldb_prim_group_change_1);
1993         if (ret != LDB_SUCCESS) return ret;
1994
1995         ret = samldb_add_step(ac, samldb_dn_from_sid);
1996         if (ret != LDB_SUCCESS) return ret;
1997
1998         ret = samldb_add_step(ac, samldb_user_dn_to_prim_group_rid);
1999         if (ret != LDB_SUCCESS) return ret;
2000
2001         /* Finds out the DN of the old primary group */
2002
2003         ret = samldb_add_step(ac, samldb_prim_group_change_2);
2004         if (ret != LDB_SUCCESS) return ret;
2005
2006         ret = samldb_add_step(ac, samldb_dn_from_sid);
2007         if (ret != LDB_SUCCESS) return ret;
2008
2009         ret = samldb_add_step(ac, samldb_prim_group_change_3);
2010         if (ret != LDB_SUCCESS) return ret;
2011
2012         return samldb_first_step(ac);
2013 }
2014
2015
2016 static int samldb_member_check_1(struct samldb_ctx *ac)
2017 {
2018         struct ldb_context *ldb;
2019         struct ldb_message_element *el;
2020
2021         ldb = ldb_module_get_ctx(ac->module);
2022
2023         el = ldb_msg_find_element(ac->msg, "member");
2024
2025         ac->user_dn = ldb_dn_from_ldb_val(ac, ldb, &el->values[ac->cnt]);
2026         if (!ldb_dn_validate(ac->user_dn))
2027                 return LDB_ERR_OPERATIONS_ERROR;
2028         ac->prim_group_rid = 0;
2029
2030         return samldb_next_step(ac);
2031 }
2032
2033 static int samldb_member_check_2(struct samldb_ctx *ac)
2034 {
2035         struct ldb_context *ldb;
2036
2037         ldb = ldb_module_get_ctx(ac->module);
2038
2039         ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb),
2040                 ac->prim_group_rid);
2041         if (ac->sid == NULL)
2042                 return LDB_ERR_OPERATIONS_ERROR;
2043         ac->res_dn = NULL;
2044
2045         return samldb_next_step(ac);
2046 }
2047
2048 static int samldb_member_check_3(struct samldb_ctx *ac)
2049 {
2050         if (ldb_dn_compare(ac->res_dn, ac->msg->dn) == 0)
2051                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
2052
2053         ++(ac->cnt);
2054
2055         return samldb_next_step(ac);
2056 }
2057
2058 static int samldb_member_check_4(struct samldb_ctx *ac)
2059 {
2060         return ldb_next_request(ac->module, ac->req);
2061 }
2062
2063 static int samldb_member_check(struct samldb_ctx *ac)
2064 {
2065         struct ldb_message_element *el;
2066         int i, ret;
2067
2068         el = ldb_msg_find_element(ac->msg, "member");
2069         ac->cnt = 0;
2070         for (i = 0; i < el->num_values; i++) {
2071                 /* Denies to add "member"s to groups which are primary ones
2072                  * for them */
2073                 ret = samldb_add_step(ac, samldb_member_check_1);
2074                 if (ret != LDB_SUCCESS) return ret;
2075
2076                 ret = samldb_add_step(ac, samldb_user_dn_to_prim_group_rid);
2077                 if (ret != LDB_SUCCESS) return ret;
2078
2079                 ret = samldb_add_step(ac, samldb_member_check_2);
2080                 if (ret != LDB_SUCCESS) return ret;
2081
2082                 ret = samldb_add_step(ac, samldb_dn_from_sid);
2083                 if (ret != LDB_SUCCESS) return ret;
2084
2085                 ret = samldb_add_step(ac, samldb_member_check_3);
2086                 if (ret != LDB_SUCCESS) return ret;
2087         }
2088
2089         ret = samldb_add_step(ac, samldb_member_check_4);
2090         if (ret != LDB_SUCCESS) return ret;
2091
2092         return samldb_first_step(ac);
2093 }
2094
2095
2096 static int samldb_prim_group_users_check_1(struct samldb_ctx *ac)
2097 {
2098         ac->dn = ac->req->op.del.dn;
2099         ac->res_sid = NULL;
2100
2101         return samldb_next_step(ac);
2102 }
2103
2104 static int samldb_prim_group_users_check_2(struct samldb_ctx *ac)
2105 {
2106         NTSTATUS status;
2107         uint32_t rid;
2108
2109         if (ac->res_sid == NULL) {
2110                 /* No SID - therefore ok here */
2111                 return ldb_next_request(ac->module, ac->req);
2112         }
2113         status = dom_sid_split_rid(ac, ac->res_sid, NULL, &rid);
2114         if (!NT_STATUS_IS_OK(status))
2115                 return LDB_ERR_OPERATIONS_ERROR;
2116
2117         if (rid == 0) {
2118                 /* Special object (security principal?) */
2119                 return ldb_next_request(ac->module, ac->req);
2120         }
2121
2122         ac->prim_group_rid = rid;
2123         ac->users_cnt = 0;
2124
2125         return samldb_next_step(ac);
2126 }
2127
2128 static int samldb_prim_group_users_check_3(struct samldb_ctx *ac)
2129 {
2130         if (ac->users_cnt > 0)
2131                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
2132
2133         return ldb_next_request(ac->module, ac->req);
2134 }
2135
2136 static int samldb_prim_group_users_check(struct samldb_ctx *ac)
2137 {
2138         int ret;
2139
2140         /* Finds out the SID/RID of the domain object */
2141
2142         ret = samldb_add_step(ac, samldb_prim_group_users_check_1);
2143         if (ret != LDB_SUCCESS) return ret;
2144
2145         ret = samldb_add_step(ac, samldb_sid_from_dn);
2146         if (ret != LDB_SUCCESS) return ret;
2147
2148         /* Deny delete requests from groups which are primary ones */
2149
2150         ret = samldb_add_step(ac, samldb_prim_group_users_check_2);
2151         if (ret != LDB_SUCCESS) return ret;
2152
2153         ret = samldb_add_step(ac, samldb_prim_group_rid_to_users_cnt);
2154         if (ret != LDB_SUCCESS) return ret;
2155
2156         ret = samldb_add_step(ac, samldb_prim_group_users_check_3);
2157         if (ret != LDB_SUCCESS) return ret;
2158
2159         return samldb_first_step(ac);
2160 }
2161
2162
2163 /* add */
2164 static int samldb_add(struct ldb_module *module, struct ldb_request *req)
2165 {
2166         struct ldb_context *ldb;
2167         struct samldb_ctx *ac;
2168         int ret;
2169
2170         ldb = ldb_module_get_ctx(module);
2171         ldb_debug(ldb, LDB_DEBUG_TRACE, "samldb_add\n");
2172
2173         /* do not manipulate our control entries */
2174         if (ldb_dn_is_special(req->op.add.message->dn)) {
2175                 return ldb_next_request(module, req);
2176         }
2177
2178         ac = samldb_ctx_init(module, req);
2179         if (ac == NULL) {
2180                 return LDB_ERR_OPERATIONS_ERROR;
2181         }
2182
2183         /* build the new msg */
2184         ac->msg = ldb_msg_copy(ac, ac->req->op.add.message);
2185         if (!ac->msg) {
2186                 talloc_free(ac);
2187                 ldb_debug(ldb, LDB_DEBUG_FATAL,
2188                           "samldb_add: ldb_msg_copy failed!\n");
2189                 return LDB_ERR_OPERATIONS_ERROR;
2190         }
2191
2192         if (samdb_find_attribute(ldb, ac->msg,
2193                                  "objectclass", "computer") != NULL) {
2194
2195                 /* make sure the computer object also has the 'user'
2196                  * objectclass so it will be handled by the next call */
2197                 ret = samdb_find_or_add_value(ldb, ac->msg,
2198                                                 "objectclass", "user");
2199                 if (ret != LDB_SUCCESS) {
2200                         talloc_free(ac);
2201                         return ret;
2202                 }
2203         }
2204
2205         if (samdb_find_attribute(ldb, ac->msg,
2206                                  "objectclass", "user") != NULL) {
2207
2208                 ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
2209                 if (ret != LDB_SUCCESS) {
2210                         talloc_free(ac);
2211                         return ret;
2212                 }
2213
2214                 return samldb_fill_object(ac, "user");
2215         }
2216
2217         if (samdb_find_attribute(ldb, ac->msg,
2218                                  "objectclass", "group") != NULL) {
2219
2220                 ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
2221                 if (ret != LDB_SUCCESS) {
2222                         talloc_free(ac);
2223                         return ret;
2224                 }
2225
2226                 return samldb_fill_object(ac, "group");
2227         }
2228
2229         /* perhaps a foreignSecurityPrincipal? */
2230         if (samdb_find_attribute(ldb, ac->msg,
2231                                  "objectclass",
2232                                  "foreignSecurityPrincipal") != 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_foreignSecurityPrincipal_object(ac);
2241         }
2242
2243         if (samdb_find_attribute(ldb, ac->msg,
2244                                  "objectclass", "classSchema") != NULL) {
2245
2246                 ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
2247                 if (ret != LDB_SUCCESS) {
2248                         talloc_free(ac);
2249                         return ret;
2250                 }
2251
2252                 return samldb_fill_object(ac, "classSchema");
2253         }
2254
2255         if (samdb_find_attribute(ldb, ac->msg,
2256                                  "objectclass", "attributeSchema") != NULL) {
2257
2258                 ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
2259                 if (ret != LDB_SUCCESS) {
2260                         talloc_free(ac);
2261                         return ret;
2262                 }
2263
2264                 return samldb_fill_object(ac, "attributeSchema");
2265         }
2266
2267         talloc_free(ac);
2268
2269         /* nothing matched, go on */
2270         return ldb_next_request(module, req);
2271 }
2272
2273 /* modify */
2274 static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
2275 {
2276         struct ldb_context *ldb;
2277         struct ldb_message *msg;
2278         struct ldb_message_element *el, *el2;
2279         int ret;
2280         uint32_t account_type;
2281
2282         if (ldb_dn_is_special(req->op.mod.message->dn)) {
2283                 /* do not manipulate our control entries */
2284                 return ldb_next_request(module, req);
2285         }
2286
2287         ldb = ldb_module_get_ctx(module);
2288
2289         if (ldb_msg_find_element(req->op.mod.message, "sAMAccountType") != NULL) {
2290                 ldb_asprintf_errstring(ldb,
2291                         "sAMAccountType must not be specified!");
2292                 return LDB_ERR_UNWILLING_TO_PERFORM;
2293         }
2294
2295         /* TODO: do not modify original request, create a new one */
2296
2297         el = ldb_msg_find_element(req->op.mod.message, "groupType");
2298         if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
2299                 uint32_t group_type;
2300
2301                 req->op.mod.message = msg = ldb_msg_copy_shallow(req,
2302                         req->op.mod.message);
2303
2304                 group_type = strtoul((const char *)el->values[0].data, NULL, 0);
2305                 account_type =  ds_gtype2atype(group_type);
2306                 ret = samdb_msg_add_uint(ldb, msg, msg,
2307                                          "sAMAccountType",
2308                                          account_type);
2309                 if (ret != LDB_SUCCESS) {
2310                         return ret;
2311                 }
2312                 el2 = ldb_msg_find_element(msg, "sAMAccountType");
2313                 el2->flags = LDB_FLAG_MOD_REPLACE;
2314         }
2315
2316         el = ldb_msg_find_element(req->op.mod.message, "userAccountControl");
2317         if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
2318                 uint32_t user_account_control;
2319
2320                 req->op.mod.message = msg = ldb_msg_copy_shallow(req,
2321                         req->op.mod.message);
2322
2323                 user_account_control = strtoul((const char *)el->values[0].data,
2324                         NULL, 0);
2325                 account_type = ds_uf2atype(user_account_control);
2326                 ret = samdb_msg_add_uint(ldb, msg, msg,
2327                                          "sAMAccountType",
2328                                          account_type);
2329                 if (ret != LDB_SUCCESS) {
2330                         return ret;
2331                 }
2332                 el2 = ldb_msg_find_element(msg, "sAMAccountType");
2333                 el2->flags = LDB_FLAG_MOD_REPLACE;
2334
2335                 if (user_account_control & UF_SERVER_TRUST_ACCOUNT) {
2336                         ret = samdb_msg_add_string(ldb, msg, msg,
2337                                                    "isCriticalSystemObject", "TRUE");
2338                         if (ret != LDB_SUCCESS) {
2339                                 return ret;
2340                         }
2341                         el2 = ldb_msg_find_element(msg, "isCriticalSystemObject");
2342                         el2->flags = LDB_FLAG_MOD_REPLACE;
2343                 }
2344         }
2345
2346         el = ldb_msg_find_element(req->op.mod.message, "primaryGroupID");
2347         if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
2348                 struct samldb_ctx *ac;
2349
2350                 ac = samldb_ctx_init(module, req);
2351                 if (ac == NULL)
2352                         return LDB_ERR_OPERATIONS_ERROR;
2353
2354                 req->op.mod.message = ac->msg = ldb_msg_copy_shallow(req,
2355                         req->op.mod.message);
2356
2357                 return samldb_prim_group_change(ac);
2358         }
2359
2360         el = ldb_msg_find_element(req->op.mod.message, "member");
2361         if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
2362                 struct samldb_ctx *ac;
2363
2364                 ac = samldb_ctx_init(module, req);
2365                 if (ac == NULL)
2366                         return LDB_ERR_OPERATIONS_ERROR;
2367
2368                 req->op.mod.message = ac->msg = ldb_msg_copy_shallow(req,
2369                         req->op.mod.message);
2370
2371                 return samldb_member_check(ac);
2372         }
2373
2374         /* nothing matched, go on */
2375         return ldb_next_request(module, req);
2376 }
2377
2378 /* delete */
2379 static int samldb_delete(struct ldb_module *module, struct ldb_request *req)
2380 {
2381         struct samldb_ctx *ac;
2382
2383         if (ldb_dn_is_special(req->op.del.dn)) {
2384                 /* do not manipulate our control entries */
2385                 return ldb_next_request(module, req);
2386         }
2387
2388         ac = samldb_ctx_init(module, req);
2389         if (ac == NULL)
2390                 return LDB_ERR_OPERATIONS_ERROR;
2391
2392         return samldb_prim_group_users_check(ac);
2393 }
2394
2395
2396 static int samldb_init(struct ldb_module *module)
2397 {
2398         return ldb_next_init(module);
2399 }
2400
2401 _PUBLIC_ const struct ldb_module_ops ldb_samldb_module_ops = {
2402         .name          = "samldb",
2403         .init_context  = samldb_init,
2404         .add           = samldb_add,
2405         .modify        = samldb_modify,
2406         .del           = samldb_delete
2407 };
2408