Finish removal of iconv_convenience in public API's.
[bbaumbach/samba-autobuild/.git] / source4 / dsdb / samdb / ldb_modules / samldb.c
1 /*
2    SAM ldb module
3
4    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
5    Copyright (C) Simo Sorce  2004-2008
6    Copyright (C) Matthias Dieter Wallnöfer 2009-2010
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         /* holds the entry SID */
63         struct dom_sid *sid;
64
65         /* holds a generic dn */
66         struct ldb_dn *dn;
67
68         /* used in conjunction with "sid" in "samldb_dn_from_sid" */
69         struct ldb_dn *res_dn;
70
71         /* used in conjunction with "dn" in "samldb_sid_from_dn" */
72         struct dom_sid *res_sid;
73
74         /* used in "samldb_user_dn_to_prim_group_rid" */
75         uint32_t prim_group_rid;
76
77         /* used in "samldb_group_add_member" and "samldb_group_del_member" */
78         struct ldb_dn *group_dn;
79         struct ldb_dn *member_dn;
80
81         /* used in "samldb_primary_group_change" */
82         struct ldb_dn *user_dn;
83         struct ldb_dn *old_prim_group_dn, *new_prim_group_dn;
84
85         /* all the async steps necessary to complete the operation */
86         struct samldb_step *steps;
87         struct samldb_step *curstep;
88
89         /* If someone set an ares to forward controls and response back to the caller */
90         struct ldb_reply *ares;
91 };
92
93 static struct samldb_ctx *samldb_ctx_init(struct ldb_module *module,
94                                           struct ldb_request *req)
95 {
96         struct ldb_context *ldb;
97         struct samldb_ctx *ac;
98
99         ldb = ldb_module_get_ctx(module);
100
101         ac = talloc_zero(req, struct samldb_ctx);
102         if (ac == NULL) {
103                 ldb_oom(ldb);
104                 return NULL;
105         }
106
107         ac->module = module;
108         ac->req = req;
109
110         return ac;
111 }
112
113 static int samldb_add_step(struct samldb_ctx *ac, samldb_step_fn_t fn)
114 {
115         struct samldb_step *step, *stepper;
116
117         step = talloc_zero(ac, struct samldb_step);
118         if (step == NULL) {
119                 return LDB_ERR_OPERATIONS_ERROR;
120         }
121
122         step->fn = fn;
123
124         if (ac->steps == NULL) {
125                 ac->steps = step;
126                 ac->curstep = step;
127         } else {
128                 if (ac->curstep == NULL)
129                         return LDB_ERR_OPERATIONS_ERROR;
130                 for (stepper = ac->curstep; stepper->next != NULL;
131                         stepper = stepper->next);
132                 stepper->next = step;
133         }
134
135         return LDB_SUCCESS;
136 }
137
138 static int samldb_first_step(struct samldb_ctx *ac)
139 {
140         if (ac->steps == NULL) {
141                 return LDB_ERR_OPERATIONS_ERROR;
142         }
143
144         ac->curstep = ac->steps;
145         return ac->curstep->fn(ac);
146 }
147
148 static int samldb_next_step(struct samldb_ctx *ac)
149 {
150         if (ac->curstep->next) {
151                 ac->curstep = ac->curstep->next;
152                 return ac->curstep->fn(ac);
153         }
154
155         /* we exit the samldb module here */
156         /* If someone set an ares to forward controls and response back to the caller, use them */
157         if (ac->ares) {
158                 return ldb_module_done(ac->req, ac->ares->controls,
159                                        ac->ares->response, LDB_SUCCESS);
160         } else {
161                 return ldb_module_done(ac->req, NULL, NULL, LDB_SUCCESS);
162         }
163 }
164
165 static int samldb_generate_samAccountName(struct ldb_message *msg)
166 {
167         char *name;
168
169         /* Format: $000000-000000000000 */
170
171         name = talloc_asprintf(msg, "$%.6X-%.6X%.6X",
172                                 (unsigned int)generate_random(),
173                                 (unsigned int)generate_random(),
174                                 (unsigned int)generate_random());
175         if (name == NULL) {
176                 return LDB_ERR_OPERATIONS_ERROR;
177         }
178         return ldb_msg_add_steal_string(msg, "samAccountName", name);
179 }
180
181 /*
182  * samldb_check_samAccountName (async)
183  */
184
185 static int samldb_check_samAccountName_callback(struct ldb_request *req,
186                                                 struct ldb_reply *ares)
187 {
188         struct samldb_ctx *ac;
189         int ret;
190
191         ac = talloc_get_type(req->context, struct samldb_ctx);
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                 /* if we get an entry it means this samAccountName
201                  * already exists */
202                 return ldb_module_done(ac->req, NULL, NULL,
203                                        LDB_ERR_ENTRY_ALREADY_EXISTS);
204
205         case LDB_REPLY_REFERRAL:
206                 /* ignore */
207                 talloc_free(ares);
208                 ret = LDB_SUCCESS;
209                 break;
210
211         case LDB_REPLY_DONE:
212                 /* not found, go on */
213                 talloc_free(ares);
214                 ret = samldb_next_step(ac);
215                 break;
216         }
217
218         if (ret != LDB_SUCCESS) {
219                 return ldb_module_done(ac->req, NULL, NULL, ret);
220         }
221
222         return LDB_SUCCESS;
223 }
224
225 static int samldb_check_samAccountName(struct samldb_ctx *ac)
226 {
227         struct ldb_context *ldb;
228         struct ldb_request *req;
229         const char *name;
230         char *filter;
231         int ret;
232
233         ldb = ldb_module_get_ctx(ac->module);
234
235         if (ldb_msg_find_element(ac->msg, "samAccountName") == NULL) {
236                 ret = samldb_generate_samAccountName(ac->msg);
237                 if (ret != LDB_SUCCESS) {
238                         return ret;
239                 }
240         }
241
242         name = ldb_msg_find_attr_as_string(ac->msg, "samAccountName", NULL);
243         if (name == NULL) {
244                 return LDB_ERR_OPERATIONS_ERROR;
245         }
246         filter = talloc_asprintf(ac, "samAccountName=%s",
247                                  ldb_binary_encode_string(ac, name));
248         if (filter == NULL) {
249                 return LDB_ERR_OPERATIONS_ERROR;
250         }
251
252         ret = ldb_build_search_req(&req, ldb, ac,
253                                    ldb_get_default_basedn(ldb),
254                                    LDB_SCOPE_SUBTREE,
255                                    filter, NULL,
256                                    NULL,
257                                    ac, samldb_check_samAccountName_callback,
258                                    ac->req);
259         talloc_free(filter);
260         if (ret != LDB_SUCCESS) {
261                 return ret;
262         }
263         return ldb_next_request(ac->module, req);
264 }
265
266
267 static int samldb_check_samAccountType(struct samldb_ctx *ac)
268 {
269         struct ldb_context *ldb;
270         unsigned int account_type;
271         unsigned int group_type;
272         unsigned int uac;
273         int ret;
274
275         ldb = ldb_module_get_ctx(ac->module);
276
277         /* make sure sAMAccountType is not specified */
278         if (ldb_msg_find_element(ac->msg, "sAMAccountType") != NULL) {
279                 ldb_asprintf_errstring(ldb,
280                         "sAMAccountType must not be specified!");
281                 return LDB_ERR_UNWILLING_TO_PERFORM;
282         }
283
284         if (strcmp("user", ac->type) == 0) {
285                 uac = samdb_result_uint(ac->msg, "userAccountControl", 0);
286                 if (uac == 0) {
287                         ldb_asprintf_errstring(ldb,
288                                 "userAccountControl invalid!");
289                         return LDB_ERR_UNWILLING_TO_PERFORM;
290                 } else {
291                         account_type = ds_uf2atype(uac);
292                         ret = samdb_msg_add_uint(ldb,
293                                                  ac->msg, ac->msg,
294                                                  "sAMAccountType",
295                                                  account_type);
296                         if (ret != LDB_SUCCESS) {
297                                 return ret;
298                         }
299                 }
300         } else
301         if (strcmp("group", ac->type) == 0) {
302
303                 group_type = samdb_result_uint(ac->msg, "groupType", 0);
304                 if (group_type == 0) {
305                         ldb_asprintf_errstring(ldb,
306                                 "groupType invalid!\n");
307                         return LDB_ERR_UNWILLING_TO_PERFORM;
308                 } else {
309                         account_type = ds_gtype2atype(group_type);
310                         ret = samdb_msg_add_uint(ldb,
311                                                  ac->msg, ac->msg,
312                                                  "sAMAccountType",
313                                                  account_type);
314                         if (ret != LDB_SUCCESS) {
315                                 return ret;
316                         }
317                 }
318         }
319
320         return samldb_next_step(ac);
321 }
322
323 static bool samldb_msg_add_sid(struct ldb_message *msg,
324                                 const char *name,
325                                 const struct dom_sid *sid)
326 {
327         struct ldb_val v;
328         enum ndr_err_code ndr_err;
329
330         ndr_err = ndr_push_struct_blob(&v, msg, sid,
331                                        (ndr_push_flags_fn_t)ndr_push_dom_sid);
332         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
333                 return false;
334         }
335         return (ldb_msg_add_value(msg, name, &v, NULL) == 0);
336 }
337
338
339 /* allocate a SID using our RID Set */
340 static int samldb_allocate_sid(struct samldb_ctx *ac)
341 {
342         uint32_t rid;
343         int ret;
344         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
345
346         ret = ridalloc_allocate_rid(ac->module, &rid);
347         if (ret != LDB_SUCCESS) {
348                 return ret;
349         }
350
351         ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
352         if (ac->sid == NULL) {
353                 ldb_module_oom(ac->module);
354                 return LDB_ERR_OPERATIONS_ERROR;
355         }
356
357         if ( ! samldb_msg_add_sid(ac->msg, "objectSid", ac->sid)) {
358                 return LDB_ERR_OPERATIONS_ERROR;
359         }
360
361         return samldb_next_step(ac);
362 }
363
364 /*
365  * samldb_dn_from_sid (async)
366  */
367
368 static int samldb_dn_from_sid(struct samldb_ctx *ac);
369
370 static int samldb_dn_from_sid_callback(struct ldb_request *req,
371         struct ldb_reply *ares)
372 {
373         struct ldb_context *ldb;
374         struct samldb_ctx *ac;
375         int ret;
376
377         ac = talloc_get_type(req->context, struct samldb_ctx);
378         ldb = ldb_module_get_ctx(ac->module);
379
380         if (!ares) {
381                 ret = LDB_ERR_OPERATIONS_ERROR;
382                 goto done;
383         }
384         if (ares->error != LDB_SUCCESS) {
385                 return ldb_module_done(ac->req, ares->controls,
386                                         ares->response, ares->error);
387         }
388
389         switch (ares->type) {
390         case LDB_REPLY_ENTRY:
391                 /* save entry */
392                 if (ac->res_dn != NULL) {
393                         /* one too many! */
394                         ldb_set_errstring(ldb,
395                                 "Invalid number of results while searching "
396                                 "for domain objects!");
397                         ret = LDB_ERR_OPERATIONS_ERROR;
398                         break;
399                 }
400                 ac->res_dn = ldb_dn_copy(ac, ares->message->dn);
401
402                 talloc_free(ares);
403                 ret = LDB_SUCCESS;
404                 break;
405
406         case LDB_REPLY_REFERRAL:
407                 /* ignore */
408                 talloc_free(ares);
409                 ret = LDB_SUCCESS;
410                 break;
411
412         case LDB_REPLY_DONE:
413                 talloc_free(ares);
414
415                 /* found or not found, go on */
416                 ret = samldb_next_step(ac);
417                 break;
418         }
419
420 done:
421         if (ret != LDB_SUCCESS) {
422                 return ldb_module_done(ac->req, NULL, NULL, ret);
423         }
424
425         return LDB_SUCCESS;
426 }
427
428 /* Finds the DN "res_dn" of an object with a given SID "sid" */
429 static int samldb_dn_from_sid(struct samldb_ctx *ac)
430 {
431         struct ldb_context *ldb;
432         static const char * const attrs[] = { NULL };
433         struct ldb_request *req;
434         char *filter;
435         int ret;
436
437         ldb = ldb_module_get_ctx(ac->module);
438
439         if (ac->sid == NULL)
440                 return LDB_ERR_OPERATIONS_ERROR;
441
442         filter = talloc_asprintf(ac, "(objectSid=%s)",
443                 ldap_encode_ndr_dom_sid(ac, ac->sid));
444         if (filter == NULL)
445                 return LDB_ERR_OPERATIONS_ERROR;
446
447         ret = ldb_build_search_req(&req, ldb, ac,
448                                 ldb_get_default_basedn(ldb),
449                                 LDB_SCOPE_SUBTREE,
450                                 filter, attrs,
451                                 NULL,
452                                 ac, samldb_dn_from_sid_callback,
453                                 ac->req);
454         if (ret != LDB_SUCCESS)
455                 return ret;
456
457         return ldb_next_request(ac->module, req);
458 }
459
460
461 static int samldb_check_primaryGroupID_1(struct samldb_ctx *ac)
462 {
463         struct ldb_context *ldb;
464         uint32_t rid;
465
466         ldb = ldb_module_get_ctx(ac->module);
467
468         rid = samdb_result_uint(ac->msg, "primaryGroupID", ~0);
469         ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
470         if (ac->sid == NULL)
471                 return LDB_ERR_OPERATIONS_ERROR;
472         ac->res_dn = NULL;
473
474         return samldb_next_step(ac);
475 }
476
477 static int samldb_check_primaryGroupID_2(struct samldb_ctx *ac)
478 {
479         if (ac->res_dn == NULL) {
480                 struct ldb_context *ldb;
481                 ldb = ldb_module_get_ctx(ac->module);
482                 ldb_asprintf_errstring(ldb,
483                                        "Failed to find group sid %s!",
484                                        dom_sid_string(ac->sid, ac->sid));
485                 return LDB_ERR_UNWILLING_TO_PERFORM;
486         }
487
488         return samldb_next_step(ac);
489 }
490
491
492 /*
493  * samldb_set_defaultObjectCategory_callback (async)
494  */
495
496 static int samldb_set_defaultObjectCategory_callback(struct ldb_request *req,
497                                                      struct ldb_reply *ares)
498 {
499         struct ldb_context *ldb;
500         struct samldb_ctx *ac;
501         int ret;
502
503         ac = talloc_get_type(req->context, struct samldb_ctx);
504         ldb = ldb_module_get_ctx(ac->module);
505
506         if (!ares) {
507                 ret = LDB_ERR_OPERATIONS_ERROR;
508                 goto done;
509         }
510
511         if (ares->type == LDB_REPLY_REFERRAL) {
512                 return ldb_module_send_referral(ac->req, ares->referral);
513         }
514
515         if (ares->error != LDB_SUCCESS) {
516                 return ldb_module_done(ac->req, ares->controls,
517                                         ares->response, ares->error);
518         }
519         if (ares->type != LDB_REPLY_DONE) {
520                 ldb_set_errstring(ldb,
521                         "Invalid reply type!");
522                 ret = LDB_ERR_OPERATIONS_ERROR;
523                 goto done;
524         }
525
526         ret = samldb_next_step(ac);
527
528 done:
529         if (ret != LDB_SUCCESS) {
530                 return ldb_module_done(ac->req, NULL, NULL, ret);
531         }
532
533         return LDB_SUCCESS;
534 }
535
536 static int samldb_set_defaultObjectCategory(struct samldb_ctx *ac)
537 {
538         struct ldb_context *ldb;
539         struct ldb_message *msg;
540         struct ldb_request *req;
541         int ret;
542
543         ldb = ldb_module_get_ctx(ac->module);
544
545         /* (Re)set the default object category to have it set to the DN in the
546          * storage format */
547         msg = ldb_msg_new(ac);
548         msg->dn = ac->msg->dn;
549         ldb_msg_add_empty(msg, "defaultObjectCategory",
550                           LDB_FLAG_MOD_REPLACE, NULL);
551         ldb_msg_add_steal_string(msg, "defaultObjectCategory",
552                                  ldb_dn_alloc_linearized(msg, ac->dn));
553
554         ret = ldb_build_mod_req(&req, ldb, ac,
555                                 msg, NULL,
556                                 ac,
557                                 samldb_set_defaultObjectCategory_callback,
558                                 ac->req);
559         if (ret != LDB_SUCCESS) {
560                 talloc_free(msg);
561                 return ret;
562         }
563
564         return ldb_next_request(ac->module, req);
565 }
566
567 /*
568  * samldb_find_for_defaultObjectCategory (async)
569  */
570
571 static int samldb_find_for_defaultObjectCategory_callback(struct ldb_request *req,
572                                                           struct ldb_reply *ares)
573 {
574         struct ldb_context *ldb;
575         struct samldb_ctx *ac;
576         int ret;
577
578         ac = talloc_get_type(req->context, struct samldb_ctx);
579         ldb = ldb_module_get_ctx(ac->module);
580
581         if (!ares) {
582                 ret = LDB_ERR_OPERATIONS_ERROR;
583                 goto done;
584         }
585         if (ares->error != LDB_SUCCESS) {
586                 if (ares->error == LDB_ERR_NO_SUCH_OBJECT) {
587                         if (ldb_request_get_control(ac->req,
588                                                     LDB_CONTROL_RELAX_OID) != NULL) {
589                                 /* Don't be pricky when the DN doesn't exist */
590                                 /* if we have the RELAX control specified */
591                                 ac->dn = req->op.search.base;
592                                 return samldb_next_step(ac);
593                         } else {
594                                 ldb_set_errstring(ldb,
595                                         "samldb_find_defaultObjectCategory: "
596                                         "Invalid DN for 'defaultObjectCategory'!");
597                                 ares->error = LDB_ERR_CONSTRAINT_VIOLATION;
598                         }
599                 }
600
601                 return ldb_module_done(ac->req, ares->controls,
602                                        ares->response, ares->error);
603         }
604
605         switch (ares->type) {
606         case LDB_REPLY_ENTRY:
607                 ac->dn = talloc_steal(ac, ares->message->dn);
608
609                 ret = LDB_SUCCESS;
610                 break;
611
612         case LDB_REPLY_REFERRAL:
613                 /* ignore */
614                 talloc_free(ares);
615                 ret = LDB_SUCCESS;
616                 break;
617
618         case LDB_REPLY_DONE:
619                 talloc_free(ares);
620
621                 if (ac->dn != NULL) {
622                         /* when found go on */
623                         ret = samldb_next_step(ac);
624                 } else {
625                         ret = LDB_ERR_OPERATIONS_ERROR;
626                 }
627                 break;
628         }
629
630 done:
631         if (ret != LDB_SUCCESS) {
632                 return ldb_module_done(ac->req, NULL, NULL, ret);
633         }
634
635         return LDB_SUCCESS;
636 }
637
638 static int samldb_find_for_defaultObjectCategory(struct samldb_ctx *ac)
639 {
640         struct ldb_context *ldb;
641         struct ldb_request *req;
642         static const char *no_attrs[] = { NULL };
643         int ret;
644         const struct ldb_val *val;
645         struct ldb_dn *def_obj_cat_dn;
646
647         ldb = ldb_module_get_ctx(ac->module);
648
649         ac->dn = NULL;
650
651         val = ldb_msg_find_ldb_val(ac->msg, "defaultObjectCategory");
652         if (val != NULL) {
653                 /* "defaultObjectCategory" has been set by the caller. Do some
654                  * checks for consistency.
655                  * NOTE: The real constraint check (that 'defaultObjectCategory'
656                  * is the DN of the new objectclass or any parent of it) is
657                  * still incomplete.
658                  * For now we say that 'defaultObjectCategory' is valid if it
659                  * exists and it is of objectclass "classSchema". */
660                 def_obj_cat_dn = ldb_dn_from_ldb_val(ac, ldb, val);
661                 if (def_obj_cat_dn == NULL) {
662                         ldb_set_errstring(ldb,
663                                 "samldb_find_defaultObjectCategory: Invalid DN "
664                                 "for 'defaultObjectCategory'!");
665                         return LDB_ERR_CONSTRAINT_VIOLATION;
666                 }
667         } else {
668                 /* "defaultObjectCategory" has not been set by the caller. Use
669                  * the entry DN for it. */
670                 def_obj_cat_dn = ac->msg->dn;
671         }
672
673         ret = ldb_build_search_req(&req, ldb, ac,
674                                    def_obj_cat_dn, LDB_SCOPE_BASE,
675                                    "objectClass=classSchema", no_attrs,
676                                    NULL,
677                                    ac, samldb_find_for_defaultObjectCategory_callback,
678                                    ac->req);
679         if (ret != LDB_SUCCESS) {
680                 return ret;
681         }
682
683         ret = dsdb_request_add_controls(req,
684                                         DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT);
685         if (ret != LDB_SUCCESS) {
686                 return ret;
687         }
688
689         return ldb_next_request(ac->module, req);
690 }
691
692 /**
693  * msDS-IntId attributeSchema attribute handling
694  * during LDB_ADD request processing
695  */
696 static int samldb_add_handle_msDS_IntId(struct samldb_ctx *ac)
697 {
698         int ret;
699         bool id_exists;
700         uint32_t msds_intid;
701         uint32_t system_flags;
702         struct ldb_context *ldb;
703         struct ldb_result *ldb_res;
704         struct ldb_dn *schema_dn;
705
706         ldb = ldb_module_get_ctx(ac->module);
707         schema_dn = ldb_get_schema_basedn(ldb);
708
709         /* replicated update should always go through */
710         if (ldb_request_get_control(ac->req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
711                 return LDB_SUCCESS;
712         }
713
714         /* msDS-IntId is handled by system and should never be
715          * passed by clients */
716         if (ldb_msg_find_element(ac->msg, "msDS-IntId")) {
717                 return LDB_ERR_UNWILLING_TO_PERFORM;
718         }
719
720         /* do not generate msDS-IntId if Relax control is passed */
721         if (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
722                 return LDB_SUCCESS;
723         }
724
725         /* check Functional Level */
726         if (dsdb_functional_level(ldb) < DS_DOMAIN_FUNCTION_2003) {
727                 return LDB_SUCCESS;
728         }
729
730         /* check systemFlags for SCHEMA_BASE_OBJECT flag */
731         system_flags = ldb_msg_find_attr_as_uint(ac->msg, "systemFlags", 0);
732         if (system_flags & SYSTEM_FLAG_SCHEMA_BASE_OBJECT) {
733                 return LDB_SUCCESS;
734         }
735
736         /* Generate new value for msDs-IntId
737          * Value should be in 0x80000000..0xBFFFFFFF range */
738         msds_intid = generate_random() % 0X3FFFFFFF;
739         msds_intid += 0x80000000;
740
741         /* probe id values until unique one is found */
742         do {
743                 msds_intid++;
744                 if (msds_intid > 0xBFFFFFFF) {
745                         msds_intid = 0x80000001;
746                 }
747
748                 ret = dsdb_module_search(ac->module, ac,
749                                          &ldb_res,
750                                          schema_dn, LDB_SCOPE_ONELEVEL, NULL, 0,
751                                          "(msDS-IntId=%d)", msds_intid);
752                 if (ret != LDB_SUCCESS) {
753                         ldb_debug_set(ldb, LDB_DEBUG_ERROR,
754                                       __location__": Searching for msDS-IntId=%d failed - %s\n",
755                                       msds_intid,
756                                       ldb_errstring(ldb));
757                         return LDB_ERR_OPERATIONS_ERROR;
758                 }
759                 id_exists = (ldb_res->count > 0);
760
761                 talloc_free(ldb_res);
762         } while(id_exists);
763
764         return ldb_msg_add_fmt(ac->msg, "msDS-IntId", "%d", msds_intid);
765 }
766
767
768 /*
769  * samldb_add_entry (async)
770  */
771
772 static int samldb_add_entry_callback(struct ldb_request *req,
773                                         struct ldb_reply *ares)
774 {
775         struct ldb_context *ldb;
776         struct samldb_ctx *ac;
777         int ret;
778
779         ac = talloc_get_type(req->context, struct samldb_ctx);
780         ldb = ldb_module_get_ctx(ac->module);
781
782         if (!ares) {
783                 return ldb_module_done(ac->req, NULL, NULL,
784                                         LDB_ERR_OPERATIONS_ERROR);
785         }
786
787         if (ares->type == LDB_REPLY_REFERRAL) {
788                 return ldb_module_send_referral(ac->req, ares->referral);
789         }
790
791         if (ares->error != LDB_SUCCESS) {
792                 return ldb_module_done(ac->req, ares->controls,
793                                         ares->response, ares->error);
794         }
795         if (ares->type != LDB_REPLY_DONE) {
796                 ldb_set_errstring(ldb,
797                         "Invalid reply type!\n");
798                 return ldb_module_done(ac->req, NULL, NULL,
799                                         LDB_ERR_OPERATIONS_ERROR);
800         }
801
802         /* The caller may wish to get controls back from the add */
803         ac->ares = talloc_steal(ac, ares);
804
805         ret = samldb_next_step(ac);
806         if (ret != LDB_SUCCESS) {
807                 return ldb_module_done(ac->req, NULL, NULL, ret);
808         }
809         return ret;
810 }
811
812 static int samldb_add_entry(struct samldb_ctx *ac)
813 {
814         struct ldb_context *ldb;
815         struct ldb_request *req;
816         int ret;
817
818         ldb = ldb_module_get_ctx(ac->module);
819
820         ret = ldb_build_add_req(&req, ldb, ac,
821                                 ac->msg,
822                                 ac->req->controls,
823                                 ac, samldb_add_entry_callback,
824                                 ac->req);
825         if (ret != LDB_SUCCESS) {
826                 return ret;
827         }
828
829         return ldb_next_request(ac->module, req);
830 }
831
832 /*
833  * return true if msg carries an attributeSchema that is intended to be RODC
834  * filtered but is also a system-critical attribute.
835  */
836 static bool check_rodc_critical_attribute(struct ldb_message *msg)
837 {
838         uint32_t schemaFlagsEx, searchFlags, rodc_filtered_flags;
839
840         schemaFlagsEx = ldb_msg_find_attr_as_uint(msg, "schemaFlagsEx", 0);
841         searchFlags = ldb_msg_find_attr_as_uint(msg, "searchFlags", 0);
842         rodc_filtered_flags = (SEARCH_FLAG_RODC_ATTRIBUTE | SEARCH_FLAG_CONFIDENTIAL);
843
844         if ((schemaFlagsEx & SCHEMA_FLAG_ATTR_IS_CRITICAL) &&
845                 ((searchFlags & rodc_filtered_flags) == rodc_filtered_flags)) {
846                 return true;
847         } else {
848                 return false;
849         }
850 }
851
852
853 static int samldb_fill_object(struct samldb_ctx *ac, const char *type)
854 {
855         struct ldb_context *ldb;
856         struct loadparm_context *lp_ctx;
857         enum sid_generator sid_generator;
858         int ret;
859
860         ldb = ldb_module_get_ctx(ac->module);
861
862         /* Add informations for the different account types */
863         ac->type = type;
864         if (strcmp(ac->type, "user") == 0) {
865                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
866                         "userAccountControl", "546");
867                 if (ret != LDB_SUCCESS) return ret;
868                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
869                         "badPwdCount", "0");
870                 if (ret != LDB_SUCCESS) return ret;
871                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
872                         "codePage", "0");
873                 if (ret != LDB_SUCCESS) return ret;
874                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
875                         "countryCode", "0");
876                 if (ret != LDB_SUCCESS) return ret;
877                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
878                         "badPasswordTime", "0");
879                 if (ret != LDB_SUCCESS) return ret;
880                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
881                         "lastLogoff", "0");
882                 if (ret != LDB_SUCCESS) return ret;
883                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
884                         "lastLogon", "0");
885                 if (ret != LDB_SUCCESS) return ret;
886                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
887                         "pwdLastSet", "0");
888                 if (ret != LDB_SUCCESS) return ret;
889                 if (!ldb_msg_find_element(ac->msg, "primaryGroupID")) {
890                         ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
891                                                  "primaryGroupID", DOMAIN_RID_USERS);
892                         if (ret != LDB_SUCCESS) return ret;
893                 }
894                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
895                         "accountExpires", "9223372036854775807");
896                 if (ret != LDB_SUCCESS) return ret;
897                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
898                         "logonCount", "0");
899                 if (ret != LDB_SUCCESS) return ret;
900         } else if (strcmp(ac->type, "group") == 0) {
901                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
902                         "groupType", "-2147483646");
903                 if (ret != LDB_SUCCESS) return ret;
904         } else if (strcmp(ac->type, "classSchema") == 0) {
905                 const struct ldb_val *rdn_value;
906
907                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
908                                                   "rdnAttId", "cn");
909                 if (ret != LDB_SUCCESS) return ret;
910
911                 /* do not allow to mark an attributeSchema as RODC filtered if it
912                  * is system-critical */
913                 if (check_rodc_critical_attribute(ac->msg)) {
914                         ldb_asprintf_errstring(ldb, "Refusing schema add of %s - cannot combine critical class with RODC filtering",
915                                                ldb_dn_get_linearized(ac->msg->dn));
916                         return LDB_ERR_UNWILLING_TO_PERFORM;
917                 }
918
919
920                 rdn_value = ldb_dn_get_rdn_val(ac->msg->dn);
921                 if (!ldb_msg_find_element(ac->msg, "lDAPDisplayName")) {
922                         /* the RDN has prefix "CN" */
923                         ret = ldb_msg_add_string(ac->msg, "lDAPDisplayName",
924                                 samdb_cn_to_lDAPDisplayName(ac,
925                                         (const char *) rdn_value->data));
926                         if (ret != LDB_SUCCESS) {
927                                 ldb_oom(ldb);
928                                 return ret;
929                         }
930                 }
931
932                 if (!ldb_msg_find_element(ac->msg, "schemaIDGUID")) {
933                         struct GUID guid;
934                         /* a new GUID */
935                         guid = GUID_random();
936                         ret = dsdb_msg_add_guid(ac->msg, &guid, "schemaIDGUID");
937                         if (ret != LDB_SUCCESS) {
938                                 ldb_oom(ldb);
939                                 return ret;
940                         }
941                 }
942
943                 ret = samldb_add_step(ac, samldb_add_entry);
944                 if (ret != LDB_SUCCESS) return ret;
945
946                 ret = samldb_add_step(ac, samldb_find_for_defaultObjectCategory);
947                 if (ret != LDB_SUCCESS) return ret;
948
949                 ret = samldb_add_step(ac, samldb_set_defaultObjectCategory);
950                 if (ret != LDB_SUCCESS) return ret;
951
952                 return samldb_first_step(ac);
953         } else if (strcmp(ac->type, "attributeSchema") == 0) {
954                 const struct ldb_val *rdn_value;
955                 rdn_value = ldb_dn_get_rdn_val(ac->msg->dn);
956                 if (!ldb_msg_find_element(ac->msg, "lDAPDisplayName")) {
957                         /* the RDN has prefix "CN" */
958                         ret = ldb_msg_add_string(ac->msg, "lDAPDisplayName",
959                                 samdb_cn_to_lDAPDisplayName(ac,
960                                         (const char *) rdn_value->data));
961                         if (ret != LDB_SUCCESS) {
962                                 ldb_oom(ldb);
963                                 return ret;
964                         }
965                 }
966
967                 /* do not allow to mark an attributeSchema as RODC filtered if it
968                  * is system-critical */
969                 if (check_rodc_critical_attribute(ac->msg)) {
970                         ldb_asprintf_errstring(ldb, "Refusing schema add of %s - cannot combine critical attribute with RODC filtering",
971                                                ldb_dn_get_linearized(ac->msg->dn));
972                         return LDB_ERR_UNWILLING_TO_PERFORM;
973                 }
974
975                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
976                                                   "isSingleValued", "FALSE");
977                 if (ret != LDB_SUCCESS) return ret;
978
979                 if (!ldb_msg_find_element(ac->msg, "schemaIDGUID")) {
980                         struct GUID guid;
981                         /* a new GUID */
982                         guid = GUID_random();
983                         ret = dsdb_msg_add_guid(ac->msg, &guid, "schemaIDGUID");
984                         if (ret != LDB_SUCCESS) {
985                                 ldb_oom(ldb);
986                                 return ret;
987                         }
988                 }
989
990                 /* handle msDS-IntID attribute */
991                 ret = samldb_add_handle_msDS_IntId(ac);
992                 if (ret != LDB_SUCCESS) return ret;
993
994                 ret = samldb_add_step(ac, samldb_add_entry);
995                 if (ret != LDB_SUCCESS) return ret;
996
997                 return samldb_first_step(ac);
998         } else {
999                 ldb_asprintf_errstring(ldb,
1000                         "Invalid entry type!");
1001                 return LDB_ERR_OPERATIONS_ERROR;
1002         }
1003
1004         /* check if we have a valid samAccountName */
1005         ret = samldb_add_step(ac, samldb_check_samAccountName);
1006         if (ret != LDB_SUCCESS) return ret;
1007
1008         /* check account_type/group_type */
1009         ret = samldb_add_step(ac, samldb_check_samAccountType);
1010         if (ret != LDB_SUCCESS) return ret;
1011
1012         /* check if we have a valid primary group ID */
1013         if (strcmp(ac->type, "user") == 0) {
1014                 ret = samldb_add_step(ac, samldb_check_primaryGroupID_1);
1015                 if (ret != LDB_SUCCESS) return ret;
1016                 ret = samldb_add_step(ac, samldb_dn_from_sid);
1017                 if (ret != LDB_SUCCESS) return ret;
1018                 ret = samldb_add_step(ac, samldb_check_primaryGroupID_2);
1019                 if (ret != LDB_SUCCESS) return ret;
1020         }
1021
1022         lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
1023                  struct loadparm_context);
1024
1025         /* don't allow objectSID to be specified without the RELAX control */
1026         ac->sid = samdb_result_dom_sid(ac, ac->msg, "objectSid");
1027         if (ac->sid && !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) &&
1028             !dsdb_module_am_system(ac->module)) {
1029                 ldb_asprintf_errstring(ldb, "No SID may be specified in user/group creation for %s",
1030                                        ldb_dn_get_linearized(ac->msg->dn));
1031                 return LDB_ERR_UNWILLING_TO_PERFORM;
1032         }
1033
1034         if ( ! ac->sid) {
1035                 sid_generator = lp_sid_generator(lp_ctx);
1036                 if (sid_generator == SID_GENERATOR_INTERNAL) {
1037                         ret = samldb_add_step(ac, samldb_allocate_sid);
1038                         if (ret != LDB_SUCCESS) return ret;
1039                 }
1040         }
1041
1042         /* finally proceed with adding the entry */
1043         ret = samldb_add_step(ac, samldb_add_entry);
1044         if (ret != LDB_SUCCESS) return ret;
1045
1046         return samldb_first_step(ac);
1047 }
1048
1049 static int samldb_fill_foreignSecurityPrincipal_object(struct samldb_ctx *ac)
1050 {
1051         struct ldb_context *ldb;
1052         int ret;
1053
1054         ldb = ldb_module_get_ctx(ac->module);
1055
1056         ac->sid = samdb_result_dom_sid(ac->msg, ac->msg, "objectSid");
1057         if (ac->sid == NULL) {
1058                 ac->sid = dom_sid_parse_talloc(ac->msg,
1059                            (const char *)ldb_dn_get_rdn_val(ac->msg->dn)->data);
1060                 if (!ac->sid) {
1061                         ldb_set_errstring(ldb,
1062                                         "No valid SID found in "
1063                                         "ForeignSecurityPrincipal CN!");
1064                         talloc_free(ac);
1065                         return LDB_ERR_CONSTRAINT_VIOLATION;
1066                 }
1067                 if ( ! samldb_msg_add_sid(ac->msg, "objectSid", ac->sid)) {
1068                         talloc_free(ac);
1069                         return LDB_ERR_OPERATIONS_ERROR;
1070                 }
1071         }
1072
1073         /* finally proceed with adding the entry */
1074         ret = samldb_add_step(ac, samldb_add_entry);
1075         if (ret != LDB_SUCCESS) return ret;
1076
1077         return samldb_first_step(ac);
1078 }
1079
1080 static int samldb_check_rdn(struct ldb_module *module, struct ldb_dn *dn)
1081 {
1082         struct ldb_context *ldb;
1083         const char *rdn_name;
1084
1085         ldb = ldb_module_get_ctx(module);
1086         rdn_name = ldb_dn_get_rdn_name(dn);
1087
1088         if (strcasecmp(rdn_name, "cn") != 0) {
1089                 ldb_asprintf_errstring(ldb,
1090                                         "Bad RDN (%s=) for samldb object, "
1091                                         "should be CN=!", rdn_name);
1092                 return LDB_ERR_CONSTRAINT_VIOLATION;
1093         }
1094
1095         return LDB_SUCCESS;
1096 }
1097
1098 static int samldb_schema_info_update(struct samldb_ctx *ac)
1099 {
1100         WERROR werr;
1101         struct ldb_context *ldb;
1102         struct dsdb_schema *schema;
1103
1104         /* replicated update should always go through */
1105         if (ldb_request_get_control(ac->req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
1106                 return LDB_SUCCESS;
1107         }
1108
1109         /* do not update schemaInfo during provisioning */
1110         if (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
1111                 return LDB_SUCCESS;
1112         }
1113
1114         ldb = ldb_module_get_ctx(ac->module);
1115         schema = dsdb_get_schema(ldb, NULL);
1116         if (!schema) {
1117                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
1118                               "samldb_schema_info_update: no dsdb_schema loaded");
1119                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
1120                 return LDB_ERR_OPERATIONS_ERROR;
1121         }
1122
1123         werr = dsdb_module_schema_info_update(ac->module, schema, 0);
1124         if (!W_ERROR_IS_OK(werr)) {
1125                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
1126                               "samldb_schema_info_update: "
1127                               "dsdb_module_schema_info_update failed with %s",
1128                               win_errstr(werr));
1129                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
1130                 return LDB_ERR_OPERATIONS_ERROR;
1131         }
1132
1133         return LDB_SUCCESS;
1134 }
1135
1136 /*
1137  * samldb_user_dn_to_prim_group_rid (async)
1138  */
1139
1140 static int samldb_user_dn_to_prim_group_rid(struct samldb_ctx *ac);
1141
1142 static int samldb_user_dn_to_prim_group_rid_callback(struct ldb_request *req,
1143         struct ldb_reply *ares)
1144 {
1145         struct ldb_context *ldb;
1146         struct samldb_ctx *ac;
1147         int ret;
1148
1149         ac = talloc_get_type(req->context, struct samldb_ctx);
1150         ldb = ldb_module_get_ctx(ac->module);
1151
1152         if (!ares) {
1153                 ret = LDB_ERR_OPERATIONS_ERROR;
1154                 goto done;
1155         }
1156         if (ares->error != LDB_SUCCESS) {
1157                 return ldb_module_done(ac->req, ares->controls,
1158                                         ares->response, ares->error);
1159         }
1160
1161         switch (ares->type) {
1162         case LDB_REPLY_ENTRY:
1163                 /* save entry */
1164                 if (ac->prim_group_rid != 0) {
1165                         /* one too many! */
1166                         ldb_set_errstring(ldb,
1167                                 "Invalid number of results while searching "
1168                                 "for domain objects!");
1169                         ret = LDB_ERR_OPERATIONS_ERROR;
1170                         break;
1171                 }
1172                 ac->prim_group_rid = samdb_result_uint(ares->message,
1173                         "primaryGroupID", ~0);
1174
1175                 talloc_free(ares);
1176                 ret = LDB_SUCCESS;
1177                 break;
1178
1179         case LDB_REPLY_REFERRAL:
1180                 /* ignore */
1181                 talloc_free(ares);
1182                 ret = LDB_SUCCESS;
1183                 break;
1184
1185         case LDB_REPLY_DONE:
1186                 talloc_free(ares);
1187                 if (ac->prim_group_rid == 0) {
1188                         ldb_asprintf_errstring(ldb,
1189                                 "Unable to get the primary group RID!");
1190                         ret = LDB_ERR_OPERATIONS_ERROR;
1191                         break;
1192                 }
1193
1194                 /* found, go on */
1195                 ret = samldb_next_step(ac);
1196                 break;
1197         }
1198
1199 done:
1200         if (ret != LDB_SUCCESS) {
1201                 return ldb_module_done(ac->req, NULL, NULL, ret);
1202         }
1203
1204         return LDB_SUCCESS;
1205 }
1206
1207 /* Locates the "primaryGroupID" attribute from a certain user specified as
1208  * "user_dn". Saves the result in "prim_group_rid". */
1209 static int samldb_user_dn_to_prim_group_rid(struct samldb_ctx *ac)
1210 {
1211         struct ldb_context *ldb;
1212         static const char * const attrs[] = { "primaryGroupID", NULL };
1213         struct ldb_request *req;
1214         int ret;
1215
1216         ldb = ldb_module_get_ctx(ac->module);
1217
1218         if (ac->user_dn == NULL)
1219                 return LDB_ERR_OPERATIONS_ERROR;
1220
1221         ret = ldb_build_search_req(&req, ldb, ac,
1222                                 ac->user_dn,
1223                                 LDB_SCOPE_BASE,
1224                                 NULL, attrs,
1225                                 NULL,
1226                                 ac, samldb_user_dn_to_prim_group_rid_callback,
1227                                 ac->req);
1228         if (ret != LDB_SUCCESS)
1229                 return ret;
1230
1231         return ldb_next_request(ac->module, req);
1232 }
1233
1234 /*
1235  * samldb_group_add_member (async)
1236  * samldb_group_del_member (async)
1237  */
1238
1239 static int samldb_group_add_del_member_callback(struct ldb_request *req,
1240         struct ldb_reply *ares)
1241 {
1242         struct ldb_context *ldb;
1243         struct samldb_ctx *ac;
1244         int ret;
1245
1246         ac = talloc_get_type(req->context, struct samldb_ctx);
1247         ldb = ldb_module_get_ctx(ac->module);
1248
1249         if (!ares) {
1250                 ret = LDB_ERR_OPERATIONS_ERROR;
1251                 goto done;
1252         }
1253
1254         if (ares->type == LDB_REPLY_REFERRAL) {
1255                 return ldb_module_send_referral(ac->req, ares->referral);
1256         }
1257
1258         if (ares->error != LDB_SUCCESS) {
1259                 if (ares->error == LDB_ERR_NO_SUCH_ATTRIBUTE) {
1260                         /* On error "NO_SUCH_ATTRIBUTE" (delete of an invalid
1261                          * "member" attribute) return "UNWILLING_TO_PERFORM" */
1262                         ares->error = LDB_ERR_UNWILLING_TO_PERFORM;
1263                 }
1264                 return ldb_module_done(ac->req, ares->controls,
1265                                         ares->response, ares->error);
1266         }
1267         if (ares->type != LDB_REPLY_DONE) {
1268                 ldb_set_errstring(ldb,
1269                         "Invalid reply type!");
1270                 ret = LDB_ERR_OPERATIONS_ERROR;
1271                 goto done;
1272         }
1273
1274         ret = samldb_next_step(ac);
1275
1276 done:
1277         if (ret != LDB_SUCCESS) {
1278                 return ldb_module_done(ac->req, NULL, NULL, ret);
1279         }
1280
1281         return LDB_SUCCESS;
1282 }
1283
1284 /* Adds a member with DN "member_dn" to a group with DN "group_dn" */
1285 static int samldb_group_add_member(struct samldb_ctx *ac)
1286 {
1287         struct ldb_context *ldb;
1288         struct ldb_request *req;
1289         struct ldb_message *msg;
1290         int ret;
1291
1292         ldb = ldb_module_get_ctx(ac->module);
1293
1294         if ((ac->group_dn == NULL) || (ac->member_dn == NULL))
1295                 return LDB_ERR_OPERATIONS_ERROR;
1296
1297         msg = ldb_msg_new(ac);
1298         msg->dn = ac->group_dn;
1299         samdb_msg_add_addval(ldb, ac, msg, "member",
1300                 ldb_dn_get_linearized(ac->member_dn));
1301
1302         ret = ldb_build_mod_req(&req, ldb, ac,
1303                                 msg, NULL,
1304                                 ac, samldb_group_add_del_member_callback,
1305                                 ac->req);
1306         if (ret != LDB_SUCCESS)
1307                 return ret;
1308
1309         return ldb_next_request(ac->module, req);
1310 }
1311
1312 /* Removes a member with DN "member_dn" from a group with DN "group_dn" */
1313 static int samldb_group_del_member(struct samldb_ctx *ac)
1314 {
1315         struct ldb_context *ldb;
1316         struct ldb_request *req;
1317         struct ldb_message *msg;
1318         int ret;
1319
1320         ldb = ldb_module_get_ctx(ac->module);
1321
1322         if ((ac->group_dn == NULL) || (ac->member_dn == NULL))
1323                 return LDB_ERR_OPERATIONS_ERROR;
1324
1325         msg = ldb_msg_new(ac);
1326         msg->dn = ac->group_dn;
1327         samdb_msg_add_delval(ldb, ac, msg, "member",
1328                 ldb_dn_get_linearized(ac->member_dn));
1329
1330         ret = ldb_build_mod_req(&req, ldb, ac,
1331                                 msg, NULL,
1332                                 ac, samldb_group_add_del_member_callback,
1333                                 ac->req);
1334         if (ret != LDB_SUCCESS)
1335                 return ret;
1336
1337         return ldb_next_request(ac->module, req);
1338 }
1339
1340
1341 static int samldb_prim_group_change_1(struct samldb_ctx *ac)
1342 {
1343         struct ldb_context *ldb;
1344         uint32_t rid;
1345
1346         ldb = ldb_module_get_ctx(ac->module);
1347
1348         ac->user_dn = ac->msg->dn;
1349
1350         rid = samdb_result_uint(ac->msg, "primaryGroupID", ~0);
1351         ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
1352         if (ac->sid == NULL)
1353                 return LDB_ERR_OPERATIONS_ERROR;
1354         ac->res_dn = NULL;
1355
1356         ac->prim_group_rid = 0;
1357
1358         return samldb_next_step(ac);
1359 }
1360
1361 static int samldb_prim_group_change_2(struct samldb_ctx *ac)
1362 {
1363         struct ldb_context *ldb;
1364
1365         ldb = ldb_module_get_ctx(ac->module);
1366
1367         if (ac->res_dn != NULL)
1368                 ac->new_prim_group_dn = ac->res_dn;
1369         else
1370                 return LDB_ERR_UNWILLING_TO_PERFORM;
1371
1372         ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb),
1373                 ac->prim_group_rid);
1374         if (ac->sid == NULL)
1375                 return LDB_ERR_OPERATIONS_ERROR;
1376         ac->res_dn = NULL;
1377
1378         return samldb_next_step(ac);
1379 }
1380
1381 static int samldb_prim_group_change_4(struct samldb_ctx *ac);
1382 static int samldb_prim_group_change_5(struct samldb_ctx *ac);
1383 static int samldb_prim_group_change_6(struct samldb_ctx *ac);
1384
1385 static int samldb_prim_group_change_3(struct samldb_ctx *ac)
1386 {
1387         int ret;
1388
1389         if (ac->res_dn != NULL)
1390                 ac->old_prim_group_dn = ac->res_dn;
1391         else
1392                 return LDB_ERR_UNWILLING_TO_PERFORM;
1393
1394         /* Only update when the primary group changed */
1395         if (ldb_dn_compare(ac->old_prim_group_dn, ac->new_prim_group_dn) != 0) {
1396                 ac->member_dn = ac->user_dn;
1397                 /* Remove the "member" attribute of the actual (new) primary
1398                  * group */
1399
1400                 ret = samldb_add_step(ac, samldb_prim_group_change_4);
1401                 if (ret != LDB_SUCCESS) return ret;
1402
1403                 ret = samldb_add_step(ac, samldb_group_del_member);
1404                 if (ret != LDB_SUCCESS) return ret;
1405
1406                 /* Add a "member" attribute for the previous primary group */
1407
1408                 ret = samldb_add_step(ac, samldb_prim_group_change_5);
1409                 if (ret != LDB_SUCCESS) return ret;
1410
1411                 ret = samldb_add_step(ac, samldb_group_add_member);
1412                 if (ret != LDB_SUCCESS) return ret;
1413         }
1414
1415         ret = samldb_add_step(ac, samldb_prim_group_change_6);
1416         if (ret != LDB_SUCCESS) return ret;
1417
1418         return samldb_next_step(ac);
1419 }
1420
1421 static int samldb_prim_group_change_4(struct samldb_ctx *ac)
1422 {
1423         ac->group_dn = ac->new_prim_group_dn;
1424
1425         return samldb_next_step(ac);
1426 }
1427
1428 static int samldb_prim_group_change_5(struct samldb_ctx *ac)
1429 {
1430         ac->group_dn = ac->old_prim_group_dn;
1431
1432         return samldb_next_step(ac);
1433 }
1434
1435 static int samldb_prim_group_change_6(struct samldb_ctx *ac)
1436 {
1437         return ldb_next_request(ac->module, ac->req);
1438 }
1439
1440 static int samldb_prim_group_change(struct samldb_ctx *ac)
1441 {
1442         int ret;
1443
1444         /* Finds out the DN of the new primary group */
1445
1446         ret = samldb_add_step(ac, samldb_prim_group_change_1);
1447         if (ret != LDB_SUCCESS) return ret;
1448
1449         ret = samldb_add_step(ac, samldb_dn_from_sid);
1450         if (ret != LDB_SUCCESS) return ret;
1451
1452         ret = samldb_add_step(ac, samldb_user_dn_to_prim_group_rid);
1453         if (ret != LDB_SUCCESS) return ret;
1454
1455         /* Finds out the DN of the old primary group */
1456
1457         ret = samldb_add_step(ac, samldb_prim_group_change_2);
1458         if (ret != LDB_SUCCESS) return ret;
1459
1460         ret = samldb_add_step(ac, samldb_dn_from_sid);
1461         if (ret != LDB_SUCCESS) return ret;
1462
1463         ret = samldb_add_step(ac, samldb_prim_group_change_3);
1464         if (ret != LDB_SUCCESS) return ret;
1465
1466         return samldb_first_step(ac);
1467 }
1468
1469
1470 static int samldb_member_check(struct samldb_ctx *ac)
1471 {
1472         struct ldb_context *ldb;
1473         struct ldb_message_element *el;
1474         struct ldb_dn *member_dn, *group_dn;
1475         uint32_t prim_group_rid;
1476         struct dom_sid *sid;
1477         unsigned int i;
1478
1479         ldb = ldb_module_get_ctx(ac->module);
1480
1481         el = ldb_msg_find_element(ac->msg, "member");
1482         for (i = 0; i < el->num_values; i++) {
1483                 /* Denies to add "member"s to groups which are primary ones
1484                  * for them */
1485                 member_dn = ldb_dn_from_ldb_val(ac, ldb, &el->values[i]);
1486                 if (!ldb_dn_validate(member_dn)) {
1487                         return LDB_ERR_OPERATIONS_ERROR;
1488                 }
1489
1490                 prim_group_rid = samdb_search_uint(ldb, ac, (uint32_t) -1,
1491                                                    member_dn, "primaryGroupID",
1492                                                    NULL);
1493                 if (prim_group_rid == (uint32_t) -1) {
1494                         /* the member hasn't to be a user account -> therefore
1495                          * no check needed in this case. */
1496                         continue;
1497                 }
1498
1499                 sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb),
1500                                       prim_group_rid);
1501                 if (sid == NULL) {
1502                         return LDB_ERR_OPERATIONS_ERROR;
1503                 }
1504
1505                 group_dn = samdb_search_dn(ldb, ac, NULL, "(objectSID=%s)",
1506                                            dom_sid_string(ac, sid));
1507                 if (group_dn == NULL) {
1508                         return LDB_ERR_OPERATIONS_ERROR;
1509                 }
1510
1511                 if (ldb_dn_compare(group_dn, ac->msg->dn) == 0) {
1512                         return LDB_ERR_ENTRY_ALREADY_EXISTS;
1513                 }
1514         }
1515
1516         return ldb_next_request(ac->module, ac->req);
1517 }
1518
1519
1520 static int samldb_prim_group_users_check(struct samldb_ctx *ac)
1521 {
1522         struct ldb_context *ldb;
1523         struct dom_sid *sid;
1524         uint32_t rid;
1525         NTSTATUS status;
1526         int count;
1527
1528         ldb = ldb_module_get_ctx(ac->module);
1529
1530         /* Finds out the SID/RID of the SAM object */
1531         sid = samdb_search_dom_sid(ldb, ac, ac->req->op.del.dn, "objectSID",
1532                                    NULL);
1533         if (sid == NULL) {
1534                 /* No SID - it might not be a SAM object - therefore ok */
1535                 return ldb_next_request(ac->module, ac->req);
1536         }
1537         status = dom_sid_split_rid(ac, sid, NULL, &rid);
1538         if (!NT_STATUS_IS_OK(status)) {
1539                 return LDB_ERR_OPERATIONS_ERROR;
1540         }
1541         if (rid == 0) {
1542                 /* Special object (security principal?) */
1543                 return ldb_next_request(ac->module, ac->req);
1544         }
1545
1546         /* Deny delete requests from groups which are primary ones */
1547         count = samdb_search_count(ldb, NULL,
1548                                    "(&(primaryGroupID=%u)(objectClass=user))",
1549                                    rid);
1550         if (count < 0) {
1551                 return LDB_ERR_OPERATIONS_ERROR;
1552         }
1553         if (count > 0) {
1554                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
1555         }
1556
1557         return ldb_next_request(ac->module, ac->req);
1558 }
1559
1560
1561 /* add */
1562 static int samldb_add(struct ldb_module *module, struct ldb_request *req)
1563 {
1564         struct ldb_context *ldb;
1565         struct samldb_ctx *ac;
1566         int ret;
1567
1568         ldb = ldb_module_get_ctx(module);
1569         ldb_debug(ldb, LDB_DEBUG_TRACE, "samldb_add\n");
1570
1571         /* do not manipulate our control entries */
1572         if (ldb_dn_is_special(req->op.add.message->dn)) {
1573                 return ldb_next_request(module, req);
1574         }
1575
1576         ac = samldb_ctx_init(module, req);
1577         if (ac == NULL) {
1578                 return LDB_ERR_OPERATIONS_ERROR;
1579         }
1580
1581         /* build the new msg */
1582         ac->msg = ldb_msg_copy(ac, ac->req->op.add.message);
1583         if (!ac->msg) {
1584                 talloc_free(ac);
1585                 ldb_debug(ldb, LDB_DEBUG_FATAL,
1586                           "samldb_add: ldb_msg_copy failed!\n");
1587                 return LDB_ERR_OPERATIONS_ERROR;
1588         }
1589
1590         if (samdb_find_attribute(ldb, ac->msg,
1591                                  "objectclass", "computer") != NULL) {
1592
1593                 /* make sure the computer object also has the 'user'
1594                  * objectclass so it will be handled by the next call */
1595                 ret = samdb_find_or_add_value(ldb, ac->msg,
1596                                                 "objectclass", "user");
1597                 if (ret != LDB_SUCCESS) {
1598                         talloc_free(ac);
1599                         return ret;
1600                 }
1601         }
1602
1603         if (samdb_find_attribute(ldb, ac->msg,
1604                                  "objectclass", "user") != NULL) {
1605
1606                 ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
1607                 if (ret != LDB_SUCCESS) {
1608                         talloc_free(ac);
1609                         return ret;
1610                 }
1611
1612                 return samldb_fill_object(ac, "user");
1613         }
1614
1615         if (samdb_find_attribute(ldb, ac->msg,
1616                                  "objectclass", "group") != NULL) {
1617
1618                 ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
1619                 if (ret != LDB_SUCCESS) {
1620                         talloc_free(ac);
1621                         return ret;
1622                 }
1623
1624                 return samldb_fill_object(ac, "group");
1625         }
1626
1627         /* perhaps a foreignSecurityPrincipal? */
1628         if (samdb_find_attribute(ldb, ac->msg,
1629                                  "objectclass",
1630                                  "foreignSecurityPrincipal") != NULL) {
1631
1632                 ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
1633                 if (ret != LDB_SUCCESS) {
1634                         talloc_free(ac);
1635                         return ret;
1636                 }
1637
1638                 return samldb_fill_foreignSecurityPrincipal_object(ac);
1639         }
1640
1641         if (samdb_find_attribute(ldb, ac->msg,
1642                                  "objectclass", "classSchema") != NULL) {
1643
1644                 ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
1645                 if (ret != LDB_SUCCESS) {
1646                         talloc_free(ac);
1647                         return ret;
1648                 }
1649
1650                 ret = samldb_schema_info_update(ac);
1651                 if (ret != LDB_SUCCESS) {
1652                         talloc_free(ac);
1653                         return ret;
1654                 }
1655
1656                 return samldb_fill_object(ac, "classSchema");
1657         }
1658
1659         if (samdb_find_attribute(ldb, ac->msg,
1660                                  "objectclass", "attributeSchema") != NULL) {
1661
1662                 ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
1663                 if (ret != LDB_SUCCESS) {
1664                         talloc_free(ac);
1665                         return ret;
1666                 }
1667
1668                 ret = samldb_schema_info_update(ac);
1669                 if (ret != LDB_SUCCESS) {
1670                         talloc_free(ac);
1671                         return ret;
1672                 }
1673
1674                 return samldb_fill_object(ac, "attributeSchema");
1675         }
1676
1677         talloc_free(ac);
1678
1679         /* nothing matched, go on */
1680         return ldb_next_request(module, req);
1681 }
1682
1683 /* modify */
1684 static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
1685 {
1686         struct ldb_context *ldb;
1687         struct ldb_message *msg;
1688         struct ldb_message_element *el, *el2;
1689         int ret;
1690         uint32_t account_type;
1691
1692         if (ldb_dn_is_special(req->op.mod.message->dn)) {
1693                 /* do not manipulate our control entries */
1694                 return ldb_next_request(module, req);
1695         }
1696
1697         ldb = ldb_module_get_ctx(module);
1698
1699         if (ldb_msg_find_element(req->op.mod.message, "sAMAccountType") != NULL) {
1700                 ldb_asprintf_errstring(ldb,
1701                         "sAMAccountType must not be specified!");
1702                 return LDB_ERR_UNWILLING_TO_PERFORM;
1703         }
1704
1705         /* msDS-IntId is not allowed to be modified
1706          * except when modification comes from replication */
1707         if (ldb_msg_find_element(req->op.mod.message, "msDS-IntId")) {
1708                 if (!ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
1709                         return LDB_ERR_CONSTRAINT_VIOLATION;
1710                 }
1711         }
1712
1713         /* TODO: do not modify original request, create a new one */
1714
1715         el = ldb_msg_find_element(req->op.mod.message, "groupType");
1716         if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
1717                 uint32_t group_type;
1718
1719                 req->op.mod.message = msg = ldb_msg_copy_shallow(req,
1720                         req->op.mod.message);
1721
1722                 group_type = strtoul((const char *)el->values[0].data, NULL, 0);
1723                 account_type =  ds_gtype2atype(group_type);
1724                 ret = samdb_msg_add_uint(ldb, msg, msg,
1725                                          "sAMAccountType",
1726                                          account_type);
1727                 if (ret != LDB_SUCCESS) {
1728                         return ret;
1729                 }
1730                 el2 = ldb_msg_find_element(msg, "sAMAccountType");
1731                 el2->flags = LDB_FLAG_MOD_REPLACE;
1732         }
1733
1734         el = ldb_msg_find_element(req->op.mod.message, "primaryGroupID");
1735         if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
1736                 struct samldb_ctx *ac;
1737
1738                 ac = samldb_ctx_init(module, req);
1739                 if (ac == NULL)
1740                         return LDB_ERR_OPERATIONS_ERROR;
1741
1742                 req->op.mod.message = ac->msg = ldb_msg_copy_shallow(req,
1743                         req->op.mod.message);
1744
1745                 return samldb_prim_group_change(ac);
1746         }
1747
1748         el = ldb_msg_find_element(req->op.mod.message, "userAccountControl");
1749         if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
1750                 uint32_t user_account_control;
1751
1752                 req->op.mod.message = msg = ldb_msg_copy_shallow(req,
1753                         req->op.mod.message);
1754
1755                 user_account_control = strtoul((const char *)el->values[0].data,
1756                         NULL, 0);
1757                 account_type = ds_uf2atype(user_account_control);
1758                 ret = samdb_msg_add_uint(ldb, msg, msg,
1759                                          "sAMAccountType",
1760                                          account_type);
1761                 if (ret != LDB_SUCCESS) {
1762                         return ret;
1763                 }
1764                 el2 = ldb_msg_find_element(msg, "sAMAccountType");
1765                 el2->flags = LDB_FLAG_MOD_REPLACE;
1766
1767                 if (user_account_control & UF_SERVER_TRUST_ACCOUNT) {
1768                         ret = samdb_msg_add_string(ldb, msg, msg,
1769                                                    "isCriticalSystemObject", "TRUE");
1770                         if (ret != LDB_SUCCESS) {
1771                                 return ret;
1772                         }
1773                         el2 = ldb_msg_find_element(msg, "isCriticalSystemObject");
1774                         el2->flags = LDB_FLAG_MOD_REPLACE;
1775
1776                         /* DCs have primaryGroupID of DOMAIN_RID_DCS */
1777                         if (!ldb_msg_find_element(msg, "primaryGroupID")) {
1778                                 ret = samdb_msg_add_uint(ldb, msg, msg,
1779                                                          "primaryGroupID", DOMAIN_RID_DCS);
1780                                 if (ret != LDB_SUCCESS) {
1781                                         return ret;
1782                                 }
1783                                 el2 = ldb_msg_find_element(msg, "primaryGroupID");
1784                                 el2->flags = LDB_FLAG_MOD_REPLACE;
1785                         }
1786                 }
1787         }
1788
1789         el = ldb_msg_find_element(req->op.mod.message, "member");
1790         if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
1791                 struct samldb_ctx *ac;
1792
1793                 ac = samldb_ctx_init(module, req);
1794                 if (ac == NULL)
1795                         return LDB_ERR_OPERATIONS_ERROR;
1796
1797                 req->op.mod.message = ac->msg = ldb_msg_copy_shallow(req,
1798                         req->op.mod.message);
1799
1800                 return samldb_member_check(ac);
1801         }
1802
1803         /* nothing matched, go on */
1804         return ldb_next_request(module, req);
1805 }
1806
1807 /* delete */
1808 static int samldb_delete(struct ldb_module *module, struct ldb_request *req)
1809 {
1810         struct samldb_ctx *ac;
1811
1812         if (ldb_dn_is_special(req->op.del.dn)) {
1813                 /* do not manipulate our control entries */
1814                 return ldb_next_request(module, req);
1815         }
1816
1817         ac = samldb_ctx_init(module, req);
1818         if (ac == NULL)
1819                 return LDB_ERR_OPERATIONS_ERROR;
1820
1821         return samldb_prim_group_users_check(ac);
1822 }
1823
1824 static int samldb_extended_allocate_rid_pool(struct ldb_module *module, struct ldb_request *req)
1825 {
1826         struct ldb_context *ldb = ldb_module_get_ctx(module);
1827         struct dsdb_fsmo_extended_op *exop;
1828         int ret;
1829
1830         exop = talloc_get_type(req->op.extended.data, struct dsdb_fsmo_extended_op);
1831         if (!exop) {
1832                 ldb_debug(ldb, LDB_DEBUG_FATAL, "samldb_extended_allocate_rid_pool: invalid extended data\n");
1833                 return LDB_ERR_PROTOCOL_ERROR;
1834         }
1835
1836         ret = ridalloc_allocate_rid_pool_fsmo(module, exop);
1837         if (ret != LDB_SUCCESS) {
1838                 return ret;
1839         }
1840
1841         return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
1842 }
1843
1844 static int samldb_extended(struct ldb_module *module, struct ldb_request *req)
1845 {
1846         if (strcmp(req->op.extended.oid, DSDB_EXTENDED_ALLOCATE_RID_POOL) == 0) {
1847                 return samldb_extended_allocate_rid_pool(module, req);
1848         }
1849
1850         return ldb_next_request(module, req);
1851 }
1852
1853
1854 _PUBLIC_ const struct ldb_module_ops ldb_samldb_module_ops = {
1855         .name          = "samldb",
1856         .add           = samldb_add,
1857         .modify        = samldb_modify,
1858         .del           = samldb_delete,
1859         .extended      = samldb_extended
1860 };
1861