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