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