ae99ebbe9edb8dcf55cb6da703ad2fa998279f12
[nivanova/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-2014
5    Copyright (C) Simo Sorce  2004-2008
6    Copyright (C) Matthias Dieter Wallnöfer 2009-2011
7    Copyright (C) Matthieu Patou 2012
8    Copyright (C) Catalyst.Net Ltd 2017
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 /*
25  *  Name: ldb
26  *
27  *  Component: ldb samldb module
28  *
29  *  Description: various internal DSDB triggers - most for SAM specific objects
30  *
31  *  Author: Simo Sorce
32  */
33
34 #include "includes.h"
35 #include "libcli/ldap/ldap_ndr.h"
36 #include "ldb_module.h"
37 #include "auth/auth.h"
38 #include "dsdb/samdb/samdb.h"
39 #include "dsdb/samdb/ldb_modules/util.h"
40 #include "dsdb/samdb/ldb_modules/ridalloc.h"
41 #include "libcli/security/security.h"
42 #include "librpc/gen_ndr/ndr_security.h"
43 #include "ldb_wrap.h"
44 #include "param/param.h"
45 #include "libds/common/flag_mapping.h"
46 #include "system/network.h"
47 #include "librpc/gen_ndr/irpc.h"
48
49 struct samldb_ctx;
50 enum samldb_add_type {
51         SAMLDB_TYPE_USER,
52         SAMLDB_TYPE_GROUP,
53         SAMLDB_TYPE_CLASS,
54         SAMLDB_TYPE_ATTRIBUTE
55 };
56
57 typedef int (*samldb_step_fn_t)(struct samldb_ctx *);
58
59 struct samldb_step {
60         struct samldb_step *next;
61         samldb_step_fn_t fn;
62 };
63
64 struct samldb_ctx {
65         struct ldb_module *module;
66         struct ldb_request *req;
67
68         /* used for add operations */
69         enum samldb_add_type type;
70
71         /* the resulting message */
72         struct ldb_message *msg;
73
74         /* used in "samldb_find_for_defaultObjectCategory" */
75         struct ldb_dn *dn, *res_dn;
76
77         /* all the async steps necessary to complete the operation */
78         struct samldb_step *steps;
79         struct samldb_step *curstep;
80
81         /* If someone set an ares to forward controls and response back to the caller */
82         struct ldb_reply *ares;
83 };
84
85 static struct samldb_ctx *samldb_ctx_init(struct ldb_module *module,
86                                           struct ldb_request *req)
87 {
88         struct ldb_context *ldb;
89         struct samldb_ctx *ac;
90
91         ldb = ldb_module_get_ctx(module);
92
93         ac = talloc_zero(req, struct samldb_ctx);
94         if (ac == NULL) {
95                 ldb_oom(ldb);
96                 return NULL;
97         }
98
99         ac->module = module;
100         ac->req = req;
101
102         return ac;
103 }
104
105 static int samldb_add_step(struct samldb_ctx *ac, samldb_step_fn_t fn)
106 {
107         struct samldb_step *step, *stepper;
108
109         step = talloc_zero(ac, struct samldb_step);
110         if (step == NULL) {
111                 return ldb_oom(ldb_module_get_ctx(ac->module));
112         }
113
114         step->fn = fn;
115
116         if (ac->steps == NULL) {
117                 ac->steps = step;
118                 ac->curstep = step;
119         } else {
120                 if (ac->curstep == NULL)
121                         return ldb_operr(ldb_module_get_ctx(ac->module));
122                 for (stepper = ac->curstep; stepper->next != NULL;
123                         stepper = stepper->next);
124                 stepper->next = step;
125         }
126
127         return LDB_SUCCESS;
128 }
129
130 static int samldb_first_step(struct samldb_ctx *ac)
131 {
132         if (ac->steps == NULL) {
133                 return ldb_operr(ldb_module_get_ctx(ac->module));
134         }
135
136         ac->curstep = ac->steps;
137         return ac->curstep->fn(ac);
138 }
139
140 static int samldb_next_step(struct samldb_ctx *ac)
141 {
142         if (ac->curstep->next) {
143                 ac->curstep = ac->curstep->next;
144                 return ac->curstep->fn(ac);
145         }
146
147         /* We exit the samldb module here. If someone set an "ares" to forward
148          * controls and response back to the caller, use them. */
149         if (ac->ares) {
150                 return ldb_module_done(ac->req, ac->ares->controls,
151                                        ac->ares->response, LDB_SUCCESS);
152         } else {
153                 return ldb_module_done(ac->req, NULL, NULL, LDB_SUCCESS);
154         }
155 }
156
157 static int samldb_unique_attr_check(struct samldb_ctx *ac, const char *attr,
158                                     const char *attr_conflict,
159                                     struct ldb_dn *base_dn)
160 {
161         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
162         const char * const no_attrs[] = { NULL };
163         struct ldb_result *res;
164         const char *enc_str;
165         struct ldb_message_element *el;
166         int ret;
167
168         el = dsdb_get_single_valued_attr(ac->msg, attr,
169                                          ac->req->operation);
170         if (el == NULL) {
171                 /* we are not affected */
172                 return LDB_SUCCESS;
173         }
174
175         if (el->num_values > 1) {
176                 ldb_asprintf_errstring(ldb,
177                                        "samldb: %s has %u values, should be single-valued!",
178                                        attr, el->num_values);
179                 return LDB_ERR_CONSTRAINT_VIOLATION;
180         } else if (el->num_values == 0) {
181                 ldb_asprintf_errstring(ldb,
182                                        "samldb: new value for %s not provided for mandatory, single-valued attribute!",
183                                        attr);
184                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
185         }
186         if (el->values[0].length == 0) {
187                 ldb_asprintf_errstring(ldb,
188                                        "samldb: %s is of zero length, should have a value!",
189                                        attr);
190                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
191         }
192         enc_str = ldb_binary_encode(ac, el->values[0]);
193
194         if (enc_str == NULL) {
195                 return ldb_module_oom(ac->module);
196         }
197
198         /* Make sure that attr (eg) "sAMAccountName" is only used once */
199
200         if (attr_conflict != NULL) {
201                 ret = dsdb_module_search(ac->module, ac, &res,
202                                          base_dn,
203                                          LDB_SCOPE_SUBTREE, no_attrs,
204                                          DSDB_FLAG_NEXT_MODULE, ac->req,
205                                          "(|(%s=%s)(%s=%s))",
206                                          attr, enc_str,
207                                          attr_conflict, enc_str);
208         } else {
209                 ret = dsdb_module_search(ac->module, ac, &res,
210                                          base_dn,
211                                          LDB_SCOPE_SUBTREE, no_attrs,
212                                          DSDB_FLAG_NEXT_MODULE, ac->req,
213                                          "(%s=%s)", attr, enc_str);
214         }
215         if (ret != LDB_SUCCESS) {
216                 return ret;
217         }
218         if (res->count > 1) {
219                 return ldb_operr(ldb);
220         } else if (res->count == 1) {
221                 if (ldb_dn_compare(res->msgs[0]->dn, ac->msg->dn) != 0) {
222                         ldb_asprintf_errstring(ldb,
223                                                "samldb: %s '%s' already in use!",
224                                                attr, enc_str);
225                         return LDB_ERR_ENTRY_ALREADY_EXISTS;
226                 }
227         }
228         talloc_free(res);
229
230         return LDB_SUCCESS;
231 }
232
233 static int samldb_sam_accountname_valid_check(struct samldb_ctx *ac)
234 {
235         int ret = samldb_unique_attr_check(ac, "samAccountName", NULL,
236                                            ldb_get_default_basedn(
237                                                    ldb_module_get_ctx(ac->module)));
238         if (ret == LDB_ERR_OBJECT_CLASS_VIOLATION) {
239                 ret = LDB_ERR_CONSTRAINT_VIOLATION;
240         }
241         return ret;
242 }
243
244 static int samldb_schema_attributeid_valid_check(struct samldb_ctx *ac)
245 {
246         int ret = samldb_unique_attr_check(ac, "attributeID", "governsID",
247                                            ldb_get_schema_basedn(
248                                                    ldb_module_get_ctx(ac->module)));
249         if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
250                 ret = LDB_ERR_UNWILLING_TO_PERFORM;
251         }
252         return ret;
253 }
254
255 static int samldb_schema_governsid_valid_check(struct samldb_ctx *ac)
256 {
257         int ret = samldb_unique_attr_check(ac, "governsID", "attributeID",
258                                            ldb_get_schema_basedn(
259                                                    ldb_module_get_ctx(ac->module)));
260         if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
261                 ret = LDB_ERR_UNWILLING_TO_PERFORM;
262         }
263         return ret;
264 }
265
266 static int samldb_schema_ldapdisplayname_valid_check(struct samldb_ctx *ac)
267 {
268         int ret = samldb_unique_attr_check(ac, "lDAPDisplayName", NULL,
269                                            ldb_get_schema_basedn(
270                                                    ldb_module_get_ctx(ac->module)));
271         if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
272                 ret = LDB_ERR_UNWILLING_TO_PERFORM;
273         }
274         return ret;
275 }
276
277 static int samldb_check_linkid_used(struct samldb_ctx *ac,
278                                     struct dsdb_schema *schema,
279                                     struct ldb_dn *schema_dn,
280                                     struct ldb_context *ldb,
281                                     int32_t linkID,
282                                     bool *found)
283 {
284         int ret;
285         struct ldb_result *ldb_res;
286
287         if (dsdb_attribute_by_linkID(schema, linkID)) {
288                 *found = true;
289                 return LDB_SUCCESS;
290         }
291
292         ret = dsdb_module_search(ac->module, ac,
293                                  &ldb_res,
294                                  schema_dn, LDB_SCOPE_ONELEVEL, NULL,
295                                  DSDB_FLAG_NEXT_MODULE,
296                                  ac->req,
297                                  "(linkID=%d)", linkID);
298         if (ret != LDB_SUCCESS) {
299                 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
300                               __location__": Searching for linkID=%d failed - %s\n",
301                               linkID,
302                               ldb_errstring(ldb));
303                 return ldb_operr(ldb);
304         }
305
306         *found = (ldb_res->count != 0);
307         talloc_free(ldb_res);
308
309         return LDB_SUCCESS;
310 }
311
312 /* Find the next open forward linkID in the schema. */
313 static int samldb_generate_next_linkid(struct samldb_ctx *ac,
314                                        struct dsdb_schema *schema,
315                                        int32_t *next_linkID)
316 {
317         int ret;
318         struct ldb_context *ldb;
319         struct ldb_dn *schema_dn;
320         bool linkID_used = true;
321
322         /*
323          * Windows starts at about 0xB0000000 in order to stop potential
324          * collisions with future additions to the schema. We pass this
325          * around as a signed int sometimes, but this should be sufficient.
326          */
327         *next_linkID = 0x40000000;
328
329         ldb = ldb_module_get_ctx(ac->module);
330         schema_dn = ldb_get_schema_basedn(ldb);
331
332         while (linkID_used) {
333                 *next_linkID += 2;
334                 ret = samldb_check_linkid_used(ac, schema,
335                                                schema_dn, ldb,
336                                                *next_linkID, &linkID_used);
337                 if (ret != LDB_SUCCESS) {
338                         return ret;
339                 }
340         }
341
342         return LDB_SUCCESS;
343 }
344
345 static int samldb_schema_add_handle_linkid(struct samldb_ctx *ac)
346 {
347         int ret;
348         bool ok, found = false;
349         struct ldb_message_element *el;
350         const char *enc_str;
351         const struct dsdb_attribute *attr;
352         struct ldb_context *ldb;
353         struct ldb_dn *schema_dn;
354         struct dsdb_schema *schema;
355         int32_t new_linkID = 0;
356
357         ldb = ldb_module_get_ctx(ac->module);
358         schema = dsdb_get_schema(ldb, ac);
359         schema_dn = ldb_get_schema_basedn(ldb);
360
361         el = dsdb_get_single_valued_attr(ac->msg, "linkID",
362                                          ac->req->operation);
363         if (el == NULL) {
364                 return LDB_SUCCESS;
365         }
366
367         enc_str = ldb_binary_encode(ac, el->values[0]);
368         if (enc_str == NULL) {
369                 return ldb_module_oom(ac->module);
370         }
371
372         ok = (strcmp(enc_str, "0") == 0);
373         if (ok) {
374                 return LDB_SUCCESS;
375         }
376
377         /*
378          * This OID indicates that the caller wants the linkID
379          * to be automatically generated. We therefore assign
380          * it the next open linkID.
381          */
382         ok = (strcmp(enc_str, "1.2.840.113556.1.2.50") == 0);
383         if (ok) {
384                 ret = samldb_generate_next_linkid(ac, schema, &new_linkID);
385                 if (ret != LDB_SUCCESS) {
386                         return ret;
387                 }
388
389                 ldb_msg_remove_element(ac->msg, el);
390                 ret = samdb_msg_add_int(ldb, ac->msg, ac->msg, "linkID",
391                                         new_linkID);
392                 return ret;
393         }
394
395         /*
396          * Using either the attributeID or lDAPDisplayName of
397          * another attribute in the linkID field indicates that
398          * we should make this the backlink of that attribute.
399          */
400         attr = dsdb_attribute_by_attributeID_oid(schema, enc_str);
401         if (attr == NULL) {
402                 attr = dsdb_attribute_by_lDAPDisplayName(schema, enc_str);
403         }
404
405         if (attr != NULL) {
406                 /*
407                  * The attribute we're adding this as a backlink of must
408                  * be a forward link.
409                  */
410                 if (attr->linkID % 2 != 0) {
411                         return LDB_ERR_UNWILLING_TO_PERFORM;
412                 }
413
414                 new_linkID = attr->linkID + 1;
415
416                 /* Make sure that this backlink doesn't already exist. */
417                 ret = samldb_check_linkid_used(ac, schema,
418                                                schema_dn, ldb,
419                                                new_linkID, &found);
420                 if (ret != LDB_SUCCESS) {
421                         return ret;
422                 }
423
424                 if (found) {
425                         return LDB_ERR_UNWILLING_TO_PERFORM;
426                 }
427
428                 ldb_msg_remove_element(ac->msg, el);
429                 ret = samdb_msg_add_int(ldb, ac->msg, ac->msg, "linkID",
430                                         new_linkID);
431                 return ret;
432         }
433
434         schema_dn = ldb_get_schema_basedn(ldb_module_get_ctx(ac->module));
435         ret = samldb_unique_attr_check(ac, "linkID", NULL, schema_dn);
436         if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
437                 return LDB_ERR_UNWILLING_TO_PERFORM;
438         } else {
439                 return ret;
440         }
441 }
442
443 static int samldb_check_mapiid_used(struct samldb_ctx *ac,
444                                     struct dsdb_schema *schema,
445                                     struct ldb_dn *schema_dn,
446                                     struct ldb_context *ldb,
447                                     int32_t mapiid,
448                                     bool *found)
449 {
450         int ret;
451         struct ldb_result *ldb_res;
452
453         ret = dsdb_module_search(ac->module, ac,
454                                  &ldb_res,
455                                  schema_dn, LDB_SCOPE_ONELEVEL, NULL,
456                                  DSDB_FLAG_NEXT_MODULE,
457                                  ac->req,
458                                  "(mAPIID=%d)", mapiid);
459         if (ret != LDB_SUCCESS) {
460                 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
461                               __location__": Searching for mAPIID=%d failed - %s\n",
462                               mapiid,
463                               ldb_errstring(ldb));
464                 return ldb_operr(ldb);
465         }
466
467         *found = (ldb_res->count != 0);
468         talloc_free(ldb_res);
469
470         return LDB_SUCCESS;
471 }
472
473 static int samldb_generate_next_mapiid(struct samldb_ctx *ac,
474                                        struct dsdb_schema *schema,
475                                        int32_t *next_mapiid)
476 {
477         int ret;
478         struct ldb_context *ldb;
479         struct ldb_dn *schema_dn;
480         bool mapiid_used = true;
481
482         /* Windows' generation seems to start about here */
483         *next_mapiid = 60000;
484
485         ldb = ldb_module_get_ctx(ac->module);
486         schema_dn = ldb_get_schema_basedn(ldb);
487
488         while (mapiid_used) {
489                 *next_mapiid += 1;
490                 ret = samldb_check_mapiid_used(ac, schema,
491                                                schema_dn, ldb,
492                                                *next_mapiid, &mapiid_used);
493                 if (ret != LDB_SUCCESS) {
494                         return ret;
495                 }
496         }
497
498         return LDB_SUCCESS;
499 }
500
501 static int samldb_schema_add_handle_mapiid(struct samldb_ctx *ac)
502 {
503         int ret;
504         bool ok;
505         struct ldb_message_element *el;
506         const char *enc_str;
507         struct ldb_context *ldb;
508         struct ldb_dn *schema_dn;
509         struct dsdb_schema *schema;
510         int32_t new_mapiid = 0;
511
512         /*
513          * The mAPIID of a new attribute should be automatically generated
514          * if a specific OID is put as the mAPIID, as according to
515          * [MS-ADTS] 3.1.1.2.3.2.
516          */
517
518         ldb = ldb_module_get_ctx(ac->module);
519         schema = dsdb_get_schema(ldb, ac);
520         schema_dn = ldb_get_schema_basedn(ldb);
521
522         el = dsdb_get_single_valued_attr(ac->msg, "mAPIID",
523                                          ac->req->operation);
524         if (el == NULL) {
525                 return LDB_SUCCESS;
526         }
527
528         enc_str = ldb_binary_encode(ac, el->values[0]);
529         if (enc_str == NULL) {
530                 return ldb_module_oom(ac->module);
531         }
532
533         ok = (strcmp(enc_str, "1.2.840.113556.1.2.49") == 0);
534         if (ok) {
535                 ret = samldb_generate_next_mapiid(ac, schema,
536                                                   &new_mapiid);
537                 if (ret != LDB_SUCCESS) {
538                         return ret;
539                 }
540
541                 ldb_msg_remove_element(ac->msg, el);
542                 ret = samdb_msg_add_int(ldb, ac->msg, ac->msg,
543                                         "mAPIID", new_mapiid);
544                 return ret;
545         }
546
547         schema_dn = ldb_get_schema_basedn(ldb_module_get_ctx(ac->module));
548         ret = samldb_unique_attr_check(ac, "mAPIID", NULL, schema_dn);
549         if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
550                 return LDB_ERR_UNWILLING_TO_PERFORM;
551         } else {
552                 return ret;
553         }
554 }
555
556 /* sAMAccountName handling */
557 static int samldb_generate_sAMAccountName(struct ldb_context *ldb,
558                                           struct ldb_message *msg)
559 {
560         char *name;
561
562         /* Format: $000000-000000000000 */
563
564         name = talloc_asprintf(msg, "$%.6X-%.6X%.6X",
565                                 (unsigned int)generate_random(),
566                                 (unsigned int)generate_random(),
567                                 (unsigned int)generate_random());
568         if (name == NULL) {
569                 return ldb_oom(ldb);
570         }
571         return ldb_msg_add_steal_string(msg, "sAMAccountName", name);
572 }
573
574 static int samldb_check_sAMAccountName(struct samldb_ctx *ac)
575 {
576         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
577         int ret;
578
579         if (ldb_msg_find_element(ac->msg, "sAMAccountName") == NULL) {
580                 ret = samldb_generate_sAMAccountName(ldb, ac->msg);
581                 if (ret != LDB_SUCCESS) {
582                         return ret;
583                 }
584         }
585
586         ret = samldb_sam_accountname_valid_check(ac);
587         if (ret != LDB_SUCCESS) {
588                 return ret;
589         }
590
591         return samldb_next_step(ac);
592 }
593
594
595 static bool samldb_msg_add_sid(struct ldb_message *msg,
596                                 const char *name,
597                                 const struct dom_sid *sid)
598 {
599         struct ldb_val v;
600         enum ndr_err_code ndr_err;
601
602         ndr_err = ndr_push_struct_blob(&v, msg, sid,
603                                        (ndr_push_flags_fn_t)ndr_push_dom_sid);
604         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
605                 return false;
606         }
607         return (ldb_msg_add_value(msg, name, &v, NULL) == 0);
608 }
609
610
611 /* allocate a SID using our RID Set */
612 static int samldb_allocate_sid(struct samldb_ctx *ac)
613 {
614         uint32_t rid;
615         struct dom_sid *sid;
616         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
617         int ret;
618
619         ret = ridalloc_allocate_rid(ac->module, &rid, ac->req);
620         if (ret != LDB_SUCCESS) {
621                 return ret;
622         }
623
624         sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
625         if (sid == NULL) {
626                 return ldb_module_oom(ac->module);
627         }
628
629         if ( ! samldb_msg_add_sid(ac->msg, "objectSid", sid)) {
630                 return ldb_operr(ldb);
631         }
632
633         return samldb_next_step(ac);
634 }
635
636 /*
637   see if a krbtgt_number is available
638  */
639 static bool samldb_krbtgtnumber_available(struct samldb_ctx *ac,
640                                           uint32_t krbtgt_number)
641 {
642         TALLOC_CTX *tmp_ctx = talloc_new(ac);
643         struct ldb_result *res;
644         const char * const no_attrs[] = { NULL };
645         int ret;
646
647         ret = dsdb_module_search(ac->module, tmp_ctx, &res,
648                                  ldb_get_default_basedn(ldb_module_get_ctx(ac->module)),
649                                  LDB_SCOPE_SUBTREE, no_attrs,
650                                  DSDB_FLAG_NEXT_MODULE,
651                                  ac->req,
652                                  "(msDC-SecondaryKrbTgtNumber=%u)",
653                                  krbtgt_number);
654         if (ret == LDB_SUCCESS && res->count == 0) {
655                 talloc_free(tmp_ctx);
656                 return true;
657         }
658         talloc_free(tmp_ctx);
659         return false;
660 }
661
662 /* special handling for add in RODC join */
663 static int samldb_rodc_add(struct samldb_ctx *ac)
664 {
665         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
666         uint32_t krbtgt_number, i_start, i;
667         int ret;
668         struct ldb_val newpass_utf16;
669
670         /* find a unused msDC-SecondaryKrbTgtNumber */
671         i_start = generate_random() & 0xFFFF;
672         if (i_start == 0) {
673                 i_start = 1;
674         }
675
676         for (i=i_start; i<=0xFFFF; i++) {
677                 if (samldb_krbtgtnumber_available(ac, i)) {
678                         krbtgt_number = i;
679                         goto found;
680                 }
681         }
682         for (i=1; i<i_start; i++) {
683                 if (samldb_krbtgtnumber_available(ac, i)) {
684                         krbtgt_number = i;
685                         goto found;
686                 }
687         }
688
689         ldb_asprintf_errstring(ldb,
690                                "%08X: Unable to find available msDS-SecondaryKrbTgtNumber",
691                                W_ERROR_V(WERR_NO_SYSTEM_RESOURCES));
692         return LDB_ERR_OTHER;
693
694 found:
695         ret = ldb_msg_add_empty(ac->msg, "msDS-SecondaryKrbTgtNumber",
696                                 LDB_FLAG_INTERNAL_DISABLE_VALIDATION, NULL);
697         if (ret != LDB_SUCCESS) {
698                 return ldb_operr(ldb);
699         }
700
701         ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
702                                  "msDS-SecondaryKrbTgtNumber", krbtgt_number);
703         if (ret != LDB_SUCCESS) {
704                 return ldb_operr(ldb);
705         }
706
707         ret = ldb_msg_add_fmt(ac->msg, "sAMAccountName", "krbtgt_%u",
708                               krbtgt_number);
709         if (ret != LDB_SUCCESS) {
710                 return ldb_operr(ldb);
711         }
712
713         newpass_utf16 = data_blob_talloc_zero(ac->module, 256);
714         if (newpass_utf16.data == NULL) {
715                 return ldb_oom(ldb);
716         }
717         /*
718          * Note that the password_hash module will ignore
719          * this value and use it's own generate_secret_buffer()
720          * that's why we can just use generate_random_buffer()
721          * here.
722          */
723         generate_random_buffer(newpass_utf16.data, newpass_utf16.length);
724         ret = ldb_msg_add_steal_value(ac->msg, "clearTextPassword", &newpass_utf16);
725         if (ret != LDB_SUCCESS) {
726                 return ldb_operr(ldb);
727         }
728
729         return samldb_next_step(ac);
730 }
731
732 static int samldb_find_for_defaultObjectCategory(struct samldb_ctx *ac)
733 {
734         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
735         struct ldb_result *res;
736         const char * const no_attrs[] = { NULL };
737         int ret;
738
739         ac->res_dn = NULL;
740
741         ret = dsdb_module_search(ac->module, ac, &res,
742                                  ac->dn, LDB_SCOPE_BASE, no_attrs,
743                                  DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT
744                                  | DSDB_FLAG_NEXT_MODULE,
745                                  ac->req,
746                                  "(objectClass=classSchema)");
747         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
748                 /* Don't be pricky when the DN doesn't exist if we have the */
749                 /* RELAX control specified */
750                 if (ldb_request_get_control(ac->req,
751                                             LDB_CONTROL_RELAX_OID) == NULL) {
752                         ldb_set_errstring(ldb,
753                                           "samldb_find_defaultObjectCategory: "
754                                           "Invalid DN for 'defaultObjectCategory'!");
755                         return LDB_ERR_CONSTRAINT_VIOLATION;
756                 }
757         }
758         if ((ret != LDB_ERR_NO_SUCH_OBJECT) && (ret != LDB_SUCCESS)) {
759                 return ret;
760         }
761
762         if (ret == LDB_SUCCESS) {
763                 /* ensure the defaultObjectCategory has a full GUID */
764                 struct ldb_message *m;
765                 m = ldb_msg_new(ac->msg);
766                 if (m == NULL) {
767                         return ldb_oom(ldb);
768                 }
769                 m->dn = ac->msg->dn;
770                 if (ldb_msg_add_string(m, "defaultObjectCategory",
771                                        ldb_dn_get_extended_linearized(m, res->msgs[0]->dn, 1)) !=
772                     LDB_SUCCESS) {
773                         return ldb_oom(ldb);
774                 }
775                 m->elements[0].flags = LDB_FLAG_MOD_REPLACE;
776
777                 ret = dsdb_module_modify(ac->module, m,
778                                          DSDB_FLAG_NEXT_MODULE,
779                                          ac->req);
780                 if (ret != LDB_SUCCESS) {
781                         return ret;
782                 }
783         }
784
785
786         ac->res_dn = ac->dn;
787
788         return samldb_next_step(ac);
789 }
790
791 /**
792  * msDS-IntId attributeSchema attribute handling
793  * during LDB_ADD request processing
794  */
795 static int samldb_add_handle_msDS_IntId(struct samldb_ctx *ac)
796 {
797         int ret;
798         bool id_exists;
799         uint32_t msds_intid;
800         int32_t system_flags;
801         struct ldb_context *ldb;
802         struct ldb_result *ldb_res;
803         struct ldb_dn *schema_dn;
804         struct samldb_msds_intid_persistant *msds_intid_struct;
805         struct dsdb_schema *schema;
806
807         ldb = ldb_module_get_ctx(ac->module);
808         schema_dn = ldb_get_schema_basedn(ldb);
809
810         /* replicated update should always go through */
811         if (ldb_request_get_control(ac->req,
812                                     DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
813                 return LDB_SUCCESS;
814         }
815
816         /* msDS-IntId is handled by system and should never be
817          * passed by clients */
818         if (ldb_msg_find_element(ac->msg, "msDS-IntId")) {
819                 return LDB_ERR_UNWILLING_TO_PERFORM;
820         }
821
822         /* do not generate msDS-IntId if Relax control is passed */
823         if (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
824                 return LDB_SUCCESS;
825         }
826
827         /* check Functional Level */
828         if (dsdb_functional_level(ldb) < DS_DOMAIN_FUNCTION_2003) {
829                 return LDB_SUCCESS;
830         }
831
832         /* check systemFlags for SCHEMA_BASE_OBJECT flag */
833         system_flags = ldb_msg_find_attr_as_int(ac->msg, "systemFlags", 0);
834         if (system_flags & SYSTEM_FLAG_SCHEMA_BASE_OBJECT) {
835                 return LDB_SUCCESS;
836         }
837         schema = dsdb_get_schema(ldb, NULL);
838         if (!schema) {
839                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
840                               "samldb_schema_info_update: no dsdb_schema loaded");
841                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
842                 return ldb_operr(ldb);
843         }
844
845         msds_intid_struct = (struct samldb_msds_intid_persistant*) ldb_get_opaque(ldb, SAMLDB_MSDS_INTID_OPAQUE);
846         if (!msds_intid_struct) {
847                 msds_intid_struct = talloc(ldb, struct samldb_msds_intid_persistant);
848                 /* Generate new value for msDs-IntId
849                 * Value should be in 0x80000000..0xBFFFFFFF range */
850                 msds_intid = generate_random() % 0X3FFFFFFF;
851                 msds_intid += 0x80000000;
852                 msds_intid_struct->msds_intid = msds_intid;
853                 DEBUG(2, ("No samldb_msds_intid_persistant struct, allocating a new one\n"));
854         } else {
855                 msds_intid = msds_intid_struct->msds_intid;
856         }
857
858         /* probe id values until unique one is found */
859         do {
860                 msds_intid++;
861                 if (msds_intid > 0xBFFFFFFF) {
862                         msds_intid = 0x80000001;
863                 }
864                 /*
865                  * We search in the schema if we have already this
866                  * intid (using dsdb_attribute_by_attributeID_id
867                  * because in the range 0x80000000 0xBFFFFFFFF,
868                  * attributeID is a DSDB_ATTID_TYPE_INTID).
869                  *
870                  * If so generate another random value.
871                  *
872                  * We have to check the DB in case someone else has
873                  * modified the database while we are doing our
874                  * changes too (this case should be very bery rare) in
875                  * order to be sure.
876                  */
877                 if (dsdb_attribute_by_attributeID_id(schema, msds_intid)) {
878                         id_exists = true;
879                         msds_intid = generate_random() % 0X3FFFFFFF;
880                         msds_intid += 0x80000000;
881                         continue;
882                 }
883
884
885                 ret = dsdb_module_search(ac->module, ac,
886                                          &ldb_res,
887                                          schema_dn, LDB_SCOPE_ONELEVEL, NULL,
888                                          DSDB_FLAG_NEXT_MODULE,
889                                          ac->req,
890                                          "(msDS-IntId=%d)", msds_intid);
891                 if (ret != LDB_SUCCESS) {
892                         ldb_debug_set(ldb, LDB_DEBUG_ERROR,
893                                       __location__": Searching for msDS-IntId=%d failed - %s\n",
894                                       msds_intid,
895                                       ldb_errstring(ldb));
896                         return ldb_operr(ldb);
897                 }
898                 id_exists = (ldb_res->count > 0);
899                 talloc_free(ldb_res);
900
901         } while(id_exists);
902         msds_intid_struct->msds_intid = msds_intid;
903         ldb_set_opaque(ldb, SAMLDB_MSDS_INTID_OPAQUE, msds_intid_struct);
904
905         return samdb_msg_add_int(ldb, ac->msg, ac->msg, "msDS-IntId",
906                                  msds_intid);
907 }
908
909
910 /*
911  * samldb_add_entry (async)
912  */
913
914 static int samldb_add_entry_callback(struct ldb_request *req,
915                                         struct ldb_reply *ares)
916 {
917         struct ldb_context *ldb;
918         struct samldb_ctx *ac;
919         int ret;
920
921         ac = talloc_get_type(req->context, struct samldb_ctx);
922         ldb = ldb_module_get_ctx(ac->module);
923
924         if (!ares) {
925                 return ldb_module_done(ac->req, NULL, NULL,
926                                         LDB_ERR_OPERATIONS_ERROR);
927         }
928
929         if (ares->type == LDB_REPLY_REFERRAL) {
930                 return ldb_module_send_referral(ac->req, ares->referral);
931         }
932
933         if (ares->error != LDB_SUCCESS) {
934                 return ldb_module_done(ac->req, ares->controls,
935                                         ares->response, ares->error);
936         }
937         if (ares->type != LDB_REPLY_DONE) {
938                 ldb_asprintf_errstring(ldb, "Invalid LDB reply type %d", ares->type);
939                 return ldb_module_done(ac->req, NULL, NULL,
940                                         LDB_ERR_OPERATIONS_ERROR);
941         }
942
943         /* The caller may wish to get controls back from the add */
944         ac->ares = talloc_steal(ac, ares);
945
946         ret = samldb_next_step(ac);
947         if (ret != LDB_SUCCESS) {
948                 return ldb_module_done(ac->req, NULL, NULL, ret);
949         }
950         return ret;
951 }
952
953 static int samldb_add_entry(struct samldb_ctx *ac)
954 {
955         struct ldb_context *ldb;
956         struct ldb_request *req;
957         int ret;
958
959         ldb = ldb_module_get_ctx(ac->module);
960
961         ret = ldb_build_add_req(&req, ldb, ac,
962                                 ac->msg,
963                                 ac->req->controls,
964                                 ac, samldb_add_entry_callback,
965                                 ac->req);
966         LDB_REQ_SET_LOCATION(req);
967         if (ret != LDB_SUCCESS) {
968                 return ret;
969         }
970
971         return ldb_next_request(ac->module, req);
972 }
973
974 /*
975  * return true if msg carries an attributeSchema that is intended to be RODC
976  * filtered but is also a system-critical attribute.
977  */
978 static bool check_rodc_critical_attribute(struct ldb_message *msg)
979 {
980         uint32_t schemaFlagsEx, searchFlags, rodc_filtered_flags;
981
982         schemaFlagsEx = ldb_msg_find_attr_as_uint(msg, "schemaFlagsEx", 0);
983         searchFlags = ldb_msg_find_attr_as_uint(msg, "searchFlags", 0);
984         rodc_filtered_flags = (SEARCH_FLAG_RODC_ATTRIBUTE
985                               | SEARCH_FLAG_CONFIDENTIAL);
986
987         if ((schemaFlagsEx & SCHEMA_FLAG_ATTR_IS_CRITICAL) &&
988                 ((searchFlags & rodc_filtered_flags) == rodc_filtered_flags)) {
989                 return true;
990         } else {
991                 return false;
992         }
993 }
994
995
996 static int samldb_fill_object(struct samldb_ctx *ac)
997 {
998         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
999         int ret;
1000
1001         /* Add information for the different account types */
1002         switch(ac->type) {
1003         case SAMLDB_TYPE_USER: {
1004                 struct ldb_control *rodc_control = ldb_request_get_control(ac->req,
1005                                                                            LDB_CONTROL_RODC_DCPROMO_OID);
1006                 if (rodc_control != NULL) {
1007                         /* see [MS-ADTS] 3.1.1.3.4.1.23 LDAP_SERVER_RODC_DCPROMO_OID */
1008                         rodc_control->critical = false;
1009                         ret = samldb_add_step(ac, samldb_rodc_add);
1010                         if (ret != LDB_SUCCESS) return ret;
1011                 }
1012
1013                 /* check if we have a valid sAMAccountName */
1014                 ret = samldb_add_step(ac, samldb_check_sAMAccountName);
1015                 if (ret != LDB_SUCCESS) return ret;
1016
1017                 ret = samldb_add_step(ac, samldb_add_entry);
1018                 if (ret != LDB_SUCCESS) return ret;
1019                 break;
1020         }
1021
1022         case SAMLDB_TYPE_GROUP: {
1023                 /* check if we have a valid sAMAccountName */
1024                 ret = samldb_add_step(ac, samldb_check_sAMAccountName);
1025                 if (ret != LDB_SUCCESS) return ret;
1026
1027                 ret = samldb_add_step(ac, samldb_add_entry);
1028                 if (ret != LDB_SUCCESS) return ret;
1029                 break;
1030         }
1031
1032         case SAMLDB_TYPE_CLASS: {
1033                 const char *lDAPDisplayName = NULL;
1034                 const struct ldb_val *rdn_value, *def_obj_cat_val;
1035                 unsigned int v = ldb_msg_find_attr_as_uint(ac->msg, "objectClassCategory", -2);
1036
1037                 /* As discussed with Microsoft through dochelp in April 2012 this is the behavior of windows*/
1038                 if (!ldb_msg_find_element(ac->msg, "subClassOf")) {
1039                         ret = ldb_msg_add_string(ac->msg, "subClassOf", "top");
1040                         if (ret != LDB_SUCCESS) return ret;
1041                 }
1042
1043                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
1044                                                   "rdnAttId", "cn");
1045                 if (ret != LDB_SUCCESS) return ret;
1046
1047                 /* do not allow one to mark an attributeSchema as RODC filtered if it
1048                  * is system-critical */
1049                 if (check_rodc_critical_attribute(ac->msg)) {
1050                         ldb_asprintf_errstring(ldb, "Refusing schema add of %s - cannot combine critical class with RODC filtering",
1051                                                ldb_dn_get_linearized(ac->msg->dn));
1052                         return LDB_ERR_UNWILLING_TO_PERFORM;
1053                 }
1054
1055                 rdn_value = ldb_dn_get_rdn_val(ac->msg->dn);
1056                 if (rdn_value == NULL) {
1057                         return ldb_operr(ldb);
1058                 }
1059                 if (!ldb_msg_find_element(ac->msg, "lDAPDisplayName")) {
1060                         /* the RDN has prefix "CN" */
1061                         ret = ldb_msg_add_string(ac->msg, "lDAPDisplayName",
1062                                 samdb_cn_to_lDAPDisplayName(ac->msg,
1063                                                             (const char *) rdn_value->data));
1064                         if (ret != LDB_SUCCESS) {
1065                                 ldb_oom(ldb);
1066                                 return ret;
1067                         }
1068                 }
1069
1070                 lDAPDisplayName = ldb_msg_find_attr_as_string(ac->msg,
1071                                                               "lDAPDisplayName",
1072                                                               NULL);
1073                 ret = ldb_valid_attr_name(lDAPDisplayName);
1074                 if (ret != 1 ||
1075                     lDAPDisplayName[0] == '*' ||
1076                     lDAPDisplayName[0] == '@')
1077                 {
1078                         return dsdb_module_werror(ac->module,
1079                                                   LDB_ERR_UNWILLING_TO_PERFORM,
1080                                                   WERR_DS_INVALID_LDAP_DISPLAY_NAME,
1081                                                   "lDAPDisplayName is invalid");
1082                 }
1083
1084                 if (!ldb_msg_find_element(ac->msg, "schemaIDGUID")) {
1085                         struct GUID guid;
1086                         /* a new GUID */
1087                         guid = GUID_random();
1088                         ret = dsdb_msg_add_guid(ac->msg, &guid, "schemaIDGUID");
1089                         if (ret != LDB_SUCCESS) {
1090                                 ldb_oom(ldb);
1091                                 return ret;
1092                         }
1093                 }
1094
1095                 def_obj_cat_val = ldb_msg_find_ldb_val(ac->msg,
1096                                                        "defaultObjectCategory");
1097                 if (def_obj_cat_val != NULL) {
1098                         /* "defaultObjectCategory" has been set by the caller.
1099                          * Do some checks for consistency.
1100                          * NOTE: The real constraint check (that
1101                          * 'defaultObjectCategory' is the DN of the new
1102                          * objectclass or any parent of it) is still incomplete.
1103                          * For now we say that 'defaultObjectCategory' is valid
1104                          * if it exists and it is of objectclass "classSchema".
1105                          */
1106                         ac->dn = ldb_dn_from_ldb_val(ac, ldb, def_obj_cat_val);
1107                         if (ac->dn == NULL) {
1108                                 ldb_set_errstring(ldb,
1109                                                   "Invalid DN for 'defaultObjectCategory'!");
1110                                 return LDB_ERR_CONSTRAINT_VIOLATION;
1111                         }
1112                 } else {
1113                         /* "defaultObjectCategory" has not been set by the
1114                          * caller. Use the entry DN for it. */
1115                         ac->dn = ac->msg->dn;
1116
1117                         ret = ldb_msg_add_string(ac->msg, "defaultObjectCategory",
1118                                                  ldb_dn_alloc_linearized(ac->msg, ac->dn));
1119                         if (ret != LDB_SUCCESS) {
1120                                 ldb_oom(ldb);
1121                                 return ret;
1122                         }
1123                 }
1124
1125                 ret = samldb_add_step(ac, samldb_add_entry);
1126                 if (ret != LDB_SUCCESS) return ret;
1127
1128                 /* Now perform the checks for the 'defaultObjectCategory'. The
1129                  * lookup DN was already saved in "ac->dn" */
1130                 ret = samldb_add_step(ac, samldb_find_for_defaultObjectCategory);
1131                 if (ret != LDB_SUCCESS) return ret;
1132
1133                 /* -2 is not a valid objectClassCategory so it means the attribute wasn't present */
1134                 if (v == -2) {
1135                         /* Windows 2003 does this*/
1136                         ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "objectClassCategory", 0);
1137                         if (ret != LDB_SUCCESS) {
1138                                 return ret;
1139                         }
1140                 }
1141                 break;
1142         }
1143
1144         case SAMLDB_TYPE_ATTRIBUTE: {
1145                 const char *lDAPDisplayName = NULL;
1146                 const struct ldb_val *rdn_value;
1147                 struct ldb_message_element *el;
1148                 rdn_value = ldb_dn_get_rdn_val(ac->msg->dn);
1149                 if (rdn_value == NULL) {
1150                         return ldb_operr(ldb);
1151                 }
1152                 if (!ldb_msg_find_element(ac->msg, "lDAPDisplayName")) {
1153                         /* the RDN has prefix "CN" */
1154                         ret = ldb_msg_add_string(ac->msg, "lDAPDisplayName",
1155                                 samdb_cn_to_lDAPDisplayName(ac->msg,
1156                                                             (const char *) rdn_value->data));
1157                         if (ret != LDB_SUCCESS) {
1158                                 ldb_oom(ldb);
1159                                 return ret;
1160                         }
1161                 }
1162
1163                 lDAPDisplayName = ldb_msg_find_attr_as_string(ac->msg,
1164                                                               "lDAPDisplayName",
1165                                                               NULL);
1166                 ret = ldb_valid_attr_name(lDAPDisplayName);
1167                 if (ret != 1 ||
1168                     lDAPDisplayName[0] == '*' ||
1169                     lDAPDisplayName[0] == '@')
1170                 {
1171                         return dsdb_module_werror(ac->module,
1172                                                   LDB_ERR_UNWILLING_TO_PERFORM,
1173                                                   WERR_DS_INVALID_LDAP_DISPLAY_NAME,
1174                                                   "lDAPDisplayName is invalid");
1175                 }
1176
1177                 /* do not allow one to mark an attributeSchema as RODC filtered if it
1178                  * is system-critical */
1179                 if (check_rodc_critical_attribute(ac->msg)) {
1180                         ldb_asprintf_errstring(ldb,
1181                                                "samldb: refusing schema add of %s - cannot combine critical attribute with RODC filtering",
1182                                                ldb_dn_get_linearized(ac->msg->dn));
1183                         return LDB_ERR_UNWILLING_TO_PERFORM;
1184                 }
1185
1186                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
1187                                                   "isSingleValued", "FALSE");
1188                 if (ret != LDB_SUCCESS) return ret;
1189
1190                 if (!ldb_msg_find_element(ac->msg, "schemaIDGUID")) {
1191                         struct GUID guid;
1192                         /* a new GUID */
1193                         guid = GUID_random();
1194                         ret = dsdb_msg_add_guid(ac->msg, &guid, "schemaIDGUID");
1195                         if (ret != LDB_SUCCESS) {
1196                                 ldb_oom(ldb);
1197                                 return ret;
1198                         }
1199                 }
1200
1201                 el = ldb_msg_find_element(ac->msg, "attributeSyntax");
1202                 if (el) {
1203                         /*
1204                          * No need to scream if there isn't as we have code later on
1205                          * that will take care of it.
1206                          */
1207                         const struct dsdb_syntax *syntax = find_syntax_map_by_ad_oid((const char *)el->values[0].data);
1208                         if (!syntax) {
1209                                 DEBUG(9, ("Can't find dsdb_syntax object for attributeSyntax %s\n",
1210                                                 (const char *)el->values[0].data));
1211                         } else {
1212                                 unsigned int v = ldb_msg_find_attr_as_uint(ac->msg, "oMSyntax", 0);
1213                                 const struct ldb_val *val = ldb_msg_find_ldb_val(ac->msg, "oMObjectClass");
1214
1215                                 if (v == 0) {
1216                                         ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "oMSyntax", syntax->oMSyntax);
1217                                         if (ret != LDB_SUCCESS) {
1218                                                 return ret;
1219                                         }
1220                                 }
1221                                 if (!val) {
1222                                         struct ldb_val val2 = ldb_val_dup(ldb, &syntax->oMObjectClass);
1223                                         if (val2.length > 0) {
1224                                                 ret = ldb_msg_add_value(ac->msg, "oMObjectClass", &val2, NULL);
1225                                                 if (ret != LDB_SUCCESS) {
1226                                                         return ret;
1227                                                 }
1228                                         }
1229                                 }
1230                         }
1231                 }
1232
1233                 /* handle msDS-IntID attribute */
1234                 ret = samldb_add_handle_msDS_IntId(ac);
1235                 if (ret != LDB_SUCCESS) return ret;
1236
1237                 ret = samldb_add_step(ac, samldb_add_entry);
1238                 if (ret != LDB_SUCCESS) return ret;
1239                 break;
1240         }
1241
1242         default:
1243                 ldb_asprintf_errstring(ldb, "Invalid entry type!");
1244                 return LDB_ERR_OPERATIONS_ERROR;
1245                 break;
1246         }
1247
1248         return samldb_first_step(ac);
1249 }
1250
1251 static int samldb_fill_foreignSecurityPrincipal_object(struct samldb_ctx *ac)
1252 {
1253         struct ldb_context *ldb = NULL;
1254         const struct ldb_val *rdn_value = NULL;
1255         struct ldb_message_element *sid_el = NULL;
1256         struct dom_sid *sid = NULL;
1257         struct ldb_control *as_system = NULL;
1258         struct ldb_control *provision = NULL;
1259         bool allowed = false;
1260         int ret;
1261
1262         ldb = ldb_module_get_ctx(ac->module);
1263
1264         as_system = ldb_request_get_control(ac->req, LDB_CONTROL_AS_SYSTEM_OID);
1265         if (as_system != NULL) {
1266                 allowed = true;
1267         }
1268
1269         provision = ldb_request_get_control(ac->req, LDB_CONTROL_PROVISION_OID);
1270         if (provision != NULL) {
1271                 allowed = true;
1272         }
1273
1274         sid_el = ldb_msg_find_element(ac->msg, "objectSid");
1275
1276         if (!allowed && sid_el == NULL) {
1277                 return dsdb_module_werror(ac->module,
1278                                 LDB_ERR_OBJECT_CLASS_VIOLATION,
1279                                 WERR_DS_MISSING_REQUIRED_ATT,
1280                                 "objectSid missing on foreignSecurityPrincipal");
1281         }
1282
1283         if (!allowed) {
1284                 return dsdb_module_werror(ac->module,
1285                                 LDB_ERR_UNWILLING_TO_PERFORM,
1286                                 WERR_DS_ILLEGAL_MOD_OPERATION,
1287                                 "foreignSecurityPrincipal object not allowed");
1288         }
1289
1290         if (sid_el != NULL) {
1291                 sid = samdb_result_dom_sid(ac->msg, ac->msg, "objectSid");
1292                 if (sid == NULL) {
1293                         ldb_set_errstring(ldb,
1294                                           "samldb: invalid objectSid!");
1295                         return LDB_ERR_CONSTRAINT_VIOLATION;
1296                 }
1297         }
1298
1299         if (sid == NULL) {
1300                 rdn_value = ldb_dn_get_rdn_val(ac->msg->dn);
1301                 if (rdn_value == NULL) {
1302                         return ldb_operr(ldb);
1303                 }
1304                 sid = dom_sid_parse_talloc(ac->msg,
1305                                            (const char *)rdn_value->data);
1306                 if (sid == NULL) {
1307                         ldb_set_errstring(ldb,
1308                                           "samldb: No valid SID found in ForeignSecurityPrincipal CN!");
1309                         return LDB_ERR_CONSTRAINT_VIOLATION;
1310                 }
1311                 if (! samldb_msg_add_sid(ac->msg, "objectSid", sid)) {
1312                         return ldb_operr(ldb);
1313                 }
1314         }
1315
1316         /* finally proceed with adding the entry */
1317         ret = samldb_add_step(ac, samldb_add_entry);
1318         if (ret != LDB_SUCCESS) return ret;
1319
1320         return samldb_first_step(ac);
1321 }
1322
1323 static int samldb_schema_info_update(struct samldb_ctx *ac)
1324 {
1325         int ret;
1326         struct ldb_context *ldb;
1327         struct dsdb_schema *schema;
1328
1329         /* replicated update should always go through */
1330         if (ldb_request_get_control(ac->req,
1331                                     DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
1332                 return LDB_SUCCESS;
1333         }
1334
1335         /* do not update schemaInfo during provisioning */
1336         if (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
1337                 return LDB_SUCCESS;
1338         }
1339
1340         ldb = ldb_module_get_ctx(ac->module);
1341         schema = dsdb_get_schema(ldb, NULL);
1342         if (!schema) {
1343                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
1344                               "samldb_schema_info_update: no dsdb_schema loaded");
1345                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
1346                 return ldb_operr(ldb);
1347         }
1348
1349         ret = dsdb_module_schema_info_update(ac->module, schema,
1350                                              DSDB_FLAG_NEXT_MODULE|
1351                                              DSDB_FLAG_AS_SYSTEM,
1352                                              ac->req);
1353         if (ret != LDB_SUCCESS) {
1354                 ldb_asprintf_errstring(ldb,
1355                                        "samldb_schema_info_update: dsdb_module_schema_info_update failed with %s",
1356                                        ldb_errstring(ldb));
1357                 return ret;
1358         }
1359
1360         return LDB_SUCCESS;
1361 }
1362
1363 static int samldb_prim_group_tester(struct samldb_ctx *ac, uint32_t rid);
1364 static int samldb_check_user_account_control_rules(struct samldb_ctx *ac,
1365                                                    struct dom_sid *sid,
1366                                                    uint32_t req_uac,
1367                                                    uint32_t user_account_control,
1368                                                    uint32_t user_account_control_old);
1369
1370 /*
1371  * "Objectclass" trigger (MS-SAMR 3.1.1.8.1)
1372  *
1373  * Has to be invoked on "add" and "modify" operations on "user", "computer" and
1374  * "group" objects.
1375  * ac->msg contains the "add"/"modify" message
1376  * ac->type contains the object type (main objectclass)
1377  */
1378 static int samldb_objectclass_trigger(struct samldb_ctx *ac)
1379 {
1380         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1381         void *skip_allocate_sids = ldb_get_opaque(ldb,
1382                                                   "skip_allocate_sids");
1383         struct ldb_message_element *el, *el2;
1384         struct dom_sid *sid;
1385         int ret;
1386
1387         /* make sure that "sAMAccountType" is not specified */
1388         el = ldb_msg_find_element(ac->msg, "sAMAccountType");
1389         if (el != NULL) {
1390                 ldb_set_errstring(ldb,
1391                                   "samldb: sAMAccountType must not be specified!");
1392                 return LDB_ERR_UNWILLING_TO_PERFORM;
1393         }
1394
1395         /* Step 1: objectSid assignment */
1396
1397         /* Don't allow the objectSid to be changed. But beside the RELAX
1398          * control we have also to guarantee that it can always be set with
1399          * SYSTEM permissions. This is needed for the "samba3sam" backend. */
1400         sid = samdb_result_dom_sid(ac, ac->msg, "objectSid");
1401         if ((sid != NULL) && (!dsdb_module_am_system(ac->module)) &&
1402             (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) == NULL)) {
1403                 ldb_set_errstring(ldb,
1404                                   "samldb: objectSid must not be specified!");
1405                 return LDB_ERR_UNWILLING_TO_PERFORM;
1406         }
1407
1408         /* but generate a new SID when we do have an add operations */
1409         if ((sid == NULL) && (ac->req->operation == LDB_ADD) && !skip_allocate_sids) {
1410                 ret = samldb_add_step(ac, samldb_allocate_sid);
1411                 if (ret != LDB_SUCCESS) return ret;
1412         }
1413
1414         switch(ac->type) {
1415         case SAMLDB_TYPE_USER: {
1416                 bool uac_generated = false, uac_add_flags = false;
1417
1418                 /* Step 1.2: Default values */
1419                 ret = dsdb_user_obj_set_defaults(ldb, ac->msg, ac->req);
1420                 if (ret != LDB_SUCCESS) return ret;
1421
1422                 /* On add operations we might need to generate a
1423                  * "userAccountControl" (if it isn't specified). */
1424                 el = ldb_msg_find_element(ac->msg, "userAccountControl");
1425                 if ((el == NULL) && (ac->req->operation == LDB_ADD)) {
1426                         ret = samdb_msg_set_uint(ldb, ac->msg, ac->msg,
1427                                                  "userAccountControl",
1428                                                  UF_NORMAL_ACCOUNT);
1429                         if (ret != LDB_SUCCESS) {
1430                                 return ret;
1431                         }
1432                         uac_generated = true;
1433                         uac_add_flags = true;
1434                 }
1435
1436                 el = ldb_msg_find_element(ac->msg, "userAccountControl");
1437                 if (el != NULL) {
1438                         uint32_t raw_uac;
1439                         uint32_t user_account_control;
1440                         /* Step 1.3: "userAccountControl" -> "sAMAccountType" mapping */
1441                         user_account_control = ldb_msg_find_attr_as_uint(ac->msg,
1442                                                                          "userAccountControl",
1443                                                                          0);
1444                         raw_uac = user_account_control;
1445                         /*
1446                          * "userAccountControl" = 0 or missing one of
1447                          * the types means "UF_NORMAL_ACCOUNT".  See
1448                          * MS-SAMR 3.1.1.8.10 point 8
1449                          */
1450                         if ((user_account_control & UF_ACCOUNT_TYPE_MASK) == 0) {
1451                                 user_account_control = UF_NORMAL_ACCOUNT | user_account_control;
1452                                 uac_generated = true;
1453                         }
1454
1455                         /*
1456                          * As per MS-SAMR 3.1.1.8.10 these flags have not to be set
1457                          */
1458                         if ((user_account_control & UF_LOCKOUT) != 0) {
1459                                 user_account_control &= ~UF_LOCKOUT;
1460                                 uac_generated = true;
1461                         }
1462                         if ((user_account_control & UF_PASSWORD_EXPIRED) != 0) {
1463                                 user_account_control &= ~UF_PASSWORD_EXPIRED;
1464                                 uac_generated = true;
1465                         }
1466
1467                         ret = samldb_check_user_account_control_rules(ac, NULL,
1468                                                                       raw_uac,
1469                                                                       user_account_control,
1470                                                                       0);
1471                         if (ret != LDB_SUCCESS) {
1472                                 return ret;
1473                         }
1474
1475                         /* Workstation and (read-only) DC objects do need objectclass "computer" */
1476                         if ((samdb_find_attribute(ldb, ac->msg,
1477                                                   "objectclass", "computer") == NULL) &&
1478                             (user_account_control &
1479                              (UF_SERVER_TRUST_ACCOUNT | UF_WORKSTATION_TRUST_ACCOUNT))) {
1480                                 ldb_set_errstring(ldb,
1481                                                   "samldb: Requested account type does need objectclass 'computer'!");
1482                                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1483                         }
1484
1485                         /* add "sAMAccountType" attribute */
1486                         ret = dsdb_user_obj_set_account_type(ldb, ac->msg, user_account_control, NULL);
1487                         if (ret != LDB_SUCCESS) {
1488                                 return ret;
1489                         }
1490
1491                         /* "isCriticalSystemObject" might be set */
1492                         if (user_account_control &
1493                             (UF_SERVER_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)) {
1494                                 ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject",
1495                                                          "TRUE");
1496                                 if (ret != LDB_SUCCESS) {
1497                                         return ret;
1498                                 }
1499                                 el2 = ldb_msg_find_element(ac->msg,
1500                                                            "isCriticalSystemObject");
1501                                 el2->flags = LDB_FLAG_MOD_REPLACE;
1502                         } else if (user_account_control & UF_WORKSTATION_TRUST_ACCOUNT) {
1503                                 ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject",
1504                                                          "FALSE");
1505                                 if (ret != LDB_SUCCESS) {
1506                                         return ret;
1507                                 }
1508                                 el2 = ldb_msg_find_element(ac->msg,
1509                                                            "isCriticalSystemObject");
1510                                 el2->flags = LDB_FLAG_MOD_REPLACE;
1511                         }
1512
1513                         /* Step 1.4: "userAccountControl" -> "primaryGroupID" mapping */
1514                         if (!ldb_msg_find_element(ac->msg, "primaryGroupID")) {
1515                                 uint32_t rid;
1516
1517                                 ret = dsdb_user_obj_set_primary_group_id(ldb, ac->msg, user_account_control, &rid);
1518                                 if (ret != LDB_SUCCESS) {
1519                                         return ret;
1520                                 }
1521                                 /*
1522                                  * Older AD deployments don't know about the
1523                                  * RODC group
1524                                  */
1525                                 if (rid == DOMAIN_RID_READONLY_DCS) {
1526                                         ret = samldb_prim_group_tester(ac, rid);
1527                                         if (ret != LDB_SUCCESS) {
1528                                                 return ret;
1529                                         }
1530                                 }
1531                         }
1532
1533                         /* Step 1.5: Add additional flags when needed */
1534                         /* Obviously this is done when the "userAccountControl"
1535                          * has been generated here (tested against Windows
1536                          * Server) */
1537                         if (uac_generated) {
1538                                 if (uac_add_flags) {
1539                                         user_account_control |= UF_ACCOUNTDISABLE;
1540                                         user_account_control |= UF_PASSWD_NOTREQD;
1541                                 }
1542
1543                                 ret = samdb_msg_set_uint(ldb, ac->msg, ac->msg,
1544                                                          "userAccountControl",
1545                                                          user_account_control);
1546                                 if (ret != LDB_SUCCESS) {
1547                                         return ret;
1548                                 }
1549                         }
1550
1551                 }
1552                 break;
1553         }
1554
1555         case SAMLDB_TYPE_GROUP: {
1556                 const char *tempstr;
1557
1558                 /* Step 2.2: Default values */
1559                 tempstr = talloc_asprintf(ac->msg, "%d",
1560                                           GTYPE_SECURITY_GLOBAL_GROUP);
1561                 if (tempstr == NULL) return ldb_operr(ldb);
1562                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
1563                         "groupType", tempstr);
1564                 if (ret != LDB_SUCCESS) return ret;
1565
1566                 /* Step 2.3: "groupType" -> "sAMAccountType" */
1567                 el = ldb_msg_find_element(ac->msg, "groupType");
1568                 if (el != NULL) {
1569                         uint32_t group_type, account_type;
1570
1571                         group_type = ldb_msg_find_attr_as_uint(ac->msg,
1572                                                                "groupType", 0);
1573
1574                         /* The creation of builtin groups requires the
1575                          * RELAX control */
1576                         if (group_type == GTYPE_SECURITY_BUILTIN_LOCAL_GROUP) {
1577                                 if (ldb_request_get_control(ac->req,
1578                                                             LDB_CONTROL_RELAX_OID) == NULL) {
1579                                         return LDB_ERR_UNWILLING_TO_PERFORM;
1580                                 }
1581                         }
1582
1583                         account_type = ds_gtype2atype(group_type);
1584                         if (account_type == 0) {
1585                                 ldb_set_errstring(ldb, "samldb: Unrecognized account type!");
1586                                 return LDB_ERR_UNWILLING_TO_PERFORM;
1587                         }
1588                         ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
1589                                                  "sAMAccountType",
1590                                                  account_type);
1591                         if (ret != LDB_SUCCESS) {
1592                                 return ret;
1593                         }
1594                         el2 = ldb_msg_find_element(ac->msg, "sAMAccountType");
1595                         el2->flags = LDB_FLAG_MOD_REPLACE;
1596                 }
1597                 break;
1598         }
1599
1600         default:
1601                 ldb_asprintf_errstring(ldb,
1602                                 "Invalid entry type!");
1603                 return LDB_ERR_OPERATIONS_ERROR;
1604                 break;
1605         }
1606
1607         return LDB_SUCCESS;
1608 }
1609
1610 /*
1611  * "Primary group ID" trigger (MS-SAMR 3.1.1.8.2)
1612  *
1613  * Has to be invoked on "add" and "modify" operations on "user" and "computer"
1614  * objects.
1615  * ac->msg contains the "add"/"modify" message
1616  */
1617
1618 static int samldb_prim_group_tester(struct samldb_ctx *ac, uint32_t rid)
1619 {
1620         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1621         struct dom_sid *sid;
1622         struct ldb_result *res;
1623         int ret;
1624         const char * const noattrs[] = { NULL };
1625
1626         sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
1627         if (sid == NULL) {
1628                 return ldb_operr(ldb);
1629         }
1630
1631         ret = dsdb_module_search(ac->module, ac, &res,
1632                                  ldb_get_default_basedn(ldb),
1633                                  LDB_SCOPE_SUBTREE,
1634                                  noattrs, DSDB_FLAG_NEXT_MODULE,
1635                                  ac->req,
1636                                  "(objectSid=%s)",
1637                                  ldap_encode_ndr_dom_sid(ac, sid));
1638         if (ret != LDB_SUCCESS) {
1639                 return ret;
1640         }
1641         if (res->count != 1) {
1642                 talloc_free(res);
1643                 ldb_asprintf_errstring(ldb,
1644                                        "Failed to find primary group with RID %u!",
1645                                        rid);
1646                 return LDB_ERR_UNWILLING_TO_PERFORM;
1647         }
1648         talloc_free(res);
1649
1650         return LDB_SUCCESS;
1651 }
1652
1653 static int samldb_prim_group_set(struct samldb_ctx *ac)
1654 {
1655         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1656         uint32_t rid;
1657
1658         rid = ldb_msg_find_attr_as_uint(ac->msg, "primaryGroupID", (uint32_t) -1);
1659         if (rid == (uint32_t) -1) {
1660                 /* we aren't affected of any primary group set */
1661                 return LDB_SUCCESS;
1662
1663         } else if (!ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
1664                 ldb_set_errstring(ldb,
1665                                   "The primary group isn't settable on add operations!");
1666                 return LDB_ERR_UNWILLING_TO_PERFORM;
1667         }
1668
1669         return samldb_prim_group_tester(ac, rid);
1670 }
1671
1672 static int samldb_prim_group_change(struct samldb_ctx *ac)
1673 {
1674         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1675         const char * const attrs[] = {
1676                 "primaryGroupID",
1677                 "memberOf",
1678                 "userAccountControl",
1679                 NULL };
1680         struct ldb_result *res, *group_res;
1681         struct ldb_message_element *el;
1682         struct ldb_message *msg;
1683         uint32_t search_flags =
1684                 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_EXTENDED_DN;
1685         uint32_t prev_rid, new_rid, uac;
1686         struct dom_sid *prev_sid, *new_sid;
1687         struct ldb_dn *prev_prim_group_dn, *new_prim_group_dn;
1688         const char *new_prim_group_dn_ext_str = NULL;
1689         struct ldb_dn *user_dn = NULL;
1690         const char *user_dn_ext_str = NULL;
1691         int ret;
1692         const char * const noattrs[] = { NULL };
1693
1694         el = dsdb_get_single_valued_attr(ac->msg, "primaryGroupID",
1695                                          ac->req->operation);
1696         if (el == NULL) {
1697                 /* we are not affected */
1698                 return LDB_SUCCESS;
1699         }
1700
1701         /* Fetch information from the existing object */
1702
1703         ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, attrs,
1704                                     search_flags, ac->req);
1705         if (ret != LDB_SUCCESS) {
1706                 return ret;
1707         }
1708         user_dn = res->msgs[0]->dn;
1709         user_dn_ext_str = ldb_dn_get_extended_linearized(ac, user_dn, 1);
1710         if (user_dn_ext_str == NULL) {
1711                 return ldb_operr(ldb);
1712         }
1713
1714         uac = ldb_msg_find_attr_as_uint(res->msgs[0], "userAccountControl", 0);
1715
1716         /* Finds out the DN of the old primary group */
1717
1718         prev_rid = ldb_msg_find_attr_as_uint(res->msgs[0], "primaryGroupID",
1719                                              (uint32_t) -1);
1720         if (prev_rid == (uint32_t) -1) {
1721                 /* User objects do always have a mandatory "primaryGroupID"
1722                  * attribute. If this doesn't exist then the object is of the
1723                  * wrong type. This is the exact Windows error code */
1724                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1725         }
1726
1727         prev_sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), prev_rid);
1728         if (prev_sid == NULL) {
1729                 return ldb_operr(ldb);
1730         }
1731
1732         /* Finds out the DN of the new primary group
1733          * Notice: in order to parse the primary group ID correctly we create
1734          * a temporary message here. */
1735
1736         msg = ldb_msg_new(ac->msg);
1737         if (msg == NULL) {
1738                 return ldb_module_oom(ac->module);
1739         }
1740         ret = ldb_msg_add(msg, el, 0);
1741         if (ret != LDB_SUCCESS) {
1742                 return ret;
1743         }
1744         new_rid = ldb_msg_find_attr_as_uint(msg, "primaryGroupID", (uint32_t) -1);
1745         talloc_free(msg);
1746         if (new_rid == (uint32_t) -1) {
1747                 /* we aren't affected of any primary group change */
1748                 return LDB_SUCCESS;
1749         }
1750
1751         if (prev_rid == new_rid) {
1752                 return LDB_SUCCESS;
1753         }
1754
1755         if ((uac & UF_SERVER_TRUST_ACCOUNT) && new_rid != DOMAIN_RID_DCS) {
1756                 ldb_asprintf_errstring(ldb,
1757                         "%08X: samldb: UF_SERVER_TRUST_ACCOUNT requires "
1758                         "primaryGroupID=%u!",
1759                         W_ERROR_V(WERR_DS_CANT_MOD_PRIMARYGROUPID),
1760                         DOMAIN_RID_DCS);
1761                 return LDB_ERR_UNWILLING_TO_PERFORM;
1762         }
1763
1764         if ((uac & UF_PARTIAL_SECRETS_ACCOUNT) && new_rid != DOMAIN_RID_READONLY_DCS) {
1765                 ldb_asprintf_errstring(ldb,
1766                         "%08X: samldb: UF_PARTIAL_SECRETS_ACCOUNT requires "
1767                         "primaryGroupID=%u!",
1768                         W_ERROR_V(WERR_DS_CANT_MOD_PRIMARYGROUPID),
1769                         DOMAIN_RID_READONLY_DCS);
1770                 return LDB_ERR_UNWILLING_TO_PERFORM;
1771         }
1772
1773         ret = dsdb_module_search(ac->module, ac, &group_res,
1774                                  ldb_get_default_basedn(ldb),
1775                                  LDB_SCOPE_SUBTREE,
1776                                  noattrs, search_flags,
1777                                  ac->req,
1778                                  "(objectSid=%s)",
1779                                  ldap_encode_ndr_dom_sid(ac, prev_sid));
1780         if (ret != LDB_SUCCESS) {
1781                 return ret;
1782         }
1783         if (group_res->count != 1) {
1784                 return ldb_operr(ldb);
1785         }
1786         prev_prim_group_dn = group_res->msgs[0]->dn;
1787
1788         new_sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), new_rid);
1789         if (new_sid == NULL) {
1790                 return ldb_operr(ldb);
1791         }
1792
1793         ret = dsdb_module_search(ac->module, ac, &group_res,
1794                                  ldb_get_default_basedn(ldb),
1795                                  LDB_SCOPE_SUBTREE,
1796                                  noattrs, search_flags,
1797                                  ac->req,
1798                                  "(objectSid=%s)",
1799                                  ldap_encode_ndr_dom_sid(ac, new_sid));
1800         if (ret != LDB_SUCCESS) {
1801                 return ret;
1802         }
1803         if (group_res->count != 1) {
1804                 /* Here we know if the specified new primary group candidate is
1805                  * valid or not. */
1806                 return LDB_ERR_UNWILLING_TO_PERFORM;
1807         }
1808         new_prim_group_dn = group_res->msgs[0]->dn;
1809         new_prim_group_dn_ext_str = ldb_dn_get_extended_linearized(ac,
1810                                                         new_prim_group_dn, 1);
1811         if (new_prim_group_dn_ext_str == NULL) {
1812                 return ldb_operr(ldb);
1813         }
1814
1815         /* We need to be already a normal member of the new primary
1816          * group in order to be successful. */
1817         el = samdb_find_attribute(ldb, res->msgs[0], "memberOf",
1818                                   new_prim_group_dn_ext_str);
1819         if (el == NULL) {
1820                 return LDB_ERR_UNWILLING_TO_PERFORM;
1821         }
1822
1823         /* Remove the "member" attribute on the new primary group */
1824         msg = ldb_msg_new(ac->msg);
1825         if (msg == NULL) {
1826                 return ldb_module_oom(ac->module);
1827         }
1828         msg->dn = new_prim_group_dn;
1829
1830         ret = samdb_msg_add_delval(ldb, msg, msg, "member", user_dn_ext_str);
1831         if (ret != LDB_SUCCESS) {
1832                 return ret;
1833         }
1834
1835         ret = dsdb_module_modify(ac->module, msg, DSDB_FLAG_NEXT_MODULE, ac->req);
1836         if (ret != LDB_SUCCESS) {
1837                 return ret;
1838         }
1839         talloc_free(msg);
1840
1841         /* Add a "member" attribute for the previous primary group */
1842         msg = ldb_msg_new(ac->msg);
1843         if (msg == NULL) {
1844                 return ldb_module_oom(ac->module);
1845         }
1846         msg->dn = prev_prim_group_dn;
1847
1848         ret = samdb_msg_add_addval(ldb, msg, msg, "member", user_dn_ext_str);
1849         if (ret != LDB_SUCCESS) {
1850                 return ret;
1851         }
1852
1853         ret = dsdb_module_modify(ac->module, msg, DSDB_FLAG_NEXT_MODULE, ac->req);
1854         if (ret != LDB_SUCCESS) {
1855                 return ret;
1856         }
1857         talloc_free(msg);
1858
1859         return LDB_SUCCESS;
1860 }
1861
1862 static int samldb_prim_group_trigger(struct samldb_ctx *ac)
1863 {
1864         int ret;
1865
1866         if (ac->req->operation == LDB_ADD) {
1867                 ret = samldb_prim_group_set(ac);
1868         } else {
1869                 ret = samldb_prim_group_change(ac);
1870         }
1871
1872         return ret;
1873 }
1874
1875 static int samldb_check_user_account_control_invariants(struct samldb_ctx *ac,
1876                                                     uint32_t user_account_control)
1877 {
1878         int i, ret = 0;
1879         bool need_check = false;
1880         const struct uac_to_guid {
1881                 uint32_t uac;
1882                 bool never;
1883                 uint32_t needs;
1884                 uint32_t not_with;
1885                 const char *error_string;
1886         } map[] = {
1887                 {
1888                         .uac = UF_TEMP_DUPLICATE_ACCOUNT,
1889                         .never = true,
1890                         .error_string = "Updating the UF_TEMP_DUPLICATE_ACCOUNT flag is never allowed"
1891                 },
1892                 {
1893                         .uac = UF_PARTIAL_SECRETS_ACCOUNT,
1894                         .needs = UF_WORKSTATION_TRUST_ACCOUNT,
1895                         .error_string = "Setting UF_PARTIAL_SECRETS_ACCOUNT only permitted with UF_WORKSTATION_TRUST_ACCOUNT"
1896                 },
1897                 {
1898                         .uac = UF_TRUSTED_FOR_DELEGATION,
1899                         .not_with = UF_PARTIAL_SECRETS_ACCOUNT,
1900                         .error_string = "Setting UF_TRUSTED_FOR_DELEGATION not allowed with UF_PARTIAL_SECRETS_ACCOUNT"
1901                 },
1902                 {
1903                         .uac = UF_NORMAL_ACCOUNT,
1904                         .not_with = UF_ACCOUNT_TYPE_MASK & ~UF_NORMAL_ACCOUNT,
1905                         .error_string = "Setting more than one account type not permitted"
1906                 },
1907                 {
1908                         .uac = UF_WORKSTATION_TRUST_ACCOUNT,
1909                         .not_with = UF_ACCOUNT_TYPE_MASK & ~UF_WORKSTATION_TRUST_ACCOUNT,
1910                         .error_string = "Setting more than one account type not permitted"
1911                 },
1912                 {
1913                         .uac = UF_INTERDOMAIN_TRUST_ACCOUNT,
1914                         .not_with = UF_ACCOUNT_TYPE_MASK & ~UF_INTERDOMAIN_TRUST_ACCOUNT,
1915                         .error_string = "Setting more than one account type not permitted"
1916                 },
1917                 {
1918                         .uac = UF_SERVER_TRUST_ACCOUNT,
1919                         .not_with = UF_ACCOUNT_TYPE_MASK & ~UF_SERVER_TRUST_ACCOUNT,
1920                         .error_string = "Setting more than one account type not permitted"
1921                 },
1922                 {
1923                         .uac = UF_TRUSTED_FOR_DELEGATION,
1924                         .not_with = UF_PARTIAL_SECRETS_ACCOUNT,
1925                         .error_string = "Setting UF_TRUSTED_FOR_DELEGATION not allowed with UF_PARTIAL_SECRETS_ACCOUNT"
1926                 }
1927         };
1928
1929         for (i = 0; i < ARRAY_SIZE(map); i++) {
1930                 if (user_account_control & map[i].uac) {
1931                         need_check = true;
1932                         break;
1933                 }
1934         }
1935         if (need_check == false) {
1936                 return LDB_SUCCESS;
1937         }
1938
1939         for (i = 0; i < ARRAY_SIZE(map); i++) {
1940                 uint32_t this_uac = user_account_control & map[i].uac;
1941                 if (this_uac != 0) {
1942                         if (map[i].never) {
1943                                 ret = LDB_ERR_OTHER;
1944                                 break;
1945                         } else if (map[i].needs != 0) {
1946                                 if ((map[i].needs & user_account_control) == 0) {
1947                                         ret = LDB_ERR_OTHER;
1948                                         break;
1949                                 }
1950                         } else if (map[i].not_with != 0) {
1951                                 if ((map[i].not_with & user_account_control) != 0) {
1952                                         ret = LDB_ERR_OTHER;
1953                                         break;
1954                                 }
1955                         }
1956                 }
1957         }
1958         if (ret != LDB_SUCCESS) {
1959                 switch (ac->req->operation) {
1960                 case LDB_ADD:
1961                         ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
1962                                                "Failed to add %s: %s",
1963                                                ldb_dn_get_linearized(ac->msg->dn),
1964                                                map[i].error_string);
1965                         break;
1966                 case LDB_MODIFY:
1967                         ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
1968                                                "Failed to modify %s: %s",
1969                                                ldb_dn_get_linearized(ac->msg->dn),
1970                                                map[i].error_string);
1971                         break;
1972                 default:
1973                         return ldb_module_operr(ac->module);
1974                 }
1975         }
1976         return ret;
1977 }
1978
1979 /**
1980  * Validate that the restriction in point 5 of MS-SAMR 3.1.1.8.10 userAccountControl is honoured
1981  *
1982  */
1983 static int samldb_check_user_account_control_acl(struct samldb_ctx *ac,
1984                                                  struct dom_sid *sid,
1985                                                  uint32_t user_account_control,
1986                                                  uint32_t user_account_control_old)
1987 {
1988         int i, ret = 0;
1989         bool need_acl_check = false;
1990         struct ldb_result *res;
1991         const char * const sd_attrs[] = {"ntSecurityDescriptor", NULL};
1992         struct security_token *user_token;
1993         struct security_descriptor *domain_sd;
1994         struct ldb_dn *domain_dn = ldb_get_default_basedn(ldb_module_get_ctx(ac->module));
1995         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1996         const struct uac_to_guid {
1997                 uint32_t uac;
1998                 uint32_t priv_to_change_from;
1999                 const char *oid;
2000                 const char *guid;
2001                 enum sec_privilege privilege;
2002                 bool delete_is_privileged;
2003                 bool admin_required;
2004                 const char *error_string;
2005         } map[] = {
2006                 {
2007                         .uac = UF_PASSWD_NOTREQD,
2008                         .guid = GUID_DRS_UPDATE_PASSWORD_NOT_REQUIRED_BIT,
2009                         .error_string = "Adding the UF_PASSWD_NOTREQD bit in userAccountControl requires the Update-Password-Not-Required-Bit right that was not given on the Domain object"
2010                 },
2011                 {
2012                         .uac = UF_DONT_EXPIRE_PASSWD,
2013                         .guid = GUID_DRS_UNEXPIRE_PASSWORD,
2014                         .error_string = "Adding the UF_DONT_EXPIRE_PASSWD bit in userAccountControl requires the Unexpire-Password right that was not given on the Domain object"
2015                 },
2016                 {
2017                         .uac = UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED,
2018                         .guid = GUID_DRS_ENABLE_PER_USER_REVERSIBLY_ENCRYPTED_PASSWORD,
2019                         .error_string = "Adding the UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED bit in userAccountControl requires the Enable-Per-User-Reversibly-Encrypted-Password right that was not given on the Domain object"
2020                 },
2021                 {
2022                         .uac = UF_SERVER_TRUST_ACCOUNT,
2023                         .guid = GUID_DRS_DS_INSTALL_REPLICA,
2024                         .error_string = "Adding the UF_SERVER_TRUST_ACCOUNT bit in userAccountControl requires the DS-Install-Replica right that was not given on the Domain object"
2025                 },
2026                 {
2027                         .uac = UF_PARTIAL_SECRETS_ACCOUNT,
2028                         .guid = GUID_DRS_DS_INSTALL_REPLICA,
2029                         .error_string = "Adding the UF_PARTIAL_SECRETS_ACCOUNT bit in userAccountControl requires the DS-Install-Replica right that was not given on the Domain object"
2030                 },
2031                 {
2032                         .uac = UF_WORKSTATION_TRUST_ACCOUNT,
2033                         .priv_to_change_from = UF_NORMAL_ACCOUNT,
2034                         .error_string = "Swapping UF_NORMAL_ACCOUNT to UF_WORKSTATION_TRUST_ACCOUNT requires the user to be a member of the domain admins group"
2035                 },
2036                 {
2037                         .uac = UF_NORMAL_ACCOUNT,
2038                         .priv_to_change_from = UF_WORKSTATION_TRUST_ACCOUNT,
2039                         .error_string = "Swapping UF_WORKSTATION_TRUST_ACCOUNT to UF_NORMAL_ACCOUNT requires the user to be a member of the domain admins group"
2040                 },
2041                 {
2042                         .uac = UF_INTERDOMAIN_TRUST_ACCOUNT,
2043                         .oid = DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
2044                         .error_string = "Updating the UF_INTERDOMAIN_TRUST_ACCOUNT bit in userAccountControl is not permitted over LDAP.  This bit is restricted to the LSA CreateTrustedDomain interface",
2045                         .delete_is_privileged = true
2046                 },
2047                 {
2048                         .uac = UF_TRUSTED_FOR_DELEGATION,
2049                         .privilege = SEC_PRIV_ENABLE_DELEGATION,
2050                         .delete_is_privileged = true,
2051                         .error_string = "Updating the UF_TRUSTED_FOR_DELEGATION bit in userAccountControl is not permitted without the SeEnableDelegationPrivilege"
2052                 },
2053                 {
2054                         .uac = UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION,
2055                         .privilege = SEC_PRIV_ENABLE_DELEGATION,
2056                         .delete_is_privileged = true,
2057                         .error_string = "Updating the UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION bit in userAccountControl is not permitted without the SeEnableDelegationPrivilege"
2058                 }
2059
2060         };
2061
2062         if (dsdb_module_am_system(ac->module)) {
2063                 return LDB_SUCCESS;
2064         }
2065
2066         for (i = 0; i < ARRAY_SIZE(map); i++) {
2067                 if (user_account_control & map[i].uac) {
2068                         need_acl_check = true;
2069                         break;
2070                 }
2071         }
2072         if (need_acl_check == false) {
2073                 return LDB_SUCCESS;
2074         }
2075
2076         user_token = acl_user_token(ac->module);
2077         if (user_token == NULL) {
2078                 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
2079         }
2080
2081         ret = dsdb_module_search_dn(ac->module, ac, &res,
2082                                     domain_dn,
2083                                     sd_attrs,
2084                                     DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED,
2085                                     ac->req);
2086         if (ret != LDB_SUCCESS) {
2087                 return ret;
2088         }
2089         if (res->count != 1) {
2090                 return ldb_module_operr(ac->module);
2091         }
2092
2093         ret = dsdb_get_sd_from_ldb_message(ldb,
2094                                            ac, res->msgs[0], &domain_sd);
2095
2096         if (ret != LDB_SUCCESS) {
2097                 return ret;
2098         }
2099
2100         for (i = 0; i < ARRAY_SIZE(map); i++) {
2101                 uint32_t this_uac_new = user_account_control & map[i].uac;
2102                 uint32_t this_uac_old = user_account_control_old & map[i].uac;
2103                 if (this_uac_new != this_uac_old) {
2104                         if (this_uac_old != 0) {
2105                                 if (map[i].delete_is_privileged == false) {
2106                                         continue;
2107                                 }
2108                         }
2109                         if (map[i].oid) {
2110                                 struct ldb_control *control = ldb_request_get_control(ac->req, map[i].oid);
2111                                 if (control == NULL) {
2112                                         ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
2113                                 }
2114                         } else if (map[i].privilege != SEC_PRIV_INVALID) {
2115                                 bool have_priv = security_token_has_privilege(user_token,
2116                                                                               map[i].privilege);
2117                                 if (have_priv == false) {
2118                                         ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
2119                                 }
2120                         } else if (map[i].priv_to_change_from & user_account_control_old) {
2121                                 bool is_admin = security_token_has_builtin_administrators(user_token);
2122                                 if (is_admin == false) {
2123                                         ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
2124                                 }
2125                         } else if (map[i].guid) {
2126                                 ret = acl_check_extended_right(ac, domain_sd,
2127                                                                user_token,
2128                                                                map[i].guid,
2129                                                                SEC_ADS_CONTROL_ACCESS,
2130                                                                sid);
2131                         } else {
2132                                 ret = LDB_SUCCESS;
2133                         }
2134                         if (ret != LDB_SUCCESS) {
2135                                 break;
2136                         }
2137                 }
2138         }
2139         if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
2140                 switch (ac->req->operation) {
2141                 case LDB_ADD:
2142                         ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
2143                                                "Failed to add %s: %s",
2144                                                ldb_dn_get_linearized(ac->msg->dn),
2145                                                map[i].error_string);
2146                         break;
2147                 case LDB_MODIFY:
2148                         ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
2149                                                "Failed to modify %s: %s",
2150                                                ldb_dn_get_linearized(ac->msg->dn),
2151                                                map[i].error_string);
2152                         break;
2153                 default:
2154                         return ldb_module_operr(ac->module);
2155                 }
2156                 if (map[i].guid) {
2157                         dsdb_acl_debug(domain_sd, acl_user_token(ac->module),
2158                                        domain_dn,
2159                                        true,
2160                                        10);
2161                 }
2162         }
2163         return ret;
2164 }
2165
2166 static int samldb_check_user_account_control_rules(struct samldb_ctx *ac,
2167                                                    struct dom_sid *sid,
2168                                                    uint32_t req_uac,
2169                                                    uint32_t user_account_control,
2170                                                    uint32_t user_account_control_old)
2171 {
2172         int ret;
2173         struct dsdb_control_password_user_account_control *uac = NULL;
2174
2175         ret = samldb_check_user_account_control_invariants(ac, user_account_control);
2176         if (ret != LDB_SUCCESS) {
2177                 return ret;
2178         }
2179         ret = samldb_check_user_account_control_acl(ac, sid, user_account_control, user_account_control_old);
2180         if (ret != LDB_SUCCESS) {
2181                 return ret;
2182         }
2183
2184         uac = talloc_zero(ac->req,
2185                           struct dsdb_control_password_user_account_control);
2186         if (uac == NULL) {
2187                 return ldb_module_oom(ac->module);
2188         }
2189
2190         uac->req_flags = req_uac;
2191         uac->old_flags = user_account_control_old;
2192         uac->new_flags = user_account_control;
2193
2194         ret = ldb_request_add_control(ac->req,
2195                                 DSDB_CONTROL_PASSWORD_USER_ACCOUNT_CONTROL_OID,
2196                                 false, uac);
2197         if (ret != LDB_SUCCESS) {
2198                 return ret;
2199         }
2200
2201         return ret;
2202 }
2203
2204
2205 /**
2206  * This function is called on LDB modify operations. It performs some additions/
2207  * replaces on the current LDB message when "userAccountControl" changes.
2208  */
2209 static int samldb_user_account_control_change(struct samldb_ctx *ac)
2210 {
2211         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
2212         uint32_t old_uac;
2213         uint32_t new_uac;
2214         uint32_t raw_uac;
2215         uint32_t old_ufa;
2216         uint32_t new_ufa;
2217         uint32_t old_uac_computed;
2218         uint32_t clear_uac;
2219         uint32_t old_atype;
2220         uint32_t new_atype;
2221         uint32_t old_pgrid;
2222         uint32_t new_pgrid;
2223         NTTIME old_lockoutTime;
2224         struct ldb_message_element *el;
2225         struct ldb_val *val;
2226         struct ldb_val computer_val;
2227         struct ldb_message *tmp_msg;
2228         struct dom_sid *sid;
2229         int ret;
2230         struct ldb_result *res;
2231         const char * const attrs[] = {
2232                 "objectClass",
2233                 "isCriticalSystemObject",
2234                 "userAccountControl",
2235                 "msDS-User-Account-Control-Computed",
2236                 "lockoutTime",
2237                 "objectSid",
2238                 NULL
2239         };
2240         bool is_computer = false;
2241         bool old_is_critical = false;
2242         bool new_is_critical = false;
2243
2244         el = dsdb_get_single_valued_attr(ac->msg, "userAccountControl",
2245                                          ac->req->operation);
2246         if (el == NULL || el->num_values == 0) {
2247                 ldb_asprintf_errstring(ldb,
2248                         "%08X: samldb: 'userAccountControl' can't be deleted!",
2249                         W_ERROR_V(WERR_DS_ILLEGAL_MOD_OPERATION));
2250                 return LDB_ERR_UNWILLING_TO_PERFORM;
2251         }
2252
2253         /* Create a temporary message for fetching the "userAccountControl" */
2254         tmp_msg = ldb_msg_new(ac->msg);
2255         if (tmp_msg == NULL) {
2256                 return ldb_module_oom(ac->module);
2257         }
2258         ret = ldb_msg_add(tmp_msg, el, 0);
2259         if (ret != LDB_SUCCESS) {
2260                 return ret;
2261         }
2262         raw_uac = ldb_msg_find_attr_as_uint(tmp_msg,
2263                                             "userAccountControl",
2264                                             0);
2265         talloc_free(tmp_msg);
2266         /*
2267          * UF_LOCKOUT, UF_PASSWD_CANT_CHANGE and UF_PASSWORD_EXPIRED
2268          * are only generated and not stored. We ignore them almost
2269          * completely, along with unknown bits and UF_SCRIPT.
2270          *
2271          * The only exception is ACB_AUTOLOCK, which features in
2272          * clear_acb when the bit is cleared in this modify operation.
2273          *
2274          * MS-SAMR 2.2.1.13 UF_FLAG Codes states that some bits are
2275          * ignored by clients and servers
2276          */
2277         new_uac = raw_uac & UF_SETTABLE_BITS;
2278
2279         /* Fetch the old "userAccountControl" and "objectClass" */
2280         ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, attrs,
2281                                     DSDB_FLAG_NEXT_MODULE, ac->req);
2282         if (ret != LDB_SUCCESS) {
2283                 return ret;
2284         }
2285         old_uac = ldb_msg_find_attr_as_uint(res->msgs[0], "userAccountControl", 0);
2286         if (old_uac == 0) {
2287                 return ldb_operr(ldb);
2288         }
2289         old_uac_computed = ldb_msg_find_attr_as_uint(res->msgs[0],
2290                                                      "msDS-User-Account-Control-Computed", 0);
2291         old_lockoutTime = ldb_msg_find_attr_as_int64(res->msgs[0],
2292                                                      "lockoutTime", 0);
2293         old_is_critical = ldb_msg_find_attr_as_bool(res->msgs[0],
2294                                                     "isCriticalSystemObject", 0);
2295         /* When we do not have objectclass "computer" we cannot switch to a (read-only) DC */
2296         el = ldb_msg_find_element(res->msgs[0], "objectClass");
2297         if (el == NULL) {
2298                 return ldb_operr(ldb);
2299         }
2300         computer_val = data_blob_string_const("computer");
2301         val = ldb_msg_find_val(el, &computer_val);
2302         if (val != NULL) {
2303                 is_computer = true;
2304         }
2305
2306         old_ufa = old_uac & UF_ACCOUNT_TYPE_MASK;
2307         old_atype = ds_uf2atype(old_ufa);
2308         old_pgrid = ds_uf2prim_group_rid(old_uac);
2309
2310         new_ufa = new_uac & UF_ACCOUNT_TYPE_MASK;
2311         if (new_ufa == 0) {
2312                 /*
2313                  * "userAccountControl" = 0 or missing one of the
2314                  * types means "UF_NORMAL_ACCOUNT".  See MS-SAMR
2315                  * 3.1.1.8.10 point 8
2316                  */
2317                 new_ufa = UF_NORMAL_ACCOUNT;
2318                 new_uac |= new_ufa;
2319         }
2320         sid = samdb_result_dom_sid(res, res->msgs[0], "objectSid");
2321         if (sid == NULL) {
2322                 return ldb_module_operr(ac->module);
2323         }
2324
2325         ret = samldb_check_user_account_control_rules(ac, sid,
2326                                                       raw_uac,
2327                                                       new_uac,
2328                                                       old_uac);
2329         if (ret != LDB_SUCCESS) {
2330                 return ret;
2331         }
2332
2333         new_atype = ds_uf2atype(new_ufa);
2334         new_pgrid = ds_uf2prim_group_rid(new_uac);
2335
2336         clear_uac = (old_uac | old_uac_computed) & ~raw_uac;
2337
2338         switch (new_ufa) {
2339         case UF_NORMAL_ACCOUNT:
2340                 new_is_critical = old_is_critical;
2341                 break;
2342
2343         case UF_INTERDOMAIN_TRUST_ACCOUNT:
2344                 new_is_critical = true;
2345                 break;
2346
2347         case UF_WORKSTATION_TRUST_ACCOUNT:
2348                 new_is_critical = false;
2349                 if (new_uac & UF_PARTIAL_SECRETS_ACCOUNT) {
2350                         if (!is_computer) {
2351                                 ldb_asprintf_errstring(ldb,
2352                                                        "%08X: samldb: UF_PARTIAL_SECRETS_ACCOUNT "
2353                                                        "requires objectclass 'computer'!",
2354                                                        W_ERROR_V(WERR_DS_MACHINE_ACCOUNT_CREATED_PRENT4));
2355                                 return LDB_ERR_UNWILLING_TO_PERFORM;
2356                         }
2357                         new_is_critical = true;
2358                 }
2359                 break;
2360
2361         case UF_SERVER_TRUST_ACCOUNT:
2362                 if (!is_computer) {
2363                         ldb_asprintf_errstring(ldb,
2364                                 "%08X: samldb: UF_SERVER_TRUST_ACCOUNT "
2365                                 "requires objectclass 'computer'!",
2366                                 W_ERROR_V(WERR_DS_MACHINE_ACCOUNT_CREATED_PRENT4));
2367                         return LDB_ERR_UNWILLING_TO_PERFORM;
2368                 }
2369                 new_is_critical = true;
2370                 break;
2371
2372         default:
2373                 ldb_asprintf_errstring(ldb,
2374                         "%08X: samldb: invalid userAccountControl[0x%08X]",
2375                         W_ERROR_V(WERR_INVALID_PARAMETER), raw_uac);
2376                 return LDB_ERR_OTHER;
2377         }
2378
2379         if (old_atype != new_atype) {
2380                 ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
2381                                          "sAMAccountType", new_atype);
2382                 if (ret != LDB_SUCCESS) {
2383                         return ret;
2384                 }
2385                 el = ldb_msg_find_element(ac->msg, "sAMAccountType");
2386                 el->flags = LDB_FLAG_MOD_REPLACE;
2387         }
2388
2389         /* As per MS-SAMR 3.1.1.8.10 these flags have not to be set */
2390         if ((clear_uac & UF_LOCKOUT) && (old_lockoutTime != 0)) {
2391                 /* "lockoutTime" reset as per MS-SAMR 3.1.1.8.10 */
2392                 ldb_msg_remove_attr(ac->msg, "lockoutTime");
2393                 ret = samdb_msg_add_uint64(ldb, ac->msg, ac->msg, "lockoutTime",
2394                                            (NTTIME)0);
2395                 if (ret != LDB_SUCCESS) {
2396                         return ret;
2397                 }
2398                 el = ldb_msg_find_element(ac->msg, "lockoutTime");
2399                 el->flags = LDB_FLAG_MOD_REPLACE;
2400         }
2401
2402         /* "isCriticalSystemObject" might be set/changed */
2403         if (old_is_critical != new_is_critical) {
2404                 ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject",
2405                                          new_is_critical ? "TRUE": "FALSE");
2406                 if (ret != LDB_SUCCESS) {
2407                         return ret;
2408                 }
2409                 el = ldb_msg_find_element(ac->msg,
2410                                            "isCriticalSystemObject");
2411                 el->flags = LDB_FLAG_MOD_REPLACE;
2412         }
2413
2414         if (!ldb_msg_find_element(ac->msg, "primaryGroupID") &&
2415             (old_pgrid != new_pgrid)) {
2416                 /* Older AD deployments don't know about the RODC group */
2417                 if (new_pgrid == DOMAIN_RID_READONLY_DCS) {
2418                         ret = samldb_prim_group_tester(ac, new_pgrid);
2419                         if (ret != LDB_SUCCESS) {
2420                                 return ret;
2421                         }
2422                 }
2423
2424                 ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
2425                                          "primaryGroupID", new_pgrid);
2426                 if (ret != LDB_SUCCESS) {
2427                         return ret;
2428                 }
2429                 el = ldb_msg_find_element(ac->msg,
2430                                            "primaryGroupID");
2431                 el->flags = LDB_FLAG_MOD_REPLACE;
2432         }
2433
2434         /* Propagate eventual "userAccountControl" attribute changes */
2435         if (old_uac != new_uac) {
2436                 char *tempstr = talloc_asprintf(ac->msg, "%d",
2437                                                 new_uac);
2438                 if (tempstr == NULL) {
2439                         return ldb_module_oom(ac->module);
2440                 }
2441
2442                 /* Overwrite "userAccountControl" correctly */
2443                 el = dsdb_get_single_valued_attr(ac->msg, "userAccountControl",
2444                                                  ac->req->operation);
2445                 el->values[0].data = (uint8_t *) tempstr;
2446                 el->values[0].length = strlen(tempstr);
2447         } else {
2448                 ldb_msg_remove_attr(ac->msg, "userAccountControl");
2449         }
2450
2451         return LDB_SUCCESS;
2452 }
2453
2454 static int samldb_check_pwd_last_set_acl(struct samldb_ctx *ac,
2455                                          struct dom_sid *sid)
2456 {
2457         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
2458         int ret = 0;
2459         struct ldb_result *res = NULL;
2460         const char * const sd_attrs[] = {"ntSecurityDescriptor", NULL};
2461         struct security_token *user_token = NULL;
2462         struct security_descriptor *domain_sd = NULL;
2463         struct ldb_dn *domain_dn = ldb_get_default_basedn(ldb_module_get_ctx(ac->module));
2464         const char *operation = "";
2465
2466         if (dsdb_module_am_system(ac->module)) {
2467                 return LDB_SUCCESS;
2468         }
2469
2470         switch (ac->req->operation) {
2471         case LDB_ADD:
2472                 operation = "add";
2473                 break;
2474         case LDB_MODIFY:
2475                 operation = "modify";
2476                 break;
2477         default:
2478                 return ldb_module_operr(ac->module);
2479         }
2480
2481         user_token = acl_user_token(ac->module);
2482         if (user_token == NULL) {
2483                 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
2484         }
2485
2486         ret = dsdb_module_search_dn(ac->module, ac, &res,
2487                                     domain_dn,
2488                                     sd_attrs,
2489                                     DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED,
2490                                     ac->req);
2491         if (ret != LDB_SUCCESS) {
2492                 return ret;
2493         }
2494         if (res->count != 1) {
2495                 return ldb_module_operr(ac->module);
2496         }
2497
2498         ret = dsdb_get_sd_from_ldb_message(ldb, ac, res->msgs[0], &domain_sd);
2499         if (ret != LDB_SUCCESS) {
2500                 return ret;
2501         }
2502
2503         ret = acl_check_extended_right(ac, domain_sd,
2504                                        user_token,
2505                                        GUID_DRS_UNEXPIRE_PASSWORD,
2506                                        SEC_ADS_CONTROL_ACCESS,
2507                                        sid);
2508         if (ret != LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
2509                 return ret;
2510         }
2511
2512         ldb_debug_set(ldb, LDB_DEBUG_WARNING,
2513                       "Failed to %s %s: "
2514                       "Setting pwdLastSet to -1 requires the "
2515                       "Unexpire-Password right that was not given "
2516                       "on the Domain object",
2517                       operation,
2518                       ldb_dn_get_linearized(ac->msg->dn));
2519         dsdb_acl_debug(domain_sd, user_token,
2520                        domain_dn, true, 10);
2521
2522         return ret;
2523 }
2524
2525 /**
2526  * This function is called on LDB modify operations. It performs some additions/
2527  * replaces on the current LDB message when "pwdLastSet" changes.
2528  */
2529 static int samldb_pwd_last_set_change(struct samldb_ctx *ac)
2530 {
2531         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
2532         NTTIME last_set = 0;
2533         struct ldb_message_element *el = NULL;
2534         struct ldb_message *tmp_msg = NULL;
2535         struct dom_sid *self_sid = NULL;
2536         int ret;
2537         struct ldb_result *res = NULL;
2538         const char * const attrs[] = {
2539                 "objectSid",
2540                 NULL
2541         };
2542
2543         el = dsdb_get_single_valued_attr(ac->msg, "pwdLastSet",
2544                                          ac->req->operation);
2545         if (el == NULL || el->num_values == 0) {
2546                 ldb_asprintf_errstring(ldb,
2547                         "%08X: samldb: 'pwdLastSet' can't be deleted!",
2548                         W_ERROR_V(WERR_DS_ILLEGAL_MOD_OPERATION));
2549                 return LDB_ERR_UNWILLING_TO_PERFORM;
2550         }
2551
2552         /* Create a temporary message for fetching the "userAccountControl" */
2553         tmp_msg = ldb_msg_new(ac->msg);
2554         if (tmp_msg == NULL) {
2555                 return ldb_module_oom(ac->module);
2556         }
2557         ret = ldb_msg_add(tmp_msg, el, 0);
2558         if (ret != LDB_SUCCESS) {
2559                 return ret;
2560         }
2561         last_set = samdb_result_nttime(tmp_msg, "pwdLastSet", 0);
2562         talloc_free(tmp_msg);
2563
2564         /*
2565          * Setting -1 (0xFFFFFFFFFFFFFFFF) requires the Unexpire-Password right
2566          */
2567         if (last_set != UINT64_MAX) {
2568                 return LDB_SUCCESS;
2569         }
2570
2571         /* Fetch the "objectSid" */
2572         ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, attrs,
2573                                     DSDB_FLAG_NEXT_MODULE, ac->req);
2574         if (ret != LDB_SUCCESS) {
2575                 return ret;
2576         }
2577         self_sid = samdb_result_dom_sid(res, res->msgs[0], "objectSid");
2578         if (self_sid == NULL) {
2579                 return ldb_module_operr(ac->module);
2580         }
2581
2582         ret = samldb_check_pwd_last_set_acl(ac, self_sid);
2583         if (ret != LDB_SUCCESS) {
2584                 return ret;
2585         }
2586
2587         return LDB_SUCCESS;
2588 }
2589
2590 static int samldb_lockout_time(struct samldb_ctx *ac)
2591 {
2592         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
2593         NTTIME lockoutTime;
2594         struct ldb_message_element *el;
2595         struct ldb_message *tmp_msg;
2596         int ret;
2597
2598         el = dsdb_get_single_valued_attr(ac->msg, "lockoutTime",
2599                                          ac->req->operation);
2600         if (el == NULL || el->num_values == 0) {
2601                 ldb_asprintf_errstring(ldb,
2602                         "%08X: samldb: 'lockoutTime' can't be deleted!",
2603                         W_ERROR_V(WERR_DS_ILLEGAL_MOD_OPERATION));
2604                 return LDB_ERR_UNWILLING_TO_PERFORM;
2605         }
2606
2607         /* Create a temporary message for fetching the "lockoutTime" */
2608         tmp_msg = ldb_msg_new(ac->msg);
2609         if (tmp_msg == NULL) {
2610                 return ldb_module_oom(ac->module);
2611         }
2612         ret = ldb_msg_add(tmp_msg, el, 0);
2613         if (ret != LDB_SUCCESS) {
2614                 return ret;
2615         }
2616         lockoutTime = ldb_msg_find_attr_as_int64(tmp_msg,
2617                                                  "lockoutTime",
2618                                                  0);
2619         talloc_free(tmp_msg);
2620
2621         if (lockoutTime != 0) {
2622                 return LDB_SUCCESS;
2623         }
2624
2625         /* lockoutTime == 0 resets badPwdCount */
2626         ldb_msg_remove_attr(ac->msg, "badPwdCount");
2627         ret = samdb_msg_add_int(ldb, ac->msg, ac->msg,
2628                                 "badPwdCount", 0);
2629         if (ret != LDB_SUCCESS) {
2630                 return ret;
2631         }
2632         el = ldb_msg_find_element(ac->msg, "badPwdCount");
2633         el->flags = LDB_FLAG_MOD_REPLACE;
2634
2635         return LDB_SUCCESS;
2636 }
2637
2638 static int samldb_group_type_change(struct samldb_ctx *ac)
2639 {
2640         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
2641         uint32_t group_type, old_group_type, account_type;
2642         struct ldb_message_element *el;
2643         struct ldb_message *tmp_msg;
2644         int ret;
2645         struct ldb_result *res;
2646         const char * const attrs[] = { "groupType", NULL };
2647
2648         el = dsdb_get_single_valued_attr(ac->msg, "groupType",
2649                                          ac->req->operation);
2650         if (el == NULL) {
2651                 /* we are not affected */
2652                 return LDB_SUCCESS;
2653         }
2654
2655         /* Create a temporary message for fetching the "groupType" */
2656         tmp_msg = ldb_msg_new(ac->msg);
2657         if (tmp_msg == NULL) {
2658                 return ldb_module_oom(ac->module);
2659         }
2660         ret = ldb_msg_add(tmp_msg, el, 0);
2661         if (ret != LDB_SUCCESS) {
2662                 return ret;
2663         }
2664         group_type = ldb_msg_find_attr_as_uint(tmp_msg, "groupType", 0);
2665         talloc_free(tmp_msg);
2666
2667         ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, attrs,
2668                                     DSDB_FLAG_NEXT_MODULE |
2669                                     DSDB_SEARCH_SHOW_DELETED, ac->req);
2670         if (ret != LDB_SUCCESS) {
2671                 return ret;
2672         }
2673         old_group_type = ldb_msg_find_attr_as_uint(res->msgs[0], "groupType", 0);
2674         if (old_group_type == 0) {
2675                 return ldb_operr(ldb);
2676         }
2677
2678         /* Group type switching isn't so easy as it seems: We can only
2679          * change in this directions: global <-> universal <-> local
2680          * On each step also the group type itself
2681          * (security/distribution) is variable. */
2682
2683         if (ldb_request_get_control(ac->req, LDB_CONTROL_PROVISION_OID) == NULL) {
2684                 switch (group_type) {
2685                 case GTYPE_SECURITY_GLOBAL_GROUP:
2686                 case GTYPE_DISTRIBUTION_GLOBAL_GROUP:
2687                         /* change to "universal" allowed */
2688                         if ((old_group_type == GTYPE_SECURITY_DOMAIN_LOCAL_GROUP) ||
2689                         (old_group_type == GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)) {
2690                                 ldb_set_errstring(ldb,
2691                                         "samldb: Change from security/distribution local group forbidden!");
2692                                 return LDB_ERR_UNWILLING_TO_PERFORM;
2693                         }
2694                 break;
2695
2696                 case GTYPE_SECURITY_UNIVERSAL_GROUP:
2697                 case GTYPE_DISTRIBUTION_UNIVERSAL_GROUP:
2698                         /* each change allowed */
2699                 break;
2700                 case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
2701                 case GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP:
2702                         /* change to "universal" allowed */
2703                         if ((old_group_type == GTYPE_SECURITY_GLOBAL_GROUP) ||
2704                         (old_group_type == GTYPE_DISTRIBUTION_GLOBAL_GROUP)) {
2705                                 ldb_set_errstring(ldb,
2706                                         "samldb: Change from security/distribution global group forbidden!");
2707                                 return LDB_ERR_UNWILLING_TO_PERFORM;
2708                         }
2709                 break;
2710
2711                 case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
2712                 default:
2713                         /* we don't allow this "groupType" values */
2714                         return LDB_ERR_UNWILLING_TO_PERFORM;
2715                 break;
2716                 }
2717         }
2718
2719         account_type =  ds_gtype2atype(group_type);
2720         if (account_type == 0) {
2721                 ldb_set_errstring(ldb, "samldb: Unrecognized account type!");
2722                 return LDB_ERR_UNWILLING_TO_PERFORM;
2723         }
2724         ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "sAMAccountType",
2725                                  account_type);
2726         if (ret != LDB_SUCCESS) {
2727                 return ret;
2728         }
2729         el = ldb_msg_find_element(ac->msg, "sAMAccountType");
2730         el->flags = LDB_FLAG_MOD_REPLACE;
2731
2732         return LDB_SUCCESS;
2733 }
2734
2735 static int samldb_member_check(struct samldb_ctx *ac)
2736 {
2737         const char * const attrs[] = { "objectSid", NULL };
2738         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
2739         struct ldb_message_element *el;
2740         struct ldb_dn *member_dn;
2741         struct dom_sid *sid;
2742         struct ldb_result *res;
2743         struct dom_sid *group_sid;
2744         unsigned int i, j;
2745         int ret;
2746
2747         /* Fetch information from the existing object */
2748
2749         ret = dsdb_module_search(ac->module, ac, &res, ac->msg->dn, LDB_SCOPE_BASE, attrs,
2750                                  DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED, ac->req, NULL);
2751         if (ret != LDB_SUCCESS) {
2752                 return ret;
2753         }
2754         if (res->count != 1) {
2755                 return ldb_operr(ldb);
2756         }
2757
2758         group_sid = samdb_result_dom_sid(res, res->msgs[0], "objectSid");
2759         if (group_sid == NULL) {
2760                 return ldb_operr(ldb);
2761         }
2762
2763         /* We've to walk over all modification entries and consider the "member"
2764          * ones. */
2765         for (i = 0; i < ac->msg->num_elements; i++) {
2766                 if (ldb_attr_cmp(ac->msg->elements[i].name, "member") != 0) {
2767                         continue;
2768                 }
2769
2770                 el = &ac->msg->elements[i];
2771                 for (j = 0; j < el->num_values; j++) {
2772                         struct ldb_result *group_res;
2773                         const char *group_attrs[] = { "primaryGroupID" , NULL };
2774                         uint32_t prim_group_rid;
2775
2776                         if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE) {
2777                                 /* Deletes will be handled in
2778                                  * repl_meta_data, and deletes not
2779                                  * matching a member will return
2780                                  * LDB_ERR_UNWILLING_TO_PERFORM
2781                                  * there */
2782                                 continue;
2783                         }
2784
2785                         member_dn = ldb_dn_from_ldb_val(ac, ldb,
2786                                                         &el->values[j]);
2787                         if (!ldb_dn_validate(member_dn)) {
2788                                 return ldb_operr(ldb);
2789                         }
2790
2791                         /* Denies to add "member"s to groups which are primary
2792                          * ones for them - in this case return
2793                          * ERR_ENTRY_ALREADY_EXISTS. */
2794
2795                         ret = dsdb_module_search_dn(ac->module, ac, &group_res,
2796                                                     member_dn, group_attrs,
2797                                                     DSDB_FLAG_NEXT_MODULE, ac->req);
2798                         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2799                                 /* member DN doesn't exist yet */
2800                                 continue;
2801                         }
2802                         if (ret != LDB_SUCCESS) {
2803                                 return ret;
2804                         }
2805                         prim_group_rid = ldb_msg_find_attr_as_uint(group_res->msgs[0], "primaryGroupID", (uint32_t)-1);
2806                         if (prim_group_rid == (uint32_t) -1) {
2807                                 /* the member hasn't to be a user account ->
2808                                  * therefore no check needed in this case. */
2809                                 continue;
2810                         }
2811
2812                         sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb),
2813                                               prim_group_rid);
2814                         if (sid == NULL) {
2815                                 return ldb_operr(ldb);
2816                         }
2817
2818                         if (dom_sid_equal(group_sid, sid)) {
2819                                 ldb_asprintf_errstring(ldb,
2820                                                        "samldb: member %s already set via primaryGroupID %u",
2821                                                        ldb_dn_get_linearized(member_dn), prim_group_rid);
2822                                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
2823                         }
2824                 }
2825         }
2826
2827         talloc_free(res);
2828
2829         return LDB_SUCCESS;
2830 }
2831
2832 /* SAM objects have special rules regarding the "description" attribute on
2833  * modify operations. */
2834 static int samldb_description_check(struct samldb_ctx *ac, bool *modified)
2835 {
2836         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
2837         const char * const attrs[] = { "objectClass", "description", NULL };
2838         struct ldb_result *res;
2839         unsigned int i;
2840         int ret;
2841
2842         /* Fetch information from the existing object */
2843         ret = dsdb_module_search(ac->module, ac, &res, ac->msg->dn, LDB_SCOPE_BASE, attrs,
2844                                  DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED, ac->req,
2845                                  "(|(objectclass=user)(objectclass=group)(objectclass=samDomain)(objectclass=samServer))");
2846         if (ret != LDB_SUCCESS) {
2847                 /* don't treat it specially ... let normal error codes
2848                    happen from other places */
2849                 ldb_reset_err_string(ldb);
2850                 return LDB_SUCCESS;
2851         }
2852         if (res->count == 0) {
2853                 /* we didn't match the filter */
2854                 talloc_free(res);
2855                 return LDB_SUCCESS;
2856         }
2857
2858         /* We've to walk over all modification entries and consider the
2859          * "description" ones. */
2860         for (i = 0; i < ac->msg->num_elements; i++) {
2861                 if (ldb_attr_cmp(ac->msg->elements[i].name, "description") == 0) {
2862                         ac->msg->elements[i].flags |= LDB_FLAG_INTERNAL_FORCE_SINGLE_VALUE_CHECK;
2863                         *modified = true;
2864                 }
2865         }
2866
2867         talloc_free(res);
2868
2869         return LDB_SUCCESS;
2870 }
2871
2872 /* This trigger adapts the "servicePrincipalName" attributes if the
2873  * "dNSHostName" and/or "sAMAccountName" attribute change(s) */
2874 static int samldb_service_principal_names_change(struct samldb_ctx *ac)
2875 {
2876         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
2877         struct ldb_message_element *el = NULL, *el2 = NULL;
2878         struct ldb_message *msg;
2879         const char * const attrs[] = { "servicePrincipalName", NULL };
2880         struct ldb_result *res;
2881         const char *dns_hostname = NULL, *old_dns_hostname = NULL,
2882                    *sam_accountname = NULL, *old_sam_accountname = NULL;
2883         unsigned int i, j;
2884         int ret;
2885
2886         el = dsdb_get_single_valued_attr(ac->msg, "dNSHostName",
2887                                          ac->req->operation);
2888         el2 = dsdb_get_single_valued_attr(ac->msg, "sAMAccountName",
2889                                           ac->req->operation);
2890         if ((el == NULL) && (el2 == NULL)) {
2891                 /* we are not affected */
2892                 return LDB_SUCCESS;
2893         }
2894
2895         /* Create a temporary message for fetching the "dNSHostName" */
2896         if (el != NULL) {
2897                 const char *dns_attrs[] = { "dNSHostName", NULL };
2898                 msg = ldb_msg_new(ac->msg);
2899                 if (msg == NULL) {
2900                         return ldb_module_oom(ac->module);
2901                 }
2902                 ret = ldb_msg_add(msg, el, 0);
2903                 if (ret != LDB_SUCCESS) {
2904                         return ret;
2905                 }
2906                 dns_hostname = talloc_strdup(ac,
2907                                              ldb_msg_find_attr_as_string(msg, "dNSHostName", NULL));
2908                 if (dns_hostname == NULL) {
2909                         return ldb_module_oom(ac->module);
2910                 }
2911
2912                 talloc_free(msg);
2913
2914                 ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn,
2915                                             dns_attrs, DSDB_FLAG_NEXT_MODULE, ac->req);
2916                 if (ret == LDB_SUCCESS) {
2917                         old_dns_hostname = ldb_msg_find_attr_as_string(res->msgs[0], "dNSHostName", NULL);
2918                 }
2919         }
2920
2921         /* Create a temporary message for fetching the "sAMAccountName" */
2922         if (el2 != NULL) {
2923                 char *tempstr, *tempstr2 = NULL;
2924                 const char *acct_attrs[] = { "sAMAccountName", NULL };
2925
2926                 msg = ldb_msg_new(ac->msg);
2927                 if (msg == NULL) {
2928                         return ldb_module_oom(ac->module);
2929                 }
2930                 ret = ldb_msg_add(msg, el2, 0);
2931                 if (ret != LDB_SUCCESS) {
2932                         return ret;
2933                 }
2934                 tempstr = talloc_strdup(ac,
2935                                         ldb_msg_find_attr_as_string(msg, "sAMAccountName", NULL));
2936                 talloc_free(msg);
2937
2938                 ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, acct_attrs,
2939                                             DSDB_FLAG_NEXT_MODULE, ac->req);
2940                 if (ret == LDB_SUCCESS) {
2941                         tempstr2 = talloc_strdup(ac,
2942                                                  ldb_msg_find_attr_as_string(res->msgs[0],
2943                                                                              "sAMAccountName", NULL));
2944                 }
2945
2946
2947                 /* The "sAMAccountName" needs some additional trimming: we need
2948                  * to remove the trailing "$"s if they exist. */
2949                 if ((tempstr != NULL) && (tempstr[0] != '\0') &&
2950                     (tempstr[strlen(tempstr) - 1] == '$')) {
2951                         tempstr[strlen(tempstr) - 1] = '\0';
2952                 }
2953                 if ((tempstr2 != NULL) && (tempstr2[0] != '\0') &&
2954                     (tempstr2[strlen(tempstr2) - 1] == '$')) {
2955                         tempstr2[strlen(tempstr2) - 1] = '\0';
2956                 }
2957                 sam_accountname = tempstr;
2958                 old_sam_accountname = tempstr2;
2959         }
2960
2961         if (old_dns_hostname == NULL) {
2962                 /* we cannot change when the old name is unknown */
2963                 dns_hostname = NULL;
2964         }
2965         if ((old_dns_hostname != NULL) && (dns_hostname != NULL) &&
2966             (strcasecmp_m(old_dns_hostname, dns_hostname) == 0)) {
2967                 /* The "dNSHostName" didn't change */
2968                 dns_hostname = NULL;
2969         }
2970
2971         if (old_sam_accountname == NULL) {
2972                 /* we cannot change when the old name is unknown */
2973                 sam_accountname = NULL;
2974         }
2975         if ((old_sam_accountname != NULL) && (sam_accountname != NULL) &&
2976             (strcasecmp_m(old_sam_accountname, sam_accountname) == 0)) {
2977                 /* The "sAMAccountName" didn't change */
2978                 sam_accountname = NULL;
2979         }
2980
2981         if ((dns_hostname == NULL) && (sam_accountname == NULL)) {
2982                 /* Well, there are information missing (old name(s)) or the
2983                  * names didn't change. We've nothing to do and can exit here */
2984                 return LDB_SUCCESS;
2985         }
2986
2987         /* Potential "servicePrincipalName" changes in the same request have to
2988          * be handled before the update (Windows behaviour). */
2989         el = ldb_msg_find_element(ac->msg, "servicePrincipalName");
2990         if (el != NULL) {
2991                 msg = ldb_msg_new(ac->msg);
2992                 if (msg == NULL) {
2993                         return ldb_module_oom(ac->module);
2994                 }
2995                 msg->dn = ac->msg->dn;
2996
2997                 do {
2998                         ret = ldb_msg_add(msg, el, el->flags);
2999                         if (ret != LDB_SUCCESS) {
3000                                 return ret;
3001                         }
3002
3003                         ldb_msg_remove_element(ac->msg, el);
3004
3005                         el = ldb_msg_find_element(ac->msg,
3006                                                   "servicePrincipalName");
3007                 } while (el != NULL);
3008
3009                 ret = dsdb_module_modify(ac->module, msg,
3010                                          DSDB_FLAG_NEXT_MODULE, ac->req);
3011                 if (ret != LDB_SUCCESS) {
3012                         return ret;
3013                 }
3014                 talloc_free(msg);
3015         }
3016
3017         /* Fetch the "servicePrincipalName"s if any */
3018         ret = dsdb_module_search(ac->module, ac, &res, ac->msg->dn, LDB_SCOPE_BASE, attrs,
3019                                  DSDB_FLAG_NEXT_MODULE, ac->req, NULL);
3020         if (ret != LDB_SUCCESS) {
3021                 return ret;
3022         }
3023         if ((res->count != 1) || (res->msgs[0]->num_elements > 1)) {
3024                 return ldb_operr(ldb);
3025         }
3026
3027         if (res->msgs[0]->num_elements == 1) {
3028                 /*
3029                  * Yes, we do have "servicePrincipalName"s. First we update them
3030                  * locally, that means we do always substitute the current
3031                  * "dNSHostName" with the new one and/or "sAMAccountName"
3032                  * without "$" with the new one and then we append the
3033                  * modified "servicePrincipalName"s as a message element
3034                  * replace to the modification request (Windows behaviour). We
3035                  * need also to make sure that the values remain case-
3036                  * insensitively unique.
3037                  */
3038
3039                 ret = ldb_msg_add_empty(ac->msg, "servicePrincipalName",
3040                                         LDB_FLAG_MOD_REPLACE, &el);
3041                 if (ret != LDB_SUCCESS) {
3042                         return ret;
3043                 }
3044
3045                 for (i = 0; i < res->msgs[0]->elements[0].num_values; i++) {
3046                         char *old_str, *new_str;
3047                         char *pos = NULL;
3048                         const char *tok;
3049                         struct ldb_val *vals;
3050                         bool found = false;
3051
3052                         old_str = (char *)
3053                                 res->msgs[0]->elements[0].values[i].data;
3054
3055                         new_str = talloc_strdup(ac->msg,
3056                                                 strtok_r(old_str, "/", &pos));
3057                         if (new_str == NULL) {
3058                                 return ldb_module_oom(ac->module);
3059                         }
3060
3061                         while ((tok = strtok_r(NULL, "/", &pos)) != NULL) {
3062                                 if ((dns_hostname != NULL) &&
3063                                     (strcasecmp_m(tok, old_dns_hostname) == 0)) {
3064                                         tok = dns_hostname;
3065                                 }
3066                                 if ((sam_accountname != NULL) &&
3067                                     (strcasecmp_m(tok, old_sam_accountname) == 0)) {
3068                                         tok = sam_accountname;
3069                                 }
3070
3071                                 new_str = talloc_asprintf(ac->msg, "%s/%s",
3072                                                           new_str, tok);
3073                                 if (new_str == NULL) {
3074                                         return ldb_module_oom(ac->module);
3075                                 }
3076                         }
3077
3078                         /* Uniqueness check */
3079                         for (j = 0; (!found) && (j < el->num_values); j++) {
3080                                 if (strcasecmp_m((char *)el->values[j].data,
3081                                                new_str) == 0) {
3082                                         found = true;
3083                                 }
3084                         }
3085                         if (found) {
3086                                 continue;
3087                         }
3088
3089                         /*
3090                          * append the new "servicePrincipalName" -
3091                          * code derived from ldb_msg_add_value().
3092                          *
3093                          * Open coded to make it clear that we must
3094                          * append to the MOD_REPLACE el created above.
3095                          */
3096                         vals = talloc_realloc(ac->msg, el->values,
3097                                               struct ldb_val,
3098                                               el->num_values + 1);
3099                         if (vals == NULL) {
3100                                 return ldb_module_oom(ac->module);
3101                         }
3102                         el->values = vals;
3103                         el->values[el->num_values] = data_blob_string_const(new_str);
3104                         ++(el->num_values);
3105                 }
3106         }
3107
3108         talloc_free(res);
3109
3110         return LDB_SUCCESS;
3111 }
3112
3113 /* This checks the "fSMORoleOwner" attributes */
3114 static int samldb_fsmo_role_owner_check(struct samldb_ctx *ac)
3115 {
3116         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
3117         const char * const no_attrs[] = { NULL };
3118         struct ldb_message_element *el;
3119         struct ldb_message *tmp_msg;
3120         struct ldb_dn *res_dn;
3121         struct ldb_result *res;
3122         int ret;
3123
3124         el = dsdb_get_single_valued_attr(ac->msg, "fSMORoleOwner",
3125                                          ac->req->operation);
3126         if (el == NULL) {
3127                 /* we are not affected */
3128                 return LDB_SUCCESS;
3129         }
3130
3131         /* Create a temporary message for fetching the "fSMORoleOwner" */
3132         tmp_msg = ldb_msg_new(ac->msg);
3133         if (tmp_msg == NULL) {
3134                 return ldb_module_oom(ac->module);
3135         }
3136         ret = ldb_msg_add(tmp_msg, el, 0);
3137         if (ret != LDB_SUCCESS) {
3138                 return ret;
3139         }
3140         res_dn = ldb_msg_find_attr_as_dn(ldb, ac, tmp_msg, "fSMORoleOwner");
3141         talloc_free(tmp_msg);
3142
3143         if (res_dn == NULL) {
3144                 ldb_set_errstring(ldb,
3145                                   "samldb: 'fSMORoleOwner' attributes have to reference 'nTDSDSA' entries!");
3146                 if (ac->req->operation == LDB_ADD) {
3147                         return LDB_ERR_CONSTRAINT_VIOLATION;
3148                 } else {
3149                         return LDB_ERR_UNWILLING_TO_PERFORM;
3150                 }
3151         }
3152
3153         /* Fetched DN has to reference a "nTDSDSA" entry */
3154         ret = dsdb_module_search(ac->module, ac, &res, res_dn, LDB_SCOPE_BASE,
3155                                  no_attrs,
3156                                  DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED,
3157                                  ac->req, "(objectClass=nTDSDSA)");
3158         if (ret != LDB_SUCCESS) {
3159                 return ret;
3160         }
3161         if (res->count != 1) {
3162                 ldb_set_errstring(ldb,
3163                                   "samldb: 'fSMORoleOwner' attributes have to reference 'nTDSDSA' entries!");
3164                 return LDB_ERR_UNWILLING_TO_PERFORM;
3165         }
3166
3167         talloc_free(res);
3168
3169         return LDB_SUCCESS;
3170 }
3171
3172 /*
3173  * Return zero if the number of zero bits in the address (looking from low to
3174  * high) is equal to or greater than the length minus the mask. Otherwise it
3175  * returns -1.
3176  */
3177 static int check_cidr_zero_bits(uint8_t *address, unsigned int len,
3178                                 unsigned int mask)
3179 {
3180         /* <address> is an integer in big-endian form, <len> bits long. All
3181            bits between <mask> and <len> must be zero. */
3182         int i;
3183         unsigned int byte_len;
3184         unsigned int byte_mask;
3185         unsigned int bit_mask;
3186         if (len == 32) {
3187                 DBG_INFO("Looking at address %02x%02x%02x%02x, mask %u\n",
3188                          address[0], address[1], address[2], address[3],
3189                           mask);
3190         } else if (len == 128){
3191                 DBG_INFO("Looking at address "
3192                          "%02x%02x-%02x%02x-%02x%02x-%02x%02x-"
3193                          "%02x%02x-%02x%02x-%02x%02x-%02x%02x, mask %u\n",
3194                          address[0], address[1], address[2], address[3],
3195                          address[4], address[5], address[6], address[7],
3196                          address[8], address[9], address[10], address[11],
3197                          address[12], address[13], address[14], address[15],
3198                          mask);
3199         }
3200
3201         if (mask > len){
3202                 DBG_INFO("mask %u is too big (> %u)\n", mask, len);
3203                 return -1;
3204         }
3205         if (mask == len){
3206                 /* single address subnet.
3207                  * In IPv4 all 255s is invalid by the bitmask != address rule
3208                  * in MS-ADTS. IPv6 does not suffer.
3209                  */
3210                 if (len == 32){
3211                         if (address[0] == 255 &&
3212                             address[1] == 255 &&
3213                             address[2] == 255 &&
3214                             address[3] == 255){
3215                                 return -1;
3216                         }
3217                 }
3218                 return 0;
3219         }
3220
3221         byte_len = len / 8;
3222         byte_mask = mask / 8;
3223
3224         for (i = byte_len - 1; i > byte_mask; i--){
3225                 DBG_DEBUG("checking byte %d %02x\n", i, address[i]);
3226                 if (address[i] != 0){
3227                         return -1;
3228                 }
3229         }
3230         bit_mask = (1 << (8 - (mask & 7))) - 1;
3231         DBG_DEBUG("checking bitmask %02x & %02x overlap %02x\n", bit_mask, address[byte_mask],
3232                   bit_mask & address[byte_mask]);
3233         if (address[byte_mask] & bit_mask){
3234                 return -1;
3235         }
3236
3237         /* According to MS-ADTS, the mask can't exactly equal the bitmask for
3238          * IPv4 (but this is fine for v6). That is 255.255.80.0/17 is bad,
3239          * because the bitmask implied by "/17" is 255.255.80.0.
3240          *
3241          * The bit_mask used in the previous check is the complement of what
3242          * we want here.
3243          */
3244         if (len == 32 && address[byte_mask] == (uint8_t)~bit_mask){
3245                 bool ok = false;
3246                 for (i = 0; i < byte_mask; i++){
3247                         if (address[i] != 255){
3248                                 ok = true;
3249                                 break;
3250                         }
3251                 }
3252                 if (ok == false){
3253                         return -1;
3254                 }
3255         }
3256         return 0;
3257 }
3258
3259
3260
3261 static int check_address_roundtrip(const char *address, int family,
3262                                    const uint8_t *address_bytes,
3263                                    char *buffer, int buffer_len)
3264 {
3265         /*
3266          * Check that the address is in the canonical RFC5952 format for IPv6,
3267          * and lacks extra leading zeros for each dotted decimal for IPv4.
3268          * Handily this is what inet_ntop() gives you.
3269          */
3270         const char *address_redux = inet_ntop(family, address_bytes,
3271                                               buffer, buffer_len);
3272         if (address_redux == NULL){
3273                 DBG_INFO("Address round trip %s failed unexpectedly"
3274                          " with errno %d\n", address, errno);
3275                 return -1;
3276         }
3277         if (strcasecmp(address, address_redux) != 0){
3278                 DBG_INFO("Address %s round trips to %s; fail!\n",
3279                          address, address_redux);
3280                 /* If the address family is IPv6, and the address is in a
3281                    certain range
3282
3283                  */
3284                 if (strchr(address_redux, '.') != NULL){
3285                         DEBUG(0, ("The IPv6 address '%s' has the misfortune of "
3286                                   "lying in a range that was once used for "
3287                                   "IPv4 embedding (that is, it might also be "
3288                                   "represented as '%s').\n", address,
3289                                   address_redux));
3290                 }
3291                 return -1;
3292         }
3293         return 0;
3294 }
3295
3296
3297
3298 /*
3299  * MS-ADTS v20150630 6.1.1.2.2.2.1 Subnet Object, refers to RFC1166 and
3300  * RFC2373. It specifies something seemingly indistinguishable from an RFC4632
3301  * CIDR address range without saying so explicitly. Here we follow the CIDR
3302  * spec.
3303  *
3304  * Return 0 on success, -1 on error.
3305  */
3306 static int verify_cidr(const char *cidr)
3307 {
3308         char *address = NULL, *slash = NULL, *endptr = NULL;
3309         bool has_colon, has_dot;
3310         int res, ret;
3311         unsigned long mask;
3312         uint8_t *address_bytes = NULL;
3313         char *address_redux = NULL;
3314         unsigned int address_len;
3315         TALLOC_CTX *frame = NULL;
3316         int error = 0;
3317
3318         DBG_DEBUG("CIDR is %s\n", cidr);
3319         frame = talloc_stackframe();
3320         address = talloc_strdup(frame, cidr);
3321         if (address == NULL){
3322                 goto error;
3323         }
3324
3325         /* there must be a '/' */
3326         slash = strchr(address, '/');
3327         if (slash == NULL){
3328                 goto error;
3329         }
3330         /* terminate the address for strchr, inet_pton */
3331         *slash = '\0';
3332
3333         mask = strtoul_err(slash + 1, &endptr, 10, &error);
3334         if (mask == 0){
3335                 DBG_INFO("Windows does not like the zero mask, "
3336                          "so nor do we: %s\n", cidr);
3337                 goto error;
3338         }
3339
3340         if (*endptr != '\0' || endptr == slash + 1 || error != 0){
3341                 DBG_INFO("CIDR mask is not a proper integer: %s\n", cidr);
3342                 goto error;
3343         }
3344
3345         address_bytes = talloc_size(frame, sizeof(struct in6_addr));
3346         if (address_bytes == NULL){
3347                 goto error;
3348         }
3349
3350         address_redux = talloc_size(frame, INET6_ADDRSTRLEN);
3351         if (address_redux == NULL){
3352                 goto error;
3353         }
3354
3355         DBG_INFO("found address %s, mask %lu\n", address, mask);
3356         has_colon = (strchr(address, ':') == NULL) ? false : true;
3357         has_dot = (strchr(address, '.') == NULL) ? false : true;
3358         if (has_dot && has_colon){
3359                 /* This seems to be an IPv4 address embedded in IPv6, which is
3360                    icky. We don't support it. */
3361                 DBG_INFO("Refusing to consider cidr '%s' with dots and colons\n",
3362                           cidr);
3363                 goto error;
3364         } else if (has_colon){  /* looks like IPv6 */
3365                 res = inet_pton(AF_INET6, address, address_bytes);
3366                 if (res != 1) {
3367                         DBG_INFO("Address in %s fails to parse as IPv6\n", cidr);
3368                         goto error;
3369                 }
3370                 address_len = 128;
3371                 if (check_address_roundtrip(address, AF_INET6, address_bytes,
3372                                             address_redux, INET6_ADDRSTRLEN)){
3373                         goto error;
3374                 }
3375         } else if (has_dot) {
3376                 /* looks like IPv4 */
3377                 if (strcmp(address, "0.0.0.0") == 0){
3378                         DBG_INFO("Windows does not like the zero IPv4 address, "
3379                                  "so nor do we.\n");
3380                         goto error;
3381                 }
3382                 res = inet_pton(AF_INET, address, address_bytes);
3383                 if (res != 1) {
3384                         DBG_INFO("Address in %s fails to parse as IPv4\n", cidr);
3385                         goto error;
3386                 }
3387                 address_len = 32;
3388
3389                 if (check_address_roundtrip(address, AF_INET, address_bytes,
3390                                             address_redux, INET_ADDRSTRLEN)){
3391                         goto error;
3392                 }
3393         } else {
3394                 /* This doesn't look like an IP address at all. */
3395                 goto error;
3396         }
3397
3398         ret = check_cidr_zero_bits(address_bytes, address_len, mask);
3399         talloc_free(frame);
3400         return ret;
3401   error:
3402         talloc_free(frame);
3403         return -1;
3404 }
3405
3406
3407 static int samldb_verify_subnet(struct samldb_ctx *ac, struct ldb_dn *dn)
3408 {
3409         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
3410         const char *cidr = NULL;
3411         const struct ldb_val *rdn_value = NULL;
3412
3413         rdn_value = ldb_dn_get_rdn_val(dn);
3414         if (rdn_value == NULL) {
3415                 ldb_set_errstring(ldb, "samldb: ldb_dn_get_rdn_val "
3416                                   "failed");
3417                 return LDB_ERR_UNWILLING_TO_PERFORM;
3418         }
3419
3420         cidr = ldb_dn_escape_value(ac, *rdn_value);
3421         DBG_INFO("looking at cidr '%s'\n", cidr);
3422         if (cidr == NULL) {
3423                 ldb_set_errstring(ldb,
3424                                   "samldb: adding an empty subnet cidr seems wrong");
3425                 return LDB_ERR_UNWILLING_TO_PERFORM;
3426         }
3427
3428         if (verify_cidr(cidr)){
3429                 ldb_set_errstring(ldb,
3430                                   "samldb: subnet value is invalid");
3431                 return LDB_ERR_INVALID_DN_SYNTAX;
3432         }
3433
3434         return LDB_SUCCESS;
3435 }
3436
3437 static char *refer_if_rodc(struct ldb_context *ldb, struct ldb_request *req,
3438                            struct ldb_dn *dn)
3439 {
3440         bool rodc = false;
3441         struct loadparm_context *lp_ctx;
3442         char *referral;
3443         int ret;
3444         WERROR err;
3445
3446         if (ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID) ||
3447             ldb_request_get_control(req, DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA)) {
3448                 return NULL;
3449         }
3450
3451         ret = samdb_rodc(ldb, &rodc);
3452         if (ret != LDB_SUCCESS) {
3453                 DEBUG(4, (__location__ ": unable to tell if we are an RODC\n"));
3454                 return NULL;
3455         }
3456
3457         if (rodc) {
3458                 const char *domain = NULL;
3459                 struct ldb_dn *fsmo_role_dn;
3460                 struct ldb_dn *role_owner_dn;
3461                 ldb_set_errstring(ldb, "RODC modify is forbidden!");
3462                 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
3463                                          struct loadparm_context);
3464
3465                 err = dsdb_get_fsmo_role_info(req, ldb, DREPL_PDC_MASTER,
3466                                               &fsmo_role_dn, &role_owner_dn);
3467                 if (W_ERROR_IS_OK(err)) {
3468                         struct ldb_dn *server_dn = ldb_dn_copy(req, role_owner_dn);
3469                         if (server_dn != NULL) {
3470                                 ldb_dn_remove_child_components(server_dn, 1);
3471
3472                                 domain = samdb_dn_to_dnshostname(ldb, req,
3473                                                                  server_dn);
3474                         }
3475                 }
3476                 if (domain == NULL) {
3477                         domain = lpcfg_dnsdomain(lp_ctx);
3478                 }
3479                 referral = talloc_asprintf(req,
3480                                            "ldap://%s/%s",
3481                                            domain,
3482                                            ldb_dn_get_linearized(dn));
3483                 return referral;
3484         }
3485
3486         return NULL;
3487 }
3488
3489
3490 /* add */
3491 static int samldb_add(struct ldb_module *module, struct ldb_request *req)
3492 {
3493         struct ldb_context *ldb;
3494         struct samldb_ctx *ac;
3495         struct ldb_message_element *el;
3496         int ret;
3497         char *referral = NULL;
3498
3499         ldb = ldb_module_get_ctx(module);
3500         ldb_debug(ldb, LDB_DEBUG_TRACE, "samldb_add\n");
3501
3502         /* do not manipulate our control entries */
3503         if (ldb_dn_is_special(req->op.add.message->dn)) {
3504                 return ldb_next_request(module, req);
3505         }
3506
3507         referral = refer_if_rodc(ldb, req, req->op.add.message->dn);
3508         if (referral != NULL) {
3509                 ret = ldb_module_send_referral(req, referral);
3510                 return ret;
3511         }
3512
3513         el = ldb_msg_find_element(req->op.add.message, "userParameters");
3514         if (el != NULL && ldb_req_is_untrusted(req)) {
3515                 const char *reason = "samldb_add: "
3516                         "setting userParameters is not supported over LDAP, "
3517                         "see https://bugzilla.samba.org/show_bug.cgi?id=8077";
3518                 ldb_debug(ldb, LDB_DEBUG_WARNING, "%s", reason);
3519                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, reason);
3520         }
3521
3522         ac = samldb_ctx_init(module, req);
3523         if (ac == NULL) {
3524                 return ldb_operr(ldb);
3525         }
3526
3527         /* build the new msg */
3528         ac->msg = ldb_msg_copy_shallow(ac, req->op.add.message);
3529         if (ac->msg == NULL) {
3530                 talloc_free(ac);
3531                 ldb_debug(ldb, LDB_DEBUG_FATAL,
3532                           "samldb_add: ldb_msg_copy_shallow failed!\n");
3533                 return ldb_operr(ldb);
3534         }
3535
3536         el = ldb_msg_find_element(ac->msg, "fSMORoleOwner");
3537         if (el != NULL) {
3538                 ret = samldb_fsmo_role_owner_check(ac);
3539                 if (ret != LDB_SUCCESS) {
3540                         return ret;
3541                 }
3542         }
3543
3544         if (samdb_find_attribute(ldb, ac->msg,
3545                                  "objectclass", "user") != NULL) {
3546                 ac->type = SAMLDB_TYPE_USER;
3547
3548                 ret = samldb_prim_group_trigger(ac);
3549                 if (ret != LDB_SUCCESS) {
3550                         return ret;
3551                 }
3552
3553                 ret = samldb_objectclass_trigger(ac);
3554                 if (ret != LDB_SUCCESS) {
3555                         return ret;
3556                 }
3557
3558                 return samldb_fill_object(ac);
3559         }
3560
3561         if (samdb_find_attribute(ldb, ac->msg,
3562                                  "objectclass", "group") != NULL) {
3563                 ac->type = SAMLDB_TYPE_GROUP;
3564
3565                 ret = samldb_objectclass_trigger(ac);
3566                 if (ret != LDB_SUCCESS) {
3567                         return ret;
3568                 }
3569
3570                 return samldb_fill_object(ac);
3571         }
3572
3573         /* perhaps a foreignSecurityPrincipal? */
3574         if (samdb_find_attribute(ldb, ac->msg,
3575                                  "objectclass",
3576                                  "foreignSecurityPrincipal") != NULL) {
3577                 return samldb_fill_foreignSecurityPrincipal_object(ac);
3578         }
3579
3580         if (samdb_find_attribute(ldb, ac->msg,
3581                                  "objectclass", "classSchema") != NULL) {
3582                 ac->type = SAMLDB_TYPE_CLASS;
3583
3584                 /* If in provision, these checks are too slow to do */
3585                 if (!ldb_request_get_control(req, DSDB_CONTROL_SKIP_DUPLICATES_CHECK_OID)) {
3586                         ret = samldb_schema_governsid_valid_check(ac);
3587                         if (ret != LDB_SUCCESS) {
3588                                 return ret;
3589                         }
3590                 }
3591
3592                 ret = samldb_schema_ldapdisplayname_valid_check(ac);
3593                 if (ret != LDB_SUCCESS) {
3594                         return ret;
3595                 }
3596
3597                 ret = samldb_schema_info_update(ac);
3598                 if (ret != LDB_SUCCESS) {
3599                         talloc_free(ac);
3600                         return ret;
3601                 }
3602
3603                 return samldb_fill_object(ac);
3604         }
3605
3606         if (samdb_find_attribute(ldb, ac->msg,
3607                                  "objectclass", "attributeSchema") != NULL) {
3608                 ac->type = SAMLDB_TYPE_ATTRIBUTE;
3609
3610                 /* If in provision, these checks are too slow to do */
3611                 if (!ldb_request_get_control(req, DSDB_CONTROL_SKIP_DUPLICATES_CHECK_OID)) {
3612                         ret = samldb_schema_attributeid_valid_check(ac);
3613                         if (ret != LDB_SUCCESS) {
3614                                 return ret;
3615                         }
3616
3617                         ret = samldb_schema_add_handle_linkid(ac);
3618                         if (ret != LDB_SUCCESS) {
3619                                 return ret;
3620                         }
3621
3622                         ret = samldb_schema_add_handle_mapiid(ac);
3623                         if (ret != LDB_SUCCESS) {
3624                                 return ret;
3625                         }
3626                 }
3627
3628                 ret = samldb_schema_ldapdisplayname_valid_check(ac);
3629                 if (ret != LDB_SUCCESS) {
3630                         return ret;
3631                 }
3632
3633                 ret = samldb_schema_info_update(ac);
3634                 if (ret != LDB_SUCCESS) {
3635                         talloc_free(ac);
3636                         return ret;
3637                 }
3638
3639                 return samldb_fill_object(ac);
3640         }
3641
3642         if (samdb_find_attribute(ldb, ac->msg,
3643                                  "objectclass", "subnet") != NULL) {
3644                 ret = samldb_verify_subnet(ac, ac->msg->dn);
3645                 if (ret != LDB_SUCCESS) {
3646                         talloc_free(ac);
3647                         return ret;
3648                 }
3649                 /* We are just checking the value is valid, and there are no
3650                    values to fill in. */
3651         }
3652
3653         talloc_free(ac);
3654
3655         /* nothing matched, go on */
3656         return ldb_next_request(module, req);
3657 }
3658
3659 /* modify */
3660 static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
3661 {
3662         struct ldb_context *ldb;
3663         struct samldb_ctx *ac;
3664         struct ldb_message_element *el, *el2;
3665         struct ldb_control *is_undelete;
3666         bool modified = false;
3667         int ret;
3668
3669         if (ldb_dn_is_special(req->op.mod.message->dn)) {
3670                 /* do not manipulate our control entries */
3671                 return ldb_next_request(module, req);
3672         }
3673
3674         ldb = ldb_module_get_ctx(module);
3675
3676         /*
3677          * we are going to need some special handling if in Undelete call.
3678          * Since tombstone_reanimate module will restore certain attributes,
3679          * we need to relax checks for: sAMAccountType, primaryGroupID
3680          */
3681         is_undelete = ldb_request_get_control(req, DSDB_CONTROL_RESTORE_TOMBSTONE_OID);
3682
3683         /* make sure that "objectSid" is not specified */
3684         el = ldb_msg_find_element(req->op.mod.message, "objectSid");
3685         if (el != NULL) {
3686                 if (ldb_request_get_control(req, LDB_CONTROL_PROVISION_OID) == NULL) {
3687                         ldb_set_errstring(ldb,
3688                                           "samldb: objectSid must not be specified!");
3689                         return LDB_ERR_UNWILLING_TO_PERFORM;
3690                 }
3691         }
3692         if (is_undelete == NULL) {
3693                 /* make sure that "sAMAccountType" is not specified */
3694                 el = ldb_msg_find_element(req->op.mod.message, "sAMAccountType");
3695                 if (el != NULL) {
3696                         ldb_set_errstring(ldb,
3697                                           "samldb: sAMAccountType must not be specified!");
3698                         return LDB_ERR_UNWILLING_TO_PERFORM;
3699                 }
3700         }
3701         /* make sure that "isCriticalSystemObject" is not specified */
3702         el = ldb_msg_find_element(req->op.mod.message, "isCriticalSystemObject");
3703         if (el != NULL) {
3704                 if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID) == NULL) {
3705                         ldb_set_errstring(ldb,
3706                                           "samldb: isCriticalSystemObject must not be specified!");
3707                         return LDB_ERR_UNWILLING_TO_PERFORM;
3708                 }
3709         }
3710
3711         /* msDS-IntId is not allowed to be modified
3712          * except when modification comes from replication */
3713         if (ldb_msg_find_element(req->op.mod.message, "msDS-IntId")) {
3714                 if (!ldb_request_get_control(req,
3715                                              DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
3716                         return LDB_ERR_CONSTRAINT_VIOLATION;
3717                 }
3718         }
3719
3720         el = ldb_msg_find_element(req->op.mod.message, "userParameters");
3721         if (el != NULL && ldb_req_is_untrusted(req)) {
3722                 const char *reason = "samldb: "
3723                         "setting userParameters is not supported over LDAP, "
3724                         "see https://bugzilla.samba.org/show_bug.cgi?id=8077";
3725                 ldb_debug(ldb, LDB_DEBUG_WARNING, "%s", reason);
3726                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, reason);
3727         }
3728
3729         ac = samldb_ctx_init(module, req);
3730         if (ac == NULL) {
3731                 return ldb_operr(ldb);
3732         }
3733
3734         /* build the new msg */
3735         ac->msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
3736         if (ac->msg == NULL) {
3737                 talloc_free(ac);
3738                 ldb_debug(ldb, LDB_DEBUG_FATAL,
3739                           "samldb_modify: ldb_msg_copy_shallow failed!\n");
3740                 return ldb_operr(ldb);
3741         }
3742
3743         if (is_undelete == NULL) {
3744                 el = ldb_msg_find_element(ac->msg, "primaryGroupID");
3745                 if (el != NULL) {
3746                         ret = samldb_prim_group_trigger(ac);
3747                         if (ret != LDB_SUCCESS) {
3748                                 return ret;
3749                         }
3750                 }
3751         }
3752
3753         el = ldb_msg_find_element(ac->msg, "userAccountControl");
3754         if (el != NULL) {
3755                 modified = true;
3756                 ret = samldb_user_account_control_change(ac);
3757                 if (ret != LDB_SUCCESS) {
3758                         return ret;
3759                 }
3760         }
3761
3762         el = ldb_msg_find_element(ac->msg, "pwdLastSet");
3763         if (el != NULL) {
3764                 modified = true;
3765                 ret = samldb_pwd_last_set_change(ac);
3766                 if (ret != LDB_SUCCESS) {
3767                         return ret;
3768                 }
3769         }
3770
3771         el = ldb_msg_find_element(ac->msg, "lockoutTime");
3772         if (el != NULL) {
3773                 modified = true;
3774                 ret = samldb_lockout_time(ac);
3775                 if (ret != LDB_SUCCESS) {
3776                         return ret;
3777                 }
3778         }
3779
3780         el = ldb_msg_find_element(ac->msg, "groupType");
3781         if (el != NULL) {
3782                 modified = true;
3783                 ret = samldb_group_type_change(ac);
3784                 if (ret != LDB_SUCCESS) {
3785                         return ret;
3786                 }
3787         }
3788
3789         el = ldb_msg_find_element(ac->msg, "sAMAccountName");
3790         if (el != NULL) {
3791                 ret = samldb_sam_accountname_valid_check(ac);
3792                 /*
3793                  * Other errors are checked for elsewhere, we just
3794                  * want to prevent duplicates
3795                  */
3796                 if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
3797                         return ret;
3798                 }
3799         }
3800
3801         el = ldb_msg_find_element(ac->msg, "ldapDisplayName");
3802         if (el != NULL) {
3803                 ret = samldb_schema_ldapdisplayname_valid_check(ac);
3804                 if (ret != LDB_SUCCESS) {
3805                         return ret;
3806                 }
3807         }
3808
3809         el = ldb_msg_find_element(ac->msg, "attributeID");
3810         if (el != NULL) {
3811                 ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
3812                                        "Once set, attributeID values may not be modified");
3813                 return LDB_ERR_CONSTRAINT_VIOLATION;
3814         }
3815
3816         el = ldb_msg_find_element(ac->msg, "governsID");
3817         if (el != NULL) {
3818                 ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
3819                                        "Once set, governsID values may not be modified");
3820                 return LDB_ERR_CONSTRAINT_VIOLATION;
3821         }
3822
3823         el = ldb_msg_find_element(ac->msg, "member");
3824         if (el != NULL) {
3825                 struct ldb_control *fix_link_sid_ctrl = NULL;
3826
3827                 fix_link_sid_ctrl = ldb_request_get_control(ac->req,
3828                                         DSDB_CONTROL_DBCHECK_FIX_LINK_DN_SID);
3829                 if (fix_link_sid_ctrl == NULL) {
3830                         ret = samldb_member_check(ac);
3831                         if (ret != LDB_SUCCESS) {
3832                                 return ret;
3833                         }
3834                 }
3835         }
3836
3837         el = ldb_msg_find_element(ac->msg, "description");
3838         if (el != NULL) {
3839                 ret = samldb_description_check(ac, &modified);
3840                 if (ret != LDB_SUCCESS) {
3841                         return ret;
3842                 }
3843         }
3844
3845         el = ldb_msg_find_element(ac->msg, "dNSHostName");
3846         el2 = ldb_msg_find_element(ac->msg, "sAMAccountName");
3847         if ((el != NULL) || (el2 != NULL)) {
3848                 modified = true;
3849                 ret = samldb_service_principal_names_change(ac);
3850                 if (ret != LDB_SUCCESS) {
3851                         return ret;
3852                 }
3853         }
3854
3855         el = ldb_msg_find_element(ac->msg, "fSMORoleOwner");
3856         if (el != NULL) {
3857                 ret = samldb_fsmo_role_owner_check(ac);
3858                 if (ret != LDB_SUCCESS) {
3859                         return ret;
3860                 }
3861         }
3862
3863         if (modified) {
3864                 struct ldb_request *child_req;
3865
3866                 /* Now perform the real modifications as a child request */
3867                 ret = ldb_build_mod_req(&child_req, ldb, ac,
3868                                         ac->msg,
3869                                         req->controls,
3870                                         req, dsdb_next_callback,
3871                                         req);
3872                 LDB_REQ_SET_LOCATION(child_req);
3873                 if (ret != LDB_SUCCESS) {
3874                         return ret;
3875                 }
3876
3877                 return ldb_next_request(module, child_req);
3878         }
3879
3880         talloc_free(ac);
3881
3882         /* no change which interests us, go on */
3883         return ldb_next_request(module, req);
3884 }
3885
3886 /* delete */
3887
3888 static int samldb_prim_group_users_check(struct samldb_ctx *ac)
3889 {
3890         struct ldb_context *ldb;
3891         struct dom_sid *sid;
3892         uint32_t rid;
3893         NTSTATUS status;
3894         int ret;
3895         struct ldb_result *res = NULL;
3896         struct ldb_result *res_users = NULL;
3897         const char * const attrs[] = { "objectSid", "isDeleted", NULL };
3898         const char * const noattrs[] = { NULL };
3899
3900         ldb = ldb_module_get_ctx(ac->module);
3901
3902         /* Finds out the SID/RID of the SAM object */
3903         ret = dsdb_module_search_dn(ac->module, ac, &res, ac->req->op.del.dn,
3904                                         attrs,
3905                                         DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED,
3906                                         ac->req);
3907         if (ret != LDB_SUCCESS) {
3908                 return ret;
3909         }
3910
3911         if (ldb_msg_check_string_attribute(res->msgs[0], "isDeleted", "TRUE")) {
3912                 return LDB_SUCCESS;
3913         }
3914
3915         sid = samdb_result_dom_sid(ac, res->msgs[0], "objectSid");
3916         if (sid == NULL) {
3917                 /* No SID - it might not be a SAM object - therefore ok */
3918                 return LDB_SUCCESS;
3919         }
3920         status = dom_sid_split_rid(ac, sid, NULL, &rid);
3921         if (!NT_STATUS_IS_OK(status)) {
3922                 return ldb_operr(ldb);
3923         }
3924         if (rid == 0) {
3925                 /* Special object (security principal?) */
3926                 return LDB_SUCCESS;
3927         }
3928         /* do not allow deletion of well-known sids */
3929         if (rid < DSDB_SAMDB_MINIMUM_ALLOWED_RID &&
3930             (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) == NULL)) {
3931                 return LDB_ERR_OTHER;
3932         }
3933
3934         /* Deny delete requests from groups which are primary ones */
3935         ret = dsdb_module_search(ac->module, ac, &res_users,
3936                                  ldb_get_default_basedn(ldb),
3937                                  LDB_SCOPE_SUBTREE, noattrs,
3938                                  DSDB_FLAG_NEXT_MODULE,
3939                                  ac->req,
3940                                  "(&(primaryGroupID=%u)(objectClass=user))", rid);
3941         if (ret != LDB_SUCCESS) {
3942                 return ret;
3943         }
3944         if (res_users->count > 0) {
3945                 ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
3946                                        "Refusing to delete %s, as it "
3947                                        "is still the primaryGroupID "
3948                                        "for %u users",
3949                                        ldb_dn_get_linearized(res->msgs[0]->dn),
3950                                        res_users->count);
3951
3952                 /*
3953                  * Yes, this seems very wrong, but we have a test
3954                  * for this exact error code in sam.py
3955                  */
3956                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
3957         }
3958
3959         return LDB_SUCCESS;
3960 }
3961
3962 static int samldb_delete(struct ldb_module *module, struct ldb_request *req)
3963 {
3964         struct samldb_ctx *ac;
3965         char *referral = NULL;
3966         int ret;
3967         struct ldb_context *ldb;
3968
3969         if (ldb_dn_is_special(req->op.del.dn)) {
3970                 /* do not manipulate our control entries */
3971                 return ldb_next_request(module, req);
3972         }
3973
3974         ldb = ldb_module_get_ctx(module);
3975
3976         referral = refer_if_rodc(ldb, req, req->op.del.dn);
3977         if (referral != NULL) {
3978                 ret = ldb_module_send_referral(req, referral);
3979                 return ret;
3980         }
3981
3982         ac = samldb_ctx_init(module, req);
3983         if (ac == NULL) {
3984                 return ldb_operr(ldb_module_get_ctx(module));
3985         }
3986
3987         ret = samldb_prim_group_users_check(ac);
3988         if (ret != LDB_SUCCESS) {
3989                 return ret;
3990         }
3991
3992         talloc_free(ac);
3993
3994         return ldb_next_request(module, req);
3995 }
3996
3997 /* rename */
3998
3999 static int check_rename_constraints(struct ldb_message *msg,
4000                                     struct samldb_ctx *ac,
4001                                     struct ldb_dn *olddn, struct ldb_dn *newdn)
4002 {
4003         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
4004         struct ldb_dn *dn1, *dn2, *nc_root;
4005         int32_t systemFlags;
4006         bool move_op = false;
4007         bool rename_op = false;
4008         int ret;
4009
4010         /* Skip the checks if old and new DN are the same, or if we have the
4011          * relax control specified or if the returned objects is already
4012          * deleted and needs only to be moved for consistency. */
4013
4014         if (ldb_dn_compare(olddn, newdn) == 0) {
4015                 return LDB_SUCCESS;
4016         }
4017         if (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) != NULL) {
4018                 return LDB_SUCCESS;
4019         }
4020
4021         if (ldb_msg_find_attr_as_bool(msg, "isDeleted", false)) {
4022                 /*
4023                  * check originating request if we are supposed
4024                  * to "see" this record in first place.
4025                  */
4026                 if (ldb_request_get_control(ac->req, LDB_CONTROL_SHOW_DELETED_OID) == NULL) {
4027                         return LDB_ERR_NO_SUCH_OBJECT;
4028                 }
4029                 return LDB_ERR_UNWILLING_TO_PERFORM;
4030         }
4031
4032         /* Objects under CN=System */
4033
4034         dn1 = ldb_dn_copy(ac, ldb_get_default_basedn(ldb));
4035         if (dn1 == NULL) return ldb_oom(ldb);
4036
4037         if ( ! ldb_dn_add_child_fmt(dn1, "CN=System")) {
4038                 talloc_free(dn1);
4039                 return LDB_ERR_OPERATIONS_ERROR;
4040         }
4041
4042         if ((ldb_dn_compare_base(dn1, olddn) == 0) &&
4043             (ldb_dn_compare_base(dn1, newdn) != 0)) {
4044                 talloc_free(dn1);
4045                 ldb_asprintf_errstring(ldb,
4046                                        "subtree_rename: Cannot move/rename %s. Objects under CN=System have to stay under it!",
4047                                        ldb_dn_get_linearized(olddn));
4048                 return LDB_ERR_OTHER;
4049         }
4050
4051         talloc_free(dn1);
4052
4053         /* LSA objects */
4054
4055         if ((samdb_find_attribute(ldb, msg, "objectClass", "secret") != NULL) ||
4056             (samdb_find_attribute(ldb, msg, "objectClass", "trustedDomain") != NULL)) {
4057                 ldb_asprintf_errstring(ldb,
4058                                        "subtree_rename: Cannot move/rename %s. It's an LSA-specific object!",
4059                                        ldb_dn_get_linearized(olddn));
4060                 return LDB_ERR_UNWILLING_TO_PERFORM;
4061         }
4062
4063         /* subnet objects */
4064         if (samdb_find_attribute(ldb, msg, "objectclass", "subnet") != NULL) {
4065                 ret = samldb_verify_subnet(ac, newdn);
4066                 if (ret != LDB_SUCCESS) {
4067                         talloc_free(ac);
4068                         return ret;
4069                 }
4070         }
4071
4072         /* systemFlags */
4073
4074         dn1 = ldb_dn_get_parent(ac, olddn);
4075         if (dn1 == NULL) return ldb_oom(ldb);
4076         dn2 = ldb_dn_get_parent(ac, newdn);
4077         if (dn2 == NULL) return ldb_oom(ldb);
4078
4079         if (ldb_dn_compare(dn1, dn2) == 0) {
4080                 rename_op = true;
4081         } else {
4082                 move_op = true;
4083         }
4084
4085         talloc_free(dn1);
4086         talloc_free(dn2);
4087
4088         systemFlags = ldb_msg_find_attr_as_int(msg, "systemFlags", 0);
4089
4090         /* Fetch name context */
4091
4092         ret = dsdb_find_nc_root(ldb, ac, olddn, &nc_root);
4093         if (ret != LDB_SUCCESS) {
4094                 return ret;
4095         }
4096
4097         if (ldb_dn_compare(nc_root, ldb_get_schema_basedn(ldb)) == 0) {
4098                 if (move_op) {
4099                         ldb_asprintf_errstring(ldb,
4100                                                "subtree_rename: Cannot move %s within schema partition",
4101                                                ldb_dn_get_linearized(olddn));
4102                         return LDB_ERR_UNWILLING_TO_PERFORM;
4103                 }
4104                 if (rename_op &&
4105                     (systemFlags & SYSTEM_FLAG_SCHEMA_BASE_OBJECT) != 0) {
4106                         ldb_asprintf_errstring(ldb,
4107                                                "subtree_rename: Cannot rename %s within schema partition",
4108                                                ldb_dn_get_linearized(olddn));
4109                         return LDB_ERR_UNWILLING_TO_PERFORM;
4110                 }
4111         } else if (ldb_dn_compare(nc_root, ldb_get_config_basedn(ldb)) == 0) {
4112                 if (move_op &&
4113                     (systemFlags & SYSTEM_FLAG_CONFIG_ALLOW_MOVE) == 0) {
4114                         /* Here we have to do more: control the
4115                          * "ALLOW_LIMITED_MOVE" flag. This means that the
4116                          * grand-grand-parents of two objects have to be equal
4117                          * in order to perform the move (this is used for
4118                          * moving "server" objects in the "sites" container). */
4119                         bool limited_move =
4120                                 systemFlags & SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE;
4121
4122                         if (limited_move) {
4123                                 dn1 = ldb_dn_copy(ac, olddn);
4124                                 if (dn1 == NULL) return ldb_oom(ldb);
4125                                 dn2 = ldb_dn_copy(ac, newdn);
4126                                 if (dn2 == NULL) return ldb_oom(ldb);
4127
4128                                 limited_move &= ldb_dn_remove_child_components(dn1, 3);
4129                                 limited_move &= ldb_dn_remove_child_components(dn2, 3);
4130                                 limited_move &= ldb_dn_compare(dn1, dn2) == 0;
4131
4132                                 talloc_free(dn1);
4133                                 talloc_free(dn2);
4134                         }
4135
4136                         if (!limited_move
4137                             && ldb_request_get_control(ac->req, DSDB_CONTROL_RESTORE_TOMBSTONE_OID) == NULL) {
4138                                 ldb_asprintf_errstring(ldb,
4139                                                        "subtree_rename: Cannot move %s to %s in config partition",
4140                                                        ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn));
4141                                 return LDB_ERR_UNWILLING_TO_PERFORM;
4142                         }
4143                 }
4144                 if (rename_op &&
4145                     (systemFlags & SYSTEM_FLAG_CONFIG_ALLOW_RENAME) == 0) {
4146                         ldb_asprintf_errstring(ldb,
4147                                                "subtree_rename: Cannot rename %s to %s within config partition",
4148                                                ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn));
4149                         return LDB_ERR_UNWILLING_TO_PERFORM;
4150                 }
4151         } else if (ldb_dn_compare(nc_root, ldb_get_default_basedn(ldb)) == 0) {
4152                 if (move_op &&
4153                     (systemFlags & SYSTEM_FLAG_DOMAIN_DISALLOW_MOVE) != 0) {
4154                         ldb_asprintf_errstring(ldb,
4155                                                "subtree_rename: Cannot move %s to %s - DISALLOW_MOVE set",
4156                                                ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn));
4157                         return LDB_ERR_UNWILLING_TO_PERFORM;
4158                 }
4159                 if (rename_op &&
4160                     (systemFlags & SYSTEM_FLAG_DOMAIN_DISALLOW_RENAME) != 0) {
4161                         ldb_asprintf_errstring(ldb,
4162                                                        "subtree_rename: Cannot rename %s to %s - DISALLOW_RENAME set",
4163                                                ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn));
4164                         return LDB_ERR_UNWILLING_TO_PERFORM;
4165                 }
4166         }
4167
4168         talloc_free(nc_root);
4169
4170         return LDB_SUCCESS;
4171 }
4172
4173
4174 static int samldb_rename_search_base_callback(struct ldb_request *req,
4175                                                struct ldb_reply *ares)
4176 {
4177         struct samldb_ctx *ac;
4178         int ret;
4179
4180         ac = talloc_get_type(req->context, struct samldb_ctx);
4181
4182         if (!ares) {
4183                 return ldb_module_done(ac->req, NULL, NULL,
4184                                         LDB_ERR_OPERATIONS_ERROR);
4185         }
4186         if (ares->error != LDB_SUCCESS) {
4187                 return ldb_module_done(ac->req, ares->controls,
4188                                         ares->response, ares->error);
4189         }
4190
4191         switch (ares->type) {
4192         case LDB_REPLY_ENTRY:
4193                 /*
4194                  * This is the root entry of the originating move
4195                  * respectively rename request. It has been already
4196                  * stored in the list using "subtree_rename_search()".
4197                  * Only this one is subject to constraint checking.
4198                  */
4199                 ret = check_rename_constraints(ares->message, ac,
4200                                                ac->req->op.rename.olddn,
4201                                                ac->req->op.rename.newdn);
4202                 if (ret != LDB_SUCCESS) {
4203                         return ldb_module_done(ac->req, NULL, NULL,
4204                                                ret);
4205                 }
4206                 break;
4207
4208         case LDB_REPLY_REFERRAL:
4209                 /* ignore */
4210                 break;
4211
4212         case LDB_REPLY_DONE:
4213
4214                 /*
4215                  * Great, no problem with the rename, so go ahead as
4216                  * if we never were here
4217                  */
4218                 ret = ldb_next_request(ac->module, ac->req);
4219                 talloc_free(ares);
4220                 return ret;
4221         }
4222
4223         talloc_free(ares);
4224         return LDB_SUCCESS;
4225 }
4226
4227
4228 /* rename */
4229 static int samldb_rename(struct ldb_module *module, struct ldb_request *req)
4230 {
4231         struct ldb_context *ldb;
4232         static const char * const attrs[] = { "objectClass", "systemFlags",
4233                                               "isDeleted", NULL };
4234         struct ldb_request *search_req;
4235         struct samldb_ctx *ac;
4236         int ret;
4237
4238         if (ldb_dn_is_special(req->op.rename.olddn)) { /* do not manipulate our control entries */
4239                 return ldb_next_request(module, req);
4240         }
4241
4242         ldb = ldb_module_get_ctx(module);
4243
4244         ac = samldb_ctx_init(module, req);
4245         if (!ac) {
4246                 return ldb_oom(ldb);
4247         }
4248
4249         ret = ldb_build_search_req(&search_req, ldb, ac,
4250                                    req->op.rename.olddn,
4251                                    LDB_SCOPE_BASE,
4252                                    "(objectClass=*)",
4253                                    attrs,
4254                                    NULL,
4255                                    ac,
4256                                    samldb_rename_search_base_callback,
4257                                    req);
4258         LDB_REQ_SET_LOCATION(search_req);
4259         if (ret != LDB_SUCCESS) {
4260                 return ret;
4261         }
4262
4263         ret = ldb_request_add_control(search_req, LDB_CONTROL_SHOW_RECYCLED_OID,
4264                                       true, NULL);
4265         if (ret != LDB_SUCCESS) {
4266                 return ret;
4267         }
4268
4269         return ldb_next_request(ac->module, search_req);
4270 }
4271
4272 /* extended */
4273
4274 static int samldb_extended_allocate_rid_pool(struct ldb_module *module, struct ldb_request *req)
4275 {
4276         struct ldb_context *ldb = ldb_module_get_ctx(module);
4277         struct dsdb_fsmo_extended_op *exop;
4278         int ret;
4279
4280         exop = talloc_get_type(req->op.extended.data,
4281                                struct dsdb_fsmo_extended_op);
4282         if (!exop) {
4283                 ldb_set_errstring(ldb,
4284                                   "samldb_extended_allocate_rid_pool: invalid extended data");
4285                 return LDB_ERR_PROTOCOL_ERROR;
4286         }
4287
4288         ret = ridalloc_allocate_rid_pool_fsmo(module, exop, req);
4289         if (ret != LDB_SUCCESS) {
4290                 return ret;
4291         }
4292
4293         return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
4294 }
4295
4296 static int samldb_extended_allocate_rid(struct ldb_module *module, struct ldb_request *req)
4297 {
4298         struct ldb_context *ldb = ldb_module_get_ctx(module);
4299         struct dsdb_extended_allocate_rid *exop;
4300         int ret;
4301
4302         exop = talloc_get_type(req->op.extended.data,
4303                                struct dsdb_extended_allocate_rid);
4304         if (!exop) {
4305                 ldb_set_errstring(ldb,
4306                                   "samldb_extended_allocate_rid: invalid extended data");
4307                 return LDB_ERR_PROTOCOL_ERROR;
4308         }
4309
4310         ret = ridalloc_allocate_rid(module, &exop->rid, req);
4311         if (ret != LDB_SUCCESS) {
4312                 return ret;
4313         }
4314
4315         return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
4316 }
4317
4318 static int samldb_extended_create_own_rid_set(struct ldb_module *module, struct ldb_request *req)
4319 {
4320         struct ldb_context *ldb = ldb_module_get_ctx(module);
4321         int ret;
4322         struct ldb_dn *dn;
4323
4324         if (req->op.extended.data != NULL) {
4325                 ldb_set_errstring(ldb,
4326                                   "samldb_extended_allocate_rid_pool_for_us: invalid extended data (should be NULL)");
4327                 return LDB_ERR_PROTOCOL_ERROR;
4328         }
4329
4330         ret = ridalloc_create_own_rid_set(module, req,
4331                                           &dn, req);
4332         if (ret != LDB_SUCCESS) {
4333                 return ret;
4334         }
4335
4336         return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
4337 }
4338
4339 static int samldb_extended(struct ldb_module *module, struct ldb_request *req)
4340 {
4341         if (strcmp(req->op.extended.oid, DSDB_EXTENDED_ALLOCATE_RID_POOL) == 0) {
4342                 return samldb_extended_allocate_rid_pool(module, req);
4343         }
4344
4345         if (strcmp(req->op.extended.oid, DSDB_EXTENDED_ALLOCATE_RID) == 0) {
4346                 return samldb_extended_allocate_rid(module, req);
4347         }
4348
4349         if (strcmp(req->op.extended.oid, DSDB_EXTENDED_CREATE_OWN_RID_SET) == 0) {
4350                 return samldb_extended_create_own_rid_set(module, req);
4351         }
4352
4353         return ldb_next_request(module, req);
4354 }
4355
4356
4357 static const struct ldb_module_ops ldb_samldb_module_ops = {
4358         .name          = "samldb",
4359         .add           = samldb_add,
4360         .modify        = samldb_modify,
4361         .del           = samldb_delete,
4362         .rename        = samldb_rename,
4363         .extended      = samldb_extended
4364 };
4365
4366
4367 int ldb_samldb_module_init(const char *version)
4368 {
4369         LDB_MODULE_CHECK_VERSION(version);
4370         return ldb_register_module(&ldb_samldb_module_ops);
4371 }