CVE-2020-25722 s4/dsdb/samldb _user_account_control_change() always add final value
[samba.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 #include "lib/util/smb_strtox.h"
49
50 #undef strcasecmp
51
52 struct samldb_ctx;
53 enum samldb_add_type {
54         SAMLDB_TYPE_USER,
55         SAMLDB_TYPE_GROUP,
56         SAMLDB_TYPE_CLASS,
57         SAMLDB_TYPE_ATTRIBUTE
58 };
59
60 typedef int (*samldb_step_fn_t)(struct samldb_ctx *);
61
62 struct samldb_step {
63         struct samldb_step *next;
64         samldb_step_fn_t fn;
65 };
66
67 struct samldb_ctx {
68         struct ldb_module *module;
69         struct ldb_request *req;
70
71         /* used for add operations */
72         enum samldb_add_type type;
73
74         /*
75          * should we apply the need_trailing_dollar restriction to
76          * samAccountName
77          */
78
79         bool need_trailing_dollar;
80
81         /* the resulting message */
82         struct ldb_message *msg;
83
84         /* used in "samldb_find_for_defaultObjectCategory" */
85         struct ldb_dn *dn, *res_dn;
86
87         /* all the async steps necessary to complete the operation */
88         struct samldb_step *steps;
89         struct samldb_step *curstep;
90
91         /* If someone set an ares to forward controls and response back to the caller */
92         struct ldb_reply *ares;
93 };
94
95 static struct samldb_ctx *samldb_ctx_init(struct ldb_module *module,
96                                           struct ldb_request *req)
97 {
98         struct ldb_context *ldb;
99         struct samldb_ctx *ac;
100
101         ldb = ldb_module_get_ctx(module);
102
103         ac = talloc_zero(req, struct samldb_ctx);
104         if (ac == NULL) {
105                 ldb_oom(ldb);
106                 return NULL;
107         }
108
109         ac->module = module;
110         ac->req = req;
111
112         return ac;
113 }
114
115 static int samldb_add_step(struct samldb_ctx *ac, samldb_step_fn_t fn)
116 {
117         struct samldb_step *step, *stepper;
118
119         step = talloc_zero(ac, struct samldb_step);
120         if (step == NULL) {
121                 return ldb_oom(ldb_module_get_ctx(ac->module));
122         }
123
124         step->fn = fn;
125
126         if (ac->steps == NULL) {
127                 ac->steps = step;
128                 ac->curstep = step;
129         } else {
130                 if (ac->curstep == NULL)
131                         return ldb_operr(ldb_module_get_ctx(ac->module));
132                 for (stepper = ac->curstep; stepper->next != NULL;
133                         stepper = stepper->next);
134                 stepper->next = step;
135         }
136
137         return LDB_SUCCESS;
138 }
139
140 static int samldb_first_step(struct samldb_ctx *ac)
141 {
142         if (ac->steps == NULL) {
143                 return ldb_operr(ldb_module_get_ctx(ac->module));
144         }
145
146         ac->curstep = ac->steps;
147         return ac->curstep->fn(ac);
148 }
149
150 static int samldb_next_step(struct samldb_ctx *ac)
151 {
152         if (ac->curstep->next) {
153                 ac->curstep = ac->curstep->next;
154                 return ac->curstep->fn(ac);
155         }
156
157         /* We exit the samldb module here. If someone set an "ares" to forward
158          * controls and response back to the caller, use them. */
159         if (ac->ares) {
160                 return ldb_module_done(ac->req, ac->ares->controls,
161                                        ac->ares->response, LDB_SUCCESS);
162         } else {
163                 return ldb_module_done(ac->req, NULL, NULL, LDB_SUCCESS);
164         }
165 }
166
167 static int samldb_get_single_valued_attr(struct ldb_context *ldb,
168                                          struct samldb_ctx *ac,
169                                          const char *attr,
170                                          const char **value)
171 {
172         /*
173          * The steps we end up going through to get and check a single valued
174          * attribute.
175          */
176         struct ldb_message_element *el = NULL;
177         int ret;
178
179         *value = NULL;
180
181         ret = dsdb_get_expected_new_values(ac,
182                                            ac->msg,
183                                            attr,
184                                            &el,
185                                            ac->req->operation);
186
187         if (ret != LDB_SUCCESS) {
188                 return ret;
189         }
190         if (el == NULL) {
191                 /* we are not affected */
192                 return LDB_SUCCESS;
193         }
194
195         if (el->num_values > 1) {
196                 ldb_asprintf_errstring(
197                         ldb,
198                         "samldb: %s has %u values, should be single-valued!",
199                         attr, el->num_values);
200                 return LDB_ERR_CONSTRAINT_VIOLATION;
201         } else if (el->num_values == 0) {
202                 ldb_asprintf_errstring(
203                         ldb,
204                         "samldb: new value for %s "
205                         "not provided for mandatory, single-valued attribute!",
206                         attr);
207                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
208         }
209
210
211         if (el->values[0].length == 0) {
212                 ldb_asprintf_errstring(
213                         ldb,
214                         "samldb: %s is of zero length, should have a value!",
215                         attr);
216                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
217         }
218
219         *value = (char *)el->values[0].data;
220
221         return LDB_SUCCESS;
222 }
223
224 static int samldb_unique_attr_check(struct samldb_ctx *ac, const char *attr,
225                                     const char *attr_conflict,
226                                     struct ldb_dn *base_dn)
227 {
228         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
229         const char * const no_attrs[] = { NULL };
230         struct ldb_result *res = NULL;
231         const char *str = NULL;
232         const char *enc_str = NULL;
233         int ret;
234
235         ret = samldb_get_single_valued_attr(ldb, ac, attr, &str);
236         if (ret != LDB_SUCCESS) {
237                 return ret;
238         }
239         if (str == NULL) {
240                 /* the attribute wasn't found */
241                 return LDB_SUCCESS;
242         }
243
244         enc_str = ldb_binary_encode_string(ac, str);
245         if (enc_str == NULL) {
246                 return ldb_module_oom(ac->module);
247         }
248
249         /*
250          * No other object should have the attribute with this value.
251          */
252         if (attr_conflict != NULL) {
253                 ret = dsdb_module_search(ac->module, ac, &res,
254                                          base_dn,
255                                          LDB_SCOPE_SUBTREE, no_attrs,
256                                          DSDB_FLAG_NEXT_MODULE, ac->req,
257                                          "(|(%s=%s)(%s=%s))",
258                                          attr, enc_str,
259                                          attr_conflict, enc_str);
260         } else {
261                 ret = dsdb_module_search(ac->module, ac, &res,
262                                          base_dn,
263                                          LDB_SCOPE_SUBTREE, no_attrs,
264                                          DSDB_FLAG_NEXT_MODULE, ac->req,
265                                          "(%s=%s)", attr, enc_str);
266         }
267         if (ret != LDB_SUCCESS) {
268                 return ret;
269         }
270         if (res->count > 1) {
271                 return ldb_operr(ldb);
272         } else if (res->count == 1) {
273                 if (ldb_dn_compare(res->msgs[0]->dn, ac->msg->dn) != 0) {
274                         ldb_asprintf_errstring(ldb,
275                                                "samldb: %s '%s' already in use!",
276                                                attr, enc_str);
277                         return LDB_ERR_ENTRY_ALREADY_EXISTS;
278                 }
279         }
280         talloc_free(res);
281
282         return LDB_SUCCESS;
283 }
284
285
286
287 static inline int samldb_sam_account_upn_clash_sub_search(
288         struct samldb_ctx *ac,
289         TALLOC_CTX *mem_ctx,
290         struct ldb_dn *base_dn,
291         const char *attr,
292         const char *value,
293         const char *err_msg
294         )
295 {
296         /*
297          * A very specific helper function for samldb_sam_account_upn_clash(),
298          * where we end up doing this same thing several times in a row.
299          */
300         const char * const no_attrs[] = { NULL };
301         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
302         struct ldb_result *res = NULL;
303         int ret;
304         char *enc_value = ldb_binary_encode_string(ac, value);
305         if (enc_value == NULL) {
306                 return ldb_module_oom(ac->module);
307         }
308         ret = dsdb_module_search(ac->module, mem_ctx, &res,
309                                  base_dn,
310                                  LDB_SCOPE_SUBTREE, no_attrs,
311                                  DSDB_FLAG_NEXT_MODULE, ac->req,
312                                  "(%s=%s)",
313                                  attr, enc_value);
314         talloc_free(enc_value);
315
316         if (ret != LDB_SUCCESS) {
317                 return ret;
318         } else if (res->count > 1) {
319                 return ldb_operr(ldb);
320         } else if (res->count == 1) {
321                 if (ldb_dn_compare(res->msgs[0]->dn, ac->msg->dn) != 0){
322                         ldb_asprintf_errstring(ldb,
323                                                "samldb: %s '%s' "
324                                                "is already in use %s",
325                                                attr, value, err_msg);
326                         /* different errors for different attrs */
327                         if (strcasecmp("userPrincipalName", attr) == 0) {
328                                 return LDB_ERR_CONSTRAINT_VIOLATION;
329                         }
330                         return LDB_ERR_ENTRY_ALREADY_EXISTS;
331                 }
332         }
333         return LDB_SUCCESS;
334 }
335
336 static int samaccountname_bad_chars_check(struct samldb_ctx *ac,
337                                           const char *name)
338 {
339         /*
340          * The rules here are based on
341          *
342          * https://social.technet.microsoft.com/wiki/contents/articles/11216.active-directory-requirements-for-creating-objects.aspx
343          *
344          * Windows considers UTF-8 sequences that map to "similar" characters
345          * (e.g. 'a', 'ā') to be the same sAMAccountName, and we don't. Names
346          * that are not valid UTF-8 *are* allowed.
347          *
348          * Additionally, Samba collapses multiple spaces, and Windows doesn't.
349          */
350         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
351         size_t i;
352
353         for (i = 0; name[i] != '\0'; i++) {
354                 uint8_t c = name[i];
355                 char *p = NULL;
356                 if (c < 32 || c == 127) {
357                         ldb_asprintf_errstring(
358                                 ldb,
359                                 "samldb: sAMAccountName contains invalid "
360                                 "0x%.2x character\n", c);
361                         return LDB_ERR_CONSTRAINT_VIOLATION;
362                 }
363                 p = strchr("\"[]:;|=+*?<>/\\,", c);
364                 if (p != NULL) {
365                         ldb_asprintf_errstring(
366                                 ldb,
367                                 "samldb: sAMAccountName contains invalid "
368                                 "'%c' character\n", c);
369                         return LDB_ERR_CONSTRAINT_VIOLATION;
370                 }
371         }
372
373         if (i == 0) {
374                 ldb_asprintf_errstring(
375                         ldb,
376                         "samldb: sAMAccountName is empty\n");
377                 return LDB_ERR_CONSTRAINT_VIOLATION;
378         }
379
380         if (name[i - 1] == '.') {
381                 ldb_asprintf_errstring(
382                         ldb,
383                         "samldb: sAMAccountName ends with '.'");
384                 return LDB_ERR_CONSTRAINT_VIOLATION;
385         }
386         return LDB_SUCCESS;
387 }
388
389 static int samldb_sam_account_upn_clash(struct samldb_ctx *ac)
390 {
391         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
392         int ret;
393         struct ldb_dn *base_dn = ldb_get_default_basedn(ldb);
394         TALLOC_CTX *tmp_ctx = NULL;
395         const char *real_sam = NULL;
396         const char *real_upn = NULL;
397         char *implied_sam = NULL;
398         char *implied_upn = NULL;
399         const char *realm = NULL;
400
401         ret = samldb_get_single_valued_attr(ldb, ac,
402                                             "sAMAccountName",
403                                             &real_sam);
404         if (ret != LDB_SUCCESS) {
405                 return ret;
406         }
407         ret = samldb_get_single_valued_attr(ldb, ac,
408                                             "userPrincipalName",
409                                             &real_upn);
410         if (ret != LDB_SUCCESS) {
411                 return ret;
412         }
413         if (real_upn == NULL && real_sam == NULL) {
414                 /* Not changing these things, so we're done */
415                 return LDB_SUCCESS;
416         }
417
418         tmp_ctx = talloc_new(ac);
419         realm = samdb_dn_to_dns_domain(tmp_ctx, base_dn);
420         if (realm == NULL) {
421                 talloc_free(tmp_ctx);
422                 return ldb_operr(ldb);
423         }
424
425         if (real_upn != NULL) {
426                 /*
427                  * note we take the last @ in the upn because the first (i.e.
428                  * sAMAccountName equivalent) part can contain @.
429                  *
430                  * It is also OK (per Windows) for a UPN to have zero @s.
431                  */
432                 char *at = NULL;
433                 char *upn_realm = NULL;
434                 implied_sam = talloc_strdup(tmp_ctx, real_upn);
435                 if (implied_sam == NULL) {
436                         talloc_free(tmp_ctx);
437                         return ldb_module_oom(ac->module);
438                 }
439
440                 at = strrchr(implied_sam, '@');
441                 if (at == NULL) {
442                         /*
443                          * there is no @ in this UPN, so we treat the whole
444                          * thing as a sAMAccountName for the purposes of a
445                          * clash.
446                          */
447                         DBG_INFO("samldb: userPrincipalName '%s' contains "
448                                  "no '@' character\n", implied_sam);
449                 } else {
450                         /*
451                          * Now, this upn only implies a sAMAccountName if the
452                          * realm is our realm. So we need to compare the tail
453                          * of the upn to the realm.
454                          */
455                         *at = '\0';
456                         upn_realm = at + 1;
457                         if (strcasecmp(upn_realm, realm) != 0) {
458                                 /* implied_sam is not the implied
459                                  * sAMAccountName after all, because it is
460                                  * from a different realm. */
461                                 TALLOC_FREE(implied_sam);
462                         }
463                 }
464         }
465
466         if (real_sam != NULL) {
467                 implied_upn = talloc_asprintf(tmp_ctx, "%s@%s",
468                                               real_sam, realm);
469                 if (implied_upn == NULL) {
470                         talloc_free(tmp_ctx);
471                         return ldb_module_oom(ac->module);
472                 }
473         }
474
475         /*
476          * Now we have all of the actual and implied names, in which to search
477          * for conflicts.
478          */
479         if (real_sam != NULL) {
480                 ret = samldb_sam_account_upn_clash_sub_search(
481                         ac, tmp_ctx, base_dn, "sAMAccountName",
482                         real_sam, "");
483
484                 if (ret != LDB_SUCCESS) {
485                         talloc_free(tmp_ctx);
486                         return ret;
487                 }
488                 ret = samaccountname_bad_chars_check(ac, real_sam);
489                 if (ret != LDB_SUCCESS) {
490                         talloc_free(tmp_ctx);
491                         return ret;
492                 }
493         }
494         if (implied_upn != NULL) {
495                 ret = samldb_sam_account_upn_clash_sub_search(
496                         ac, tmp_ctx, base_dn, "userPrincipalName", implied_upn,
497                         "(implied by sAMAccountName)");
498
499                 if (ret != LDB_SUCCESS) {
500                         talloc_free(tmp_ctx);
501                         return ret;
502                 }
503         }
504         if (real_upn != NULL) {
505                 ret = samldb_sam_account_upn_clash_sub_search(
506                         ac, tmp_ctx, base_dn, "userPrincipalName",
507                         real_upn, "");
508
509                 if (ret != LDB_SUCCESS) {
510                         talloc_free(tmp_ctx);
511                         return ret;
512                 }
513         }
514         if (implied_sam != NULL) {
515                 ret = samldb_sam_account_upn_clash_sub_search(
516                         ac, tmp_ctx, base_dn, "sAMAccountName", implied_sam,
517                         "(implied by userPrincipalName)");
518                 if (ret != LDB_SUCCESS) {
519                         talloc_free(tmp_ctx);
520                         return ret;
521                 }
522         }
523
524         talloc_free(tmp_ctx);
525         return LDB_SUCCESS;
526 }
527
528
529 /* This is run during an add or modify */
530 static int samldb_sam_accountname_valid_check(struct samldb_ctx *ac)
531 {
532         int ret = 0;
533         bool is_admin;
534         struct security_token *user_token = NULL;
535         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
536         struct ldb_message_element *el = NULL;
537
538         ret = dsdb_get_expected_new_values(ac,
539                                            ac->msg,
540                                            "samAccountName",
541                                            &el,
542                                            ac->req->operation);
543         if (ret != LDB_SUCCESS) {
544                 return ret;
545         }
546
547         if (el == NULL || el->num_values == 0) {
548                 ldb_asprintf_errstring(ldb,
549                         "%08X: samldb: 'samAccountName' can't be deleted/empty!",
550                         W_ERROR_V(WERR_DS_ILLEGAL_MOD_OPERATION));
551                 if (ac->req->operation == LDB_ADD) {
552                         return LDB_ERR_CONSTRAINT_VIOLATION;
553                 } else {
554                         return LDB_ERR_UNWILLING_TO_PERFORM;
555                 }
556         }
557
558         ret = samldb_unique_attr_check(ac, "samAccountName", NULL,
559                                        ldb_get_default_basedn(
560                                                ldb_module_get_ctx(ac->module)));
561
562         /*
563          * Error code munging to try and match what must be some quite
564          * strange code-paths in Windows
565          */
566         if (ret == LDB_ERR_CONSTRAINT_VIOLATION
567             && ac->req->operation == LDB_MODIFY) {
568                 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
569         } else if (ret == LDB_ERR_OBJECT_CLASS_VIOLATION) {
570                 ret = LDB_ERR_CONSTRAINT_VIOLATION;
571         }
572         if (ret != LDB_SUCCESS) {
573                 return ret;
574         }
575
576         ret = samldb_sam_account_upn_clash(ac);
577         if (ret != LDB_SUCCESS) {
578                 return ret;
579         }
580
581         if (!ac->need_trailing_dollar) {
582                 return LDB_SUCCESS;
583         }
584
585         /* This does not permit a single $ */
586         if (el->values[0].length < 2) {
587                 ldb_asprintf_errstring(ldb,
588                                        "%08X: samldb: 'samAccountName' "
589                                        "can't just be one character!",
590                         W_ERROR_V(WERR_DS_ILLEGAL_MOD_OPERATION));
591                 return LDB_ERR_UNWILLING_TO_PERFORM;
592         }
593
594         user_token = acl_user_token(ac->module);
595         if (user_token == NULL) {
596                 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
597         }
598
599         is_admin
600                 = security_token_has_builtin_administrators(user_token);
601
602         if (is_admin) {
603                 /*
604                  * Administrators are allowed to select strange names.
605                  * This is poor practice but not prevented.
606                  */
607                 return false;
608         }
609
610         if (el->values[0].data[el->values[0].length - 1] != '$') {
611                 ldb_asprintf_errstring(ldb,
612                                        "%08X: samldb: 'samAccountName' "
613                                        "must have a trailing $!",
614                         W_ERROR_V(WERR_DS_ILLEGAL_MOD_OPERATION));
615                 return LDB_ERR_UNWILLING_TO_PERFORM;
616         }
617         if (el->values[0].data[el->values[0].length - 2] == '$') {
618                 ldb_asprintf_errstring(ldb,
619                                        "%08X: samldb: 'samAccountName' "
620                                        "must not have a double trailing $!",
621                         W_ERROR_V(WERR_DS_ILLEGAL_MOD_OPERATION));
622                 return LDB_ERR_UNWILLING_TO_PERFORM;
623         }
624
625         return ret;
626 }
627
628 static int samldb_schema_attributeid_valid_check(struct samldb_ctx *ac)
629 {
630         int ret = samldb_unique_attr_check(ac, "attributeID", "governsID",
631                                            ldb_get_schema_basedn(
632                                                    ldb_module_get_ctx(ac->module)));
633         if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
634                 ret = LDB_ERR_UNWILLING_TO_PERFORM;
635         }
636         return ret;
637 }
638
639 static int samldb_schema_governsid_valid_check(struct samldb_ctx *ac)
640 {
641         int ret = samldb_unique_attr_check(ac, "governsID", "attributeID",
642                                            ldb_get_schema_basedn(
643                                                    ldb_module_get_ctx(ac->module)));
644         if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
645                 ret = LDB_ERR_UNWILLING_TO_PERFORM;
646         }
647         return ret;
648 }
649
650 static int samldb_schema_ldapdisplayname_valid_check(struct samldb_ctx *ac)
651 {
652         int ret = samldb_unique_attr_check(ac, "lDAPDisplayName", NULL,
653                                            ldb_get_schema_basedn(
654                                                    ldb_module_get_ctx(ac->module)));
655         if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
656                 ret = LDB_ERR_UNWILLING_TO_PERFORM;
657         }
658         return ret;
659 }
660
661 static int samldb_check_linkid_used(struct samldb_ctx *ac,
662                                     struct dsdb_schema *schema,
663                                     struct ldb_dn *schema_dn,
664                                     struct ldb_context *ldb,
665                                     int32_t linkID,
666                                     bool *found)
667 {
668         int ret;
669         struct ldb_result *ldb_res;
670
671         if (dsdb_attribute_by_linkID(schema, linkID)) {
672                 *found = true;
673                 return LDB_SUCCESS;
674         }
675
676         ret = dsdb_module_search(ac->module, ac,
677                                  &ldb_res,
678                                  schema_dn, LDB_SCOPE_ONELEVEL, NULL,
679                                  DSDB_FLAG_NEXT_MODULE,
680                                  ac->req,
681                                  "(linkID=%d)", linkID);
682         if (ret != LDB_SUCCESS) {
683                 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
684                               __location__": Searching for linkID=%d failed - %s\n",
685                               linkID,
686                               ldb_errstring(ldb));
687                 return ldb_operr(ldb);
688         }
689
690         *found = (ldb_res->count != 0);
691         talloc_free(ldb_res);
692
693         return LDB_SUCCESS;
694 }
695
696 /* Find the next open forward linkID in the schema. */
697 static int samldb_generate_next_linkid(struct samldb_ctx *ac,
698                                        struct dsdb_schema *schema,
699                                        int32_t *next_linkID)
700 {
701         int ret;
702         struct ldb_context *ldb;
703         struct ldb_dn *schema_dn;
704         bool linkID_used = true;
705
706         /*
707          * Windows starts at about 0xB0000000 in order to stop potential
708          * collisions with future additions to the schema. We pass this
709          * around as a signed int sometimes, but this should be sufficient.
710          */
711         *next_linkID = 0x40000000;
712
713         ldb = ldb_module_get_ctx(ac->module);
714         schema_dn = ldb_get_schema_basedn(ldb);
715
716         while (linkID_used) {
717                 *next_linkID += 2;
718                 ret = samldb_check_linkid_used(ac, schema,
719                                                schema_dn, ldb,
720                                                *next_linkID, &linkID_used);
721                 if (ret != LDB_SUCCESS) {
722                         return ret;
723                 }
724         }
725
726         return LDB_SUCCESS;
727 }
728
729 static int samldb_schema_add_handle_linkid(struct samldb_ctx *ac)
730 {
731         int ret;
732         bool ok, found = false;
733         struct ldb_message_element *el;
734         const char *enc_str;
735         const struct dsdb_attribute *attr;
736         struct ldb_context *ldb;
737         struct ldb_dn *schema_dn;
738         struct dsdb_schema *schema;
739         int32_t new_linkID = 0;
740
741         ldb = ldb_module_get_ctx(ac->module);
742         schema = dsdb_get_schema(ldb, ac);
743         schema_dn = ldb_get_schema_basedn(ldb);
744
745         ret = dsdb_get_expected_new_values(ac,
746                                            ac->msg,
747                                            "linkID",
748                                            &el,
749                                            ac->req->operation);
750         if (ret != LDB_SUCCESS) {
751                 return ret;
752         }
753
754         if (el == NULL) {
755                 return LDB_SUCCESS;
756         }
757
758         enc_str = ldb_binary_encode(ac, el->values[0]);
759         if (enc_str == NULL) {
760                 return ldb_module_oom(ac->module);
761         }
762
763         ok = (strcmp(enc_str, "0") == 0);
764         if (ok) {
765                 return LDB_SUCCESS;
766         }
767
768         /*
769          * This OID indicates that the caller wants the linkID
770          * to be automatically generated. We therefore assign
771          * it the next open linkID.
772          */
773         ok = (strcmp(enc_str, "1.2.840.113556.1.2.50") == 0);
774         if (ok) {
775                 ret = samldb_generate_next_linkid(ac, schema, &new_linkID);
776                 if (ret != LDB_SUCCESS) {
777                         return ret;
778                 }
779
780                 ldb_msg_remove_element(ac->msg, el);
781                 ret = samdb_msg_add_int(ldb, ac->msg, ac->msg, "linkID",
782                                         new_linkID);
783                 return ret;
784         }
785
786         /*
787          * Using either the attributeID or lDAPDisplayName of
788          * another attribute in the linkID field indicates that
789          * we should make this the backlink of that attribute.
790          */
791         attr = dsdb_attribute_by_attributeID_oid(schema, enc_str);
792         if (attr == NULL) {
793                 attr = dsdb_attribute_by_lDAPDisplayName(schema, enc_str);
794         }
795
796         if (attr != NULL) {
797                 /*
798                  * The attribute we're adding this as a backlink of must
799                  * be a forward link.
800                  */
801                 if (attr->linkID % 2 != 0) {
802                         return LDB_ERR_UNWILLING_TO_PERFORM;
803                 }
804
805                 new_linkID = attr->linkID + 1;
806
807                 /* Make sure that this backlink doesn't already exist. */
808                 ret = samldb_check_linkid_used(ac, schema,
809                                                schema_dn, ldb,
810                                                new_linkID, &found);
811                 if (ret != LDB_SUCCESS) {
812                         return ret;
813                 }
814
815                 if (found) {
816                         return LDB_ERR_UNWILLING_TO_PERFORM;
817                 }
818
819                 ldb_msg_remove_element(ac->msg, el);
820                 ret = samdb_msg_add_int(ldb, ac->msg, ac->msg, "linkID",
821                                         new_linkID);
822                 return ret;
823         }
824
825         schema_dn = ldb_get_schema_basedn(ldb_module_get_ctx(ac->module));
826         ret = samldb_unique_attr_check(ac, "linkID", NULL, schema_dn);
827         if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
828                 return LDB_ERR_UNWILLING_TO_PERFORM;
829         } else {
830                 return ret;
831         }
832 }
833
834 static int samldb_check_mapiid_used(struct samldb_ctx *ac,
835                                     struct dsdb_schema *schema,
836                                     struct ldb_dn *schema_dn,
837                                     struct ldb_context *ldb,
838                                     int32_t mapiid,
839                                     bool *found)
840 {
841         int ret;
842         struct ldb_result *ldb_res;
843
844         ret = dsdb_module_search(ac->module, ac,
845                                  &ldb_res,
846                                  schema_dn, LDB_SCOPE_ONELEVEL, NULL,
847                                  DSDB_FLAG_NEXT_MODULE,
848                                  ac->req,
849                                  "(mAPIID=%d)", mapiid);
850         if (ret != LDB_SUCCESS) {
851                 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
852                               __location__": Searching for mAPIID=%d failed - %s\n",
853                               mapiid,
854                               ldb_errstring(ldb));
855                 return ldb_operr(ldb);
856         }
857
858         *found = (ldb_res->count != 0);
859         talloc_free(ldb_res);
860
861         return LDB_SUCCESS;
862 }
863
864 static int samldb_generate_next_mapiid(struct samldb_ctx *ac,
865                                        struct dsdb_schema *schema,
866                                        int32_t *next_mapiid)
867 {
868         int ret;
869         struct ldb_context *ldb;
870         struct ldb_dn *schema_dn;
871         bool mapiid_used = true;
872
873         /* Windows' generation seems to start about here */
874         *next_mapiid = 60000;
875
876         ldb = ldb_module_get_ctx(ac->module);
877         schema_dn = ldb_get_schema_basedn(ldb);
878
879         while (mapiid_used) {
880                 *next_mapiid += 1;
881                 ret = samldb_check_mapiid_used(ac, schema,
882                                                schema_dn, ldb,
883                                                *next_mapiid, &mapiid_used);
884                 if (ret != LDB_SUCCESS) {
885                         return ret;
886                 }
887         }
888
889         return LDB_SUCCESS;
890 }
891
892 static int samldb_schema_add_handle_mapiid(struct samldb_ctx *ac)
893 {
894         int ret;
895         bool ok;
896         struct ldb_message_element *el;
897         const char *enc_str;
898         struct ldb_context *ldb;
899         struct ldb_dn *schema_dn;
900         struct dsdb_schema *schema;
901         int32_t new_mapiid = 0;
902
903         /*
904          * The mAPIID of a new attribute should be automatically generated
905          * if a specific OID is put as the mAPIID, as according to
906          * [MS-ADTS] 3.1.1.2.3.2.
907          */
908
909         ldb = ldb_module_get_ctx(ac->module);
910         schema = dsdb_get_schema(ldb, ac);
911         schema_dn = ldb_get_schema_basedn(ldb);
912
913         ret = dsdb_get_expected_new_values(ac,
914                                            ac->msg,
915                                            "mAPIID",
916                                            &el,
917                                            ac->req->operation);
918         if (ret != LDB_SUCCESS) {
919                 return ret;
920         }
921
922         if (el == NULL) {
923                 return LDB_SUCCESS;
924         }
925
926         enc_str = ldb_binary_encode(ac, el->values[0]);
927         if (enc_str == NULL) {
928                 return ldb_module_oom(ac->module);
929         }
930
931         ok = (strcmp(enc_str, "1.2.840.113556.1.2.49") == 0);
932         if (ok) {
933                 ret = samldb_generate_next_mapiid(ac, schema,
934                                                   &new_mapiid);
935                 if (ret != LDB_SUCCESS) {
936                         return ret;
937                 }
938
939                 ldb_msg_remove_element(ac->msg, el);
940                 ret = samdb_msg_add_int(ldb, ac->msg, ac->msg,
941                                         "mAPIID", new_mapiid);
942                 return ret;
943         }
944
945         schema_dn = ldb_get_schema_basedn(ldb_module_get_ctx(ac->module));
946         ret = samldb_unique_attr_check(ac, "mAPIID", NULL, schema_dn);
947         if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
948                 return LDB_ERR_UNWILLING_TO_PERFORM;
949         } else {
950                 return ret;
951         }
952 }
953
954 /* sAMAccountName handling */
955 static int samldb_generate_sAMAccountName(struct samldb_ctx *ac,
956                                           struct ldb_message *msg)
957 {
958         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
959         char *name;
960
961         /*
962          * This is currently a Samba-only behaviour, to add a trailing
963          * $ even for the generated accounts.
964          */
965
966         if (ac->need_trailing_dollar) {
967                 /* Format: $000000-00000000000$ */
968                 name = talloc_asprintf(msg, "$%.6X-%.6X%.5X$",
969                                        (unsigned int)generate_random(),
970                                        (unsigned int)generate_random(),
971                                        (unsigned int)generate_random());
972         } else {
973                 /* Format: $000000-000000000000 */
974
975                 name = talloc_asprintf(msg, "$%.6X-%.6X%.6X",
976                                        (unsigned int)generate_random(),
977                                        (unsigned int)generate_random(),
978                                        (unsigned int)generate_random());
979         }
980         if (name == NULL) {
981                 return ldb_oom(ldb);
982         }
983         return ldb_msg_add_steal_string(msg, "sAMAccountName", name);
984 }
985
986 static int samldb_check_sAMAccountName(struct samldb_ctx *ac)
987 {
988         int ret;
989
990         if (ldb_msg_find_element(ac->msg, "sAMAccountName") == NULL) {
991                 ret = samldb_generate_sAMAccountName(ac, ac->msg);
992                 if (ret != LDB_SUCCESS) {
993                         return ret;
994                 }
995         }
996
997         ret = samldb_sam_accountname_valid_check(ac);
998         if (ret != LDB_SUCCESS) {
999                 return ret;
1000         }
1001
1002         return samldb_next_step(ac);
1003 }
1004
1005
1006 static bool samldb_msg_add_sid(struct ldb_message *msg,
1007                                 const char *name,
1008                                 const struct dom_sid *sid)
1009 {
1010         struct ldb_val v;
1011         enum ndr_err_code ndr_err;
1012
1013         ndr_err = ndr_push_struct_blob(&v, msg, sid,
1014                                        (ndr_push_flags_fn_t)ndr_push_dom_sid);
1015         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1016                 return false;
1017         }
1018         return (ldb_msg_add_value(msg, name, &v, NULL) == 0);
1019 }
1020
1021
1022 /* allocate a SID using our RID Set */
1023 static int samldb_allocate_sid(struct samldb_ctx *ac)
1024 {
1025         uint32_t rid;
1026         struct dom_sid *sid;
1027         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1028         int ret;
1029
1030         ret = ridalloc_allocate_rid(ac->module, &rid, ac->req);
1031         if (ret != LDB_SUCCESS) {
1032                 return ret;
1033         }
1034
1035         sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
1036         if (sid == NULL) {
1037                 return ldb_module_oom(ac->module);
1038         }
1039
1040         if ( ! samldb_msg_add_sid(ac->msg, "objectSid", sid)) {
1041                 return ldb_operr(ldb);
1042         }
1043
1044         return samldb_next_step(ac);
1045 }
1046
1047 /*
1048   see if a krbtgt_number is available
1049  */
1050 static bool samldb_krbtgtnumber_available(struct samldb_ctx *ac,
1051                                           uint32_t krbtgt_number)
1052 {
1053         TALLOC_CTX *tmp_ctx = talloc_new(ac);
1054         struct ldb_result *res;
1055         const char * const no_attrs[] = { NULL };
1056         int ret;
1057
1058         ret = dsdb_module_search(ac->module, tmp_ctx, &res,
1059                                  ldb_get_default_basedn(ldb_module_get_ctx(ac->module)),
1060                                  LDB_SCOPE_SUBTREE, no_attrs,
1061                                  DSDB_FLAG_NEXT_MODULE,
1062                                  ac->req,
1063                                  "(msDS-SecondaryKrbTgtNumber=%u)",
1064                                  krbtgt_number);
1065         if (ret == LDB_SUCCESS && res->count == 0) {
1066                 talloc_free(tmp_ctx);
1067                 return true;
1068         }
1069         talloc_free(tmp_ctx);
1070         return false;
1071 }
1072
1073 /* special handling for add in RODC join */
1074 static int samldb_rodc_add(struct samldb_ctx *ac)
1075 {
1076         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1077         uint32_t krbtgt_number, i_start, i;
1078         int ret;
1079         struct ldb_val newpass_utf16;
1080
1081         /* find a unused msDS-SecondaryKrbTgtNumber */
1082         i_start = generate_random() & 0xFFFF;
1083         if (i_start == 0) {
1084                 i_start = 1;
1085         }
1086
1087         for (i=i_start; i<=0xFFFF; i++) {
1088                 if (samldb_krbtgtnumber_available(ac, i)) {
1089                         krbtgt_number = i;
1090                         goto found;
1091                 }
1092         }
1093         for (i=1; i<i_start; i++) {
1094                 if (samldb_krbtgtnumber_available(ac, i)) {
1095                         krbtgt_number = i;
1096                         goto found;
1097                 }
1098         }
1099
1100         ldb_asprintf_errstring(ldb,
1101                                "%08X: Unable to find available msDS-SecondaryKrbTgtNumber",
1102                                W_ERROR_V(WERR_NO_SYSTEM_RESOURCES));
1103         return LDB_ERR_OTHER;
1104
1105 found:
1106         ret = ldb_msg_add_empty(ac->msg, "msDS-SecondaryKrbTgtNumber",
1107                                 LDB_FLAG_INTERNAL_DISABLE_VALIDATION, NULL);
1108         if (ret != LDB_SUCCESS) {
1109                 return ldb_operr(ldb);
1110         }
1111
1112         ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
1113                                  "msDS-SecondaryKrbTgtNumber", krbtgt_number);
1114         if (ret != LDB_SUCCESS) {
1115                 return ldb_operr(ldb);
1116         }
1117
1118         ret = ldb_msg_add_fmt(ac->msg, "sAMAccountName", "krbtgt_%u",
1119                               krbtgt_number);
1120         if (ret != LDB_SUCCESS) {
1121                 return ldb_operr(ldb);
1122         }
1123
1124         newpass_utf16 = data_blob_talloc_zero(ac->module, 256);
1125         if (newpass_utf16.data == NULL) {
1126                 return ldb_oom(ldb);
1127         }
1128         /*
1129          * Note that the password_hash module will ignore
1130          * this value and use it's own generate_secret_buffer()
1131          * that's why we can just use generate_random_buffer()
1132          * here.
1133          */
1134         generate_random_buffer(newpass_utf16.data, newpass_utf16.length);
1135         ret = ldb_msg_add_steal_value(ac->msg, "clearTextPassword", &newpass_utf16);
1136         if (ret != LDB_SUCCESS) {
1137                 return ldb_operr(ldb);
1138         }
1139
1140         return samldb_next_step(ac);
1141 }
1142
1143 static int samldb_find_for_defaultObjectCategory(struct samldb_ctx *ac)
1144 {
1145         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1146         struct ldb_result *res;
1147         const char * const no_attrs[] = { NULL };
1148         int ret;
1149
1150         ac->res_dn = NULL;
1151
1152         ret = dsdb_module_search(ac->module, ac, &res,
1153                                  ac->dn, LDB_SCOPE_BASE, no_attrs,
1154                                  DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT
1155                                  | DSDB_FLAG_NEXT_MODULE,
1156                                  ac->req,
1157                                  "(objectClass=classSchema)");
1158         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1159                 /* Don't be pricky when the DN doesn't exist if we have the */
1160                 /* RELAX control specified */
1161                 if (ldb_request_get_control(ac->req,
1162                                             LDB_CONTROL_RELAX_OID) == NULL) {
1163                         ldb_set_errstring(ldb,
1164                                           "samldb_find_defaultObjectCategory: "
1165                                           "Invalid DN for 'defaultObjectCategory'!");
1166                         return LDB_ERR_CONSTRAINT_VIOLATION;
1167                 }
1168         }
1169         if ((ret != LDB_ERR_NO_SUCH_OBJECT) && (ret != LDB_SUCCESS)) {
1170                 return ret;
1171         }
1172
1173         if (ret == LDB_SUCCESS) {
1174                 /* ensure the defaultObjectCategory has a full GUID */
1175                 struct ldb_message *m;
1176                 m = ldb_msg_new(ac->msg);
1177                 if (m == NULL) {
1178                         return ldb_oom(ldb);
1179                 }
1180                 m->dn = ac->msg->dn;
1181                 if (ldb_msg_add_string(m, "defaultObjectCategory",
1182                                        ldb_dn_get_extended_linearized(m, res->msgs[0]->dn, 1)) !=
1183                     LDB_SUCCESS) {
1184                         return ldb_oom(ldb);
1185                 }
1186                 m->elements[0].flags = LDB_FLAG_MOD_REPLACE;
1187
1188                 ret = dsdb_module_modify(ac->module, m,
1189                                          DSDB_FLAG_NEXT_MODULE,
1190                                          ac->req);
1191                 if (ret != LDB_SUCCESS) {
1192                         return ret;
1193                 }
1194         }
1195
1196
1197         ac->res_dn = ac->dn;
1198
1199         return samldb_next_step(ac);
1200 }
1201
1202 /**
1203  * msDS-IntId attributeSchema attribute handling
1204  * during LDB_ADD request processing
1205  */
1206 static int samldb_add_handle_msDS_IntId(struct samldb_ctx *ac)
1207 {
1208         int ret;
1209         bool id_exists;
1210         uint32_t msds_intid;
1211         int32_t system_flags;
1212         struct ldb_context *ldb;
1213         struct ldb_result *ldb_res;
1214         struct ldb_dn *schema_dn;
1215         struct samldb_msds_intid_persistant *msds_intid_struct;
1216         struct dsdb_schema *schema;
1217
1218         ldb = ldb_module_get_ctx(ac->module);
1219         schema_dn = ldb_get_schema_basedn(ldb);
1220
1221         /* replicated update should always go through */
1222         if (ldb_request_get_control(ac->req,
1223                                     DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
1224                 return LDB_SUCCESS;
1225         }
1226
1227         /* msDS-IntId is handled by system and should never be
1228          * passed by clients */
1229         if (ldb_msg_find_element(ac->msg, "msDS-IntId")) {
1230                 return LDB_ERR_UNWILLING_TO_PERFORM;
1231         }
1232
1233         /* do not generate msDS-IntId if Relax control is passed */
1234         if (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
1235                 return LDB_SUCCESS;
1236         }
1237
1238         /* check Functional Level */
1239         if (dsdb_functional_level(ldb) < DS_DOMAIN_FUNCTION_2003) {
1240                 return LDB_SUCCESS;
1241         }
1242
1243         /* check systemFlags for SCHEMA_BASE_OBJECT flag */
1244         system_flags = ldb_msg_find_attr_as_int(ac->msg, "systemFlags", 0);
1245         if (system_flags & SYSTEM_FLAG_SCHEMA_BASE_OBJECT) {
1246                 return LDB_SUCCESS;
1247         }
1248         schema = dsdb_get_schema(ldb, NULL);
1249         if (!schema) {
1250                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
1251                               "samldb_schema_info_update: no dsdb_schema loaded");
1252                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
1253                 return ldb_operr(ldb);
1254         }
1255
1256         msds_intid_struct = (struct samldb_msds_intid_persistant*) ldb_get_opaque(ldb, SAMLDB_MSDS_INTID_OPAQUE);
1257         if (!msds_intid_struct) {
1258                 msds_intid_struct = talloc(ldb, struct samldb_msds_intid_persistant);
1259                 /* Generate new value for msDs-IntId
1260                 * Value should be in 0x80000000..0xBFFFFFFF range */
1261                 msds_intid = generate_random() % 0X3FFFFFFF;
1262                 msds_intid += 0x80000000;
1263                 msds_intid_struct->msds_intid = msds_intid;
1264                 DEBUG(2, ("No samldb_msds_intid_persistant struct, allocating a new one\n"));
1265         } else {
1266                 msds_intid = msds_intid_struct->msds_intid;
1267         }
1268
1269         /* probe id values until unique one is found */
1270         do {
1271                 msds_intid++;
1272                 if (msds_intid > 0xBFFFFFFF) {
1273                         msds_intid = 0x80000001;
1274                 }
1275                 /*
1276                  * We search in the schema if we have already this
1277                  * intid (using dsdb_attribute_by_attributeID_id
1278                  * because in the range 0x80000000 0xBFFFFFFFF,
1279                  * attributeID is a DSDB_ATTID_TYPE_INTID).
1280                  *
1281                  * If so generate another random value.
1282                  *
1283                  * We have to check the DB in case someone else has
1284                  * modified the database while we are doing our
1285                  * changes too (this case should be very bery rare) in
1286                  * order to be sure.
1287                  */
1288                 if (dsdb_attribute_by_attributeID_id(schema, msds_intid)) {
1289                         id_exists = true;
1290                         msds_intid = generate_random() % 0X3FFFFFFF;
1291                         msds_intid += 0x80000000;
1292                         continue;
1293                 }
1294
1295
1296                 ret = dsdb_module_search(ac->module, ac,
1297                                          &ldb_res,
1298                                          schema_dn, LDB_SCOPE_ONELEVEL, NULL,
1299                                          DSDB_FLAG_NEXT_MODULE,
1300                                          ac->req,
1301                                          "(msDS-IntId=%d)", msds_intid);
1302                 if (ret != LDB_SUCCESS) {
1303                         ldb_debug_set(ldb, LDB_DEBUG_ERROR,
1304                                       __location__": Searching for msDS-IntId=%d failed - %s\n",
1305                                       msds_intid,
1306                                       ldb_errstring(ldb));
1307                         return ldb_operr(ldb);
1308                 }
1309                 id_exists = (ldb_res->count > 0);
1310                 talloc_free(ldb_res);
1311
1312         } while(id_exists);
1313         msds_intid_struct->msds_intid = msds_intid;
1314         ldb_set_opaque(ldb, SAMLDB_MSDS_INTID_OPAQUE, msds_intid_struct);
1315
1316         return samdb_msg_add_int(ldb, ac->msg, ac->msg, "msDS-IntId",
1317                                  msds_intid);
1318 }
1319
1320
1321 /*
1322  * samldb_add_entry (async)
1323  */
1324
1325 static int samldb_add_entry_callback(struct ldb_request *req,
1326                                         struct ldb_reply *ares)
1327 {
1328         struct ldb_context *ldb;
1329         struct samldb_ctx *ac;
1330         int ret;
1331
1332         ac = talloc_get_type(req->context, struct samldb_ctx);
1333         ldb = ldb_module_get_ctx(ac->module);
1334
1335         if (!ares) {
1336                 return ldb_module_done(ac->req, NULL, NULL,
1337                                         LDB_ERR_OPERATIONS_ERROR);
1338         }
1339
1340         if (ares->type == LDB_REPLY_REFERRAL) {
1341                 return ldb_module_send_referral(ac->req, ares->referral);
1342         }
1343
1344         if (ares->error != LDB_SUCCESS) {
1345                 return ldb_module_done(ac->req, ares->controls,
1346                                         ares->response, ares->error);
1347         }
1348         if (ares->type != LDB_REPLY_DONE) {
1349                 ldb_asprintf_errstring(ldb, "Invalid LDB reply type %d", ares->type);
1350                 return ldb_module_done(ac->req, NULL, NULL,
1351                                         LDB_ERR_OPERATIONS_ERROR);
1352         }
1353
1354         /* The caller may wish to get controls back from the add */
1355         ac->ares = talloc_steal(ac, ares);
1356
1357         ret = samldb_next_step(ac);
1358         if (ret != LDB_SUCCESS) {
1359                 return ldb_module_done(ac->req, NULL, NULL, ret);
1360         }
1361         return ret;
1362 }
1363
1364 static int samldb_add_entry(struct samldb_ctx *ac)
1365 {
1366         struct ldb_context *ldb;
1367         struct ldb_request *req;
1368         int ret;
1369
1370         ldb = ldb_module_get_ctx(ac->module);
1371
1372         ret = ldb_build_add_req(&req, ldb, ac,
1373                                 ac->msg,
1374                                 ac->req->controls,
1375                                 ac, samldb_add_entry_callback,
1376                                 ac->req);
1377         LDB_REQ_SET_LOCATION(req);
1378         if (ret != LDB_SUCCESS) {
1379                 return ret;
1380         }
1381
1382         return ldb_next_request(ac->module, req);
1383 }
1384
1385 /*
1386  * return true if msg carries an attributeSchema that is intended to be RODC
1387  * filtered but is also a system-critical attribute.
1388  */
1389 static bool check_rodc_critical_attribute(struct ldb_message *msg)
1390 {
1391         uint32_t schemaFlagsEx, searchFlags, rodc_filtered_flags;
1392
1393         schemaFlagsEx = ldb_msg_find_attr_as_uint(msg, "schemaFlagsEx", 0);
1394         searchFlags = ldb_msg_find_attr_as_uint(msg, "searchFlags", 0);
1395         rodc_filtered_flags = (SEARCH_FLAG_RODC_ATTRIBUTE
1396                               | SEARCH_FLAG_CONFIDENTIAL);
1397
1398         if ((schemaFlagsEx & SCHEMA_FLAG_ATTR_IS_CRITICAL) &&
1399                 ((searchFlags & rodc_filtered_flags) == rodc_filtered_flags)) {
1400                 return true;
1401         } else {
1402                 return false;
1403         }
1404 }
1405
1406
1407 static int samldb_fill_object(struct samldb_ctx *ac)
1408 {
1409         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1410         int ret;
1411
1412         /* Add information for the different account types */
1413         switch(ac->type) {
1414         case SAMLDB_TYPE_USER: {
1415                 struct ldb_control *rodc_control = ldb_request_get_control(ac->req,
1416                                                                            LDB_CONTROL_RODC_DCPROMO_OID);
1417                 if (rodc_control != NULL) {
1418                         /* see [MS-ADTS] 3.1.1.3.4.1.23 LDAP_SERVER_RODC_DCPROMO_OID */
1419                         rodc_control->critical = false;
1420                         ret = samldb_add_step(ac, samldb_rodc_add);
1421                         if (ret != LDB_SUCCESS) return ret;
1422                 }
1423
1424                 /* check if we have a valid sAMAccountName */
1425                 ret = samldb_add_step(ac, samldb_check_sAMAccountName);
1426                 if (ret != LDB_SUCCESS) return ret;
1427
1428                 ret = samldb_add_step(ac, samldb_add_entry);
1429                 if (ret != LDB_SUCCESS) return ret;
1430                 break;
1431         }
1432
1433         case SAMLDB_TYPE_GROUP: {
1434                 /* check if we have a valid sAMAccountName */
1435                 ret = samldb_add_step(ac, samldb_check_sAMAccountName);
1436                 if (ret != LDB_SUCCESS) return ret;
1437
1438                 ret = samldb_add_step(ac, samldb_add_entry);
1439                 if (ret != LDB_SUCCESS) return ret;
1440                 break;
1441         }
1442
1443         case SAMLDB_TYPE_CLASS: {
1444                 const char *lDAPDisplayName = NULL;
1445                 const struct ldb_val *rdn_value, *def_obj_cat_val;
1446                 unsigned int v = ldb_msg_find_attr_as_uint(ac->msg, "objectClassCategory", -2);
1447
1448                 /* As discussed with Microsoft through dochelp in April 2012 this is the behavior of windows*/
1449                 if (!ldb_msg_find_element(ac->msg, "subClassOf")) {
1450                         ret = ldb_msg_add_string(ac->msg, "subClassOf", "top");
1451                         if (ret != LDB_SUCCESS) return ret;
1452                 }
1453
1454                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
1455                                                   "rdnAttId", "cn");
1456                 if (ret != LDB_SUCCESS) return ret;
1457
1458                 /* do not allow one to mark an attributeSchema as RODC filtered if it
1459                  * is system-critical */
1460                 if (check_rodc_critical_attribute(ac->msg)) {
1461                         ldb_asprintf_errstring(ldb, "Refusing schema add of %s - cannot combine critical class with RODC filtering",
1462                                                ldb_dn_get_linearized(ac->msg->dn));
1463                         return LDB_ERR_UNWILLING_TO_PERFORM;
1464                 }
1465
1466                 rdn_value = ldb_dn_get_rdn_val(ac->msg->dn);
1467                 if (rdn_value == NULL) {
1468                         return ldb_operr(ldb);
1469                 }
1470                 if (!ldb_msg_find_element(ac->msg, "lDAPDisplayName")) {
1471                         /* the RDN has prefix "CN" */
1472                         ret = ldb_msg_add_string(ac->msg, "lDAPDisplayName",
1473                                 samdb_cn_to_lDAPDisplayName(ac->msg,
1474                                                             (const char *) rdn_value->data));
1475                         if (ret != LDB_SUCCESS) {
1476                                 ldb_oom(ldb);
1477                                 return ret;
1478                         }
1479                 }
1480
1481                 lDAPDisplayName = ldb_msg_find_attr_as_string(ac->msg,
1482                                                               "lDAPDisplayName",
1483                                                               NULL);
1484                 ret = ldb_valid_attr_name(lDAPDisplayName);
1485                 if (ret != 1 ||
1486                     lDAPDisplayName[0] == '*' ||
1487                     lDAPDisplayName[0] == '@')
1488                 {
1489                         return dsdb_module_werror(ac->module,
1490                                                   LDB_ERR_UNWILLING_TO_PERFORM,
1491                                                   WERR_DS_INVALID_LDAP_DISPLAY_NAME,
1492                                                   "lDAPDisplayName is invalid");
1493                 }
1494
1495                 if (!ldb_msg_find_element(ac->msg, "schemaIDGUID")) {
1496                         struct GUID guid;
1497                         /* a new GUID */
1498                         guid = GUID_random();
1499                         ret = dsdb_msg_add_guid(ac->msg, &guid, "schemaIDGUID");
1500                         if (ret != LDB_SUCCESS) {
1501                                 ldb_oom(ldb);
1502                                 return ret;
1503                         }
1504                 }
1505
1506                 def_obj_cat_val = ldb_msg_find_ldb_val(ac->msg,
1507                                                        "defaultObjectCategory");
1508                 if (def_obj_cat_val != NULL) {
1509                         /* "defaultObjectCategory" has been set by the caller.
1510                          * Do some checks for consistency.
1511                          * NOTE: The real constraint check (that
1512                          * 'defaultObjectCategory' is the DN of the new
1513                          * objectclass or any parent of it) is still incomplete.
1514                          * For now we say that 'defaultObjectCategory' is valid
1515                          * if it exists and it is of objectclass "classSchema".
1516                          */
1517                         ac->dn = ldb_dn_from_ldb_val(ac, ldb, def_obj_cat_val);
1518                         if (ac->dn == NULL) {
1519                                 ldb_set_errstring(ldb,
1520                                                   "Invalid DN for 'defaultObjectCategory'!");
1521                                 return LDB_ERR_CONSTRAINT_VIOLATION;
1522                         }
1523                 } else {
1524                         /* "defaultObjectCategory" has not been set by the
1525                          * caller. Use the entry DN for it. */
1526                         ac->dn = ac->msg->dn;
1527
1528                         ret = ldb_msg_add_string(ac->msg, "defaultObjectCategory",
1529                                                  ldb_dn_alloc_linearized(ac->msg, ac->dn));
1530                         if (ret != LDB_SUCCESS) {
1531                                 ldb_oom(ldb);
1532                                 return ret;
1533                         }
1534                 }
1535
1536                 ret = samldb_add_step(ac, samldb_add_entry);
1537                 if (ret != LDB_SUCCESS) return ret;
1538
1539                 /* Now perform the checks for the 'defaultObjectCategory'. The
1540                  * lookup DN was already saved in "ac->dn" */
1541                 ret = samldb_add_step(ac, samldb_find_for_defaultObjectCategory);
1542                 if (ret != LDB_SUCCESS) return ret;
1543
1544                 /* -2 is not a valid objectClassCategory so it means the attribute wasn't present */
1545                 if (v == -2) {
1546                         /* Windows 2003 does this*/
1547                         ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "objectClassCategory", 0);
1548                         if (ret != LDB_SUCCESS) {
1549                                 return ret;
1550                         }
1551                 }
1552                 break;
1553         }
1554
1555         case SAMLDB_TYPE_ATTRIBUTE: {
1556                 const char *lDAPDisplayName = NULL;
1557                 const struct ldb_val *rdn_value;
1558                 struct ldb_message_element *el;
1559                 rdn_value = ldb_dn_get_rdn_val(ac->msg->dn);
1560                 if (rdn_value == NULL) {
1561                         return ldb_operr(ldb);
1562                 }
1563                 if (!ldb_msg_find_element(ac->msg, "lDAPDisplayName")) {
1564                         /* the RDN has prefix "CN" */
1565                         ret = ldb_msg_add_string(ac->msg, "lDAPDisplayName",
1566                                 samdb_cn_to_lDAPDisplayName(ac->msg,
1567                                                             (const char *) rdn_value->data));
1568                         if (ret != LDB_SUCCESS) {
1569                                 ldb_oom(ldb);
1570                                 return ret;
1571                         }
1572                 }
1573
1574                 lDAPDisplayName = ldb_msg_find_attr_as_string(ac->msg,
1575                                                               "lDAPDisplayName",
1576                                                               NULL);
1577                 ret = ldb_valid_attr_name(lDAPDisplayName);
1578                 if (ret != 1 ||
1579                     lDAPDisplayName[0] == '*' ||
1580                     lDAPDisplayName[0] == '@')
1581                 {
1582                         return dsdb_module_werror(ac->module,
1583                                                   LDB_ERR_UNWILLING_TO_PERFORM,
1584                                                   WERR_DS_INVALID_LDAP_DISPLAY_NAME,
1585                                                   "lDAPDisplayName is invalid");
1586                 }
1587
1588                 /* do not allow one to mark an attributeSchema as RODC filtered if it
1589                  * is system-critical */
1590                 if (check_rodc_critical_attribute(ac->msg)) {
1591                         ldb_asprintf_errstring(ldb,
1592                                                "samldb: refusing schema add of %s - cannot combine critical attribute with RODC filtering",
1593                                                ldb_dn_get_linearized(ac->msg->dn));
1594                         return LDB_ERR_UNWILLING_TO_PERFORM;
1595                 }
1596
1597                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
1598                                                   "isSingleValued", "FALSE");
1599                 if (ret != LDB_SUCCESS) return ret;
1600
1601                 if (!ldb_msg_find_element(ac->msg, "schemaIDGUID")) {
1602                         struct GUID guid;
1603                         /* a new GUID */
1604                         guid = GUID_random();
1605                         ret = dsdb_msg_add_guid(ac->msg, &guid, "schemaIDGUID");
1606                         if (ret != LDB_SUCCESS) {
1607                                 ldb_oom(ldb);
1608                                 return ret;
1609                         }
1610                 }
1611
1612                 el = ldb_msg_find_element(ac->msg, "attributeSyntax");
1613                 if (el) {
1614                         /*
1615                          * No need to scream if there isn't as we have code later on
1616                          * that will take care of it.
1617                          */
1618                         const struct dsdb_syntax *syntax = find_syntax_map_by_ad_oid((const char *)el->values[0].data);
1619                         if (!syntax) {
1620                                 DEBUG(9, ("Can't find dsdb_syntax object for attributeSyntax %s\n",
1621                                                 (const char *)el->values[0].data));
1622                         } else {
1623                                 unsigned int v = ldb_msg_find_attr_as_uint(ac->msg, "oMSyntax", 0);
1624                                 const struct ldb_val *val = ldb_msg_find_ldb_val(ac->msg, "oMObjectClass");
1625
1626                                 if (v == 0) {
1627                                         ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "oMSyntax", syntax->oMSyntax);
1628                                         if (ret != LDB_SUCCESS) {
1629                                                 return ret;
1630                                         }
1631                                 }
1632                                 if (!val) {
1633                                         struct ldb_val val2 = ldb_val_dup(ldb, &syntax->oMObjectClass);
1634                                         if (val2.length > 0) {
1635                                                 ret = ldb_msg_add_value(ac->msg, "oMObjectClass", &val2, NULL);
1636                                                 if (ret != LDB_SUCCESS) {
1637                                                         return ret;
1638                                                 }
1639                                         }
1640                                 }
1641                         }
1642                 }
1643
1644                 /* handle msDS-IntID attribute */
1645                 ret = samldb_add_handle_msDS_IntId(ac);
1646                 if (ret != LDB_SUCCESS) return ret;
1647
1648                 ret = samldb_add_step(ac, samldb_add_entry);
1649                 if (ret != LDB_SUCCESS) return ret;
1650                 break;
1651         }
1652
1653         default:
1654                 ldb_asprintf_errstring(ldb, "Invalid entry type!");
1655                 return LDB_ERR_OPERATIONS_ERROR;
1656                 break;
1657         }
1658
1659         return samldb_first_step(ac);
1660 }
1661
1662 static int samldb_fill_foreignSecurityPrincipal_object(struct samldb_ctx *ac)
1663 {
1664         struct ldb_context *ldb = NULL;
1665         const struct ldb_val *rdn_value = NULL;
1666         struct ldb_message_element *sid_el = NULL;
1667         struct dom_sid *sid = NULL;
1668         struct ldb_control *as_system = NULL;
1669         struct ldb_control *provision = NULL;
1670         bool allowed = false;
1671         int ret;
1672
1673         ldb = ldb_module_get_ctx(ac->module);
1674
1675         as_system = ldb_request_get_control(ac->req, LDB_CONTROL_AS_SYSTEM_OID);
1676         if (as_system != NULL) {
1677                 allowed = true;
1678         }
1679
1680         provision = ldb_request_get_control(ac->req, LDB_CONTROL_PROVISION_OID);
1681         if (provision != NULL) {
1682                 allowed = true;
1683         }
1684
1685         sid_el = ldb_msg_find_element(ac->msg, "objectSid");
1686
1687         if (!allowed && sid_el == NULL) {
1688                 return dsdb_module_werror(ac->module,
1689                                 LDB_ERR_OBJECT_CLASS_VIOLATION,
1690                                 WERR_DS_MISSING_REQUIRED_ATT,
1691                                 "objectSid missing on foreignSecurityPrincipal");
1692         }
1693
1694         if (!allowed) {
1695                 return dsdb_module_werror(ac->module,
1696                                 LDB_ERR_UNWILLING_TO_PERFORM,
1697                                 WERR_DS_ILLEGAL_MOD_OPERATION,
1698                                 "foreignSecurityPrincipal object not allowed");
1699         }
1700
1701         if (sid_el != NULL) {
1702                 sid = samdb_result_dom_sid(ac->msg, ac->msg, "objectSid");
1703                 if (sid == NULL) {
1704                         ldb_set_errstring(ldb,
1705                                           "samldb: invalid objectSid!");
1706                         return LDB_ERR_CONSTRAINT_VIOLATION;
1707                 }
1708         }
1709
1710         if (sid == NULL) {
1711                 rdn_value = ldb_dn_get_rdn_val(ac->msg->dn);
1712                 if (rdn_value == NULL) {
1713                         return ldb_operr(ldb);
1714                 }
1715                 sid = dom_sid_parse_talloc(ac->msg,
1716                                            (const char *)rdn_value->data);
1717                 if (sid == NULL) {
1718                         ldb_set_errstring(ldb,
1719                                           "samldb: No valid SID found in ForeignSecurityPrincipal CN!");
1720                         return LDB_ERR_CONSTRAINT_VIOLATION;
1721                 }
1722                 if (! samldb_msg_add_sid(ac->msg, "objectSid", sid)) {
1723                         return ldb_operr(ldb);
1724                 }
1725         }
1726
1727         /* finally proceed with adding the entry */
1728         ret = samldb_add_step(ac, samldb_add_entry);
1729         if (ret != LDB_SUCCESS) return ret;
1730
1731         return samldb_first_step(ac);
1732 }
1733
1734 static int samldb_schema_info_update(struct samldb_ctx *ac)
1735 {
1736         int ret;
1737         struct ldb_context *ldb;
1738         struct dsdb_schema *schema;
1739
1740         /* replicated update should always go through */
1741         if (ldb_request_get_control(ac->req,
1742                                     DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
1743                 return LDB_SUCCESS;
1744         }
1745
1746         /* do not update schemaInfo during provisioning */
1747         if (ldb_request_get_control(ac->req, LDB_CONTROL_PROVISION_OID)) {
1748                 return LDB_SUCCESS;
1749         }
1750
1751         ldb = ldb_module_get_ctx(ac->module);
1752         schema = dsdb_get_schema(ldb, NULL);
1753         if (!schema) {
1754                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
1755                               "samldb_schema_info_update: no dsdb_schema loaded");
1756                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
1757                 return ldb_operr(ldb);
1758         }
1759
1760         ret = dsdb_module_schema_info_update(ac->module, schema,
1761                                              DSDB_FLAG_NEXT_MODULE|
1762                                              DSDB_FLAG_AS_SYSTEM,
1763                                              ac->req);
1764         if (ret != LDB_SUCCESS) {
1765                 ldb_asprintf_errstring(ldb,
1766                                        "samldb_schema_info_update: dsdb_module_schema_info_update failed with %s",
1767                                        ldb_errstring(ldb));
1768                 return ret;
1769         }
1770
1771         return LDB_SUCCESS;
1772 }
1773
1774 static int samldb_prim_group_tester(struct samldb_ctx *ac, uint32_t rid);
1775 static int samldb_check_user_account_control_rules(struct samldb_ctx *ac,
1776                                                    struct dom_sid *sid,
1777                                                    uint32_t req_uac,
1778                                                    uint32_t user_account_control,
1779                                                    uint32_t user_account_control_old,
1780                                                    bool is_computer_objectclass);
1781
1782 /*
1783  * "Objectclass" trigger (MS-SAMR 3.1.1.8.1)
1784  *
1785  * Has to be invoked on "add" operations on "user", "computer" and
1786  * "group" objects.
1787  * ac->msg contains the "add"
1788  * ac->type contains the object type (main objectclass)
1789  */
1790 static int samldb_objectclass_trigger(struct samldb_ctx *ac)
1791 {
1792         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1793         void *skip_allocate_sids = ldb_get_opaque(ldb,
1794                                                   "skip_allocate_sids");
1795         struct ldb_message_element *el, *el2;
1796         struct dom_sid *sid;
1797         int ret;
1798
1799         /* make sure that "sAMAccountType" is not specified */
1800         el = ldb_msg_find_element(ac->msg, "sAMAccountType");
1801         if (el != NULL) {
1802                 ldb_set_errstring(ldb,
1803                                   "samldb: sAMAccountType must not be specified!");
1804                 return LDB_ERR_UNWILLING_TO_PERFORM;
1805         }
1806
1807         /* Step 1: objectSid assignment */
1808
1809         /* Don't allow the objectSid to be changed. But beside the RELAX
1810          * control we have also to guarantee that it can always be set with
1811          * SYSTEM permissions. This is needed for the "samba3sam" backend. */
1812         sid = samdb_result_dom_sid(ac, ac->msg, "objectSid");
1813         if ((sid != NULL) && (!dsdb_module_am_system(ac->module)) &&
1814             (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) == NULL)) {
1815                 ldb_set_errstring(ldb,
1816                                   "samldb: objectSid must not be specified!");
1817                 return LDB_ERR_UNWILLING_TO_PERFORM;
1818         }
1819
1820         /* but generate a new SID when we do have an add operations */
1821         if ((sid == NULL) && (ac->req->operation == LDB_ADD) && !skip_allocate_sids) {
1822                 ret = samldb_add_step(ac, samldb_allocate_sid);
1823                 if (ret != LDB_SUCCESS) return ret;
1824         }
1825
1826         switch(ac->type) {
1827         case SAMLDB_TYPE_USER: {
1828                 uint32_t raw_uac;
1829                 uint32_t user_account_control;
1830                 bool is_computer_objectclass;
1831                 bool uac_generated = false, uac_add_flags = false;
1832                 uint32_t default_user_account_control = UF_NORMAL_ACCOUNT;
1833                 /* Step 1.2: Default values */
1834                 ret = dsdb_user_obj_set_defaults(ldb, ac->msg, ac->req);
1835                 if (ret != LDB_SUCCESS) return ret;
1836
1837                 is_computer_objectclass
1838                         = (samdb_find_attribute(ldb,
1839                                                  ac->msg,
1840                                                 "objectclass",
1841                                                 "computer")
1842                            != NULL);
1843
1844                 if (is_computer_objectclass) {
1845                         default_user_account_control
1846                                 = UF_WORKSTATION_TRUST_ACCOUNT;
1847                 }
1848
1849
1850                 /* On add operations we might need to generate a
1851                  * "userAccountControl" (if it isn't specified). */
1852                 el = ldb_msg_find_element(ac->msg, "userAccountControl");
1853                 if (el == NULL) {
1854                         ret = samdb_msg_set_uint(ldb, ac->msg, ac->msg,
1855                                                  "userAccountControl",
1856                                                  default_user_account_control);
1857                         if (ret != LDB_SUCCESS) {
1858                                 return ret;
1859                         }
1860                         uac_generated = true;
1861                         uac_add_flags = true;
1862                 }
1863
1864                 el = ldb_msg_find_element(ac->msg, "userAccountControl");
1865                 SMB_ASSERT(el != NULL);
1866
1867                 /* Step 1.3: "userAccountControl" -> "sAMAccountType" mapping */
1868                 user_account_control = ldb_msg_find_attr_as_uint(ac->msg,
1869                                                                  "userAccountControl",
1870                                                                  0);
1871                 raw_uac = user_account_control;
1872                 /*
1873                  * "userAccountControl" = 0 or missing one of
1874                  * the types means "UF_NORMAL_ACCOUNT"
1875                  * or "UF_WORKSTATION_TRUST_ACCOUNT" (if a computer).
1876                  * See MS-SAMR 3.1.1.8.10 point 8
1877                  */
1878                 if ((user_account_control & UF_ACCOUNT_TYPE_MASK) == 0) {
1879                         user_account_control
1880                                 = default_user_account_control
1881                                 | user_account_control;
1882                         uac_generated = true;
1883                 }
1884
1885                 /*
1886                  * As per MS-SAMR 3.1.1.8.10 these flags have not to be set
1887                  */
1888                 if ((user_account_control & UF_LOCKOUT) != 0) {
1889                         user_account_control &= ~UF_LOCKOUT;
1890                         uac_generated = true;
1891                 }
1892                 if ((user_account_control & UF_PASSWORD_EXPIRED) != 0) {
1893                         user_account_control &= ~UF_PASSWORD_EXPIRED;
1894                         uac_generated = true;
1895                 }
1896
1897                 ret = samldb_check_user_account_control_rules(ac, NULL,
1898                                                               raw_uac,
1899                                                               user_account_control,
1900                                                               0,
1901                                                               is_computer_objectclass);
1902                 if (ret != LDB_SUCCESS) {
1903                         return ret;
1904                 }
1905
1906                 /*
1907                  * Require, for non-admin modifications, a trailing $
1908                  * for either objectclass=computer or a trust account
1909                  * type in userAccountControl
1910                  */
1911                 if ((user_account_control
1912                      & UF_TRUST_ACCOUNT_MASK) != 0) {
1913                         ac->need_trailing_dollar = true;
1914                 }
1915
1916                 if (is_computer_objectclass) {
1917                         ac->need_trailing_dollar = true;
1918                 }
1919
1920                 /* add "sAMAccountType" attribute */
1921                 ret = dsdb_user_obj_set_account_type(ldb, ac->msg, user_account_control, NULL);
1922                 if (ret != LDB_SUCCESS) {
1923                         return ret;
1924                 }
1925
1926                 /* "isCriticalSystemObject" might be set */
1927                 if (user_account_control &
1928                     (UF_SERVER_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)) {
1929                         ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject",
1930                                                  "TRUE");
1931                         if (ret != LDB_SUCCESS) {
1932                                 return ret;
1933                         }
1934                         el2 = ldb_msg_find_element(ac->msg,
1935                                                    "isCriticalSystemObject");
1936                         el2->flags = LDB_FLAG_MOD_REPLACE;
1937                 } else if (user_account_control & UF_WORKSTATION_TRUST_ACCOUNT) {
1938                         ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject",
1939                                                  "FALSE");
1940                         if (ret != LDB_SUCCESS) {
1941                                 return ret;
1942                         }
1943                         el2 = ldb_msg_find_element(ac->msg,
1944                                                    "isCriticalSystemObject");
1945                         el2->flags = LDB_FLAG_MOD_REPLACE;
1946                 }
1947
1948                 /* Step 1.4: "userAccountControl" -> "primaryGroupID" mapping */
1949                 if (!ldb_msg_find_element(ac->msg, "primaryGroupID")) {
1950                         uint32_t rid;
1951
1952                         ret = dsdb_user_obj_set_primary_group_id(ldb, ac->msg, user_account_control, &rid);
1953                         if (ret != LDB_SUCCESS) {
1954                                 return ret;
1955                         }
1956                         /*
1957                          * Older AD deployments don't know about the
1958                          * RODC group
1959                          */
1960                         if (rid == DOMAIN_RID_READONLY_DCS) {
1961                                 ret = samldb_prim_group_tester(ac, rid);
1962                                 if (ret != LDB_SUCCESS) {
1963                                         return ret;
1964                                 }
1965                         }
1966                 }
1967
1968                 /* Step 1.5: Add additional flags when needed */
1969                 /* Obviously this is done when the "userAccountControl"
1970                  * has been generated here (tested against Windows
1971                  * Server) */
1972                 if (uac_generated) {
1973                         if (uac_add_flags) {
1974                                 user_account_control |= UF_ACCOUNTDISABLE;
1975                                 user_account_control |= UF_PASSWD_NOTREQD;
1976                         }
1977
1978                         ret = samdb_msg_set_uint(ldb, ac->msg, ac->msg,
1979                                                  "userAccountControl",
1980                                                  user_account_control);
1981                         if (ret != LDB_SUCCESS) {
1982                                 return ret;
1983                         }
1984                 }
1985                 break;
1986         }
1987
1988         case SAMLDB_TYPE_GROUP: {
1989                 const char *tempstr;
1990
1991                 /* Step 2.2: Default values */
1992                 tempstr = talloc_asprintf(ac->msg, "%d",
1993                                           GTYPE_SECURITY_GLOBAL_GROUP);
1994                 if (tempstr == NULL) return ldb_operr(ldb);
1995                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
1996                         "groupType", tempstr);
1997                 if (ret != LDB_SUCCESS) return ret;
1998
1999                 /* Step 2.3: "groupType" -> "sAMAccountType" */
2000                 el = ldb_msg_find_element(ac->msg, "groupType");
2001                 if (el != NULL) {
2002                         uint32_t group_type, account_type;
2003
2004                         group_type = ldb_msg_find_attr_as_uint(ac->msg,
2005                                                                "groupType", 0);
2006
2007                         /* The creation of builtin groups requires the
2008                          * RELAX control */
2009                         if (group_type == GTYPE_SECURITY_BUILTIN_LOCAL_GROUP) {
2010                                 if (ldb_request_get_control(ac->req,
2011                                                             LDB_CONTROL_RELAX_OID) == NULL) {
2012                                         return LDB_ERR_UNWILLING_TO_PERFORM;
2013                                 }
2014                         }
2015
2016                         account_type = ds_gtype2atype(group_type);
2017                         if (account_type == 0) {
2018                                 ldb_set_errstring(ldb, "samldb: Unrecognized account type!");
2019                                 return LDB_ERR_UNWILLING_TO_PERFORM;
2020                         }
2021                         ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
2022                                                  "sAMAccountType",
2023                                                  account_type);
2024                         if (ret != LDB_SUCCESS) {
2025                                 return ret;
2026                         }
2027                         el2 = ldb_msg_find_element(ac->msg, "sAMAccountType");
2028                         el2->flags = LDB_FLAG_MOD_REPLACE;
2029                 }
2030                 break;
2031         }
2032
2033         default:
2034                 ldb_asprintf_errstring(ldb,
2035                                 "Invalid entry type!");
2036                 return LDB_ERR_OPERATIONS_ERROR;
2037                 break;
2038         }
2039
2040         return LDB_SUCCESS;
2041 }
2042
2043 /*
2044  * "Primary group ID" trigger (MS-SAMR 3.1.1.8.2)
2045  *
2046  * Has to be invoked on "add" and "modify" operations on "user" and "computer"
2047  * objects.
2048  * ac->msg contains the "add"/"modify" message
2049  */
2050
2051 static int samldb_prim_group_tester(struct samldb_ctx *ac, uint32_t rid)
2052 {
2053         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
2054         struct dom_sid *sid;
2055         struct ldb_result *res;
2056         int ret;
2057         const char * const noattrs[] = { NULL };
2058
2059         sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
2060         if (sid == NULL) {
2061                 return ldb_operr(ldb);
2062         }
2063
2064         ret = dsdb_module_search(ac->module, ac, &res,
2065                                  ldb_get_default_basedn(ldb),
2066                                  LDB_SCOPE_SUBTREE,
2067                                  noattrs, DSDB_FLAG_NEXT_MODULE,
2068                                  ac->req,
2069                                  "(objectSid=%s)",
2070                                  ldap_encode_ndr_dom_sid(ac, sid));
2071         if (ret != LDB_SUCCESS) {
2072                 return ret;
2073         }
2074         if (res->count != 1) {
2075                 talloc_free(res);
2076                 ldb_asprintf_errstring(ldb,
2077                                        "Failed to find primary group with RID %u!",
2078                                        rid);
2079                 return LDB_ERR_UNWILLING_TO_PERFORM;
2080         }
2081         talloc_free(res);
2082
2083         return LDB_SUCCESS;
2084 }
2085
2086 static int samldb_prim_group_set(struct samldb_ctx *ac)
2087 {
2088         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
2089         uint32_t rid;
2090
2091         rid = ldb_msg_find_attr_as_uint(ac->msg, "primaryGroupID", (uint32_t) -1);
2092         if (rid == (uint32_t) -1) {
2093                 /* we aren't affected of any primary group set */
2094                 return LDB_SUCCESS;
2095
2096         } else if (!ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
2097                 ldb_set_errstring(ldb,
2098                                   "The primary group isn't settable on add operations!");
2099                 return LDB_ERR_UNWILLING_TO_PERFORM;
2100         }
2101
2102         return samldb_prim_group_tester(ac, rid);
2103 }
2104
2105 static int samldb_prim_group_change(struct samldb_ctx *ac)
2106 {
2107         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
2108         const char * const attrs[] = {
2109                 "primaryGroupID",
2110                 "memberOf",
2111                 "userAccountControl",
2112                 NULL };
2113         struct ldb_result *res, *group_res;
2114         struct ldb_message_element *el;
2115         struct ldb_message *msg;
2116         uint32_t search_flags =
2117                 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_EXTENDED_DN;
2118         uint32_t prev_rid, new_rid, uac;
2119         struct dom_sid *prev_sid, *new_sid;
2120         struct ldb_dn *prev_prim_group_dn, *new_prim_group_dn;
2121         const char *new_prim_group_dn_ext_str = NULL;
2122         struct ldb_dn *user_dn = NULL;
2123         const char *user_dn_ext_str = NULL;
2124         int ret;
2125         const char * const noattrs[] = { NULL };
2126
2127         ret = dsdb_get_expected_new_values(ac,
2128                                            ac->msg,
2129                                            "primaryGroupID",
2130                                            &el,
2131                                            ac->req->operation);
2132         if (ret != LDB_SUCCESS) {
2133                 return ret;
2134         }
2135
2136         if (el == NULL) {
2137                 /* we are not affected */
2138                 return LDB_SUCCESS;
2139         }
2140
2141         /* Fetch information from the existing object */
2142
2143         ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, attrs,
2144                                     search_flags, ac->req);
2145         if (ret != LDB_SUCCESS) {
2146                 return ret;
2147         }
2148         user_dn = res->msgs[0]->dn;
2149         user_dn_ext_str = ldb_dn_get_extended_linearized(ac, user_dn, 1);
2150         if (user_dn_ext_str == NULL) {
2151                 return ldb_operr(ldb);
2152         }
2153
2154         uac = ldb_msg_find_attr_as_uint(res->msgs[0], "userAccountControl", 0);
2155
2156         /* Finds out the DN of the old primary group */
2157
2158         prev_rid = ldb_msg_find_attr_as_uint(res->msgs[0], "primaryGroupID",
2159                                              (uint32_t) -1);
2160         if (prev_rid == (uint32_t) -1) {
2161                 /* User objects do always have a mandatory "primaryGroupID"
2162                  * attribute. If this doesn't exist then the object is of the
2163                  * wrong type. This is the exact Windows error code */
2164                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
2165         }
2166
2167         prev_sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), prev_rid);
2168         if (prev_sid == NULL) {
2169                 return ldb_operr(ldb);
2170         }
2171
2172         /* Finds out the DN of the new primary group
2173          * Notice: in order to parse the primary group ID correctly we create
2174          * a temporary message here. */
2175
2176         msg = ldb_msg_new(ac->msg);
2177         if (msg == NULL) {
2178                 return ldb_module_oom(ac->module);
2179         }
2180         ret = ldb_msg_add(msg, el, 0);
2181         if (ret != LDB_SUCCESS) {
2182                 return ret;
2183         }
2184         new_rid = ldb_msg_find_attr_as_uint(msg, "primaryGroupID", (uint32_t) -1);
2185         talloc_free(msg);
2186         if (new_rid == (uint32_t) -1) {
2187                 /* we aren't affected of any primary group change */
2188                 return LDB_SUCCESS;
2189         }
2190
2191         if (prev_rid == new_rid) {
2192                 return LDB_SUCCESS;
2193         }
2194
2195         if ((uac & UF_SERVER_TRUST_ACCOUNT) && new_rid != DOMAIN_RID_DCS) {
2196                 ldb_asprintf_errstring(ldb,
2197                         "%08X: samldb: UF_SERVER_TRUST_ACCOUNT requires "
2198                         "primaryGroupID=%u!",
2199                         W_ERROR_V(WERR_DS_CANT_MOD_PRIMARYGROUPID),
2200                         DOMAIN_RID_DCS);
2201                 return LDB_ERR_UNWILLING_TO_PERFORM;
2202         }
2203
2204         if ((uac & UF_PARTIAL_SECRETS_ACCOUNT) && new_rid != DOMAIN_RID_READONLY_DCS) {
2205                 ldb_asprintf_errstring(ldb,
2206                         "%08X: samldb: UF_PARTIAL_SECRETS_ACCOUNT requires "
2207                         "primaryGroupID=%u!",
2208                         W_ERROR_V(WERR_DS_CANT_MOD_PRIMARYGROUPID),
2209                         DOMAIN_RID_READONLY_DCS);
2210                 return LDB_ERR_UNWILLING_TO_PERFORM;
2211         }
2212
2213         ret = dsdb_module_search(ac->module, ac, &group_res,
2214                                  ldb_get_default_basedn(ldb),
2215                                  LDB_SCOPE_SUBTREE,
2216                                  noattrs, search_flags,
2217                                  ac->req,
2218                                  "(objectSid=%s)",
2219                                  ldap_encode_ndr_dom_sid(ac, prev_sid));
2220         if (ret != LDB_SUCCESS) {
2221                 return ret;
2222         }
2223         if (group_res->count != 1) {
2224                 return ldb_operr(ldb);
2225         }
2226         prev_prim_group_dn = group_res->msgs[0]->dn;
2227
2228         new_sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), new_rid);
2229         if (new_sid == NULL) {
2230                 return ldb_operr(ldb);
2231         }
2232
2233         ret = dsdb_module_search(ac->module, ac, &group_res,
2234                                  ldb_get_default_basedn(ldb),
2235                                  LDB_SCOPE_SUBTREE,
2236                                  noattrs, search_flags,
2237                                  ac->req,
2238                                  "(objectSid=%s)",
2239                                  ldap_encode_ndr_dom_sid(ac, new_sid));
2240         if (ret != LDB_SUCCESS) {
2241                 return ret;
2242         }
2243         if (group_res->count != 1) {
2244                 /* Here we know if the specified new primary group candidate is
2245                  * valid or not. */
2246                 return LDB_ERR_UNWILLING_TO_PERFORM;
2247         }
2248         new_prim_group_dn = group_res->msgs[0]->dn;
2249         new_prim_group_dn_ext_str = ldb_dn_get_extended_linearized(ac,
2250                                                         new_prim_group_dn, 1);
2251         if (new_prim_group_dn_ext_str == NULL) {
2252                 return ldb_operr(ldb);
2253         }
2254
2255         /* We need to be already a normal member of the new primary
2256          * group in order to be successful. */
2257         el = samdb_find_attribute(ldb, res->msgs[0], "memberOf",
2258                                   new_prim_group_dn_ext_str);
2259         if (el == NULL) {
2260                 return LDB_ERR_UNWILLING_TO_PERFORM;
2261         }
2262
2263         /* Remove the "member" attribute on the new primary group */
2264         msg = ldb_msg_new(ac->msg);
2265         if (msg == NULL) {
2266                 return ldb_module_oom(ac->module);
2267         }
2268         msg->dn = new_prim_group_dn;
2269
2270         ret = samdb_msg_add_delval(ldb, msg, msg, "member", user_dn_ext_str);
2271         if (ret != LDB_SUCCESS) {
2272                 return ret;
2273         }
2274
2275         ret = dsdb_module_modify(ac->module, msg, DSDB_FLAG_NEXT_MODULE, ac->req);
2276         if (ret != LDB_SUCCESS) {
2277                 return ret;
2278         }
2279         talloc_free(msg);
2280
2281         /* Add a "member" attribute for the previous primary group */
2282         msg = ldb_msg_new(ac->msg);
2283         if (msg == NULL) {
2284                 return ldb_module_oom(ac->module);
2285         }
2286         msg->dn = prev_prim_group_dn;
2287
2288         ret = samdb_msg_add_addval(ldb, msg, msg, "member", user_dn_ext_str);
2289         if (ret != LDB_SUCCESS) {
2290                 return ret;
2291         }
2292
2293         ret = dsdb_module_modify(ac->module, msg, DSDB_FLAG_NEXT_MODULE, ac->req);
2294         if (ret != LDB_SUCCESS) {
2295                 return ret;
2296         }
2297         talloc_free(msg);
2298
2299         return LDB_SUCCESS;
2300 }
2301
2302 static int samldb_prim_group_trigger(struct samldb_ctx *ac)
2303 {
2304         int ret;
2305
2306         if (ac->req->operation == LDB_ADD) {
2307                 ret = samldb_prim_group_set(ac);
2308         } else {
2309                 ret = samldb_prim_group_change(ac);
2310         }
2311
2312         return ret;
2313 }
2314
2315 static int samldb_check_user_account_control_invariants(struct samldb_ctx *ac,
2316                                                     uint32_t user_account_control)
2317 {
2318         size_t i;
2319         int ret = 0;
2320         bool need_check = false;
2321         const struct uac_to_guid {
2322                 uint32_t uac;
2323                 bool never;
2324                 uint32_t needs;
2325                 uint32_t not_with;
2326                 const char *error_string;
2327         } map[] = {
2328                 {
2329                         .uac = UF_TEMP_DUPLICATE_ACCOUNT,
2330                         .never = true,
2331                         .error_string = "Updating the UF_TEMP_DUPLICATE_ACCOUNT flag is never allowed"
2332                 },
2333                 {
2334                         .uac = UF_PARTIAL_SECRETS_ACCOUNT,
2335                         .needs = UF_WORKSTATION_TRUST_ACCOUNT,
2336                         .error_string = "Setting UF_PARTIAL_SECRETS_ACCOUNT only permitted with UF_WORKSTATION_TRUST_ACCOUNT"
2337                 },
2338                 {
2339                         .uac = UF_TRUSTED_FOR_DELEGATION,
2340                         .not_with = UF_PARTIAL_SECRETS_ACCOUNT,
2341                         .error_string = "Setting UF_TRUSTED_FOR_DELEGATION not allowed with UF_PARTIAL_SECRETS_ACCOUNT"
2342                 },
2343                 {
2344                         .uac = UF_NORMAL_ACCOUNT,
2345                         .not_with = UF_ACCOUNT_TYPE_MASK & ~UF_NORMAL_ACCOUNT,
2346                         .error_string = "Setting more than one account type not permitted"
2347                 },
2348                 {
2349                         .uac = UF_WORKSTATION_TRUST_ACCOUNT,
2350                         .not_with = UF_ACCOUNT_TYPE_MASK & ~UF_WORKSTATION_TRUST_ACCOUNT,
2351                         .error_string = "Setting more than one account type not permitted"
2352                 },
2353                 {
2354                         .uac = UF_INTERDOMAIN_TRUST_ACCOUNT,
2355                         .not_with = UF_ACCOUNT_TYPE_MASK & ~UF_INTERDOMAIN_TRUST_ACCOUNT,
2356                         .error_string = "Setting more than one account type not permitted"
2357                 },
2358                 {
2359                         .uac = UF_SERVER_TRUST_ACCOUNT,
2360                         .not_with = UF_ACCOUNT_TYPE_MASK & ~UF_SERVER_TRUST_ACCOUNT,
2361                         .error_string = "Setting more than one account type not permitted"
2362                 },
2363                 {
2364                         .uac = UF_TRUSTED_FOR_DELEGATION,
2365                         .not_with = UF_PARTIAL_SECRETS_ACCOUNT,
2366                         .error_string = "Setting UF_TRUSTED_FOR_DELEGATION not allowed with UF_PARTIAL_SECRETS_ACCOUNT"
2367                 }
2368         };
2369
2370         for (i = 0; i < ARRAY_SIZE(map); i++) {
2371                 if (user_account_control & map[i].uac) {
2372                         need_check = true;
2373                         break;
2374                 }
2375         }
2376         if (need_check == false) {
2377                 return LDB_SUCCESS;
2378         }
2379
2380         for (i = 0; i < ARRAY_SIZE(map); i++) {
2381                 uint32_t this_uac = user_account_control & map[i].uac;
2382                 if (this_uac != 0) {
2383                         if (map[i].never) {
2384                                 ret = LDB_ERR_OTHER;
2385                                 break;
2386                         } else if (map[i].needs != 0) {
2387                                 if ((map[i].needs & user_account_control) == 0) {
2388                                         ret = LDB_ERR_OTHER;
2389                                         break;
2390                                 }
2391                         } else if (map[i].not_with != 0) {
2392                                 if ((map[i].not_with & user_account_control) != 0) {
2393                                         ret = LDB_ERR_OTHER;
2394                                         break;
2395                                 }
2396                         }
2397                 }
2398         }
2399         if (ret != LDB_SUCCESS) {
2400                 switch (ac->req->operation) {
2401                 case LDB_ADD:
2402                         ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
2403                                                "Failed to add %s: %s",
2404                                                ldb_dn_get_linearized(ac->msg->dn),
2405                                                map[i].error_string);
2406                         break;
2407                 case LDB_MODIFY:
2408                         ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
2409                                                "Failed to modify %s: %s",
2410                                                ldb_dn_get_linearized(ac->msg->dn),
2411                                                map[i].error_string);
2412                         break;
2413                 default:
2414                         return ldb_module_operr(ac->module);
2415                 }
2416         }
2417         return ret;
2418 }
2419
2420 /*
2421  * It would be best if these rules apply, always, but for now they
2422  * apply only to non-admins
2423  */
2424 static int samldb_check_user_account_control_objectclass_invariants(
2425         struct samldb_ctx *ac,
2426         uint32_t user_account_control,
2427         uint32_t user_account_control_old,
2428         bool is_computer_objectclass)
2429 {
2430         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
2431
2432         uint32_t old_ufa = user_account_control_old & UF_ACCOUNT_TYPE_MASK;
2433         uint32_t new_ufa = user_account_control & UF_ACCOUNT_TYPE_MASK;
2434
2435         uint32_t old_rodc = user_account_control_old & UF_PARTIAL_SECRETS_ACCOUNT;
2436         uint32_t new_rodc = user_account_control & UF_PARTIAL_SECRETS_ACCOUNT;
2437
2438         bool is_admin;
2439         struct security_token *user_token
2440                 = acl_user_token(ac->module);
2441         if (user_token == NULL) {
2442                 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
2443         }
2444
2445         is_admin
2446                 = security_token_has_builtin_administrators(user_token);
2447
2448
2449         /*
2450          * We want to allow changes to (eg) disable an account
2451          * that was created wrong, only checking the
2452          * objectclass if the account type changes.
2453          */
2454         if (old_ufa == new_ufa && old_rodc == new_rodc) {
2455                 return LDB_SUCCESS;
2456         }
2457
2458         switch (new_ufa) {
2459         case UF_NORMAL_ACCOUNT:
2460                 if (is_computer_objectclass && !is_admin) {
2461                         ldb_asprintf_errstring(ldb,
2462                                 "%08X: samldb: UF_NORMAL_ACCOUNT "
2463                                 "requires objectclass 'user' not 'computer'!",
2464                                 W_ERROR_V(WERR_DS_MACHINE_ACCOUNT_CREATED_PRENT4));
2465                         return LDB_ERR_OBJECT_CLASS_VIOLATION;
2466                 }
2467                 break;
2468
2469         case UF_INTERDOMAIN_TRUST_ACCOUNT:
2470                 if (is_computer_objectclass) {
2471                         ldb_asprintf_errstring(ldb,
2472                                 "%08X: samldb: UF_INTERDOMAIN_TRUST_ACCOUNT "
2473                                 "requires objectclass 'user' not 'computer'!",
2474                                 W_ERROR_V(WERR_DS_MACHINE_ACCOUNT_CREATED_PRENT4));
2475                         return LDB_ERR_OBJECT_CLASS_VIOLATION;
2476                 }
2477                 break;
2478
2479         case UF_WORKSTATION_TRUST_ACCOUNT:
2480                 if (!is_computer_objectclass) {
2481                         /*
2482                          * Modify of a user account account into a
2483                          * workstation without objectclass computer
2484                          * as an admin is still permitted, but not
2485                          * to make an RODC
2486                          */
2487                         if (is_admin
2488                             && ac->req->operation == LDB_MODIFY
2489                             && new_rodc == 0) {
2490                                 break;
2491                         }
2492                         ldb_asprintf_errstring(ldb,
2493                                 "%08X: samldb: UF_WORKSTATION_TRUST_ACCOUNT "
2494                                 "requires objectclass 'computer'!",
2495                                 W_ERROR_V(WERR_DS_MACHINE_ACCOUNT_CREATED_PRENT4));
2496                         return LDB_ERR_OBJECT_CLASS_VIOLATION;
2497                 }
2498                 break;
2499
2500         case UF_SERVER_TRUST_ACCOUNT:
2501                 if (!is_computer_objectclass) {
2502                         ldb_asprintf_errstring(ldb,
2503                                 "%08X: samldb: UF_SERVER_TRUST_ACCOUNT "
2504                                 "requires objectclass 'computer'!",
2505                                 W_ERROR_V(WERR_DS_MACHINE_ACCOUNT_CREATED_PRENT4));
2506                         return LDB_ERR_OBJECT_CLASS_VIOLATION;
2507                 }
2508                 break;
2509
2510         default:
2511                 ldb_asprintf_errstring(ldb,
2512                         "%08X: samldb: invalid userAccountControl[0x%08X]",
2513                         W_ERROR_V(WERR_INVALID_PARAMETER),
2514                                        user_account_control);
2515                 return LDB_ERR_OTHER;
2516         }
2517         return LDB_SUCCESS;
2518 }
2519
2520 static int samldb_get_domain_secdesc_and_oc(struct samldb_ctx *ac,
2521                                             struct security_descriptor **domain_sd,
2522                                             const struct dsdb_class **objectclass)
2523 {
2524         const char * const sd_attrs[] = {"ntSecurityDescriptor", "objectClass", NULL};
2525         struct ldb_result *res;
2526         struct ldb_dn *domain_dn = ldb_get_default_basedn(ldb_module_get_ctx(ac->module));
2527         const struct dsdb_schema *schema = NULL;
2528         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
2529         int ret = dsdb_module_search_dn(ac->module, ac, &res,
2530                                         domain_dn,
2531                                         sd_attrs,
2532                                         DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED,
2533                                         ac->req);
2534         if (ret != LDB_SUCCESS) {
2535                 return ret;
2536         }
2537         if (res->count != 1) {
2538                 return ldb_module_operr(ac->module);
2539         }
2540
2541         schema = dsdb_get_schema(ldb, ac->req);
2542         if (!schema) {
2543                 return ldb_module_operr(ac->module);;
2544         }
2545         *objectclass = dsdb_get_structural_oc_from_msg(schema, res->msgs[0]);
2546         return dsdb_get_sd_from_ldb_message(ldb_module_get_ctx(ac->module),
2547                                             ac, res->msgs[0], domain_sd);
2548
2549 }
2550
2551 /**
2552  * Validate that the restriction in point 5 of MS-SAMR 3.1.1.8.10 userAccountControl is honoured
2553  *
2554  */
2555 static int samldb_check_user_account_control_acl(struct samldb_ctx *ac,
2556                                                  struct dom_sid *sid,
2557                                                  uint32_t user_account_control,
2558                                                  uint32_t user_account_control_old)
2559 {
2560         size_t i;
2561         int ret = 0;
2562         bool need_acl_check = false;
2563         struct security_token *user_token;
2564         struct security_descriptor *domain_sd;
2565         const struct dsdb_class *objectclass = NULL;
2566         const struct uac_to_guid {
2567                 uint32_t uac;
2568                 uint32_t priv_to_change_from;
2569                 const char *oid;
2570                 const char *guid;
2571                 enum sec_privilege privilege;
2572                 bool delete_is_privileged;
2573                 bool admin_required;
2574                 const char *error_string;
2575         } map[] = {
2576                 {
2577                         .uac = UF_PASSWD_NOTREQD,
2578                         .guid = GUID_DRS_UPDATE_PASSWORD_NOT_REQUIRED_BIT,
2579                         .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"
2580                 },
2581                 {
2582                         .uac = UF_DONT_EXPIRE_PASSWD,
2583                         .guid = GUID_DRS_UNEXPIRE_PASSWORD,
2584                         .error_string = "Adding the UF_DONT_EXPIRE_PASSWD bit in userAccountControl requires the Unexpire-Password right that was not given on the Domain object"
2585                 },
2586                 {
2587                         .uac = UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED,
2588                         .guid = GUID_DRS_ENABLE_PER_USER_REVERSIBLY_ENCRYPTED_PASSWORD,
2589                         .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"
2590                 },
2591                 {
2592                         .uac = UF_SERVER_TRUST_ACCOUNT,
2593                         .guid = GUID_DRS_DS_INSTALL_REPLICA,
2594                         .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"
2595                 },
2596                 {
2597                         .uac = UF_PARTIAL_SECRETS_ACCOUNT,
2598                         .guid = GUID_DRS_DS_INSTALL_REPLICA,
2599                         .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"
2600                 },
2601                 {
2602                         .uac = UF_WORKSTATION_TRUST_ACCOUNT,
2603                         .priv_to_change_from = UF_NORMAL_ACCOUNT,
2604                         .error_string = "Swapping UF_NORMAL_ACCOUNT to UF_WORKSTATION_TRUST_ACCOUNT requires the user to be a member of the domain admins group"
2605                 },
2606                 {
2607                         .uac = UF_NORMAL_ACCOUNT,
2608                         .priv_to_change_from = UF_WORKSTATION_TRUST_ACCOUNT,
2609                         .error_string = "Swapping UF_WORKSTATION_TRUST_ACCOUNT to UF_NORMAL_ACCOUNT requires the user to be a member of the domain admins group"
2610                 },
2611                 {
2612                         .uac = UF_INTERDOMAIN_TRUST_ACCOUNT,
2613                         .oid = DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
2614                         .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",
2615                         .delete_is_privileged = true
2616                 },
2617                 {
2618                         .uac = UF_TRUSTED_FOR_DELEGATION,
2619                         .privilege = SEC_PRIV_ENABLE_DELEGATION,
2620                         .delete_is_privileged = true,
2621                         .error_string = "Updating the UF_TRUSTED_FOR_DELEGATION bit in userAccountControl is not permitted without the SeEnableDelegationPrivilege"
2622                 },
2623                 {
2624                         .uac = UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION,
2625                         .privilege = SEC_PRIV_ENABLE_DELEGATION,
2626                         .delete_is_privileged = true,
2627                         .error_string = "Updating the UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION bit in userAccountControl is not permitted without the SeEnableDelegationPrivilege"
2628                 }
2629
2630         };
2631
2632         if (dsdb_module_am_system(ac->module)) {
2633                 return LDB_SUCCESS;
2634         }
2635
2636         for (i = 0; i < ARRAY_SIZE(map); i++) {
2637                 if (user_account_control & map[i].uac) {
2638                         need_acl_check = true;
2639                         break;
2640                 }
2641         }
2642         if (need_acl_check == false) {
2643                 return LDB_SUCCESS;
2644         }
2645
2646         user_token = acl_user_token(ac->module);
2647         if (user_token == NULL) {
2648                 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
2649         }
2650
2651         ret = samldb_get_domain_secdesc_and_oc(ac, &domain_sd, &objectclass);
2652         if (ret != LDB_SUCCESS) {
2653                 return ret;
2654         }
2655
2656         for (i = 0; i < ARRAY_SIZE(map); i++) {
2657                 uint32_t this_uac_new = user_account_control & map[i].uac;
2658                 uint32_t this_uac_old = user_account_control_old & map[i].uac;
2659                 if (this_uac_new != this_uac_old) {
2660                         if (this_uac_old != 0) {
2661                                 if (map[i].delete_is_privileged == false) {
2662                                         continue;
2663                                 }
2664                         }
2665                         if (map[i].oid) {
2666                                 struct ldb_control *control = ldb_request_get_control(ac->req, map[i].oid);
2667                                 if (control == NULL) {
2668                                         ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
2669                                 }
2670                         } else if (map[i].privilege != SEC_PRIV_INVALID) {
2671                                 bool have_priv = security_token_has_privilege(user_token,
2672                                                                               map[i].privilege);
2673                                 if (have_priv == false) {
2674                                         ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
2675                                 }
2676                         } else if (map[i].priv_to_change_from & user_account_control_old) {
2677                                 bool is_admin = security_token_has_builtin_administrators(user_token);
2678                                 if (is_admin == false) {
2679                                         ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
2680                                 }
2681                         } else if (map[i].guid) {
2682                                 ret = acl_check_extended_right(ac,
2683                                                                ac->module,
2684                                                                ac->req,
2685                                                                objectclass,
2686                                                                domain_sd,
2687                                                                user_token,
2688                                                                map[i].guid,
2689                                                                SEC_ADS_CONTROL_ACCESS,
2690                                                                sid);
2691                         } else {
2692                                 ret = LDB_SUCCESS;
2693                         }
2694                         if (ret != LDB_SUCCESS) {
2695                                 break;
2696                         }
2697                 }
2698         }
2699         if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
2700                 switch (ac->req->operation) {
2701                 case LDB_ADD:
2702                         ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
2703                                                "Failed to add %s: %s",
2704                                                ldb_dn_get_linearized(ac->msg->dn),
2705                                                map[i].error_string);
2706                         break;
2707                 case LDB_MODIFY:
2708                         ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
2709                                                "Failed to modify %s: %s",
2710                                                ldb_dn_get_linearized(ac->msg->dn),
2711                                                map[i].error_string);
2712                         break;
2713                 default:
2714                         return ldb_module_operr(ac->module);
2715                 }
2716                 if (map[i].guid) {
2717                         struct ldb_dn *domain_dn
2718                                 = ldb_get_default_basedn(ldb_module_get_ctx(ac->module));
2719                         dsdb_acl_debug(domain_sd, acl_user_token(ac->module),
2720                                        domain_dn,
2721                                        true,
2722                                        10);
2723                 }
2724         }
2725         return ret;
2726 }
2727
2728 static int samldb_check_user_account_control_rules(struct samldb_ctx *ac,
2729                                                    struct dom_sid *sid,
2730                                                    uint32_t req_uac,
2731                                                    uint32_t user_account_control,
2732                                                    uint32_t user_account_control_old,
2733                                                    bool is_computer_objectclass)
2734 {
2735         int ret;
2736         struct dsdb_control_password_user_account_control *uac = NULL;
2737
2738         ret = samldb_check_user_account_control_invariants(ac, user_account_control);
2739         if (ret != LDB_SUCCESS) {
2740                 return ret;
2741         }
2742         ret = samldb_check_user_account_control_objectclass_invariants(ac,
2743                                                                        user_account_control,
2744                                                                        user_account_control_old,
2745                                                                        is_computer_objectclass);
2746         if (ret != LDB_SUCCESS) {
2747                 return ret;
2748         }
2749
2750         ret = samldb_check_user_account_control_acl(ac, sid, user_account_control, user_account_control_old);
2751         if (ret != LDB_SUCCESS) {
2752                 return ret;
2753         }
2754
2755         uac = talloc_zero(ac->req,
2756                           struct dsdb_control_password_user_account_control);
2757         if (uac == NULL) {
2758                 return ldb_module_oom(ac->module);
2759         }
2760
2761         uac->req_flags = req_uac;
2762         uac->old_flags = user_account_control_old;
2763         uac->new_flags = user_account_control;
2764
2765         ret = ldb_request_add_control(ac->req,
2766                                 DSDB_CONTROL_PASSWORD_USER_ACCOUNT_CONTROL_OID,
2767                                 false, uac);
2768         if (ret != LDB_SUCCESS) {
2769                 return ret;
2770         }
2771
2772         return ret;
2773 }
2774
2775
2776 /**
2777  * This function is called on LDB modify operations. It performs some additions/
2778  * replaces on the current LDB message when "userAccountControl" changes.
2779  */
2780 static int samldb_user_account_control_change(struct samldb_ctx *ac)
2781 {
2782         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
2783         uint32_t old_uac;
2784         uint32_t new_uac;
2785         uint32_t raw_uac;
2786         uint32_t old_ufa;
2787         uint32_t new_ufa;
2788         uint32_t old_uac_computed;
2789         uint32_t clear_uac;
2790         uint32_t old_atype;
2791         uint32_t new_atype;
2792         uint32_t old_pgrid;
2793         uint32_t new_pgrid;
2794         NTTIME old_lockoutTime;
2795         struct ldb_message_element *el;
2796         struct ldb_val *val;
2797         struct ldb_val computer_val;
2798         struct ldb_message *tmp_msg;
2799         struct dom_sid *sid;
2800         int ret;
2801         struct ldb_result *res;
2802         const char * const attrs[] = {
2803                 "objectClass",
2804                 "isCriticalSystemObject",
2805                 "userAccountControl",
2806                 "msDS-User-Account-Control-Computed",
2807                 "lockoutTime",
2808                 "objectSid",
2809                 NULL
2810         };
2811         bool is_computer_objectclass = false;
2812         bool old_is_critical = false;
2813         bool new_is_critical = false;
2814
2815         ret = dsdb_get_expected_new_values(ac,
2816                                            ac->msg,
2817                                            "userAccountControl",
2818                                            &el,
2819                                            ac->req->operation);
2820         if (ret != LDB_SUCCESS) {
2821                 return ret;
2822         }
2823
2824         if (el == NULL || el->num_values == 0) {
2825                 ldb_asprintf_errstring(ldb,
2826                         "%08X: samldb: 'userAccountControl' can't be deleted!",
2827                         W_ERROR_V(WERR_DS_ILLEGAL_MOD_OPERATION));
2828                 return LDB_ERR_UNWILLING_TO_PERFORM;
2829         }
2830
2831         /* Create a temporary message for fetching the "userAccountControl" */
2832         tmp_msg = ldb_msg_new(ac->msg);
2833         if (tmp_msg == NULL) {
2834                 return ldb_module_oom(ac->module);
2835         }
2836         ret = ldb_msg_add(tmp_msg, el, 0);
2837         if (ret != LDB_SUCCESS) {
2838                 return ret;
2839         }
2840         raw_uac = ldb_msg_find_attr_as_uint(tmp_msg,
2841                                             "userAccountControl",
2842                                             0);
2843         talloc_free(tmp_msg);
2844         /*
2845          * UF_LOCKOUT, UF_PASSWD_CANT_CHANGE and UF_PASSWORD_EXPIRED
2846          * are only generated and not stored. We ignore them almost
2847          * completely, along with unknown bits and UF_SCRIPT.
2848          *
2849          * The only exception is ACB_AUTOLOCK, which features in
2850          * clear_acb when the bit is cleared in this modify operation.
2851          *
2852          * MS-SAMR 2.2.1.13 UF_FLAG Codes states that some bits are
2853          * ignored by clients and servers
2854          */
2855         new_uac = raw_uac & UF_SETTABLE_BITS;
2856
2857         /* Fetch the old "userAccountControl" and "objectClass" */
2858         ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, attrs,
2859                                     DSDB_FLAG_NEXT_MODULE, ac->req);
2860         if (ret != LDB_SUCCESS) {
2861                 return ret;
2862         }
2863         old_uac = ldb_msg_find_attr_as_uint(res->msgs[0], "userAccountControl", 0);
2864         if (old_uac == 0) {
2865                 return ldb_operr(ldb);
2866         }
2867         old_uac_computed = ldb_msg_find_attr_as_uint(res->msgs[0],
2868                                                      "msDS-User-Account-Control-Computed", 0);
2869         old_lockoutTime = ldb_msg_find_attr_as_int64(res->msgs[0],
2870                                                      "lockoutTime", 0);
2871         old_is_critical = ldb_msg_find_attr_as_bool(res->msgs[0],
2872                                                     "isCriticalSystemObject", 0);
2873         /*
2874          * When we do not have objectclass "computer" we cannot
2875          * switch to a workstation or (RO)DC
2876          */
2877         el = ldb_msg_find_element(res->msgs[0], "objectClass");
2878         if (el == NULL) {
2879                 return ldb_operr(ldb);
2880         }
2881         computer_val = data_blob_string_const("computer");
2882         val = ldb_msg_find_val(el, &computer_val);
2883         if (val != NULL) {
2884                 is_computer_objectclass = true;
2885         }
2886
2887         old_ufa = old_uac & UF_ACCOUNT_TYPE_MASK;
2888         old_atype = ds_uf2atype(old_ufa);
2889         old_pgrid = ds_uf2prim_group_rid(old_uac);
2890
2891         new_ufa = new_uac & UF_ACCOUNT_TYPE_MASK;
2892         if (new_ufa == 0) {
2893                 /*
2894                  * "userAccountControl" = 0 or missing one of the
2895                  * types means "UF_NORMAL_ACCOUNT".  See MS-SAMR
2896                  * 3.1.1.8.10 point 8
2897                  */
2898                 new_ufa = UF_NORMAL_ACCOUNT;
2899                 new_uac |= new_ufa;
2900         }
2901         sid = samdb_result_dom_sid(res, res->msgs[0], "objectSid");
2902         if (sid == NULL) {
2903                 return ldb_module_operr(ac->module);
2904         }
2905
2906         ret = samldb_check_user_account_control_rules(ac, sid,
2907                                                       raw_uac,
2908                                                       new_uac,
2909                                                       old_uac,
2910                                                       is_computer_objectclass);
2911         if (ret != LDB_SUCCESS) {
2912                 return ret;
2913         }
2914
2915         new_atype = ds_uf2atype(new_ufa);
2916         new_pgrid = ds_uf2prim_group_rid(new_uac);
2917
2918         clear_uac = (old_uac | old_uac_computed) & ~raw_uac;
2919
2920         switch (new_ufa) {
2921         case UF_NORMAL_ACCOUNT:
2922                 new_is_critical = old_is_critical;
2923                 break;
2924
2925         case UF_INTERDOMAIN_TRUST_ACCOUNT:
2926                 new_is_critical = true;
2927                 break;
2928
2929         case UF_WORKSTATION_TRUST_ACCOUNT:
2930                 new_is_critical = false;
2931                 if (new_uac & UF_PARTIAL_SECRETS_ACCOUNT) {
2932                         new_is_critical = true;
2933                 }
2934                 break;
2935
2936         case UF_SERVER_TRUST_ACCOUNT:
2937                 new_is_critical = true;
2938                 break;
2939
2940         default:
2941                 ldb_asprintf_errstring(ldb,
2942                         "%08X: samldb: invalid userAccountControl[0x%08X]",
2943                         W_ERROR_V(WERR_INVALID_PARAMETER), raw_uac);
2944                 return LDB_ERR_OTHER;
2945         }
2946
2947         if (old_atype != new_atype) {
2948                 ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
2949                                          "sAMAccountType", new_atype);
2950                 if (ret != LDB_SUCCESS) {
2951                         return ret;
2952                 }
2953                 el = ldb_msg_find_element(ac->msg, "sAMAccountType");
2954                 el->flags = LDB_FLAG_MOD_REPLACE;
2955         }
2956
2957         /* As per MS-SAMR 3.1.1.8.10 these flags have not to be set */
2958         if ((clear_uac & UF_LOCKOUT) && (old_lockoutTime != 0)) {
2959                 /* "lockoutTime" reset as per MS-SAMR 3.1.1.8.10 */
2960                 ldb_msg_remove_attr(ac->msg, "lockoutTime");
2961                 ret = samdb_msg_add_uint64(ldb, ac->msg, ac->msg, "lockoutTime",
2962                                            (NTTIME)0);
2963                 if (ret != LDB_SUCCESS) {
2964                         return ret;
2965                 }
2966                 el = ldb_msg_find_element(ac->msg, "lockoutTime");
2967                 el->flags = LDB_FLAG_MOD_REPLACE;
2968         }
2969
2970         /*
2971          * "isCriticalSystemObject" might be set/changed
2972          *
2973          * Even a change from UF_NORMAL_ACCOUNT (implicitly FALSE) to
2974          * UF_WORKSTATION_TRUST_ACCOUNT (actually FALSE) triggers
2975          * creating the attribute.
2976          */
2977         if (old_is_critical != new_is_critical || old_atype != new_atype) {
2978                 ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject",
2979                                          new_is_critical ? "TRUE": "FALSE");
2980                 if (ret != LDB_SUCCESS) {
2981                         return ret;
2982                 }
2983                 el = ldb_msg_find_element(ac->msg,
2984                                            "isCriticalSystemObject");
2985                 el->flags = LDB_FLAG_MOD_REPLACE;
2986         }
2987
2988         if (!ldb_msg_find_element(ac->msg, "primaryGroupID") &&
2989             (old_pgrid != new_pgrid)) {
2990                 /* Older AD deployments don't know about the RODC group */
2991                 if (new_pgrid == DOMAIN_RID_READONLY_DCS) {
2992                         ret = samldb_prim_group_tester(ac, new_pgrid);
2993                         if (ret != LDB_SUCCESS) {
2994                                 return ret;
2995                         }
2996                 }
2997
2998                 ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
2999                                          "primaryGroupID", new_pgrid);
3000                 if (ret != LDB_SUCCESS) {
3001                         return ret;
3002                 }
3003                 el = ldb_msg_find_element(ac->msg,
3004                                            "primaryGroupID");
3005                 el->flags = LDB_FLAG_MOD_REPLACE;
3006         }
3007
3008         /* Propagate eventual "userAccountControl" attribute changes */
3009         if (old_uac != new_uac) {
3010                 char *tempstr = talloc_asprintf(ac->msg, "%d",
3011                                                 new_uac);
3012                 if (tempstr == NULL) {
3013                         return ldb_module_oom(ac->module);
3014                 }
3015
3016                 ret = ldb_msg_add_empty(ac->msg,
3017                                         "userAccountControl",
3018                                         LDB_FLAG_MOD_REPLACE,
3019                                         &el);
3020                 el->values = talloc(ac->msg, struct ldb_val);
3021                 el->num_values = 1;
3022                 el->values[0].data = (uint8_t *) tempstr;
3023                 el->values[0].length = strlen(tempstr);
3024         } else {
3025                 ldb_msg_remove_attr(ac->msg, "userAccountControl");
3026         }
3027
3028         return LDB_SUCCESS;
3029 }
3030
3031 static int samldb_check_pwd_last_set_acl(struct samldb_ctx *ac,
3032                                          struct dom_sid *sid)
3033 {
3034         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
3035         int ret = 0;
3036         struct security_token *user_token = NULL;
3037         struct security_descriptor *domain_sd = NULL;
3038         struct ldb_dn *domain_dn = ldb_get_default_basedn(ldb_module_get_ctx(ac->module));
3039         const char *operation = "";
3040         const struct dsdb_class *objectclass = NULL;
3041
3042         if (dsdb_module_am_system(ac->module)) {
3043                 return LDB_SUCCESS;
3044         }
3045
3046         switch (ac->req->operation) {
3047         case LDB_ADD:
3048                 operation = "add";
3049                 break;
3050         case LDB_MODIFY:
3051                 operation = "modify";
3052                 break;
3053         default:
3054                 return ldb_module_operr(ac->module);
3055         }
3056
3057         user_token = acl_user_token(ac->module);
3058         if (user_token == NULL) {
3059                 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
3060         }
3061
3062         ret = samldb_get_domain_secdesc_and_oc(ac, &domain_sd, &objectclass);
3063         if (ret != LDB_SUCCESS) {
3064                 return ret;
3065         }
3066         ret = acl_check_extended_right(ac,
3067                                        ac->module,
3068                                        ac->req,
3069                                        objectclass,
3070                                        domain_sd,
3071                                        user_token,
3072                                        GUID_DRS_UNEXPIRE_PASSWORD,
3073                                        SEC_ADS_CONTROL_ACCESS,
3074                                        sid);
3075         if (ret != LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
3076                 return ret;
3077         }
3078
3079         ldb_debug_set(ldb, LDB_DEBUG_WARNING,
3080                       "Failed to %s %s: "
3081                       "Setting pwdLastSet to -1 requires the "
3082                       "Unexpire-Password right that was not given "
3083                       "on the Domain object",
3084                       operation,
3085                       ldb_dn_get_linearized(ac->msg->dn));
3086         dsdb_acl_debug(domain_sd, user_token,
3087                        domain_dn, true, 10);
3088
3089         return ret;
3090 }
3091
3092 /**
3093  * This function is called on LDB modify operations. It performs some additions/
3094  * replaces on the current LDB message when "pwdLastSet" changes.
3095  */
3096 static int samldb_pwd_last_set_change(struct samldb_ctx *ac)
3097 {
3098         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
3099         NTTIME last_set = 0;
3100         struct ldb_message_element *el = NULL;
3101         struct ldb_message *tmp_msg = NULL;
3102         struct dom_sid *self_sid = NULL;
3103         int ret;
3104         struct ldb_result *res = NULL;
3105         const char * const attrs[] = {
3106                 "objectSid",
3107                 NULL
3108         };
3109
3110         el = dsdb_get_single_valued_attr(ac->msg, "pwdLastSet",
3111                                          ac->req->operation);
3112         if (el == NULL || el->num_values == 0) {
3113                 ldb_asprintf_errstring(ldb,
3114                         "%08X: samldb: 'pwdLastSet' can't be deleted!",
3115                         W_ERROR_V(WERR_DS_ILLEGAL_MOD_OPERATION));
3116                 return LDB_ERR_UNWILLING_TO_PERFORM;
3117         }
3118
3119         /* Create a temporary message for fetching the "userAccountControl" */
3120         tmp_msg = ldb_msg_new(ac->msg);
3121         if (tmp_msg == NULL) {
3122                 return ldb_module_oom(ac->module);
3123         }
3124         ret = ldb_msg_add(tmp_msg, el, 0);
3125         if (ret != LDB_SUCCESS) {
3126                 return ret;
3127         }
3128         last_set = samdb_result_nttime(tmp_msg, "pwdLastSet", 0);
3129         talloc_free(tmp_msg);
3130
3131         /*
3132          * Setting -1 (0xFFFFFFFFFFFFFFFF) requires the Unexpire-Password right
3133          */
3134         if (last_set != UINT64_MAX) {
3135                 return LDB_SUCCESS;
3136         }
3137
3138         /* Fetch the "objectSid" */
3139         ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, attrs,
3140                                     DSDB_FLAG_NEXT_MODULE, ac->req);
3141         if (ret != LDB_SUCCESS) {
3142                 return ret;
3143         }
3144         self_sid = samdb_result_dom_sid(res, res->msgs[0], "objectSid");
3145         if (self_sid == NULL) {
3146                 return ldb_module_operr(ac->module);
3147         }
3148
3149         ret = samldb_check_pwd_last_set_acl(ac, self_sid);
3150         if (ret != LDB_SUCCESS) {
3151                 return ret;
3152         }
3153
3154         return LDB_SUCCESS;
3155 }
3156
3157 static int samldb_lockout_time(struct samldb_ctx *ac)
3158 {
3159         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
3160         NTTIME lockoutTime;
3161         struct ldb_message_element *el;
3162         struct ldb_message *tmp_msg;
3163         int ret;
3164
3165         el = dsdb_get_single_valued_attr(ac->msg, "lockoutTime",
3166                                          ac->req->operation);
3167         if (el == NULL || el->num_values == 0) {
3168                 ldb_asprintf_errstring(ldb,
3169                         "%08X: samldb: 'lockoutTime' can't be deleted!",
3170                         W_ERROR_V(WERR_DS_ILLEGAL_MOD_OPERATION));
3171                 return LDB_ERR_UNWILLING_TO_PERFORM;
3172         }
3173
3174         /* Create a temporary message for fetching the "lockoutTime" */
3175         tmp_msg = ldb_msg_new(ac->msg);
3176         if (tmp_msg == NULL) {
3177                 return ldb_module_oom(ac->module);
3178         }
3179         ret = ldb_msg_add(tmp_msg, el, 0);
3180         if (ret != LDB_SUCCESS) {
3181                 return ret;
3182         }
3183         lockoutTime = ldb_msg_find_attr_as_int64(tmp_msg,
3184                                                  "lockoutTime",
3185                                                  0);
3186         talloc_free(tmp_msg);
3187
3188         if (lockoutTime != 0) {
3189                 return LDB_SUCCESS;
3190         }
3191
3192         /* lockoutTime == 0 resets badPwdCount */
3193         ldb_msg_remove_attr(ac->msg, "badPwdCount");
3194         ret = samdb_msg_add_int(ldb, ac->msg, ac->msg,
3195                                 "badPwdCount", 0);
3196         if (ret != LDB_SUCCESS) {
3197                 return ret;
3198         }
3199         el = ldb_msg_find_element(ac->msg, "badPwdCount");
3200         el->flags = LDB_FLAG_MOD_REPLACE;
3201
3202         return LDB_SUCCESS;
3203 }
3204
3205 static int samldb_group_type_change(struct samldb_ctx *ac)
3206 {
3207         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
3208         uint32_t group_type, old_group_type, account_type;
3209         struct ldb_message_element *el;
3210         struct ldb_message *tmp_msg;
3211         int ret;
3212         struct ldb_result *res;
3213         const char * const attrs[] = { "groupType", NULL };
3214
3215         el = dsdb_get_single_valued_attr(ac->msg, "groupType",
3216                                          ac->req->operation);
3217         if (el == NULL) {
3218                 /* we are not affected */
3219                 return LDB_SUCCESS;
3220         }
3221
3222         /* Create a temporary message for fetching the "groupType" */
3223         tmp_msg = ldb_msg_new(ac->msg);
3224         if (tmp_msg == NULL) {
3225                 return ldb_module_oom(ac->module);
3226         }
3227         ret = ldb_msg_add(tmp_msg, el, 0);
3228         if (ret != LDB_SUCCESS) {
3229                 return ret;
3230         }
3231         group_type = ldb_msg_find_attr_as_uint(tmp_msg, "groupType", 0);
3232         talloc_free(tmp_msg);
3233
3234         ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, attrs,
3235                                     DSDB_FLAG_NEXT_MODULE |
3236                                     DSDB_SEARCH_SHOW_DELETED, ac->req);
3237         if (ret != LDB_SUCCESS) {
3238                 return ret;
3239         }
3240         old_group_type = ldb_msg_find_attr_as_uint(res->msgs[0], "groupType", 0);
3241         if (old_group_type == 0) {
3242                 return ldb_operr(ldb);
3243         }
3244
3245         /* Group type switching isn't so easy as it seems: We can only
3246          * change in this directions: global <-> universal <-> local
3247          * On each step also the group type itself
3248          * (security/distribution) is variable. */
3249
3250         if (ldb_request_get_control(ac->req, LDB_CONTROL_PROVISION_OID) == NULL) {
3251                 switch (group_type) {
3252                 case GTYPE_SECURITY_GLOBAL_GROUP:
3253                 case GTYPE_DISTRIBUTION_GLOBAL_GROUP:
3254                         /* change to "universal" allowed */
3255                         if ((old_group_type == GTYPE_SECURITY_DOMAIN_LOCAL_GROUP) ||
3256                         (old_group_type == GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)) {
3257                                 ldb_set_errstring(ldb,
3258                                         "samldb: Change from security/distribution local group forbidden!");
3259                                 return LDB_ERR_UNWILLING_TO_PERFORM;
3260                         }
3261                 break;
3262
3263                 case GTYPE_SECURITY_UNIVERSAL_GROUP:
3264                 case GTYPE_DISTRIBUTION_UNIVERSAL_GROUP:
3265                         /* each change allowed */
3266                 break;
3267                 case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
3268                 case GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP:
3269                         /* change to "universal" allowed */
3270                         if ((old_group_type == GTYPE_SECURITY_GLOBAL_GROUP) ||
3271                         (old_group_type == GTYPE_DISTRIBUTION_GLOBAL_GROUP)) {
3272                                 ldb_set_errstring(ldb,
3273                                         "samldb: Change from security/distribution global group forbidden!");
3274                                 return LDB_ERR_UNWILLING_TO_PERFORM;
3275                         }
3276                 break;
3277
3278                 case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
3279                 default:
3280                         /* we don't allow this "groupType" values */
3281                         return LDB_ERR_UNWILLING_TO_PERFORM;
3282                 break;
3283                 }
3284         }
3285
3286         account_type =  ds_gtype2atype(group_type);
3287         if (account_type == 0) {
3288                 ldb_set_errstring(ldb, "samldb: Unrecognized account type!");
3289                 return LDB_ERR_UNWILLING_TO_PERFORM;
3290         }
3291         ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "sAMAccountType",
3292                                  account_type);
3293         if (ret != LDB_SUCCESS) {
3294                 return ret;
3295         }
3296         el = ldb_msg_find_element(ac->msg, "sAMAccountType");
3297         el->flags = LDB_FLAG_MOD_REPLACE;
3298
3299         return LDB_SUCCESS;
3300 }
3301
3302 static int samldb_member_check(struct samldb_ctx *ac)
3303 {
3304         const char * const attrs[] = { "objectSid", NULL };
3305         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
3306         struct ldb_message_element *el;
3307         struct ldb_dn *member_dn;
3308         struct dom_sid *sid;
3309         struct ldb_result *res;
3310         struct dom_sid *group_sid;
3311         unsigned int i, j;
3312         int ret;
3313
3314         /* Fetch information from the existing object */
3315
3316         ret = dsdb_module_search(ac->module, ac, &res, ac->msg->dn, LDB_SCOPE_BASE, attrs,
3317                                  DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED, ac->req, NULL);
3318         if (ret != LDB_SUCCESS) {
3319                 return ret;
3320         }
3321         if (res->count != 1) {
3322                 return ldb_operr(ldb);
3323         }
3324
3325         group_sid = samdb_result_dom_sid(res, res->msgs[0], "objectSid");
3326         if (group_sid == NULL) {
3327                 return ldb_operr(ldb);
3328         }
3329
3330         /* We've to walk over all modification entries and consider the "member"
3331          * ones. */
3332         for (i = 0; i < ac->msg->num_elements; i++) {
3333                 if (ldb_attr_cmp(ac->msg->elements[i].name, "member") != 0) {
3334                         continue;
3335                 }
3336
3337                 el = &ac->msg->elements[i];
3338                 for (j = 0; j < el->num_values; j++) {
3339                         struct ldb_result *group_res;
3340                         const char *group_attrs[] = { "primaryGroupID" , NULL };
3341                         uint32_t prim_group_rid;
3342
3343                         if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE) {
3344                                 /* Deletes will be handled in
3345                                  * repl_meta_data, and deletes not
3346                                  * matching a member will return
3347                                  * LDB_ERR_UNWILLING_TO_PERFORM
3348                                  * there */
3349                                 continue;
3350                         }
3351
3352                         member_dn = ldb_dn_from_ldb_val(ac, ldb,
3353                                                         &el->values[j]);
3354                         if (!ldb_dn_validate(member_dn)) {
3355                                 return ldb_operr(ldb);
3356                         }
3357
3358                         /* Denies to add "member"s to groups which are primary
3359                          * ones for them - in this case return
3360                          * ERR_ENTRY_ALREADY_EXISTS. */
3361
3362                         ret = dsdb_module_search_dn(ac->module, ac, &group_res,
3363                                                     member_dn, group_attrs,
3364                                                     DSDB_FLAG_NEXT_MODULE, ac->req);
3365                         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
3366                                 /* member DN doesn't exist yet */
3367                                 continue;
3368                         }
3369                         if (ret != LDB_SUCCESS) {
3370                                 return ret;
3371                         }
3372                         prim_group_rid = ldb_msg_find_attr_as_uint(group_res->msgs[0], "primaryGroupID", (uint32_t)-1);
3373                         if (prim_group_rid == (uint32_t) -1) {
3374                                 /* the member hasn't to be a user account ->
3375                                  * therefore no check needed in this case. */
3376                                 continue;
3377                         }
3378
3379                         sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb),
3380                                               prim_group_rid);
3381                         if (sid == NULL) {
3382                                 return ldb_operr(ldb);
3383                         }
3384
3385                         if (dom_sid_equal(group_sid, sid)) {
3386                                 ldb_asprintf_errstring(ldb,
3387                                                        "samldb: member %s already set via primaryGroupID %u",
3388                                                        ldb_dn_get_linearized(member_dn), prim_group_rid);
3389                                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
3390                         }
3391                 }
3392         }
3393
3394         talloc_free(res);
3395
3396         return LDB_SUCCESS;
3397 }
3398
3399 /* SAM objects have special rules regarding the "description" attribute on
3400  * modify operations. */
3401 static int samldb_description_check(struct samldb_ctx *ac, bool *modified)
3402 {
3403         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
3404         const char * const attrs[] = { "objectClass", "description", NULL };
3405         struct ldb_result *res;
3406         unsigned int i;
3407         int ret;
3408
3409         /* Fetch information from the existing object */
3410         ret = dsdb_module_search(ac->module, ac, &res, ac->msg->dn, LDB_SCOPE_BASE, attrs,
3411                                  DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED, ac->req,
3412                                  "(|(objectclass=user)(objectclass=group)(objectclass=samDomain)(objectclass=samServer))");
3413         if (ret != LDB_SUCCESS) {
3414                 /* don't treat it specially ... let normal error codes
3415                    happen from other places */
3416                 ldb_reset_err_string(ldb);
3417                 return LDB_SUCCESS;
3418         }
3419         if (res->count == 0) {
3420                 /* we didn't match the filter */
3421                 talloc_free(res);
3422                 return LDB_SUCCESS;
3423         }
3424
3425         /* We've to walk over all modification entries and consider the
3426          * "description" ones. */
3427         for (i = 0; i < ac->msg->num_elements; i++) {
3428                 if (ldb_attr_cmp(ac->msg->elements[i].name, "description") == 0) {
3429                         ac->msg->elements[i].flags |= LDB_FLAG_INTERNAL_FORCE_SINGLE_VALUE_CHECK;
3430                         *modified = true;
3431                 }
3432         }
3433
3434         talloc_free(res);
3435
3436         return LDB_SUCCESS;
3437 }
3438
3439 #define SPN_ALIAS_NONE 0
3440 #define SPN_ALIAS_LINK 1
3441 #define SPN_ALIAS_TARGET 2
3442
3443 static int find_spn_aliases(struct ldb_context *ldb,
3444                             TALLOC_CTX *mem_ctx,
3445                             const char *service_class,
3446                             char ***aliases,
3447                             size_t *n_aliases,
3448                             int *direction)
3449 {
3450         /*
3451          * If you change the way this works, you should also look at changing
3452          * LDB_lookup_spn_alias() in source4/dsdb/samdb/cracknames.c, which
3453          * does some of the same work.
3454          *
3455          * In particular, note that sPNMappings are resolved on a first come,
3456          * first served basis. For example, if we have
3457          *
3458          *  host=ldap,cifs
3459          *  foo=ldap
3460          *  cifs=host,alerter
3461          *
3462          * then 'ldap', 'cifs', and 'host' will resolve to 'host', and
3463          * 'alerter' will resolve to 'cifs'.
3464          *
3465          * If this resolution method is made more complicated, then the
3466          * cracknames function should also be changed.
3467          */
3468         size_t i, j;
3469         int ret;
3470         bool ok;
3471         struct ldb_result *res = NULL;
3472         struct ldb_message_element *spnmappings = NULL;
3473         TALLOC_CTX *tmp_ctx = NULL;
3474         struct ldb_dn *service_dn = NULL;
3475
3476         const char *attrs[] = {
3477                 "sPNMappings",
3478                 NULL
3479         };
3480
3481         *direction = SPN_ALIAS_NONE;
3482
3483         tmp_ctx = talloc_new(mem_ctx);
3484         if (tmp_ctx == NULL) {
3485                 return ldb_oom(ldb);
3486         }
3487
3488         service_dn = ldb_dn_new(
3489                 tmp_ctx, ldb,
3490                 "CN=Directory Service,CN=Windows NT,CN=Services");
3491         if (service_dn == NULL) {
3492                 talloc_free(tmp_ctx);
3493                 return ldb_oom(ldb);
3494         }
3495
3496         ok = ldb_dn_add_base(service_dn, ldb_get_config_basedn(ldb));
3497         if (! ok) {
3498                 talloc_free(tmp_ctx);
3499                 return LDB_ERR_OPERATIONS_ERROR;
3500         }
3501
3502         ret = ldb_search(ldb, tmp_ctx, &res, service_dn, LDB_SCOPE_BASE,
3503                          attrs, "(objectClass=nTDSService)");
3504
3505         if (ret != LDB_SUCCESS || res->count != 1) {
3506                 DBG_WARNING("sPNMappings not found.\n");
3507                 talloc_free(tmp_ctx);
3508                 return ret;
3509         }
3510
3511         spnmappings = ldb_msg_find_element(res->msgs[0], "sPNMappings");
3512         if (spnmappings == NULL || spnmappings->num_values == 0) {
3513                 DBG_WARNING("no sPNMappings attribute\n");
3514                 talloc_free(tmp_ctx);
3515                 return LDB_ERR_NO_SUCH_OBJECT;
3516         }
3517         *n_aliases = 0;
3518
3519         for (i = 0; i < spnmappings->num_values; i++) {
3520                 char *p = NULL;
3521                 char *mapping = talloc_strndup(
3522                         tmp_ctx,
3523                         (char *)spnmappings->values[i].data,
3524                         spnmappings->values[i].length);
3525                 if (mapping == NULL) {
3526                         talloc_free(tmp_ctx);
3527                         return ldb_oom(ldb);
3528                 }
3529
3530                 p = strchr(mapping, '=');
3531                 if (p == NULL) {
3532                         talloc_free(tmp_ctx);
3533                         return LDB_ERR_ALIAS_PROBLEM;
3534                 }
3535                 p[0] = '\0';
3536                 p++;
3537
3538                 if (strcasecmp(mapping, service_class) == 0) {
3539                         /*
3540                          * We need to return the reverse aliases for this one.
3541                          *
3542                          * typically, this means the service_class is "host"
3543                          * and the mapping is "host=alerter,appmgmt,cisvc,..",
3544                          * so we get "alerter", "appmgmt", etc in the list of
3545                          * aliases.
3546                          */
3547
3548                         /* There is one more field than there are commas */
3549                         size_t n = 1;
3550
3551                         for (j = 0; p[j] != '\0'; j++) {
3552                                 if (p[j] == ',') {
3553                                         n++;
3554                                         p[j] = '\0';
3555                                 }
3556                         }
3557                         *aliases = talloc_array(mem_ctx, char*, n);
3558                         if (*aliases == NULL) {
3559                                 talloc_free(tmp_ctx);
3560                                 return ldb_oom(ldb);
3561                         }
3562                         *n_aliases = n;
3563                         talloc_steal(mem_ctx, mapping);
3564                         for (j = 0; j < n; j++) {
3565                                 (*aliases)[j] = p;
3566                                 p += strlen(p) + 1;
3567                         }
3568                         talloc_free(tmp_ctx);
3569                         *direction = SPN_ALIAS_LINK;
3570                         return LDB_SUCCESS;
3571                 }
3572                 /*
3573                  * We need to look along the list to see if service_class is
3574                  * there; if so, we return a list of one item (probably "host").
3575                  */
3576                 do {
3577                         char *str = p;
3578                         p = strchr(p, ',');
3579                         if (p != NULL) {
3580                                 p[0] = '\0';
3581                                 p++;
3582                         }
3583                         if (strcasecmp(str, service_class) == 0) {
3584                                 *aliases = talloc_array(mem_ctx, char*, 1);
3585                                 if (*aliases == NULL) {
3586                                         talloc_free(tmp_ctx);
3587                                         return ldb_oom(ldb);
3588                                 }
3589                                 *n_aliases = 1;
3590                                 (*aliases)[0] = mapping;
3591                                 talloc_steal(mem_ctx, mapping);
3592                                 talloc_free(tmp_ctx);
3593                                 *direction = SPN_ALIAS_TARGET;
3594                                 return LDB_SUCCESS;
3595                         }
3596                 } while (p != NULL);
3597         }
3598         DBG_INFO("no sPNMappings alias for '%s'\n", service_class);
3599         talloc_free(tmp_ctx);
3600         *aliases = NULL;
3601         *n_aliases = 0;
3602         return LDB_SUCCESS;
3603 }
3604
3605
3606 static int get_spn_dn(struct ldb_context *ldb,
3607                       TALLOC_CTX *tmp_ctx,
3608                       const char *candidate,
3609                       struct ldb_dn **dn)
3610 {
3611         int ret;
3612         const char *empty_attrs[] = { NULL };
3613         struct ldb_message *msg = NULL;
3614         struct ldb_dn *base_dn = ldb_get_default_basedn(ldb);
3615
3616         const char *enc_candidate = NULL;
3617
3618         *dn = NULL;
3619
3620         enc_candidate = ldb_binary_encode_string(tmp_ctx, candidate);
3621         if (enc_candidate == NULL) {
3622                 return ldb_operr(ldb);
3623         }
3624
3625         ret = dsdb_search_one(ldb,
3626                               tmp_ctx,
3627                               &msg,
3628                               base_dn,
3629                               LDB_SCOPE_SUBTREE,
3630                               empty_attrs,
3631                               0,
3632                               "(servicePrincipalName=%s)",
3633                               enc_candidate);
3634         if (ret != LDB_SUCCESS) {
3635                 return ret;
3636         }
3637         *dn = msg->dn;
3638         return LDB_SUCCESS;
3639 }
3640
3641
3642 static int check_spn_write_rights(struct ldb_context *ldb,
3643                                   TALLOC_CTX *mem_ctx,
3644                                   const char *spn,
3645                                   struct ldb_dn *dn)
3646 {
3647         int ret;
3648         struct ldb_message *msg = NULL;
3649         struct ldb_message_element *del_el = NULL;
3650         struct ldb_message_element *add_el = NULL;
3651         struct ldb_val val = {
3652                 .data = discard_const_p(uint8_t, spn),
3653                 .length = strlen(spn)
3654         };
3655
3656         msg = ldb_msg_new(mem_ctx);
3657         if (msg == NULL) {
3658                 return ldb_oom(ldb);
3659         }
3660         msg->dn = dn;
3661
3662         ret = ldb_msg_add_empty(msg,
3663                                 "servicePrincipalName",
3664                                 LDB_FLAG_MOD_DELETE,
3665                                 &del_el);
3666         if (ret != LDB_SUCCESS) {
3667                 talloc_free(msg);
3668                 return ret;
3669         }
3670
3671         del_el->values = talloc_array(msg->elements, struct ldb_val, 1);
3672         if (del_el->values == NULL) {
3673                 talloc_free(msg);
3674                 return ret;
3675         }
3676
3677         del_el->values[0] = val;
3678         del_el->num_values = 1;
3679
3680         ret = ldb_msg_add_empty(msg,
3681                                 "servicePrincipalName",
3682                                 LDB_FLAG_MOD_ADD,
3683                                 &add_el);
3684         if (ret != LDB_SUCCESS) {
3685                 talloc_free(msg);
3686                 return ret;
3687         }
3688
3689         add_el->values = talloc_array(msg->elements, struct ldb_val, 1);
3690         if (add_el->values == NULL) {
3691                 talloc_free(msg);
3692                 return ret;
3693         }
3694
3695         add_el->values[0] = val;
3696         add_el->num_values = 1;
3697
3698         ret = ldb_modify(ldb, msg);
3699         if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
3700                 DBG_ERR("hmm I think we're OK, but not sure\n");
3701         } else if (ret != LDB_SUCCESS) {
3702                 DBG_ERR("SPN write rights check failed with %d\n", ret);
3703                 talloc_free(msg);
3704                 return ret;
3705         }
3706         talloc_free(msg);
3707         return LDB_SUCCESS;
3708 }
3709
3710
3711 static int check_spn_alias_collision(struct ldb_context *ldb,
3712                                      TALLOC_CTX *mem_ctx,
3713                                      const char *spn,
3714                                      struct ldb_dn *target_dn)
3715 {
3716         int ret;
3717         char *service_class = NULL;
3718         char *spn_tail = NULL;
3719         char *p = NULL;
3720         char **aliases = NULL;
3721         size_t n_aliases = 0;
3722         size_t i, len;
3723         TALLOC_CTX *tmp_ctx = NULL;
3724         const char *target_dnstr = ldb_dn_get_linearized(target_dn);
3725         int link_direction;
3726
3727         tmp_ctx = talloc_new(mem_ctx);
3728         if (tmp_ctx == NULL) {
3729                 return ldb_oom(ldb);
3730         }
3731
3732         /*
3733          * "dns/example.com/xxx"  gives
3734          *    service_class = "dns"
3735          *    spn_tail      = "example.com/xxx"
3736          */
3737         p = strchr(spn, '/');
3738         if (p == NULL) {
3739                 /* bad SPN */
3740                 talloc_free(tmp_ctx);
3741                 return ldb_error(ldb,
3742                                  LDB_ERR_OPERATIONS_ERROR,
3743                                  "malformed servicePrincipalName");
3744         }
3745         len = p - spn;
3746
3747         service_class = talloc_strndup(tmp_ctx, spn, len);
3748         if (service_class == NULL) {
3749                 talloc_free(tmp_ctx);
3750                 return ldb_oom(ldb);
3751         }
3752         spn_tail = p + 1;
3753
3754         ret = find_spn_aliases(ldb,
3755                                tmp_ctx,
3756                                service_class,
3757                                &aliases,
3758                                &n_aliases,
3759                                &link_direction);
3760         if (ret != LDB_SUCCESS) {
3761                 talloc_free(tmp_ctx);
3762                 return ret;
3763         }
3764
3765         /*
3766          * we have the list of aliases, and now we need to combined them with
3767          * spn_tail and see if we can find the SPN.
3768          */
3769         for (i = 0; i < n_aliases; i++) {
3770                 struct ldb_dn *colliding_dn = NULL;
3771                 const char *colliding_dnstr = NULL;
3772
3773                 char *candidate = talloc_asprintf(tmp_ctx,
3774                                                   "%s/%s",
3775                                                   aliases[i],
3776                                                   spn_tail);
3777                 if (candidate == NULL) {
3778                         talloc_free(tmp_ctx);
3779                         return ldb_oom(ldb);
3780                 }
3781
3782                 ret = get_spn_dn(ldb, tmp_ctx, candidate, &colliding_dn);
3783                 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
3784                         DBG_DEBUG("SPN alias '%s' not found (good)\n",
3785                                   candidate);
3786                         talloc_free(candidate);
3787                         continue;
3788                 }
3789                 if (ret != LDB_SUCCESS) {
3790                         DBG_ERR("SPN '%s' search error %d\n", candidate, ret);
3791                         talloc_free(tmp_ctx);
3792                         return ret;
3793                 }
3794
3795                 target_dnstr = ldb_dn_get_linearized(target_dn);
3796                 /*
3797                  * We have found an existing SPN that matches the alias. That
3798                  * is OK only if it is on the object we are trying to add to,
3799                  * or if the SPN on the other side is a more generic alias for
3800                  * this one and we also have rights to modify it.
3801                  *
3802                  * That is, we can put "host/X" and "cifs/X" on the same
3803                  * object, but not on different objects, unless we put the
3804                  * host/X on first, and could also change that object when we
3805                  * add cifs/X. It is forbidden to add the objects in the other
3806                  * order.
3807                  *
3808                  * The rationale for this is that adding "cifs/X" effectively
3809                  * changes "host/X" by diverting traffic. If "host/X" can be
3810                  * added after "cifs/X", a sneaky person could get "cifs/X" in
3811                  * first, making "host/X" have less effect than intended.
3812                  *
3813                  * Note: we also can't have "host/X" and "Host/X" on the same
3814                  * object, but that is not relevant here.
3815                  */
3816
3817                 ret = ldb_dn_compare(colliding_dn, target_dn);
3818                 if (ret != 0) {
3819                         colliding_dnstr = ldb_dn_get_linearized(colliding_dn);
3820                         DBG_ERR("trying to add SPN '%s' on '%s' when '%s' is "
3821                                 "on '%s'\n",
3822                                 spn,
3823                                 target_dnstr,
3824                                 candidate,
3825                                 colliding_dnstr);
3826
3827                         if (link_direction == SPN_ALIAS_LINK) {
3828                                 /* we don't allow host/X if there is a
3829                                  * cifs/X */
3830                                 talloc_free(tmp_ctx);
3831                                 return LDB_ERR_CONSTRAINT_VIOLATION;
3832                         }
3833                         ret = check_spn_write_rights(ldb,
3834                                                      tmp_ctx,
3835                                                      candidate,
3836                                                      colliding_dn);
3837                         if (ret != LDB_SUCCESS) {
3838                                 DBG_ERR("SPN '%s' is on '%s' so '%s' can't be "
3839                                         "added to '%s'\n",
3840                                         candidate,
3841                                         colliding_dnstr,
3842                                         spn,
3843                                         target_dnstr);
3844                                 talloc_free(tmp_ctx);
3845                                 ldb_asprintf_errstring(ldb,
3846                                                        "samldb: spn[%s] would cause a conflict",
3847                                                        spn);
3848                                 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
3849                         }
3850                 } else {
3851                         DBG_INFO("SPNs '%s' and '%s' alias both on '%s'\n",
3852                                  candidate, spn, target_dnstr);
3853                 }
3854                 talloc_free(candidate);
3855         }
3856
3857         talloc_free(tmp_ctx);
3858         return LDB_SUCCESS;
3859 }
3860
3861 static int check_spn_direct_collision(struct ldb_context *ldb,
3862                                       TALLOC_CTX *mem_ctx,
3863                                       const char *spn,
3864                                       struct ldb_dn *target_dn)
3865 {
3866         int ret;
3867         TALLOC_CTX *tmp_ctx = NULL;
3868         struct ldb_dn *colliding_dn = NULL;
3869         const char *target_dnstr = NULL;
3870         const char *colliding_dnstr = NULL;
3871
3872         tmp_ctx = talloc_new(mem_ctx);
3873         if (tmp_ctx == NULL) {
3874                 return ldb_oom(ldb);
3875         }
3876
3877         ret = get_spn_dn(ldb, tmp_ctx, spn, &colliding_dn);
3878         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
3879                 DBG_DEBUG("SPN '%s' not found (good)\n", spn);
3880                 talloc_free(tmp_ctx);
3881                 return LDB_SUCCESS;
3882         }
3883         if (ret != LDB_SUCCESS) {
3884                 DBG_ERR("SPN '%s' search error %d\n", spn, ret);
3885                 talloc_free(tmp_ctx);
3886                 if (ret == LDB_ERR_COMPARE_TRUE) {
3887                         /*
3888                          * COMPARE_TRUE has special meaning here and we don't
3889                          * want to return it by mistake.
3890                          */
3891                         ret = LDB_ERR_OPERATIONS_ERROR;
3892                 }
3893                 return ret;
3894         }
3895         /*
3896          * We have found this exact SPN. This is mostly harmless (depend on
3897          * ADD vs REPLACE) when the spn is being put on the object that
3898          * already has, so we let it through to succeed or fail as some other
3899          * module sees fit.
3900          */
3901         target_dnstr = ldb_dn_get_linearized(target_dn);
3902         ret = ldb_dn_compare(colliding_dn, target_dn);
3903         if (ret != 0) {
3904                 colliding_dnstr = ldb_dn_get_linearized(colliding_dn);
3905                 DBG_ERR("SPN '%s' is on '%s' so it can't be "
3906                         "added to '%s'\n",
3907                         spn,
3908                         colliding_dnstr,
3909                         target_dnstr);
3910                 ldb_asprintf_errstring(ldb,
3911                                        "samldb: spn[%s] would cause a conflict",
3912                                        spn);
3913                 talloc_free(tmp_ctx);
3914                 return LDB_ERR_CONSTRAINT_VIOLATION;
3915         }
3916
3917         DBG_INFO("SPN '%s' is already on '%s'\n",
3918                  spn, target_dnstr);
3919         talloc_free(tmp_ctx);
3920         return LDB_ERR_COMPARE_TRUE;
3921 }
3922
3923
3924 static int count_spn_components(struct ldb_val val)
3925 {
3926         /*
3927          * a 3 part servicePrincipalName has two slashes, like
3928          * ldap/example.com/DomainDNSZones.example.com.
3929          *
3930          * In krb5_parse_name_flags() we don't count "\/" as a slash (i.e.
3931          * escaped by a backslash), but this is not the behaviour of Windows
3932          * on setting a servicePrincipalName -- slashes are counted regardless
3933          * of backslashes.
3934          *
3935          * Accordingly, here we ignore backslashes. This will reject
3936          * multi-slash SPNs that krb5_parse_name_flags() would accept, and
3937          * allow ones in the form "a\/b" that it won't parse.
3938          */
3939         size_t i;
3940         int slashes = 0;
3941         for (i = 0; i < val.length; i++) {
3942                 char c = val.data[i];
3943                 if (c == '/') {
3944                         slashes++;
3945                         if (slashes == 3) {
3946                                 /* at this point we don't care */
3947                                 return 4;
3948                         }
3949                 }
3950         }
3951         return slashes + 1;
3952 }
3953
3954
3955 /* Check that "servicePrincipalName" changes do not introduce a collision
3956  * globally. */
3957 static int samldb_spn_uniqueness_check(struct samldb_ctx *ac,
3958                                        struct ldb_message_element *spn_el)
3959 {
3960         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
3961         int ret;
3962         const char *spn = NULL;
3963         size_t i;
3964         TALLOC_CTX *tmp_ctx = talloc_new(ac->msg);
3965         if (tmp_ctx == NULL) {
3966                 return ldb_oom(ldb);
3967         }
3968
3969         for (i = 0; i < spn_el->num_values; i++) {
3970                 int n_components;
3971                 spn = (char *)spn_el->values[i].data;
3972
3973                 n_components = count_spn_components(spn_el->values[i]);
3974                 if (n_components > 3 || n_components < 2) {
3975                         ldb_asprintf_errstring(ldb,
3976                                                "samldb: spn[%s] invalid with %u components",
3977                                                spn, n_components);
3978                         talloc_free(tmp_ctx);
3979                         return LDB_ERR_CONSTRAINT_VIOLATION;
3980                 }
3981
3982                 ret = check_spn_direct_collision(ldb,
3983                                                  tmp_ctx,
3984                                                  spn,
3985                                                  ac->msg->dn);
3986                 if (ret == LDB_ERR_COMPARE_TRUE) {
3987                         DBG_INFO("SPN %s re-added to the same object\n", spn);
3988                         talloc_free(tmp_ctx);
3989                         return LDB_SUCCESS;
3990                 }
3991                 if (ret != LDB_SUCCESS) {
3992                         DBG_ERR("SPN %s failed direct uniqueness check\n", spn);
3993                         talloc_free(tmp_ctx);
3994                         return ret;
3995                 }
3996
3997                 ret = check_spn_alias_collision(ldb,
3998                                                 tmp_ctx,
3999                                                 spn,
4000                                                 ac->msg->dn);
4001
4002                 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
4003                         /* we have no sPNMappings, hence no aliases */
4004                         break;
4005                 }
4006                 if (ret != LDB_SUCCESS) {
4007                         DBG_ERR("SPN %s failed alias uniqueness check\n", spn);
4008                         talloc_free(tmp_ctx);
4009                         return ret;
4010                 }
4011                 DBG_INFO("SPN %s seems to be unique\n", spn);
4012         }
4013
4014         talloc_free(tmp_ctx);
4015         return LDB_SUCCESS;
4016 }
4017
4018
4019
4020 /* This trigger adapts the "servicePrincipalName" attributes if the
4021  * "dNSHostName" and/or "sAMAccountName" attribute change(s) */
4022 static int samldb_service_principal_names_change(struct samldb_ctx *ac)
4023 {
4024         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
4025         struct ldb_message_element *el = NULL, *el2 = NULL;
4026         struct ldb_message *msg;
4027         const char * const attrs[] = { "servicePrincipalName", NULL };
4028         struct ldb_result *res;
4029         const char *dns_hostname = NULL, *old_dns_hostname = NULL,
4030                    *sam_accountname = NULL, *old_sam_accountname = NULL;
4031         unsigned int i, j;
4032         int ret;
4033
4034         el = dsdb_get_single_valued_attr(ac->msg, "dNSHostName",
4035                                          ac->req->operation);
4036         el2 = dsdb_get_single_valued_attr(ac->msg, "sAMAccountName",
4037                                           ac->req->operation);
4038         if ((el == NULL) && (el2 == NULL)) {
4039                 /* we are not affected */
4040                 return LDB_SUCCESS;
4041         }
4042
4043         /* Create a temporary message for fetching the "dNSHostName" */
4044         if (el != NULL) {
4045                 const char *dns_attrs[] = { "dNSHostName", NULL };
4046                 msg = ldb_msg_new(ac->msg);
4047                 if (msg == NULL) {
4048                         return ldb_module_oom(ac->module);
4049                 }
4050                 ret = ldb_msg_add(msg, el, 0);
4051                 if (ret != LDB_SUCCESS) {
4052                         return ret;
4053                 }
4054                 dns_hostname = talloc_strdup(ac,
4055                                              ldb_msg_find_attr_as_string(msg, "dNSHostName", NULL));
4056                 if (dns_hostname == NULL) {
4057                         return ldb_module_oom(ac->module);
4058                 }
4059
4060                 talloc_free(msg);
4061
4062                 ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn,
4063                                             dns_attrs, DSDB_FLAG_NEXT_MODULE, ac->req);
4064                 if (ret == LDB_SUCCESS) {
4065                         old_dns_hostname = ldb_msg_find_attr_as_string(res->msgs[0], "dNSHostName", NULL);
4066                 }
4067         }
4068
4069         /* Create a temporary message for fetching the "sAMAccountName" */
4070         if (el2 != NULL) {
4071                 char *tempstr, *tempstr2 = NULL;
4072                 const char *acct_attrs[] = { "sAMAccountName", NULL };
4073
4074                 msg = ldb_msg_new(ac->msg);
4075                 if (msg == NULL) {
4076                         return ldb_module_oom(ac->module);
4077                 }
4078                 ret = ldb_msg_add(msg, el2, 0);
4079                 if (ret != LDB_SUCCESS) {
4080                         return ret;
4081                 }
4082                 tempstr = talloc_strdup(ac,
4083                                         ldb_msg_find_attr_as_string(msg, "sAMAccountName", NULL));
4084                 talloc_free(msg);
4085
4086                 ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, acct_attrs,
4087                                             DSDB_FLAG_NEXT_MODULE, ac->req);
4088                 if (ret == LDB_SUCCESS) {
4089                         tempstr2 = talloc_strdup(ac,
4090                                                  ldb_msg_find_attr_as_string(res->msgs[0],
4091                                                                              "sAMAccountName", NULL));
4092                 }
4093
4094
4095                 /* The "sAMAccountName" needs some additional trimming: we need
4096                  * to remove the trailing "$"s if they exist. */
4097                 if ((tempstr != NULL) && (tempstr[0] != '\0') &&
4098                     (tempstr[strlen(tempstr) - 1] == '$')) {
4099                         tempstr[strlen(tempstr) - 1] = '\0';
4100                 }
4101                 if ((tempstr2 != NULL) && (tempstr2[0] != '\0') &&
4102                     (tempstr2[strlen(tempstr2) - 1] == '$')) {
4103                         tempstr2[strlen(tempstr2) - 1] = '\0';
4104                 }
4105                 sam_accountname = tempstr;
4106                 old_sam_accountname = tempstr2;
4107         }
4108
4109         if (old_dns_hostname == NULL) {
4110                 /* we cannot change when the old name is unknown */
4111                 dns_hostname = NULL;
4112         }
4113         if ((old_dns_hostname != NULL) && (dns_hostname != NULL) &&
4114             (strcasecmp_m(old_dns_hostname, dns_hostname) == 0)) {
4115                 /* The "dNSHostName" didn't change */
4116                 dns_hostname = NULL;
4117         }
4118
4119         if (old_sam_accountname == NULL) {
4120                 /* we cannot change when the old name is unknown */
4121                 sam_accountname = NULL;
4122         }
4123         if ((old_sam_accountname != NULL) && (sam_accountname != NULL) &&
4124             (strcasecmp_m(old_sam_accountname, sam_accountname) == 0)) {
4125                 /* The "sAMAccountName" didn't change */
4126                 sam_accountname = NULL;
4127         }
4128
4129         if ((dns_hostname == NULL) && (sam_accountname == NULL)) {
4130                 /* Well, there are information missing (old name(s)) or the
4131                  * names didn't change. We've nothing to do and can exit here */
4132                 return LDB_SUCCESS;
4133         }
4134
4135         /*
4136          * Potential "servicePrincipalName" changes in the same request have
4137          * to be handled before the update (Windows behaviour).
4138          *
4139          * We extract the SPN changes into a new message and run it through
4140          * the stack from this module, so that it subjects them to the SPN
4141          * checks we have here.
4142          */
4143         el = ldb_msg_find_element(ac->msg, "servicePrincipalName");
4144         if (el != NULL) {
4145                 msg = ldb_msg_new(ac->msg);
4146                 if (msg == NULL) {
4147                         return ldb_module_oom(ac->module);
4148                 }
4149                 msg->dn = ac->msg->dn;
4150
4151                 do {
4152                         ret = ldb_msg_add(msg, el, el->flags);
4153                         if (ret != LDB_SUCCESS) {
4154                                 return ret;
4155                         }
4156
4157                         ldb_msg_remove_element(ac->msg, el);
4158
4159                         el = ldb_msg_find_element(ac->msg,
4160                                                   "servicePrincipalName");
4161                 } while (el != NULL);
4162
4163                 ret = dsdb_module_modify(ac->module, msg,
4164                                          DSDB_FLAG_OWN_MODULE, ac->req);
4165                 if (ret != LDB_SUCCESS) {
4166                         return ret;
4167                 }
4168                 talloc_free(msg);
4169         }
4170
4171         /* Fetch the "servicePrincipalName"s if any */
4172         ret = dsdb_module_search(ac->module, ac, &res, ac->msg->dn, LDB_SCOPE_BASE, attrs,
4173                                  DSDB_FLAG_NEXT_MODULE, ac->req, NULL);
4174         if (ret != LDB_SUCCESS) {
4175                 return ret;
4176         }
4177         if ((res->count != 1) || (res->msgs[0]->num_elements > 1)) {
4178                 return ldb_operr(ldb);
4179         }
4180
4181         if (res->msgs[0]->num_elements == 1) {
4182                 /*
4183                  * Yes, we do have "servicePrincipalName"s. First we update them
4184                  * locally, that means we do always substitute the current
4185                  * "dNSHostName" with the new one and/or "sAMAccountName"
4186                  * without "$" with the new one and then we append the
4187                  * modified "servicePrincipalName"s as a message element
4188                  * replace to the modification request (Windows behaviour). We
4189                  * need also to make sure that the values remain case-
4190                  * insensitively unique.
4191                  */
4192
4193                 ret = ldb_msg_add_empty(ac->msg, "servicePrincipalName",
4194                                         LDB_FLAG_MOD_REPLACE, &el);
4195                 if (ret != LDB_SUCCESS) {
4196                         return ret;
4197                 }
4198
4199                 for (i = 0; i < res->msgs[0]->elements[0].num_values; i++) {
4200                         char *old_str, *new_str;
4201                         char *pos = NULL;
4202                         const char *tok;
4203                         struct ldb_val *vals;
4204                         bool found = false;
4205
4206                         old_str = (char *)
4207                                 res->msgs[0]->elements[0].values[i].data;
4208
4209                         new_str = talloc_strdup(ac->msg,
4210                                                 strtok_r(old_str, "/", &pos));
4211                         if (new_str == NULL) {
4212                                 return ldb_module_oom(ac->module);
4213                         }
4214
4215                         while ((tok = strtok_r(NULL, "/", &pos)) != NULL) {
4216                                 if ((dns_hostname != NULL) &&
4217                                     (strcasecmp_m(tok, old_dns_hostname) == 0)) {
4218                                         tok = dns_hostname;
4219                                 }
4220                                 if ((sam_accountname != NULL) &&
4221                                     (strcasecmp_m(tok, old_sam_accountname) == 0)) {
4222                                         tok = sam_accountname;
4223                                 }
4224
4225                                 new_str = talloc_asprintf(ac->msg, "%s/%s",
4226                                                           new_str, tok);
4227                                 if (new_str == NULL) {
4228                                         return ldb_module_oom(ac->module);
4229                                 }
4230                         }
4231
4232                         /* Uniqueness check */
4233                         for (j = 0; (!found) && (j < el->num_values); j++) {
4234                                 if (strcasecmp_m((char *)el->values[j].data,
4235                                                new_str) == 0) {
4236                                         found = true;
4237                                 }
4238                         }
4239                         if (found) {
4240                                 continue;
4241                         }
4242
4243                         /*
4244                          * append the new "servicePrincipalName" -
4245                          * code derived from ldb_msg_add_value().
4246                          *
4247                          * Open coded to make it clear that we must
4248                          * append to the MOD_REPLACE el created above.
4249                          */
4250                         vals = talloc_realloc(ac->msg, el->values,
4251                                               struct ldb_val,
4252                                               el->num_values + 1);
4253                         if (vals == NULL) {
4254                                 return ldb_module_oom(ac->module);
4255                         }
4256                         el->values = vals;
4257                         el->values[el->num_values] = data_blob_string_const(new_str);
4258                         ++(el->num_values);
4259                 }
4260         }
4261
4262         talloc_free(res);
4263
4264         return LDB_SUCCESS;
4265 }
4266
4267 /* This checks the "fSMORoleOwner" attributes */
4268 static int samldb_fsmo_role_owner_check(struct samldb_ctx *ac)
4269 {
4270         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
4271         const char * const no_attrs[] = { NULL };
4272         struct ldb_message_element *el;
4273         struct ldb_message *tmp_msg;
4274         struct ldb_dn *res_dn;
4275         struct ldb_result *res;
4276         int ret;
4277
4278         el = dsdb_get_single_valued_attr(ac->msg, "fSMORoleOwner",
4279                                          ac->req->operation);
4280         if (el == NULL) {
4281                 /* we are not affected */
4282                 return LDB_SUCCESS;
4283         }
4284
4285         /* Create a temporary message for fetching the "fSMORoleOwner" */
4286         tmp_msg = ldb_msg_new(ac->msg);
4287         if (tmp_msg == NULL) {
4288                 return ldb_module_oom(ac->module);
4289         }
4290         ret = ldb_msg_add(tmp_msg, el, 0);
4291         if (ret != LDB_SUCCESS) {
4292                 return ret;
4293         }
4294         res_dn = ldb_msg_find_attr_as_dn(ldb, ac, tmp_msg, "fSMORoleOwner");
4295         talloc_free(tmp_msg);
4296
4297         if (res_dn == NULL) {
4298                 ldb_set_errstring(ldb,
4299                                   "samldb: 'fSMORoleOwner' attributes have to reference 'nTDSDSA' entries!");
4300                 if (ac->req->operation == LDB_ADD) {
4301                         return LDB_ERR_CONSTRAINT_VIOLATION;
4302                 } else {
4303                         return LDB_ERR_UNWILLING_TO_PERFORM;
4304                 }
4305         }
4306
4307         /* Fetched DN has to reference a "nTDSDSA" entry */
4308         ret = dsdb_module_search(ac->module, ac, &res, res_dn, LDB_SCOPE_BASE,
4309                                  no_attrs,
4310                                  DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED,
4311                                  ac->req, "(objectClass=nTDSDSA)");
4312         if (ret != LDB_SUCCESS) {
4313                 return ret;
4314         }
4315         if (res->count != 1) {
4316                 ldb_set_errstring(ldb,
4317                                   "samldb: 'fSMORoleOwner' attributes have to reference 'nTDSDSA' entries!");
4318                 return LDB_ERR_UNWILLING_TO_PERFORM;
4319         }
4320
4321         talloc_free(res);
4322
4323         return LDB_SUCCESS;
4324 }
4325
4326 /*
4327  * Return zero if the number of zero bits in the address (looking from low to
4328  * high) is equal to or greater than the length minus the mask. Otherwise it
4329  * returns -1.
4330  */
4331 static int check_cidr_zero_bits(uint8_t *address, unsigned int len,
4332                                 unsigned int mask)
4333 {
4334         /* <address> is an integer in big-endian form, <len> bits long. All
4335            bits between <mask> and <len> must be zero. */
4336         int i;
4337         unsigned int byte_len;
4338         unsigned int byte_mask;
4339         unsigned int bit_mask;
4340         if (len == 32) {
4341                 DBG_INFO("Looking at address %02x%02x%02x%02x, mask %u\n",
4342                          address[0], address[1], address[2], address[3],
4343                           mask);
4344         } else if (len == 128){
4345                 DBG_INFO("Looking at address "
4346                          "%02x%02x-%02x%02x-%02x%02x-%02x%02x-"
4347                          "%02x%02x-%02x%02x-%02x%02x-%02x%02x, mask %u\n",
4348                          address[0], address[1], address[2], address[3],
4349                          address[4], address[5], address[6], address[7],
4350                          address[8], address[9], address[10], address[11],
4351                          address[12], address[13], address[14], address[15],
4352                          mask);
4353         }
4354
4355         if (mask > len){
4356                 DBG_INFO("mask %u is too big (> %u)\n", mask, len);
4357                 return -1;
4358         }
4359         if (mask == len){
4360                 /* single address subnet.
4361                  * In IPv4 all 255s is invalid by the bitmask != address rule
4362                  * in MS-ADTS. IPv6 does not suffer.
4363                  */
4364                 if (len == 32){
4365                         if (address[0] == 255 &&
4366                             address[1] == 255 &&
4367                             address[2] == 255 &&
4368                             address[3] == 255){
4369                                 return -1;
4370                         }
4371                 }
4372                 return 0;
4373         }
4374
4375         byte_len = len / 8;
4376         byte_mask = mask / 8;
4377
4378         for (i = byte_len - 1; i > byte_mask; i--){
4379                 DBG_DEBUG("checking byte %d %02x\n", i, address[i]);
4380                 if (address[i] != 0){
4381                         return -1;
4382                 }
4383         }
4384         bit_mask = (1 << (8 - (mask & 7))) - 1;
4385         DBG_DEBUG("checking bitmask %02x & %02x overlap %02x\n", bit_mask, address[byte_mask],
4386                   bit_mask & address[byte_mask]);
4387         if (address[byte_mask] & bit_mask){
4388                 return -1;
4389         }
4390
4391         /* According to MS-ADTS, the mask can't exactly equal the bitmask for
4392          * IPv4 (but this is fine for v6). That is 255.255.80.0/17 is bad,
4393          * because the bitmask implied by "/17" is 255.255.80.0.
4394          *
4395          * The bit_mask used in the previous check is the complement of what
4396          * we want here.
4397          */
4398         if (len == 32 && address[byte_mask] == (uint8_t)~bit_mask){
4399                 bool ok = false;
4400                 for (i = 0; i < byte_mask; i++){
4401                         if (address[i] != 255){
4402                                 ok = true;
4403                                 break;
4404                         }
4405                 }
4406                 if (ok == false){
4407                         return -1;
4408                 }
4409         }
4410         return 0;
4411 }
4412
4413
4414
4415 static int check_address_roundtrip(const char *address, int family,
4416                                    const uint8_t *address_bytes,
4417                                    char *buffer, int buffer_len)
4418 {
4419         /*
4420          * Check that the address is in the canonical RFC5952 format for IPv6,
4421          * and lacks extra leading zeros for each dotted decimal for IPv4.
4422          * Handily this is what inet_ntop() gives you.
4423          */
4424         const char *address_redux = inet_ntop(family, address_bytes,
4425                                               buffer, buffer_len);
4426         if (address_redux == NULL){
4427                 DBG_INFO("Address round trip %s failed unexpectedly"
4428                          " with errno %d\n", address, errno);
4429                 return -1;
4430         }
4431         if (strcasecmp(address, address_redux) != 0){
4432                 DBG_INFO("Address %s round trips to %s; fail!\n",
4433                          address, address_redux);
4434                 /* If the address family is IPv6, and the address is in a
4435                    certain range
4436
4437                  */
4438                 if (strchr(address_redux, '.') != NULL){
4439                         DEBUG(0, ("The IPv6 address '%s' has the misfortune of "
4440                                   "lying in a range that was once used for "
4441                                   "IPv4 embedding (that is, it might also be "
4442                                   "represented as '%s').\n", address,
4443                                   address_redux));
4444                 }
4445                 return -1;
4446         }
4447         return 0;
4448 }
4449
4450
4451
4452 /*
4453  * MS-ADTS v20150630 6.1.1.2.2.2.1 Subnet Object, refers to RFC1166 and
4454  * RFC2373. It specifies something seemingly indistinguishable from an RFC4632
4455  * CIDR address range without saying so explicitly. Here we follow the CIDR
4456  * spec.
4457  *
4458  * Return 0 on success, -1 on error.
4459  */
4460 static int verify_cidr(const char *cidr)
4461 {
4462         char *address = NULL, *slash = NULL;
4463         bool has_colon, has_dot;
4464         int res, ret;
4465         unsigned long mask;
4466         uint8_t *address_bytes = NULL;
4467         char *address_redux = NULL;
4468         unsigned int address_len;
4469         TALLOC_CTX *frame = NULL;
4470         int error = 0;
4471
4472         DBG_DEBUG("CIDR is %s\n", cidr);
4473         frame = talloc_stackframe();
4474         address = talloc_strdup(frame, cidr);
4475         if (address == NULL){
4476                 goto error;
4477         }
4478
4479         /* there must be a '/' */
4480         slash = strchr(address, '/');
4481         if (slash == NULL){
4482                 goto error;
4483         }
4484         /* terminate the address for strchr, inet_pton */
4485         *slash = '\0';
4486
4487         mask = smb_strtoul(slash + 1, NULL, 10, &error, SMB_STR_FULL_STR_CONV);
4488         if (mask == 0){
4489                 DBG_INFO("Windows does not like the zero mask, "
4490                          "so nor do we: %s\n", cidr);
4491                 goto error;
4492         }
4493
4494         if (error != 0){
4495                 DBG_INFO("CIDR mask is not a proper integer: %s\n", cidr);
4496                 goto error;
4497         }
4498
4499         address_bytes = talloc_size(frame, sizeof(struct in6_addr));
4500         if (address_bytes == NULL){
4501                 goto error;
4502         }
4503
4504         address_redux = talloc_size(frame, INET6_ADDRSTRLEN);
4505         if (address_redux == NULL){
4506                 goto error;
4507         }
4508
4509         DBG_INFO("found address %s, mask %lu\n", address, mask);
4510         has_colon = (strchr(address, ':') == NULL) ? false : true;
4511         has_dot = (strchr(address, '.') == NULL) ? false : true;
4512         if (has_dot && has_colon){
4513                 /* This seems to be an IPv4 address embedded in IPv6, which is
4514                    icky. We don't support it. */
4515                 DBG_INFO("Refusing to consider cidr '%s' with dots and colons\n",
4516                           cidr);
4517                 goto error;
4518         } else if (has_colon){  /* looks like IPv6 */
4519                 res = inet_pton(AF_INET6, address, address_bytes);
4520                 if (res != 1) {
4521                         DBG_INFO("Address in %s fails to parse as IPv6\n", cidr);
4522                         goto error;
4523                 }
4524                 address_len = 128;
4525                 if (check_address_roundtrip(address, AF_INET6, address_bytes,
4526                                             address_redux, INET6_ADDRSTRLEN)){
4527                         goto error;
4528                 }
4529         } else if (has_dot) {
4530                 /* looks like IPv4 */
4531                 if (strcmp(address, "0.0.0.0") == 0){
4532                         DBG_INFO("Windows does not like the zero IPv4 address, "
4533                                  "so nor do we.\n");
4534                         goto error;
4535                 }
4536                 res = inet_pton(AF_INET, address, address_bytes);
4537                 if (res != 1) {
4538                         DBG_INFO("Address in %s fails to parse as IPv4\n", cidr);
4539                         goto error;
4540                 }
4541                 address_len = 32;
4542
4543                 if (check_address_roundtrip(address, AF_INET, address_bytes,
4544                                             address_redux, INET_ADDRSTRLEN)){
4545                         goto error;
4546                 }
4547         } else {
4548                 /* This doesn't look like an IP address at all. */
4549                 goto error;
4550         }
4551
4552         ret = check_cidr_zero_bits(address_bytes, address_len, mask);
4553         talloc_free(frame);
4554         return ret;
4555   error:
4556         talloc_free(frame);
4557         return -1;
4558 }
4559
4560
4561 static int samldb_verify_subnet(struct samldb_ctx *ac, struct ldb_dn *dn)
4562 {
4563         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
4564         const char *cidr = NULL;
4565         const struct ldb_val *rdn_value = NULL;
4566
4567         rdn_value = ldb_dn_get_rdn_val(dn);
4568         if (rdn_value == NULL) {
4569                 ldb_set_errstring(ldb, "samldb: ldb_dn_get_rdn_val "
4570                                   "failed");
4571                 return LDB_ERR_UNWILLING_TO_PERFORM;
4572         }
4573
4574         cidr = ldb_dn_escape_value(ac, *rdn_value);
4575         DBG_INFO("looking at cidr '%s'\n", cidr);
4576         if (cidr == NULL) {
4577                 ldb_set_errstring(ldb,
4578                                   "samldb: adding an empty subnet cidr seems wrong");
4579                 return LDB_ERR_UNWILLING_TO_PERFORM;
4580         }
4581
4582         if (verify_cidr(cidr)){
4583                 ldb_set_errstring(ldb,
4584                                   "samldb: subnet value is invalid");
4585                 return LDB_ERR_INVALID_DN_SYNTAX;
4586         }
4587
4588         return LDB_SUCCESS;
4589 }
4590
4591 static char *refer_if_rodc(struct ldb_context *ldb, struct ldb_request *req,
4592                            struct ldb_dn *dn)
4593 {
4594         bool rodc = false;
4595         struct loadparm_context *lp_ctx;
4596         char *referral;
4597         int ret;
4598         WERROR err;
4599
4600         if (ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID) ||
4601             ldb_request_get_control(req, DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA)) {
4602                 return NULL;
4603         }
4604
4605         ret = samdb_rodc(ldb, &rodc);
4606         if (ret != LDB_SUCCESS) {
4607                 DEBUG(4, (__location__ ": unable to tell if we are an RODC\n"));
4608                 return NULL;
4609         }
4610
4611         if (rodc) {
4612                 const char *domain = NULL;
4613                 struct ldb_dn *fsmo_role_dn;
4614                 struct ldb_dn *role_owner_dn;
4615                 ldb_set_errstring(ldb, "RODC modify is forbidden!");
4616                 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
4617                                          struct loadparm_context);
4618
4619                 err = dsdb_get_fsmo_role_info(req, ldb, DREPL_PDC_MASTER,
4620                                               &fsmo_role_dn, &role_owner_dn);
4621                 if (W_ERROR_IS_OK(err)) {
4622                         struct ldb_dn *server_dn = ldb_dn_copy(req, role_owner_dn);
4623                         if (server_dn != NULL) {
4624                                 ldb_dn_remove_child_components(server_dn, 1);
4625
4626                                 domain = samdb_dn_to_dnshostname(ldb, req,
4627                                                                  server_dn);
4628                         }
4629                 }
4630                 if (domain == NULL) {
4631                         domain = lpcfg_dnsdomain(lp_ctx);
4632                 }
4633                 referral = talloc_asprintf(req,
4634                                            "ldap://%s/%s",
4635                                            domain,
4636                                            ldb_dn_get_linearized(dn));
4637                 return referral;
4638         }
4639
4640         return NULL;
4641 }
4642
4643 /*
4644  * Restrict all access to sensitive attributes.
4645  *
4646  * We don't want to even inspect the values, so we can use the same
4647  * routine for ADD and MODIFY.
4648  *
4649  */
4650
4651 static int samldb_check_sensitive_attributes(struct samldb_ctx *ac)
4652 {
4653         struct ldb_message_element *el = NULL;
4654         struct security_token *user_token = NULL;
4655         int ret;
4656
4657         if (dsdb_module_am_system(ac->module)) {
4658                 return LDB_SUCCESS;
4659         }
4660
4661         user_token = acl_user_token(ac->module);
4662         if (user_token == NULL) {
4663                 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
4664         }
4665
4666         el = ldb_msg_find_element(ac->msg, "sidHistory");
4667         if (el) {
4668                /*
4669                 * sidHistory is restricted to the (not implemented
4670                 * yet in Samba) DsAddSidHistory call (direct LDB access is
4671                 * as SYSTEM so will bypass this).
4672                 *
4673                 * If you want to modify this, say to merge domains,
4674                 * directly modify the sam.ldb as root.
4675                 */
4676                 ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
4677                                        "sidHistory "
4678                                        "(entry %s) cannot be created "
4679                                        "or changed over LDAP!",
4680                                        ldb_dn_get_linearized(ac->msg->dn));
4681                 return LDB_ERR_UNWILLING_TO_PERFORM;
4682         }
4683
4684         el = ldb_msg_find_element(ac->msg, "msDS-SecondaryKrbTgtNumber");
4685         if (el) {
4686                 struct security_descriptor *domain_sd;
4687                 const struct dsdb_class *objectclass = NULL;
4688                 /*
4689                  * msDS-SecondaryKrbTgtNumber allows the creator to
4690                  * become an RODC, this is trusted as an RODC
4691                  * account
4692                  */
4693                 ret = samldb_get_domain_secdesc_and_oc(ac, &domain_sd, &objectclass);
4694                 if (ret != LDB_SUCCESS) {
4695                         return ret;
4696                 }
4697                 ret = acl_check_extended_right(ac,
4698                                                ac->module,
4699                                                ac->req,
4700                                                objectclass,
4701                                                domain_sd,
4702                                                user_token,
4703                                                GUID_DRS_DS_INSTALL_REPLICA,
4704                                                SEC_ADS_CONTROL_ACCESS,
4705                                                NULL);
4706                 if (ret != LDB_SUCCESS) {
4707                         ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
4708                                                "msDS-SecondaryKrbTgtNumber "
4709                                                "(entry %s) cannot be created "
4710                                                "or changed without "
4711                                                "DS-Install-Replica extended right!",
4712                                                ldb_dn_get_linearized(ac->msg->dn));
4713                         return ret;
4714                 }
4715         }
4716
4717         el = ldb_msg_find_element(ac->msg, "msDS-AllowedToDelegateTo");
4718         if (el) {
4719                 /*
4720                  * msDS-AllowedToDelegateTo is incredibly powerful,
4721                  * given that it allows a server to become ANY USER on
4722                  * the target server only listed by SPN so needs to be
4723                  * protected just as the userAccountControl
4724                  * UF_TRUSTED_FOR_DELEGATION is.
4725                  */
4726
4727                 bool have_priv = security_token_has_privilege(user_token,
4728                                                               SEC_PRIV_ENABLE_DELEGATION);
4729                 if (have_priv == false) {
4730                         ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
4731                                                "msDS-AllowedToDelegateTo "
4732                                                "(entry %s) cannot be created "
4733                                                "or changed without SePrivEnableDelegation!",
4734                                                ldb_dn_get_linearized(ac->msg->dn));
4735                         return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
4736                 }
4737         }
4738         return LDB_SUCCESS;
4739 }
4740 /* add */
4741 static int samldb_add(struct ldb_module *module, struct ldb_request *req)
4742 {
4743         struct ldb_context *ldb;
4744         struct samldb_ctx *ac;
4745         struct ldb_message_element *el;
4746         int ret;
4747         char *referral = NULL;
4748
4749         ldb = ldb_module_get_ctx(module);
4750         ldb_debug(ldb, LDB_DEBUG_TRACE, "samldb_add\n");
4751
4752         /* do not manipulate our control entries */
4753         if (ldb_dn_is_special(req->op.add.message->dn)) {
4754                 return ldb_next_request(module, req);
4755         }
4756
4757         referral = refer_if_rodc(ldb, req, req->op.add.message->dn);
4758         if (referral != NULL) {
4759                 ret = ldb_module_send_referral(req, referral);
4760                 return ret;
4761         }
4762
4763         el = ldb_msg_find_element(req->op.add.message, "userParameters");
4764         if (el != NULL && ldb_req_is_untrusted(req)) {
4765                 const char *reason = "samldb_add: "
4766                         "setting userParameters is not supported over LDAP, "
4767                         "see https://bugzilla.samba.org/show_bug.cgi?id=8077";
4768                 ldb_debug(ldb, LDB_DEBUG_WARNING, "%s", reason);
4769                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, reason);
4770         }
4771
4772         ac = samldb_ctx_init(module, req);
4773         if (ac == NULL) {
4774                 return ldb_operr(ldb);
4775         }
4776
4777         /* build the new msg */
4778         ac->msg = ldb_msg_copy_shallow(ac, req->op.add.message);
4779         if (ac->msg == NULL) {
4780                 talloc_free(ac);
4781                 ldb_debug(ldb, LDB_DEBUG_FATAL,
4782                           "samldb_add: ldb_msg_copy_shallow failed!\n");
4783                 return ldb_operr(ldb);
4784         }
4785
4786         ret = samldb_check_sensitive_attributes(ac);
4787         if (ret != LDB_SUCCESS) {
4788                 talloc_free(ac);
4789                 return ret;
4790         }
4791
4792         el = ldb_msg_find_element(ac->msg, "fSMORoleOwner");
4793         if (el != NULL) {
4794                 ret = samldb_fsmo_role_owner_check(ac);
4795                 if (ret != LDB_SUCCESS) {
4796                         return ret;
4797                 }
4798         }
4799
4800         if (samdb_find_attribute(ldb, ac->msg,
4801                                  "objectclass", "user") != NULL) {
4802                 ac->type = SAMLDB_TYPE_USER;
4803
4804                 ret = samldb_prim_group_trigger(ac);
4805                 if (ret != LDB_SUCCESS) {
4806                         return ret;
4807                 }
4808
4809                 ret = samldb_objectclass_trigger(ac);
4810                 if (ret != LDB_SUCCESS) {
4811                         return ret;
4812                 }
4813
4814                 return samldb_fill_object(ac);
4815         }
4816
4817         if (samdb_find_attribute(ldb, ac->msg,
4818                                  "objectclass", "group") != NULL) {
4819                 ac->type = SAMLDB_TYPE_GROUP;
4820
4821                 ret = samldb_objectclass_trigger(ac);
4822                 if (ret != LDB_SUCCESS) {
4823                         return ret;
4824                 }
4825
4826                 return samldb_fill_object(ac);
4827         }
4828
4829         /* perhaps a foreignSecurityPrincipal? */
4830         if (samdb_find_attribute(ldb, ac->msg,
4831                                  "objectclass",
4832                                  "foreignSecurityPrincipal") != NULL) {
4833                 return samldb_fill_foreignSecurityPrincipal_object(ac);
4834         }
4835
4836         if (samdb_find_attribute(ldb, ac->msg,
4837                                  "objectclass", "classSchema") != NULL) {
4838                 ac->type = SAMLDB_TYPE_CLASS;
4839
4840                 /* If in provision, these checks are too slow to do */
4841                 if (!ldb_request_get_control(req, DSDB_CONTROL_SKIP_DUPLICATES_CHECK_OID)) {
4842                         ret = samldb_schema_governsid_valid_check(ac);
4843                         if (ret != LDB_SUCCESS) {
4844                                 return ret;
4845                         }
4846                 }
4847
4848                 ret = samldb_schema_ldapdisplayname_valid_check(ac);
4849                 if (ret != LDB_SUCCESS) {
4850                         return ret;
4851                 }
4852
4853                 ret = samldb_schema_info_update(ac);
4854                 if (ret != LDB_SUCCESS) {
4855                         talloc_free(ac);
4856                         return ret;
4857                 }
4858
4859                 return samldb_fill_object(ac);
4860         }
4861
4862         if (samdb_find_attribute(ldb, ac->msg,
4863                                  "objectclass", "attributeSchema") != NULL) {
4864                 ac->type = SAMLDB_TYPE_ATTRIBUTE;
4865
4866                 /* If in provision, these checks are too slow to do */
4867                 if (!ldb_request_get_control(req, DSDB_CONTROL_SKIP_DUPLICATES_CHECK_OID)) {
4868                         ret = samldb_schema_attributeid_valid_check(ac);
4869                         if (ret != LDB_SUCCESS) {
4870                                 return ret;
4871                         }
4872
4873                         ret = samldb_schema_add_handle_linkid(ac);
4874                         if (ret != LDB_SUCCESS) {
4875                                 return ret;
4876                         }
4877
4878                         ret = samldb_schema_add_handle_mapiid(ac);
4879                         if (ret != LDB_SUCCESS) {
4880                                 return ret;
4881                         }
4882                 }
4883
4884                 ret = samldb_schema_ldapdisplayname_valid_check(ac);
4885                 if (ret != LDB_SUCCESS) {
4886                         return ret;
4887                 }
4888
4889                 ret = samldb_schema_info_update(ac);
4890                 if (ret != LDB_SUCCESS) {
4891                         talloc_free(ac);
4892                         return ret;
4893                 }
4894
4895                 return samldb_fill_object(ac);
4896         }
4897
4898
4899         el = ldb_msg_find_element(ac->msg, "servicePrincipalName");
4900         if ((el != NULL)) {
4901                 /*
4902                  * We need to check whether the SPN collides with an existing
4903                  * one (anywhere) including via aliases.
4904                  */
4905                 ret = samldb_spn_uniqueness_check(ac, el);
4906                 if (ret != LDB_SUCCESS) {
4907                         return ret;
4908                 }
4909         }
4910
4911         if (samdb_find_attribute(ldb, ac->msg,
4912                                  "objectclass", "subnet") != NULL) {
4913                 ret = samldb_verify_subnet(ac, ac->msg->dn);
4914                 if (ret != LDB_SUCCESS) {
4915                         talloc_free(ac);
4916                         return ret;
4917                 }
4918                 /* We are just checking the value is valid, and there are no
4919                    values to fill in. */
4920         }
4921
4922         talloc_free(ac);
4923
4924         /* nothing matched, go on */
4925         return ldb_next_request(module, req);
4926 }
4927
4928 /* modify */
4929 static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
4930 {
4931         struct ldb_context *ldb;
4932         struct samldb_ctx *ac;
4933         struct ldb_message_element *el, *el2;
4934         struct ldb_control *is_undelete;
4935         bool modified = false;
4936         int ret;
4937
4938         if (ldb_dn_is_special(req->op.mod.message->dn)) {
4939                 /* do not manipulate our control entries */
4940                 return ldb_next_request(module, req);
4941         }
4942
4943         ldb = ldb_module_get_ctx(module);
4944
4945         /*
4946          * we are going to need some special handling if in Undelete call.
4947          * Since tombstone_reanimate module will restore certain attributes,
4948          * we need to relax checks for: sAMAccountType, primaryGroupID
4949          */
4950         is_undelete = ldb_request_get_control(req, DSDB_CONTROL_RESTORE_TOMBSTONE_OID);
4951
4952         /* make sure that "objectSid" is not specified */
4953         el = ldb_msg_find_element(req->op.mod.message, "objectSid");
4954         if (el != NULL) {
4955                 if (ldb_request_get_control(req, LDB_CONTROL_PROVISION_OID) == NULL) {
4956                         ldb_set_errstring(ldb,
4957                                           "samldb: objectSid must not be specified!");
4958                         return LDB_ERR_UNWILLING_TO_PERFORM;
4959                 }
4960         }
4961         if (is_undelete == NULL) {
4962                 /* make sure that "sAMAccountType" is not specified */
4963                 el = ldb_msg_find_element(req->op.mod.message, "sAMAccountType");
4964                 if (el != NULL) {
4965                         ldb_set_errstring(ldb,
4966                                           "samldb: sAMAccountType must not be specified!");
4967                         return LDB_ERR_UNWILLING_TO_PERFORM;
4968                 }
4969         }
4970         /* make sure that "isCriticalSystemObject" is not specified */
4971         el = ldb_msg_find_element(req->op.mod.message, "isCriticalSystemObject");
4972         if (el != NULL) {
4973                 if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID) == NULL) {
4974                         ldb_set_errstring(ldb,
4975                                           "samldb: isCriticalSystemObject must not be specified!");
4976                         return LDB_ERR_UNWILLING_TO_PERFORM;
4977                 }
4978         }
4979
4980         /* msDS-IntId is not allowed to be modified
4981          * except when modification comes from replication */
4982         if (ldb_msg_find_element(req->op.mod.message, "msDS-IntId")) {
4983                 if (!ldb_request_get_control(req,
4984                                              DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
4985                         return LDB_ERR_CONSTRAINT_VIOLATION;
4986                 }
4987         }
4988
4989         el = ldb_msg_find_element(req->op.mod.message, "userParameters");
4990         if (el != NULL && ldb_req_is_untrusted(req)) {
4991                 const char *reason = "samldb: "
4992                         "setting userParameters is not supported over LDAP, "
4993                         "see https://bugzilla.samba.org/show_bug.cgi?id=8077";
4994                 ldb_debug(ldb, LDB_DEBUG_WARNING, "%s", reason);
4995                 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, reason);
4996         }
4997
4998         ac = samldb_ctx_init(module, req);
4999         if (ac == NULL) {
5000                 return ldb_operr(ldb);
5001         }
5002
5003         /* build the new msg */
5004         ac->msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
5005         if (ac->msg == NULL) {
5006                 talloc_free(ac);
5007                 ldb_debug(ldb, LDB_DEBUG_FATAL,
5008                           "samldb_modify: ldb_msg_copy_shallow failed!\n");
5009                 return ldb_operr(ldb);
5010         }
5011
5012         ret = samldb_check_sensitive_attributes(ac);
5013         if (ret != LDB_SUCCESS) {
5014                 talloc_free(ac);
5015                 return ret;
5016         }
5017
5018         if (is_undelete == NULL) {
5019                 el = ldb_msg_find_element(ac->msg, "primaryGroupID");
5020                 if (el != NULL) {
5021                         ret = samldb_prim_group_trigger(ac);
5022                         if (ret != LDB_SUCCESS) {
5023                                 return ret;
5024                         }
5025                 }
5026         }
5027
5028         el = ldb_msg_find_element(ac->msg, "userAccountControl");
5029         if (el != NULL) {
5030                 modified = true;
5031                 ret = samldb_user_account_control_change(ac);
5032                 if (ret != LDB_SUCCESS) {
5033                         return ret;
5034                 }
5035         }
5036
5037         el = ldb_msg_find_element(ac->msg, "pwdLastSet");
5038         if (el != NULL) {
5039                 modified = true;
5040                 ret = samldb_pwd_last_set_change(ac);
5041                 if (ret != LDB_SUCCESS) {
5042                         return ret;
5043                 }
5044         }
5045
5046         el = ldb_msg_find_element(ac->msg, "lockoutTime");
5047         if (el != NULL) {
5048                 modified = true;
5049                 ret = samldb_lockout_time(ac);
5050                 if (ret != LDB_SUCCESS) {
5051                         return ret;
5052                 }
5053         }
5054
5055         el = ldb_msg_find_element(ac->msg, "groupType");
5056         if (el != NULL) {
5057                 modified = true;
5058                 ret = samldb_group_type_change(ac);
5059                 if (ret != LDB_SUCCESS) {
5060                         return ret;
5061                 }
5062         }
5063
5064         el = ldb_msg_find_element(ac->msg, "sAMAccountName");
5065         if (el != NULL) {
5066                 uint32_t user_account_control;
5067                 struct ldb_result *res = NULL;
5068                 const char * const attrs[] = { "userAccountControl",
5069                                                "objectclass",
5070                                                NULL };
5071                 ret = dsdb_module_search_dn(ac->module,
5072                                             ac,
5073                                             &res,
5074                                             ac->msg->dn,
5075                                             attrs,
5076                                             DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED,
5077                                             ac->req);
5078                 if (ret != LDB_SUCCESS) {
5079                         return ret;
5080                 }
5081                 user_account_control
5082                         = ldb_msg_find_attr_as_uint(res->msgs[0],
5083                                                     "userAccountControl",
5084                                                     0);
5085
5086                 if ((user_account_control
5087                      & UF_TRUST_ACCOUNT_MASK) != 0) {
5088                         ac->need_trailing_dollar = true;
5089
5090                 } else if (samdb_find_attribute(ldb,
5091                                                 res->msgs[0],
5092                                                 "objectclass",
5093                                                 "computer")
5094                            != NULL) {
5095                         ac->need_trailing_dollar = true;
5096                 }
5097
5098                 ret = samldb_sam_accountname_valid_check(ac);
5099                 if (ret != LDB_SUCCESS) {
5100                         return ret;
5101                 }
5102         }
5103
5104         el = ldb_msg_find_element(ac->msg, "userPrincipalName");
5105         if (el != NULL) {
5106                 ret = samldb_sam_account_upn_clash(ac);
5107                 if (ret != LDB_SUCCESS) {
5108                         talloc_free(ac);
5109                         return ret;
5110                 }
5111         }
5112
5113         el = ldb_msg_find_element(ac->msg, "ldapDisplayName");
5114         if (el != NULL) {
5115                 ret = samldb_schema_ldapdisplayname_valid_check(ac);
5116                 if (ret != LDB_SUCCESS) {
5117                         return ret;
5118                 }
5119         }
5120
5121         el = ldb_msg_find_element(ac->msg, "attributeID");
5122         if (el != NULL) {
5123                 ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
5124                                        "Once set, attributeID values may not be modified");
5125                 return LDB_ERR_CONSTRAINT_VIOLATION;
5126         }
5127
5128         el = ldb_msg_find_element(ac->msg, "governsID");
5129         if (el != NULL) {
5130                 ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
5131                                        "Once set, governsID values may not be modified");
5132                 return LDB_ERR_CONSTRAINT_VIOLATION;
5133         }
5134
5135         el = ldb_msg_find_element(ac->msg, "member");
5136         if (el != NULL) {
5137                 struct ldb_control *fix_link_sid_ctrl = NULL;
5138
5139                 fix_link_sid_ctrl = ldb_request_get_control(ac->req,
5140                                         DSDB_CONTROL_DBCHECK_FIX_LINK_DN_SID);
5141                 if (fix_link_sid_ctrl == NULL) {
5142                         ret = samldb_member_check(ac);
5143                         if (ret != LDB_SUCCESS) {
5144                                 return ret;
5145                         }
5146                 }
5147         }
5148
5149         el = ldb_msg_find_element(ac->msg, "description");
5150         if (el != NULL) {
5151                 ret = samldb_description_check(ac, &modified);
5152                 if (ret != LDB_SUCCESS) {
5153                         return ret;
5154                 }
5155         }
5156
5157         el = ldb_msg_find_element(ac->msg, "dNSHostName");
5158         el2 = ldb_msg_find_element(ac->msg, "sAMAccountName");
5159         if ((el != NULL) || (el2 != NULL)) {
5160                 modified = true;
5161                 /*
5162                  * samldb_service_principal_names_change() might add SPN
5163                  * changes to the request, so this must come before the SPN
5164                  * uniqueness check below.
5165                  *
5166                  * Note we ALSO have to do the SPN uniqueness check inside
5167                  * samldb_service_principal_names_change(), because it does a
5168                  * subrequest to do requested SPN modifications *before* its
5169                  * automatic ones are added.
5170                  */
5171                 ret = samldb_service_principal_names_change(ac);
5172                 if (ret != LDB_SUCCESS) {
5173                         return ret;
5174                 }
5175         }
5176
5177         el = ldb_msg_find_element(ac->msg, "servicePrincipalName");
5178         if ((el != NULL)) {
5179                 /*
5180                  * We need to check whether the SPN collides with an existing
5181                  * one (anywhere) including via aliases.
5182                  */
5183                 modified = true;
5184                 ret = samldb_spn_uniqueness_check(ac, el);
5185                 if (ret != LDB_SUCCESS) {
5186                         return ret;
5187                 }
5188         }
5189
5190         el = ldb_msg_find_element(ac->msg, "fSMORoleOwner");
5191         if (el != NULL) {
5192                 ret = samldb_fsmo_role_owner_check(ac);
5193                 if (ret != LDB_SUCCESS) {
5194                         return ret;
5195                 }
5196         }
5197
5198         if (modified) {
5199                 struct ldb_request *child_req;
5200
5201                 /* Now perform the real modifications as a child request */
5202                 ret = ldb_build_mod_req(&child_req, ldb, ac,
5203                                         ac->msg,
5204                                         req->controls,
5205                                         req, dsdb_next_callback,
5206                                         req);
5207                 LDB_REQ_SET_LOCATION(child_req);
5208                 if (ret != LDB_SUCCESS) {
5209                         return ret;
5210                 }
5211
5212                 return ldb_next_request(module, child_req);
5213         }
5214
5215         talloc_free(ac);
5216
5217         /* no change which interests us, go on */
5218         return ldb_next_request(module, req);
5219 }
5220
5221 /* delete */
5222
5223 static int samldb_prim_group_users_check(struct samldb_ctx *ac)
5224 {
5225         struct ldb_context *ldb;
5226         struct dom_sid *sid;
5227         uint32_t rid;
5228         NTSTATUS status;
5229         int ret;
5230         struct ldb_result *res = NULL;
5231         struct ldb_result *res_users = NULL;
5232         const char * const attrs[] = { "objectSid", "isDeleted", NULL };
5233         const char * const noattrs[] = { NULL };
5234
5235         ldb = ldb_module_get_ctx(ac->module);
5236
5237         /* Finds out the SID/RID of the SAM object */
5238         ret = dsdb_module_search_dn(ac->module, ac, &res, ac->req->op.del.dn,
5239                                         attrs,
5240                                         DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED,
5241                                         ac->req);
5242         if (ret != LDB_SUCCESS) {
5243                 return ret;
5244         }
5245
5246         if (ldb_msg_check_string_attribute(res->msgs[0], "isDeleted", "TRUE")) {
5247                 return LDB_SUCCESS;
5248         }
5249
5250         sid = samdb_result_dom_sid(ac, res->msgs[0], "objectSid");
5251         if (sid == NULL) {
5252                 /* No SID - it might not be a SAM object - therefore ok */
5253                 return LDB_SUCCESS;
5254         }
5255         status = dom_sid_split_rid(ac, sid, NULL, &rid);
5256         if (!NT_STATUS_IS_OK(status)) {
5257                 return ldb_operr(ldb);
5258         }
5259         if (rid == 0) {
5260                 /* Special object (security principal?) */
5261                 return LDB_SUCCESS;
5262         }
5263         /* do not allow deletion of well-known sids */
5264         if (rid < DSDB_SAMDB_MINIMUM_ALLOWED_RID &&
5265             (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) == NULL)) {
5266                 return LDB_ERR_OTHER;
5267         }
5268
5269         /* Deny delete requests from groups which are primary ones */
5270         ret = dsdb_module_search(ac->module, ac, &res_users,
5271                                  ldb_get_default_basedn(ldb),
5272                                  LDB_SCOPE_SUBTREE, noattrs,
5273                                  DSDB_FLAG_NEXT_MODULE,
5274                                  ac->req,
5275                                  "(&(primaryGroupID=%u)(objectClass=user))", rid);
5276         if (ret != LDB_SUCCESS) {
5277                 return ret;
5278         }
5279         if (res_users->count > 0) {
5280                 ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
5281                                        "Refusing to delete %s, as it "
5282                                        "is still the primaryGroupID "
5283                                        "for %u users",
5284                                        ldb_dn_get_linearized(res->msgs[0]->dn),
5285                                        res_users->count);
5286
5287                 /*
5288                  * Yes, this seems very wrong, but we have a test
5289                  * for this exact error code in sam.py
5290                  */
5291                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
5292         }
5293
5294         return LDB_SUCCESS;
5295 }
5296
5297 static int samldb_delete(struct ldb_module *module, struct ldb_request *req)
5298 {
5299         struct samldb_ctx *ac;
5300         char *referral = NULL;
5301         int ret;
5302         struct ldb_context *ldb;
5303
5304         if (ldb_dn_is_special(req->op.del.dn)) {
5305                 /* do not manipulate our control entries */
5306                 return ldb_next_request(module, req);
5307         }
5308
5309         ldb = ldb_module_get_ctx(module);
5310
5311         referral = refer_if_rodc(ldb, req, req->op.del.dn);
5312         if (referral != NULL) {
5313                 ret = ldb_module_send_referral(req, referral);
5314                 return ret;
5315         }
5316
5317         ac = samldb_ctx_init(module, req);
5318         if (ac == NULL) {
5319                 return ldb_operr(ldb_module_get_ctx(module));
5320         }
5321
5322         ret = samldb_prim_group_users_check(ac);
5323         if (ret != LDB_SUCCESS) {
5324                 return ret;
5325         }
5326
5327         talloc_free(ac);
5328
5329         return ldb_next_request(module, req);
5330 }
5331
5332 /* rename */
5333
5334 static int check_rename_constraints(struct ldb_message *msg,
5335                                     struct samldb_ctx *ac,
5336                                     struct ldb_dn *olddn, struct ldb_dn *newdn)
5337 {
5338         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
5339         struct ldb_dn *dn1, *dn2, *nc_root;
5340         int32_t systemFlags;
5341         bool move_op = false;
5342         bool rename_op = false;
5343         int ret;
5344
5345         /* Skip the checks if old and new DN are the same, or if we have the
5346          * relax control specified or if the returned objects is already
5347          * deleted and needs only to be moved for consistency. */
5348
5349         if (ldb_dn_compare(olddn, newdn) == 0) {
5350                 return LDB_SUCCESS;
5351         }
5352         if (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) != NULL) {
5353                 return LDB_SUCCESS;
5354         }
5355
5356         if (ldb_msg_find_attr_as_bool(msg, "isDeleted", false)) {
5357                 /*
5358                  * check originating request if we are supposed
5359                  * to "see" this record in first place.
5360                  */
5361                 if (ldb_request_get_control(ac->req, LDB_CONTROL_SHOW_DELETED_OID) == NULL) {
5362                         return LDB_ERR_NO_SUCH_OBJECT;
5363                 }
5364                 return LDB_ERR_UNWILLING_TO_PERFORM;
5365         }
5366
5367         /* Objects under CN=System */
5368
5369         dn1 = ldb_dn_copy(ac, ldb_get_default_basedn(ldb));
5370         if (dn1 == NULL) return ldb_oom(ldb);
5371
5372         if ( ! ldb_dn_add_child_fmt(dn1, "CN=System")) {
5373                 talloc_free(dn1);
5374                 return LDB_ERR_OPERATIONS_ERROR;
5375         }
5376
5377         if ((ldb_dn_compare_base(dn1, olddn) == 0) &&
5378             (ldb_dn_compare_base(dn1, newdn) != 0)) {
5379                 talloc_free(dn1);
5380                 ldb_asprintf_errstring(ldb,
5381                                        "subtree_rename: Cannot move/rename %s. Objects under CN=System have to stay under it!",
5382                                        ldb_dn_get_linearized(olddn));
5383                 return LDB_ERR_OTHER;
5384         }
5385
5386         talloc_free(dn1);
5387
5388         /* LSA objects */
5389
5390         if ((samdb_find_attribute(ldb, msg, "objectClass", "secret") != NULL) ||
5391             (samdb_find_attribute(ldb, msg, "objectClass", "trustedDomain") != NULL)) {
5392                 ldb_asprintf_errstring(ldb,
5393                                        "subtree_rename: Cannot move/rename %s. It's an LSA-specific object!",
5394                                        ldb_dn_get_linearized(olddn));
5395                 return LDB_ERR_UNWILLING_TO_PERFORM;
5396         }
5397
5398         /* subnet objects */
5399         if (samdb_find_attribute(ldb, msg, "objectclass", "subnet") != NULL) {
5400                 ret = samldb_verify_subnet(ac, newdn);
5401                 if (ret != LDB_SUCCESS) {
5402                         return ret;
5403                 }
5404         }
5405
5406         /* systemFlags */
5407
5408         dn1 = ldb_dn_get_parent(ac, olddn);
5409         if (dn1 == NULL) return ldb_oom(ldb);
5410         dn2 = ldb_dn_get_parent(ac, newdn);
5411         if (dn2 == NULL) return ldb_oom(ldb);
5412
5413         if (ldb_dn_compare(dn1, dn2) == 0) {
5414                 rename_op = true;
5415         } else {
5416                 move_op = true;
5417         }
5418
5419         talloc_free(dn1);
5420         talloc_free(dn2);
5421
5422         systemFlags = ldb_msg_find_attr_as_int(msg, "systemFlags", 0);
5423
5424         /* Fetch name context */
5425
5426         ret = dsdb_find_nc_root(ldb, ac, olddn, &nc_root);
5427         if (ret != LDB_SUCCESS) {
5428                 return ret;
5429         }
5430
5431         if (ldb_dn_compare(nc_root, ldb_get_schema_basedn(ldb)) == 0) {
5432                 if (move_op) {
5433                         ldb_asprintf_errstring(ldb,
5434                                                "subtree_rename: Cannot move %s within schema partition",
5435                                                ldb_dn_get_linearized(olddn));
5436                         return LDB_ERR_UNWILLING_TO_PERFORM;
5437                 }
5438                 if (rename_op &&
5439                     (systemFlags & SYSTEM_FLAG_SCHEMA_BASE_OBJECT) != 0) {
5440                         ldb_asprintf_errstring(ldb,
5441                                                "subtree_rename: Cannot rename %s within schema partition",
5442                                                ldb_dn_get_linearized(olddn));
5443                         return LDB_ERR_UNWILLING_TO_PERFORM;
5444                 }
5445         } else if (ldb_dn_compare(nc_root, ldb_get_config_basedn(ldb)) == 0) {
5446                 if (move_op &&
5447                     (systemFlags & SYSTEM_FLAG_CONFIG_ALLOW_MOVE) == 0) {
5448                         /* Here we have to do more: control the
5449                          * "ALLOW_LIMITED_MOVE" flag. This means that the
5450                          * grand-grand-parents of two objects have to be equal
5451                          * in order to perform the move (this is used for
5452                          * moving "server" objects in the "sites" container). */
5453                         bool limited_move =
5454                                 systemFlags & SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE;
5455
5456                         if (limited_move) {
5457                                 dn1 = ldb_dn_copy(ac, olddn);
5458                                 if (dn1 == NULL) return ldb_oom(ldb);
5459                                 dn2 = ldb_dn_copy(ac, newdn);
5460                                 if (dn2 == NULL) return ldb_oom(ldb);
5461
5462                                 limited_move &= ldb_dn_remove_child_components(dn1, 3);
5463                                 limited_move &= ldb_dn_remove_child_components(dn2, 3);
5464                                 limited_move &= ldb_dn_compare(dn1, dn2) == 0;
5465
5466                                 talloc_free(dn1);
5467                                 talloc_free(dn2);
5468                         }
5469
5470                         if (!limited_move
5471                             && ldb_request_get_control(ac->req, DSDB_CONTROL_RESTORE_TOMBSTONE_OID) == NULL) {
5472                                 ldb_asprintf_errstring(ldb,
5473                                                        "subtree_rename: Cannot move %s to %s in config partition",
5474                                                        ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn));
5475                                 return LDB_ERR_UNWILLING_TO_PERFORM;
5476                         }
5477                 }
5478                 if (rename_op &&
5479                     (systemFlags & SYSTEM_FLAG_CONFIG_ALLOW_RENAME) == 0) {
5480                         ldb_asprintf_errstring(ldb,
5481                                                "subtree_rename: Cannot rename %s to %s within config partition",
5482                                                ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn));
5483                         return LDB_ERR_UNWILLING_TO_PERFORM;
5484                 }
5485         } else if (ldb_dn_compare(nc_root, ldb_get_default_basedn(ldb)) == 0) {
5486                 if (move_op &&
5487                     (systemFlags & SYSTEM_FLAG_DOMAIN_DISALLOW_MOVE) != 0) {
5488                         ldb_asprintf_errstring(ldb,
5489                                                "subtree_rename: Cannot move %s to %s - DISALLOW_MOVE set",
5490                                                ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn));
5491                         return LDB_ERR_UNWILLING_TO_PERFORM;
5492                 }
5493                 if (rename_op &&
5494                     (systemFlags & SYSTEM_FLAG_DOMAIN_DISALLOW_RENAME) != 0) {
5495                         ldb_asprintf_errstring(ldb,
5496                                                        "subtree_rename: Cannot rename %s to %s - DISALLOW_RENAME set",
5497                                                ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn));
5498                         return LDB_ERR_UNWILLING_TO_PERFORM;
5499                 }
5500         }
5501
5502         talloc_free(nc_root);
5503
5504         return LDB_SUCCESS;
5505 }
5506
5507
5508 static int samldb_rename_search_base_callback(struct ldb_request *req,
5509                                                struct ldb_reply *ares)
5510 {
5511         struct samldb_ctx *ac;
5512         int ret;
5513
5514         ac = talloc_get_type(req->context, struct samldb_ctx);
5515
5516         if (!ares) {
5517                 return ldb_module_done(ac->req, NULL, NULL,
5518                                         LDB_ERR_OPERATIONS_ERROR);
5519         }
5520         if (ares->error != LDB_SUCCESS) {
5521                 return ldb_module_done(ac->req, ares->controls,
5522                                         ares->response, ares->error);
5523         }
5524
5525         switch (ares->type) {
5526         case LDB_REPLY_ENTRY:
5527                 /*
5528                  * This is the root entry of the originating move
5529                  * respectively rename request. It has been already
5530                  * stored in the list using "subtree_rename_search()".
5531                  * Only this one is subject to constraint checking.
5532                  */
5533                 ret = check_rename_constraints(ares->message, ac,
5534                                                ac->req->op.rename.olddn,
5535                                                ac->req->op.rename.newdn);
5536                 if (ret != LDB_SUCCESS) {
5537                         return ldb_module_done(ac->req, NULL, NULL,
5538                                                ret);
5539                 }
5540                 break;
5541
5542         case LDB_REPLY_REFERRAL:
5543                 /* ignore */
5544                 break;
5545
5546         case LDB_REPLY_DONE:
5547
5548                 /*
5549                  * Great, no problem with the rename, so go ahead as
5550                  * if we never were here
5551                  */
5552                 ret = ldb_next_request(ac->module, ac->req);
5553                 talloc_free(ares);
5554                 return ret;
5555         }
5556
5557         talloc_free(ares);
5558         return LDB_SUCCESS;
5559 }
5560
5561
5562 /* rename */
5563 static int samldb_rename(struct ldb_module *module, struct ldb_request *req)
5564 {
5565         struct ldb_context *ldb;
5566         static const char * const attrs[] = { "objectClass", "systemFlags",
5567                                               "isDeleted", NULL };
5568         struct ldb_request *search_req;
5569         struct samldb_ctx *ac;
5570         int ret;
5571
5572         if (ldb_dn_is_special(req->op.rename.olddn)) { /* do not manipulate our control entries */
5573                 return ldb_next_request(module, req);
5574         }
5575
5576         ldb = ldb_module_get_ctx(module);
5577
5578         ac = samldb_ctx_init(module, req);
5579         if (!ac) {
5580                 return ldb_oom(ldb);
5581         }
5582
5583         ret = ldb_build_search_req(&search_req, ldb, ac,
5584                                    req->op.rename.olddn,
5585                                    LDB_SCOPE_BASE,
5586                                    "(objectClass=*)",
5587                                    attrs,
5588                                    NULL,
5589                                    ac,
5590                                    samldb_rename_search_base_callback,
5591                                    req);
5592         LDB_REQ_SET_LOCATION(search_req);
5593         if (ret != LDB_SUCCESS) {
5594                 return ret;
5595         }
5596
5597         ret = ldb_request_add_control(search_req, LDB_CONTROL_SHOW_RECYCLED_OID,
5598                                       true, NULL);
5599         if (ret != LDB_SUCCESS) {
5600                 return ret;
5601         }
5602
5603         return ldb_next_request(ac->module, search_req);
5604 }
5605
5606 /* extended */
5607
5608 static int samldb_extended_allocate_rid_pool(struct ldb_module *module, struct ldb_request *req)
5609 {
5610         struct ldb_context *ldb = ldb_module_get_ctx(module);
5611         struct dsdb_fsmo_extended_op *exop;
5612         int ret;
5613
5614         exop = talloc_get_type(req->op.extended.data,
5615                                struct dsdb_fsmo_extended_op);
5616         if (!exop) {
5617                 ldb_set_errstring(ldb,
5618                                   "samldb_extended_allocate_rid_pool: invalid extended data");
5619                 return LDB_ERR_PROTOCOL_ERROR;
5620         }
5621
5622         ret = ridalloc_allocate_rid_pool_fsmo(module, exop, req);
5623         if (ret != LDB_SUCCESS) {
5624                 return ret;
5625         }
5626
5627         return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
5628 }
5629
5630 static int samldb_extended_allocate_rid(struct ldb_module *module, struct ldb_request *req)
5631 {
5632         struct ldb_context *ldb = ldb_module_get_ctx(module);
5633         struct dsdb_extended_allocate_rid *exop;
5634         int ret;
5635
5636         exop = talloc_get_type(req->op.extended.data,
5637                                struct dsdb_extended_allocate_rid);
5638         if (!exop) {
5639                 ldb_set_errstring(ldb,
5640                                   "samldb_extended_allocate_rid: invalid extended data");
5641                 return LDB_ERR_PROTOCOL_ERROR;
5642         }
5643
5644         ret = ridalloc_allocate_rid(module, &exop->rid, req);
5645         if (ret != LDB_SUCCESS) {
5646                 return ret;
5647         }
5648
5649         return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
5650 }
5651
5652 static int samldb_extended_create_own_rid_set(struct ldb_module *module, struct ldb_request *req)
5653 {
5654         struct ldb_context *ldb = ldb_module_get_ctx(module);
5655         int ret;
5656         struct ldb_dn *dn;
5657
5658         if (req->op.extended.data != NULL) {
5659                 ldb_set_errstring(ldb,
5660                                   "samldb_extended_create_own_rid_set: invalid extended data (should be NULL)");
5661                 return LDB_ERR_PROTOCOL_ERROR;
5662         }
5663
5664         ret = ridalloc_create_own_rid_set(module, req,
5665                                           &dn, req);
5666         if (ret != LDB_SUCCESS) {
5667                 return ret;
5668         }
5669
5670         return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
5671 }
5672
5673 static int samldb_extended(struct ldb_module *module, struct ldb_request *req)
5674 {
5675         if (strcmp(req->op.extended.oid, DSDB_EXTENDED_ALLOCATE_RID_POOL) == 0) {
5676                 return samldb_extended_allocate_rid_pool(module, req);
5677         }
5678
5679         if (strcmp(req->op.extended.oid, DSDB_EXTENDED_ALLOCATE_RID) == 0) {
5680                 return samldb_extended_allocate_rid(module, req);
5681         }
5682
5683         if (strcmp(req->op.extended.oid, DSDB_EXTENDED_CREATE_OWN_RID_SET) == 0) {
5684                 return samldb_extended_create_own_rid_set(module, req);
5685         }
5686
5687         return ldb_next_request(module, req);
5688 }
5689
5690
5691 static const struct ldb_module_ops ldb_samldb_module_ops = {
5692         .name          = "samldb",
5693         .add           = samldb_add,
5694         .modify        = samldb_modify,
5695         .del           = samldb_delete,
5696         .rename        = samldb_rename,
5697         .extended      = samldb_extended
5698 };
5699
5700
5701 int ldb_samldb_module_init(const char *version)
5702 {
5703         LDB_MODULE_CHECK_VERSION(version);
5704         return ldb_register_module(&ldb_samldb_module_ops);
5705 }