d8f68c884beba2a7bcf49a8809cc5f99125cf20b
[mat/samba.git] / source4 / dsdb / samdb / ldb_modules / samldb.c
1 /*
2    SAM ldb module
3
4    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
5    Copyright (C) Simo Sorce  2004-2008
6    Copyright (C) Matthias Dieter Wallnöfer 2009-2011
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 /*
23  *  Name: ldb
24  *
25  *  Component: ldb samldb module
26  *
27  *  Description: various internal DSDB triggers - most for SAM specific objects
28  *
29  *  Author: Simo Sorce
30  */
31
32 #include "includes.h"
33 #include "libcli/ldap/ldap_ndr.h"
34 #include "ldb_module.h"
35 #include "dsdb/samdb/samdb.h"
36 #include "dsdb/samdb/ldb_modules/util.h"
37 #include "dsdb/samdb/ldb_modules/ridalloc.h"
38 #include "libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
40 #include "ldb_wrap.h"
41 #include "param/param.h"
42 #include "libds/common/flag_mapping.h"
43
44 struct samldb_ctx;
45
46 typedef int (*samldb_step_fn_t)(struct samldb_ctx *);
47
48 struct samldb_step {
49         struct samldb_step *next;
50         samldb_step_fn_t fn;
51 };
52
53 struct samldb_ctx {
54         struct ldb_module *module;
55         struct ldb_request *req;
56
57         /* used for add operations */
58         const char *type;
59
60         /* the resulting message */
61         struct ldb_message *msg;
62
63         /* used in "samldb_find_for_defaultObjectCategory" */
64         struct ldb_dn *dn, *res_dn;
65
66         /* all the async steps necessary to complete the operation */
67         struct samldb_step *steps;
68         struct samldb_step *curstep;
69
70         /* If someone set an ares to forward controls and response back to the caller */
71         struct ldb_reply *ares;
72 };
73
74 static struct samldb_ctx *samldb_ctx_init(struct ldb_module *module,
75                                           struct ldb_request *req)
76 {
77         struct ldb_context *ldb;
78         struct samldb_ctx *ac;
79
80         ldb = ldb_module_get_ctx(module);
81
82         ac = talloc_zero(req, struct samldb_ctx);
83         if (ac == NULL) {
84                 ldb_oom(ldb);
85                 return NULL;
86         }
87
88         ac->module = module;
89         ac->req = req;
90
91         return ac;
92 }
93
94 static int samldb_add_step(struct samldb_ctx *ac, samldb_step_fn_t fn)
95 {
96         struct samldb_step *step, *stepper;
97
98         step = talloc_zero(ac, struct samldb_step);
99         if (step == NULL) {
100                 return ldb_oom(ldb_module_get_ctx(ac->module));
101         }
102
103         step->fn = fn;
104
105         if (ac->steps == NULL) {
106                 ac->steps = step;
107                 ac->curstep = step;
108         } else {
109                 if (ac->curstep == NULL)
110                         return ldb_operr(ldb_module_get_ctx(ac->module));
111                 for (stepper = ac->curstep; stepper->next != NULL;
112                         stepper = stepper->next);
113                 stepper->next = step;
114         }
115
116         return LDB_SUCCESS;
117 }
118
119 static int samldb_first_step(struct samldb_ctx *ac)
120 {
121         if (ac->steps == NULL) {
122                 return ldb_operr(ldb_module_get_ctx(ac->module));
123         }
124
125         ac->curstep = ac->steps;
126         return ac->curstep->fn(ac);
127 }
128
129 static int samldb_next_step(struct samldb_ctx *ac)
130 {
131         if (ac->curstep->next) {
132                 ac->curstep = ac->curstep->next;
133                 return ac->curstep->fn(ac);
134         }
135
136         /* We exit the samldb module here. If someone set an "ares" to forward
137          * controls and response back to the caller, use them. */
138         if (ac->ares) {
139                 return ldb_module_done(ac->req, ac->ares->controls,
140                                        ac->ares->response, LDB_SUCCESS);
141         } else {
142                 return ldb_module_done(ac->req, NULL, NULL, LDB_SUCCESS);
143         }
144 }
145
146
147 /* sAMAccountName handling */
148
149 static int samldb_generate_sAMAccountName(struct ldb_context *ldb,
150                                           struct ldb_message *msg)
151 {
152         char *name;
153
154         /* Format: $000000-000000000000 */
155
156         name = talloc_asprintf(msg, "$%.6X-%.6X%.6X",
157                                 (unsigned int)generate_random(),
158                                 (unsigned int)generate_random(),
159                                 (unsigned int)generate_random());
160         if (name == NULL) {
161                 return ldb_oom(ldb);
162         }
163         return ldb_msg_add_steal_string(msg, "sAMAccountName", name);
164 }
165
166 static int samldb_check_sAMAccountName(struct samldb_ctx *ac)
167 {
168         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
169         const char *name;
170         int ret;
171         struct ldb_result *res;
172         const char *noattrs[] = { NULL };
173
174         if (ldb_msg_find_element(ac->msg, "sAMAccountName") == NULL) {
175                 ret = samldb_generate_sAMAccountName(ldb, ac->msg);
176                 if (ret != LDB_SUCCESS) {
177                         return ret;
178                 }
179         }
180
181         name = ldb_msg_find_attr_as_string(ac->msg, "sAMAccountName", NULL);
182         if (name == NULL) {
183                 /* The "sAMAccountName" cannot be nothing */
184                 ldb_set_errstring(ldb,
185                                   "samldb: Empty account names aren't allowed!");
186                 return LDB_ERR_CONSTRAINT_VIOLATION;
187         }
188
189         ret = dsdb_module_search(ac->module, ac, &res,
190                                  ldb_get_default_basedn(ldb), LDB_SCOPE_SUBTREE, noattrs,
191                                  DSDB_FLAG_NEXT_MODULE,
192                                  ac->req,
193                                  "(sAMAccountName=%s)",
194                                  ldb_binary_encode_string(ac, name));
195         if (ret != LDB_SUCCESS) {
196                 return ret;
197         }
198         if (res->count != 0) {
199                 ldb_asprintf_errstring(ldb,
200                                        "samldb: Account name (sAMAccountName) '%s' already in use!",
201                                        name);
202                 talloc_free(res);
203                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
204         }
205         talloc_free(res);
206
207         return samldb_next_step(ac);
208 }
209
210
211 static bool samldb_msg_add_sid(struct ldb_message *msg,
212                                 const char *name,
213                                 const struct dom_sid *sid)
214 {
215         struct ldb_val v;
216         enum ndr_err_code ndr_err;
217
218         ndr_err = ndr_push_struct_blob(&v, msg, sid,
219                                        (ndr_push_flags_fn_t)ndr_push_dom_sid);
220         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
221                 return false;
222         }
223         return (ldb_msg_add_value(msg, name, &v, NULL) == 0);
224 }
225
226
227 /* allocate a SID using our RID Set */
228 static int samldb_allocate_sid(struct samldb_ctx *ac)
229 {
230         uint32_t rid;
231         struct dom_sid *sid;
232         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
233         int ret;
234
235         ret = ridalloc_allocate_rid(ac->module, &rid, ac->req);
236         if (ret != LDB_SUCCESS) {
237                 return ret;
238         }
239
240         sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
241         if (sid == NULL) {
242                 return ldb_module_oom(ac->module);
243         }
244
245         if ( ! samldb_msg_add_sid(ac->msg, "objectSid", sid)) {
246                 return ldb_operr(ldb);
247         }
248
249         return samldb_next_step(ac);
250 }
251
252 /*
253   see if a krbtgt_number is available
254  */
255 static bool samldb_krbtgtnumber_available(struct samldb_ctx *ac,
256                                           uint32_t krbtgt_number)
257 {
258         TALLOC_CTX *tmp_ctx = talloc_new(ac);
259         struct ldb_result *res;
260         const char *no_attrs[] = { NULL };
261         int ret;
262
263         ret = dsdb_module_search(ac->module, tmp_ctx, &res,
264                                  ldb_get_default_basedn(ldb_module_get_ctx(ac->module)),
265                                  LDB_SCOPE_SUBTREE, no_attrs,
266                                  DSDB_FLAG_NEXT_MODULE,
267                                  ac->req,
268                                  "(msDC-SecondaryKrbTgtNumber=%u)",
269                                  krbtgt_number);
270         if (ret == LDB_SUCCESS && res->count == 0) {
271                 talloc_free(tmp_ctx);
272                 return true;
273         }
274         talloc_free(tmp_ctx);
275         return false;
276 }
277
278 /* special handling for add in RODC join */
279 static int samldb_rodc_add(struct samldb_ctx *ac)
280 {
281         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
282         uint32_t krbtgt_number, i_start, i;
283         int ret;
284         char *newpass;
285         struct ldb_val newpass_utf16;
286
287         /* find a unused msDC-SecondaryKrbTgtNumber */
288         i_start = generate_random() & 0xFFFF;
289         if (i_start == 0) {
290                 i_start = 1;
291         }
292
293         for (i=i_start; i<=0xFFFF; i++) {
294                 if (samldb_krbtgtnumber_available(ac, i)) {
295                         krbtgt_number = i;
296                         goto found;
297                 }
298         }
299         for (i=1; i<i_start; i++) {
300                 if (samldb_krbtgtnumber_available(ac, i)) {
301                         krbtgt_number = i;
302                         goto found;
303                 }
304         }
305
306         ldb_asprintf_errstring(ldb,
307                                "%08X: Unable to find available msDS-SecondaryKrbTgtNumber",
308                                W_ERROR_V(WERR_NO_SYSTEM_RESOURCES));
309         return LDB_ERR_OTHER;
310
311 found:
312         ret = ldb_msg_add_empty(ac->msg, "msDS-SecondaryKrbTgtNumber",
313                                 LDB_FLAG_INTERNAL_DISABLE_VALIDATION, NULL);
314         if (ret != LDB_SUCCESS) {
315                 return ldb_operr(ldb);
316         }
317
318         ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
319                                  "msDS-SecondaryKrbTgtNumber", krbtgt_number);
320         if (ret != LDB_SUCCESS) {
321                 return ldb_operr(ldb);
322         }
323
324         ret = ldb_msg_add_fmt(ac->msg, "sAMAccountName", "krbtgt_%u",
325                               krbtgt_number);
326         if (ret != LDB_SUCCESS) {
327                 return ldb_operr(ldb);
328         }
329
330         newpass = generate_random_password(ac->msg, 128, 255);
331         if (newpass == NULL) {
332                 return ldb_operr(ldb);
333         }
334
335         if (!convert_string_talloc(ac,
336                                    CH_UNIX, CH_UTF16,
337                                    newpass, strlen(newpass),
338                                    (void *)&newpass_utf16.data,
339                                    &newpass_utf16.length)) {
340                 ldb_asprintf_errstring(ldb,
341                                        "samldb_rodc_add: "
342                                        "failed to generate UTF16 password from random password");
343                 return LDB_ERR_OPERATIONS_ERROR;
344         }
345         ret = ldb_msg_add_steal_value(ac->msg, "clearTextPassword", &newpass_utf16);
346         if (ret != LDB_SUCCESS) {
347                 return ldb_operr(ldb);
348         }
349
350         return samldb_next_step(ac);
351 }
352
353 static int samldb_find_for_defaultObjectCategory(struct samldb_ctx *ac)
354 {
355         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
356         struct ldb_result *res;
357         const char *no_attrs[] = { NULL };
358         int ret;
359
360         ac->res_dn = NULL;
361
362         ret = dsdb_module_search(ac->module, ac, &res,
363                                  ac->dn, LDB_SCOPE_BASE, no_attrs,
364                                  DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT
365                                  | DSDB_FLAG_NEXT_MODULE,
366                                  ac->req,
367                                  "(objectClass=classSchema)");
368         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
369                 /* Don't be pricky when the DN doesn't exist if we have the */
370                 /* RELAX control specified */
371                 if (ldb_request_get_control(ac->req,
372                                             LDB_CONTROL_RELAX_OID) == NULL) {
373                         ldb_set_errstring(ldb,
374                                           "samldb_find_defaultObjectCategory: "
375                                           "Invalid DN for 'defaultObjectCategory'!");
376                         return LDB_ERR_CONSTRAINT_VIOLATION;
377                 }
378         }
379         if ((ret != LDB_ERR_NO_SUCH_OBJECT) && (ret != LDB_SUCCESS)) {
380                 return ret;
381         }
382
383         if (ret == LDB_SUCCESS) {
384                 /* ensure the defaultObjectCategory has a full GUID */
385                 struct ldb_message *m;
386                 m = ldb_msg_new(ac->msg);
387                 if (m == NULL) {
388                         return ldb_oom(ldb);
389                 }
390                 m->dn = ac->msg->dn;
391                 if (ldb_msg_add_string(m, "defaultObjectCategory",
392                                        ldb_dn_get_extended_linearized(m, res->msgs[0]->dn, 1)) !=
393                     LDB_SUCCESS) {
394                         return ldb_oom(ldb);
395                 }
396                 m->elements[0].flags = LDB_FLAG_MOD_REPLACE;
397
398                 ret = dsdb_module_modify(ac->module, m,
399                                          DSDB_FLAG_NEXT_MODULE,
400                                          ac->req);
401                 if (ret != LDB_SUCCESS) {
402                         return ret;
403                 }
404         }
405
406
407         ac->res_dn = ac->dn;
408
409         return samldb_next_step(ac);
410 }
411
412 /**
413  * msDS-IntId attributeSchema attribute handling
414  * during LDB_ADD request processing
415  */
416 static int samldb_add_handle_msDS_IntId(struct samldb_ctx *ac)
417 {
418         int ret;
419         bool id_exists;
420         uint32_t msds_intid;
421         int32_t system_flags;
422         struct ldb_context *ldb;
423         struct ldb_result *ldb_res;
424         struct ldb_dn *schema_dn;
425
426         ldb = ldb_module_get_ctx(ac->module);
427         schema_dn = ldb_get_schema_basedn(ldb);
428
429         /* replicated update should always go through */
430         if (ldb_request_get_control(ac->req,
431                                     DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
432                 return LDB_SUCCESS;
433         }
434
435         /* msDS-IntId is handled by system and should never be
436          * passed by clients */
437         if (ldb_msg_find_element(ac->msg, "msDS-IntId")) {
438                 return LDB_ERR_UNWILLING_TO_PERFORM;
439         }
440
441         /* do not generate msDS-IntId if Relax control is passed */
442         if (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
443                 return LDB_SUCCESS;
444         }
445
446         /* check Functional Level */
447         if (dsdb_functional_level(ldb) < DS_DOMAIN_FUNCTION_2003) {
448                 return LDB_SUCCESS;
449         }
450
451         /* check systemFlags for SCHEMA_BASE_OBJECT flag */
452         system_flags = ldb_msg_find_attr_as_int(ac->msg, "systemFlags", 0);
453         if (system_flags & SYSTEM_FLAG_SCHEMA_BASE_OBJECT) {
454                 return LDB_SUCCESS;
455         }
456
457         /* Generate new value for msDs-IntId
458          * Value should be in 0x80000000..0xBFFFFFFF range */
459         msds_intid = generate_random() % 0X3FFFFFFF;
460         msds_intid += 0x80000000;
461
462         /* probe id values until unique one is found */
463         do {
464                 msds_intid++;
465                 if (msds_intid > 0xBFFFFFFF) {
466                         msds_intid = 0x80000001;
467                 }
468
469                 ret = dsdb_module_search(ac->module, ac,
470                                          &ldb_res,
471                                          schema_dn, LDB_SCOPE_ONELEVEL, NULL,
472                                          DSDB_FLAG_NEXT_MODULE,
473                                          ac->req,
474                                          "(msDS-IntId=%d)", msds_intid);
475                 if (ret != LDB_SUCCESS) {
476                         ldb_debug_set(ldb, LDB_DEBUG_ERROR,
477                                       __location__": Searching for msDS-IntId=%d failed - %s\n",
478                                       msds_intid,
479                                       ldb_errstring(ldb));
480                         return ldb_operr(ldb);
481                 }
482                 id_exists = (ldb_res->count > 0);
483
484                 talloc_free(ldb_res);
485         } while(id_exists);
486
487         return samdb_msg_add_int(ldb, ac->msg, ac->msg, "msDS-IntId",
488                                  msds_intid);
489 }
490
491
492 /*
493  * samldb_add_entry (async)
494  */
495
496 static int samldb_add_entry_callback(struct ldb_request *req,
497                                         struct ldb_reply *ares)
498 {
499         struct ldb_context *ldb;
500         struct samldb_ctx *ac;
501         int ret;
502
503         ac = talloc_get_type(req->context, struct samldb_ctx);
504         ldb = ldb_module_get_ctx(ac->module);
505
506         if (!ares) {
507                 return ldb_module_done(ac->req, NULL, NULL,
508                                         LDB_ERR_OPERATIONS_ERROR);
509         }
510
511         if (ares->type == LDB_REPLY_REFERRAL) {
512                 return ldb_module_send_referral(ac->req, ares->referral);
513         }
514
515         if (ares->error != LDB_SUCCESS) {
516                 return ldb_module_done(ac->req, ares->controls,
517                                         ares->response, ares->error);
518         }
519         if (ares->type != LDB_REPLY_DONE) {
520                 ldb_asprintf_errstring(ldb, "Invalid LDB reply type %d", ares->type);
521                 return ldb_module_done(ac->req, NULL, NULL,
522                                         LDB_ERR_OPERATIONS_ERROR);
523         }
524
525         /* The caller may wish to get controls back from the add */
526         ac->ares = talloc_steal(ac, ares);
527
528         ret = samldb_next_step(ac);
529         if (ret != LDB_SUCCESS) {
530                 return ldb_module_done(ac->req, NULL, NULL, ret);
531         }
532         return ret;
533 }
534
535 static int samldb_add_entry(struct samldb_ctx *ac)
536 {
537         struct ldb_context *ldb;
538         struct ldb_request *req;
539         int ret;
540
541         ldb = ldb_module_get_ctx(ac->module);
542
543         ret = ldb_build_add_req(&req, ldb, ac,
544                                 ac->msg,
545                                 ac->req->controls,
546                                 ac, samldb_add_entry_callback,
547                                 ac->req);
548         LDB_REQ_SET_LOCATION(req);
549         if (ret != LDB_SUCCESS) {
550                 return ret;
551         }
552
553         return ldb_next_request(ac->module, req);
554 }
555
556 /*
557  * return true if msg carries an attributeSchema that is intended to be RODC
558  * filtered but is also a system-critical attribute.
559  */
560 static bool check_rodc_critical_attribute(struct ldb_message *msg)
561 {
562         uint32_t schemaFlagsEx, searchFlags, rodc_filtered_flags;
563
564         schemaFlagsEx = ldb_msg_find_attr_as_uint(msg, "schemaFlagsEx", 0);
565         searchFlags = ldb_msg_find_attr_as_uint(msg, "searchFlags", 0);
566         rodc_filtered_flags = (SEARCH_FLAG_RODC_ATTRIBUTE
567                               | SEARCH_FLAG_CONFIDENTIAL);
568
569         if ((schemaFlagsEx & SCHEMA_FLAG_ATTR_IS_CRITICAL) &&
570                 ((searchFlags & rodc_filtered_flags) == rodc_filtered_flags)) {
571                 return true;
572         } else {
573                 return false;
574         }
575 }
576
577
578 static int samldb_fill_object(struct samldb_ctx *ac)
579 {
580         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
581         int ret;
582
583         /* Add information for the different account types */
584         if (strcmp(ac->type, "user") == 0) {
585                 struct ldb_control *rodc_control = ldb_request_get_control(ac->req,
586                                                                            LDB_CONTROL_RODC_DCPROMO_OID);
587                 if (rodc_control != NULL) {
588                         /* see [MS-ADTS] 3.1.1.3.4.1.23 LDAP_SERVER_RODC_DCPROMO_OID */
589                         rodc_control->critical = false;
590                         ret = samldb_add_step(ac, samldb_rodc_add);
591                         if (ret != LDB_SUCCESS) return ret;
592                 }
593
594                 /* check if we have a valid sAMAccountName */
595                 ret = samldb_add_step(ac, samldb_check_sAMAccountName);
596                 if (ret != LDB_SUCCESS) return ret;
597
598                 ret = samldb_add_step(ac, samldb_add_entry);
599                 if (ret != LDB_SUCCESS) return ret;
600
601         } else if (strcmp(ac->type, "group") == 0) {
602                 /* check if we have a valid sAMAccountName */
603                 ret = samldb_add_step(ac, samldb_check_sAMAccountName);
604                 if (ret != LDB_SUCCESS) return ret;
605
606                 ret = samldb_add_step(ac, samldb_add_entry);
607                 if (ret != LDB_SUCCESS) return ret;
608
609         } else if (strcmp(ac->type, "classSchema") == 0) {
610                 const struct ldb_val *rdn_value, *def_obj_cat_val;
611
612                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
613                                                   "rdnAttId", "cn");
614                 if (ret != LDB_SUCCESS) return ret;
615
616                 /* do not allow to mark an attributeSchema as RODC filtered if it
617                  * is system-critical */
618                 if (check_rodc_critical_attribute(ac->msg)) {
619                         ldb_asprintf_errstring(ldb, "Refusing schema add of %s - cannot combine critical class with RODC filtering",
620                                                ldb_dn_get_linearized(ac->msg->dn));
621                         return LDB_ERR_UNWILLING_TO_PERFORM;
622                 }
623
624                 rdn_value = ldb_dn_get_rdn_val(ac->msg->dn);
625                 if (rdn_value == NULL) {
626                         return ldb_operr(ldb);
627                 }
628                 if (!ldb_msg_find_element(ac->msg, "lDAPDisplayName")) {
629                         /* the RDN has prefix "CN" */
630                         ret = ldb_msg_add_string(ac->msg, "lDAPDisplayName",
631                                 samdb_cn_to_lDAPDisplayName(ac->msg,
632                                                             (const char *) rdn_value->data));
633                         if (ret != LDB_SUCCESS) {
634                                 ldb_oom(ldb);
635                                 return ret;
636                         }
637                 }
638
639                 if (!ldb_msg_find_element(ac->msg, "schemaIDGUID")) {
640                         struct GUID guid;
641                         /* a new GUID */
642                         guid = GUID_random();
643                         ret = dsdb_msg_add_guid(ac->msg, &guid, "schemaIDGUID");
644                         if (ret != LDB_SUCCESS) {
645                                 ldb_oom(ldb);
646                                 return ret;
647                         }
648                 }
649
650                 def_obj_cat_val = ldb_msg_find_ldb_val(ac->msg,
651                                                        "defaultObjectCategory");
652                 if (def_obj_cat_val != NULL) {
653                         /* "defaultObjectCategory" has been set by the caller.
654                          * Do some checks for consistency.
655                          * NOTE: The real constraint check (that
656                          * 'defaultObjectCategory' is the DN of the new
657                          * objectclass or any parent of it) is still incomplete.
658                          * For now we say that 'defaultObjectCategory' is valid
659                          * if it exists and it is of objectclass "classSchema".
660                          */
661                         ac->dn = ldb_dn_from_ldb_val(ac, ldb, def_obj_cat_val);
662                         if (ac->dn == NULL) {
663                                 ldb_set_errstring(ldb,
664                                                   "Invalid DN for 'defaultObjectCategory'!");
665                                 return LDB_ERR_CONSTRAINT_VIOLATION;
666                         }
667                 } else {
668                         /* "defaultObjectCategory" has not been set by the
669                          * caller. Use the entry DN for it. */
670                         ac->dn = ac->msg->dn;
671
672                         ret = ldb_msg_add_string(ac->msg, "defaultObjectCategory",
673                                                  ldb_dn_alloc_linearized(ac->msg, ac->dn));
674                         if (ret != LDB_SUCCESS) {
675                                 ldb_oom(ldb);
676                                 return ret;
677                         }
678                 }
679
680                 ret = samldb_add_step(ac, samldb_add_entry);
681                 if (ret != LDB_SUCCESS) return ret;
682
683                 /* Now perform the checks for the 'defaultObjectCategory'. The
684                  * lookup DN was already saved in "ac->dn" */
685                 ret = samldb_add_step(ac, samldb_find_for_defaultObjectCategory);
686                 if (ret != LDB_SUCCESS) return ret;
687
688         } else if (strcmp(ac->type, "attributeSchema") == 0) {
689                 const struct ldb_val *rdn_value;
690                 rdn_value = ldb_dn_get_rdn_val(ac->msg->dn);
691                 if (rdn_value == NULL) {
692                         return ldb_operr(ldb);
693                 }
694                 if (!ldb_msg_find_element(ac->msg, "lDAPDisplayName")) {
695                         /* the RDN has prefix "CN" */
696                         ret = ldb_msg_add_string(ac->msg, "lDAPDisplayName",
697                                 samdb_cn_to_lDAPDisplayName(ac->msg,
698                                                             (const char *) rdn_value->data));
699                         if (ret != LDB_SUCCESS) {
700                                 ldb_oom(ldb);
701                                 return ret;
702                         }
703                 }
704
705                 /* do not allow to mark an attributeSchema as RODC filtered if it
706                  * is system-critical */
707                 if (check_rodc_critical_attribute(ac->msg)) {
708                         ldb_asprintf_errstring(ldb,
709                                                "samldb: refusing schema add of %s - cannot combine critical attribute with RODC filtering",
710                                                ldb_dn_get_linearized(ac->msg->dn));
711                         return LDB_ERR_UNWILLING_TO_PERFORM;
712                 }
713
714                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
715                                                   "isSingleValued", "FALSE");
716                 if (ret != LDB_SUCCESS) return ret;
717
718                 if (!ldb_msg_find_element(ac->msg, "schemaIDGUID")) {
719                         struct GUID guid;
720                         /* a new GUID */
721                         guid = GUID_random();
722                         ret = dsdb_msg_add_guid(ac->msg, &guid, "schemaIDGUID");
723                         if (ret != LDB_SUCCESS) {
724                                 ldb_oom(ldb);
725                                 return ret;
726                         }
727                 }
728
729                 /* handle msDS-IntID attribute */
730                 ret = samldb_add_handle_msDS_IntId(ac);
731                 if (ret != LDB_SUCCESS) return ret;
732
733                 ret = samldb_add_step(ac, samldb_add_entry);
734                 if (ret != LDB_SUCCESS) return ret;
735
736         } else {
737                 ldb_asprintf_errstring(ldb,
738                         "Invalid entry type!");
739                 return LDB_ERR_OPERATIONS_ERROR;
740         }
741
742         return samldb_first_step(ac);
743 }
744
745 static int samldb_fill_foreignSecurityPrincipal_object(struct samldb_ctx *ac)
746 {
747         struct ldb_context *ldb;
748         const struct ldb_val *rdn_value;
749         struct dom_sid *sid;
750         int ret;
751
752         ldb = ldb_module_get_ctx(ac->module);
753
754         sid = samdb_result_dom_sid(ac->msg, ac->msg, "objectSid");
755         if (sid == NULL) {
756                 rdn_value = ldb_dn_get_rdn_val(ac->msg->dn);
757                 if (rdn_value == NULL) {
758                         return ldb_operr(ldb);
759                 }
760                 sid = dom_sid_parse_talloc(ac->msg,
761                                            (const char *)rdn_value->data);
762                 if (sid == NULL) {
763                         ldb_set_errstring(ldb,
764                                           "samldb: No valid SID found in ForeignSecurityPrincipal CN!");
765                         return LDB_ERR_CONSTRAINT_VIOLATION;
766                 }
767                 if (! samldb_msg_add_sid(ac->msg, "objectSid", sid)) {
768                         return ldb_operr(ldb);
769                 }
770         }
771
772         /* finally proceed with adding the entry */
773         ret = samldb_add_step(ac, samldb_add_entry);
774         if (ret != LDB_SUCCESS) return ret;
775
776         return samldb_first_step(ac);
777 }
778
779 static int samldb_schema_info_update(struct samldb_ctx *ac)
780 {
781         int ret;
782         struct ldb_context *ldb;
783         struct dsdb_schema *schema;
784
785         /* replicated update should always go through */
786         if (ldb_request_get_control(ac->req,
787                                     DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
788                 return LDB_SUCCESS;
789         }
790
791         /* do not update schemaInfo during provisioning */
792         if (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
793                 return LDB_SUCCESS;
794         }
795
796         ldb = ldb_module_get_ctx(ac->module);
797         schema = dsdb_get_schema(ldb, NULL);
798         if (!schema) {
799                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
800                               "samldb_schema_info_update: no dsdb_schema loaded");
801                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
802                 return ldb_operr(ldb);
803         }
804
805         ret = dsdb_module_schema_info_update(ac->module, schema,
806                                              DSDB_FLAG_NEXT_MODULE|
807                                              DSDB_FLAG_AS_SYSTEM,
808                                              ac->req);
809         if (ret != LDB_SUCCESS) {
810                 ldb_asprintf_errstring(ldb,
811                                        "samldb_schema_info_update: dsdb_module_schema_info_update failed with %s",
812                                        ldb_errstring(ldb));
813                 return ret;
814         }
815
816         return LDB_SUCCESS;
817 }
818
819 static int samldb_prim_group_tester(struct samldb_ctx *ac, uint32_t rid);
820
821 /*
822  * "Objectclass" trigger (MS-SAMR 3.1.1.8.1)
823  *
824  * Has to be invoked on "add" and "modify" operations on "user", "computer" and
825  * "group" objects.
826  * ac->msg contains the "add"/"modify" message
827  * ac->type contains the object type (main objectclass)
828  */
829 static int samldb_objectclass_trigger(struct samldb_ctx *ac)
830 {
831         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
832         void *skip_allocate_sids = ldb_get_opaque(ldb,
833                                                   "skip_allocate_sids");
834         struct ldb_message_element *el, *el2;
835         struct dom_sid *sid;
836         int ret;
837
838         /* make sure that "sAMAccountType" is not specified */
839         el = ldb_msg_find_element(ac->msg, "sAMAccountType");
840         if (el != NULL) {
841                 ldb_set_errstring(ldb,
842                                   "samldb: sAMAccountType must not be specified!");
843                 return LDB_ERR_UNWILLING_TO_PERFORM;
844         }
845
846         /* Step 1: objectSid assignment */
847
848         /* Don't allow the objectSid to be changed. But beside the RELAX
849          * control we have also to guarantee that it can always be set with
850          * SYSTEM permissions. This is needed for the "samba3sam" backend. */
851         sid = samdb_result_dom_sid(ac, ac->msg, "objectSid");
852         if ((sid != NULL) && (!dsdb_module_am_system(ac->module)) &&
853             (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) == NULL)) {
854                 ldb_set_errstring(ldb,
855                                   "samldb: objectSid must not be specified!");
856                 return LDB_ERR_UNWILLING_TO_PERFORM;
857         }
858
859         /* but generate a new SID when we do have an add operations */
860         if ((sid == NULL) && (ac->req->operation == LDB_ADD) && !skip_allocate_sids) {
861                 ret = samldb_add_step(ac, samldb_allocate_sid);
862                 if (ret != LDB_SUCCESS) return ret;
863         }
864
865         if (strcmp(ac->type, "user") == 0) {
866                 bool uac_generated = false;
867
868                 /* Step 1.2: Default values */
869                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
870                         "accountExpires", "9223372036854775807");
871                 if (ret != LDB_SUCCESS) return ret;
872                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
873                         "badPasswordTime", "0");
874                 if (ret != LDB_SUCCESS) return ret;
875                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
876                         "badPwdCount", "0");
877                 if (ret != LDB_SUCCESS) return ret;
878                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
879                         "codePage", "0");
880                 if (ret != LDB_SUCCESS) return ret;
881                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
882                         "countryCode", "0");
883                 if (ret != LDB_SUCCESS) return ret;
884                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
885                         "lastLogoff", "0");
886                 if (ret != LDB_SUCCESS) return ret;
887                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
888                         "lastLogon", "0");
889                 if (ret != LDB_SUCCESS) return ret;
890                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
891                         "logonCount", "0");
892                 if (ret != LDB_SUCCESS) return ret;
893                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
894                         "pwdLastSet", "0");
895                 if (ret != LDB_SUCCESS) return ret;
896
897                 /* On add operations we might need to generate a
898                  * "userAccountControl" (if it isn't specified). */
899                 el = ldb_msg_find_element(ac->msg, "userAccountControl");
900                 if ((el == NULL) && (ac->req->operation == LDB_ADD)) {
901                         ret = samdb_msg_set_uint(ldb, ac->msg, ac->msg,
902                                                  "userAccountControl",
903                                                  UF_NORMAL_ACCOUNT);
904                         if (ret != LDB_SUCCESS) {
905                                 return ret;
906                         }
907                         uac_generated = true;
908                 }
909
910                 el = ldb_msg_find_element(ac->msg, "userAccountControl");
911                 if (el != NULL) {
912                         uint32_t user_account_control, account_type;
913
914                         /* Step 1.3: "userAccountControl" -> "sAMAccountType" mapping */
915                         user_account_control = ldb_msg_find_attr_as_uint(ac->msg,
916                                                                          "userAccountControl",
917                                                                          0);
918
919                         /* Temporary duplicate accounts aren't allowed */
920                         if ((user_account_control & UF_TEMP_DUPLICATE_ACCOUNT) != 0) {
921                                 return LDB_ERR_OTHER;
922                         }
923
924                         /* Workstation and (read-only) DC objects do need objectclass "computer" */
925                         if ((samdb_find_attribute(ldb, ac->msg,
926                                                   "objectclass", "computer") == NULL) &&
927                             (user_account_control &
928                              (UF_SERVER_TRUST_ACCOUNT | UF_WORKSTATION_TRUST_ACCOUNT))) {
929                                 ldb_set_errstring(ldb,
930                                                   "samldb: Requested account type does need objectclass 'computer'!");
931                                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
932                         }
933
934                         account_type = ds_uf2atype(user_account_control);
935                         if (account_type == 0) {
936                                 ldb_set_errstring(ldb, "samldb: Unrecognized account type!");
937                                 return LDB_ERR_UNWILLING_TO_PERFORM;
938                         }
939                         ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
940                                                  "sAMAccountType",
941                                                  account_type);
942                         if (ret != LDB_SUCCESS) {
943                                 return ret;
944                         }
945                         el2 = ldb_msg_find_element(ac->msg, "sAMAccountType");
946                         el2->flags = LDB_FLAG_MOD_REPLACE;
947
948                         /* "isCriticalSystemObject" might be set */
949                         if (user_account_control &
950                             (UF_SERVER_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)) {
951                                 ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject",
952                                                          "TRUE");
953                                 if (ret != LDB_SUCCESS) {
954                                         return ret;
955                                 }
956                                 el2 = ldb_msg_find_element(ac->msg,
957                                                            "isCriticalSystemObject");
958                                 el2->flags = LDB_FLAG_MOD_REPLACE;
959                         } else if (user_account_control & UF_WORKSTATION_TRUST_ACCOUNT) {
960                                 ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject",
961                                                          "FALSE");
962                                 if (ret != LDB_SUCCESS) {
963                                         return ret;
964                                 }
965                                 el2 = ldb_msg_find_element(ac->msg,
966                                                            "isCriticalSystemObject");
967                                 el2->flags = LDB_FLAG_MOD_REPLACE;
968                         }
969
970                         /* Step 1.4: "userAccountControl" -> "primaryGroupID" mapping */
971                         if (!ldb_msg_find_element(ac->msg, "primaryGroupID")) {
972                                 uint32_t rid = ds_uf2prim_group_rid(user_account_control);
973
974                                 /*
975                                  * Older AD deployments don't know about the
976                                  * RODC group
977                                  */
978                                 if (rid == DOMAIN_RID_READONLY_DCS) {
979                                         ret = samldb_prim_group_tester(ac, rid);
980                                         if (ret != LDB_SUCCESS) {
981                                                 return ret;
982                                         }
983                                 }
984
985                                 ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
986                                                          "primaryGroupID", rid);
987                                 if (ret != LDB_SUCCESS) {
988                                         return ret;
989                                 }
990                                 el2 = ldb_msg_find_element(ac->msg,
991                                                            "primaryGroupID");
992                                 el2->flags = LDB_FLAG_MOD_REPLACE;
993                         }
994
995                         /* Step 1.5: Add additional flags when needed */
996                         /* Obviously this is done when the "userAccountControl"
997                          * has been generated here (tested against Windows
998                          * Server) */
999                         if (uac_generated) {
1000                                 user_account_control |= UF_ACCOUNTDISABLE;
1001                                 user_account_control |= UF_PASSWD_NOTREQD;
1002
1003                                 ret = samdb_msg_set_uint(ldb, ac->msg, ac->msg,
1004                                                          "userAccountControl",
1005                                                          user_account_control);
1006                                 if (ret != LDB_SUCCESS) {
1007                                         return ret;
1008                                 }
1009                         }
1010                 }
1011
1012         } else if (strcmp(ac->type, "group") == 0) {
1013                 const char *tempstr;
1014
1015                 /* Step 2.2: Default values */
1016                 tempstr = talloc_asprintf(ac->msg, "%d",
1017                                           GTYPE_SECURITY_GLOBAL_GROUP);
1018                 if (tempstr == NULL) return ldb_operr(ldb);
1019                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
1020                         "groupType", tempstr);
1021                 if (ret != LDB_SUCCESS) return ret;
1022
1023                 /* Step 2.3: "groupType" -> "sAMAccountType" */
1024                 el = ldb_msg_find_element(ac->msg, "groupType");
1025                 if (el != NULL) {
1026                         uint32_t group_type, account_type;
1027
1028                         group_type = ldb_msg_find_attr_as_uint(ac->msg,
1029                                                                "groupType", 0);
1030
1031                         /* The creation of builtin groups requires the
1032                          * RELAX control */
1033                         if (group_type == GTYPE_SECURITY_BUILTIN_LOCAL_GROUP) {
1034                                 if (ldb_request_get_control(ac->req,
1035                                                             LDB_CONTROL_RELAX_OID) == NULL) {
1036                                         return LDB_ERR_UNWILLING_TO_PERFORM;
1037                                 }
1038                         }
1039
1040                         account_type = ds_gtype2atype(group_type);
1041                         if (account_type == 0) {
1042                                 ldb_set_errstring(ldb, "samldb: Unrecognized account type!");
1043                                 return LDB_ERR_UNWILLING_TO_PERFORM;
1044                         }
1045                         ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
1046                                                  "sAMAccountType",
1047                                                  account_type);
1048                         if (ret != LDB_SUCCESS) {
1049                                 return ret;
1050                         }
1051                         el2 = ldb_msg_find_element(ac->msg, "sAMAccountType");
1052                         el2->flags = LDB_FLAG_MOD_REPLACE;
1053                 }
1054         }
1055
1056         return LDB_SUCCESS;
1057 }
1058
1059 /*
1060  * "Primary group ID" trigger (MS-SAMR 3.1.1.8.2)
1061  *
1062  * Has to be invoked on "add" and "modify" operations on "user" and "computer"
1063  * objects.
1064  * ac->msg contains the "add"/"modify" message
1065  */
1066
1067 static int samldb_prim_group_tester(struct samldb_ctx *ac, uint32_t rid)
1068 {
1069         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1070         struct dom_sid *sid;
1071         struct ldb_result *res;
1072         int ret;
1073         const char *noattrs[] = { NULL };
1074
1075         sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
1076         if (sid == NULL) {
1077                 return ldb_operr(ldb);
1078         }
1079
1080         ret = dsdb_module_search(ac->module, ac, &res,
1081                                  ldb_get_default_basedn(ldb),
1082                                  LDB_SCOPE_SUBTREE,
1083                                  noattrs, DSDB_FLAG_NEXT_MODULE,
1084                                  ac->req,
1085                                  "(objectSid=%s)",
1086                                  ldap_encode_ndr_dom_sid(ac, sid));
1087         if (ret != LDB_SUCCESS) {
1088                 return ret;
1089         }
1090         if (res->count != 1) {
1091                 talloc_free(res);
1092                 ldb_asprintf_errstring(ldb,
1093                                        "Failed to find primary group with RID %u!",
1094                                        rid);
1095                 return LDB_ERR_UNWILLING_TO_PERFORM;
1096         }
1097         talloc_free(res);
1098
1099         return LDB_SUCCESS;
1100 }
1101
1102 static int samldb_prim_group_set(struct samldb_ctx *ac)
1103 {
1104         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1105         uint32_t rid;
1106
1107         rid = ldb_msg_find_attr_as_uint(ac->msg, "primaryGroupID", (uint32_t) -1);
1108         if (rid == (uint32_t) -1) {
1109                 /* we aren't affected of any primary group set */
1110                 return LDB_SUCCESS;
1111
1112         } else if (!ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
1113                 ldb_set_errstring(ldb,
1114                                   "The primary group isn't settable on add operations!");
1115                 return LDB_ERR_UNWILLING_TO_PERFORM;
1116         }
1117
1118         return samldb_prim_group_tester(ac, rid);
1119 }
1120
1121 static int samldb_prim_group_change(struct samldb_ctx *ac)
1122 {
1123         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1124         const char * attrs[] = { "primaryGroupID", "memberOf", NULL };
1125         struct ldb_result *res, *group_res;
1126         struct ldb_message_element *el;
1127         struct ldb_message *msg;
1128         uint32_t prev_rid, new_rid;
1129         struct dom_sid *prev_sid, *new_sid;
1130         struct ldb_dn *prev_prim_group_dn, *new_prim_group_dn;
1131         int ret;
1132         const char *noattrs[] = { NULL };
1133
1134         el = dsdb_get_single_valued_attr(ac->msg, "primaryGroupID",
1135                                          ac->req->operation);
1136         if (el == NULL) {
1137                 /* we are not affected */
1138                 return LDB_SUCCESS;
1139         }
1140
1141         /* Fetch information from the existing object */
1142
1143         ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, attrs,
1144                                     DSDB_FLAG_NEXT_MODULE, ac->req);
1145         if (ret != LDB_SUCCESS) {
1146                 return ret;
1147         }
1148
1149         /* Finds out the DN of the old primary group */
1150
1151         prev_rid = ldb_msg_find_attr_as_uint(res->msgs[0], "primaryGroupID",
1152                                              (uint32_t) -1);
1153         if (prev_rid == (uint32_t) -1) {
1154                 /* User objects do always have a mandatory "primaryGroupID"
1155                  * attribute. If this doesn't exist then the object is of the
1156                  * wrong type. This is the exact Windows error code */
1157                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1158         }
1159
1160         prev_sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), prev_rid);
1161         if (prev_sid == NULL) {
1162                 return ldb_operr(ldb);
1163         }
1164
1165         /* Finds out the DN of the new primary group
1166          * Notice: in order to parse the primary group ID correctly we create
1167          * a temporary message here. */
1168
1169         msg = ldb_msg_new(ac->msg);
1170         if (msg == NULL) {
1171                 return ldb_module_oom(ac->module);
1172         }
1173         ret = ldb_msg_add(msg, el, 0);
1174         if (ret != LDB_SUCCESS) {
1175                 return ret;
1176         }
1177         new_rid = ldb_msg_find_attr_as_uint(msg, "primaryGroupID", (uint32_t) -1);
1178         talloc_free(msg);
1179         if (new_rid == (uint32_t) -1) {
1180                 /* we aren't affected of any primary group change */
1181                 return LDB_SUCCESS;
1182         }
1183
1184         if (prev_rid == new_rid) {
1185                 return LDB_SUCCESS;
1186         }
1187
1188         ret = dsdb_module_search(ac->module, ac, &group_res,
1189                                  ldb_get_default_basedn(ldb),
1190                                  LDB_SCOPE_SUBTREE,
1191                                  noattrs, DSDB_FLAG_NEXT_MODULE,
1192                                  ac->req,
1193                                  "(objectSid=%s)",
1194                                  ldap_encode_ndr_dom_sid(ac, prev_sid));
1195         if (ret != LDB_SUCCESS) {
1196                 return ret;
1197         }
1198         if (group_res->count != 1) {
1199                 return ldb_operr(ldb);
1200         }
1201         prev_prim_group_dn = group_res->msgs[0]->dn;
1202
1203         new_sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), new_rid);
1204         if (new_sid == NULL) {
1205                 return ldb_operr(ldb);
1206         }
1207
1208         ret = dsdb_module_search(ac->module, ac, &group_res,
1209                                  ldb_get_default_basedn(ldb),
1210                                  LDB_SCOPE_SUBTREE,
1211                                  noattrs, DSDB_FLAG_NEXT_MODULE,
1212                                  ac->req,
1213                                  "(objectSid=%s)",
1214                                  ldap_encode_ndr_dom_sid(ac, new_sid));
1215         if (ret != LDB_SUCCESS) {
1216                 return ret;
1217         }
1218         if (group_res->count != 1) {
1219                 /* Here we know if the specified new primary group candidate is
1220                  * valid or not. */
1221                 return LDB_ERR_UNWILLING_TO_PERFORM;
1222         }
1223         new_prim_group_dn = group_res->msgs[0]->dn;
1224
1225         /* We need to be already a normal member of the new primary
1226          * group in order to be successful. */
1227         el = samdb_find_attribute(ldb, res->msgs[0], "memberOf",
1228                                   ldb_dn_get_linearized(new_prim_group_dn));
1229         if (el == NULL) {
1230                 return LDB_ERR_UNWILLING_TO_PERFORM;
1231         }
1232
1233         /* Remove the "member" attribute on the new primary group */
1234         msg = ldb_msg_new(ac->msg);
1235         if (msg == NULL) {
1236                 return ldb_module_oom(ac->module);
1237         }
1238         msg->dn = new_prim_group_dn;
1239
1240         ret = samdb_msg_add_delval(ldb, msg, msg, "member",
1241                                    ldb_dn_get_linearized(ac->msg->dn));
1242         if (ret != LDB_SUCCESS) {
1243                 return ret;
1244         }
1245
1246         ret = dsdb_module_modify(ac->module, msg, DSDB_FLAG_NEXT_MODULE, ac->req);
1247         if (ret != LDB_SUCCESS) {
1248                 return ret;
1249         }
1250         talloc_free(msg);
1251
1252         /* Add a "member" attribute for the previous primary group */
1253         msg = ldb_msg_new(ac->msg);
1254         if (msg == NULL) {
1255                 return ldb_module_oom(ac->module);
1256         }
1257         msg->dn = prev_prim_group_dn;
1258
1259         ret = samdb_msg_add_addval(ldb, msg, msg, "member",
1260                                    ldb_dn_get_linearized(ac->msg->dn));
1261         if (ret != LDB_SUCCESS) {
1262                 return ret;
1263         }
1264
1265         ret = dsdb_module_modify(ac->module, msg, DSDB_FLAG_NEXT_MODULE, ac->req);
1266         if (ret != LDB_SUCCESS) {
1267                 return ret;
1268         }
1269         talloc_free(msg);
1270
1271         return LDB_SUCCESS;
1272 }
1273
1274 static int samldb_prim_group_trigger(struct samldb_ctx *ac)
1275 {
1276         int ret;
1277
1278         if (ac->req->operation == LDB_ADD) {
1279                 ret = samldb_prim_group_set(ac);
1280         } else {
1281                 ret = samldb_prim_group_change(ac);
1282         }
1283
1284         return ret;
1285 }
1286
1287
1288 /**
1289  * This function is called on LDB modify operations. It performs some additions/
1290  * replaces on the current LDB message when "userAccountControl" changes.
1291  */
1292 static int samldb_user_account_control_change(struct samldb_ctx *ac)
1293 {
1294         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1295         uint32_t user_account_control, old_user_account_control, account_type;
1296         struct ldb_message_element *el;
1297         struct ldb_message *tmp_msg;
1298         int ret;
1299         struct ldb_result *res;
1300         const char *attrs[] = { "userAccountControl", "objectClass", NULL };
1301         unsigned int i;
1302         bool is_computer = false;
1303
1304         el = dsdb_get_single_valued_attr(ac->msg, "userAccountControl",
1305                                          ac->req->operation);
1306         if (el == NULL) {
1307                 /* we are not affected */
1308                 return LDB_SUCCESS;
1309         }
1310
1311         /* Create a temporary message for fetching the "userAccountControl" */
1312         tmp_msg = ldb_msg_new(ac->msg);
1313         if (tmp_msg == NULL) {
1314                 return ldb_module_oom(ac->module);
1315         }
1316         ret = ldb_msg_add(tmp_msg, el, 0);
1317         if (ret != LDB_SUCCESS) {
1318                 return ret;
1319         }
1320         user_account_control = ldb_msg_find_attr_as_uint(tmp_msg,
1321                                                          "userAccountControl",
1322                                                          0);
1323         talloc_free(tmp_msg);
1324
1325         /* Temporary duplicate accounts aren't allowed */
1326         if ((user_account_control & UF_TEMP_DUPLICATE_ACCOUNT) != 0) {
1327                 return LDB_ERR_OTHER;
1328         }
1329
1330         /* Fetch the old "userAccountControl" and "objectClass" */
1331         ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, attrs,
1332                                     DSDB_FLAG_NEXT_MODULE, ac->req);
1333         if (ret != LDB_SUCCESS) {
1334                 return ret;
1335         }
1336         old_user_account_control = ldb_msg_find_attr_as_uint(res->msgs[0], "userAccountControl", 0);
1337         if (old_user_account_control == 0) {
1338                 return ldb_operr(ldb);
1339         }
1340         el = ldb_msg_find_element(res->msgs[0], "objectClass");
1341         if (el == NULL) {
1342                 return ldb_operr(ldb);
1343         }
1344
1345         /* When we do not have objectclass "computer" we cannot switch to a (read-only) DC */
1346         for (i = 0; i < el->num_values; i++) {
1347                 if (ldb_attr_cmp((char *)el->values[i].data, "computer") == 0) {
1348                         is_computer = true;
1349                         break;
1350                 }
1351         }
1352         if (!is_computer &&
1353             (user_account_control & (UF_SERVER_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT))) {
1354                 ldb_set_errstring(ldb,
1355                                   "samldb: Requested account type does need objectclass 'computer'!");
1356                 return LDB_ERR_UNWILLING_TO_PERFORM;
1357         }
1358
1359         /*
1360          * The functions "ds_uf2atype" and "ds_uf2prim_group_rid" are used as
1361          * detectors for account type changes.
1362          * So if the account type does change then we need to adjust the
1363          * "sAMAccountType", the "isCriticalSystemObject" and the
1364          * "primaryGroupID" attribute.
1365          */
1366         if ((ds_uf2atype(user_account_control)
1367              == ds_uf2atype(old_user_account_control)) &&
1368             (ds_uf2prim_group_rid(user_account_control)
1369              == ds_uf2prim_group_rid(old_user_account_control))) {
1370                 return LDB_SUCCESS;
1371         }
1372
1373         account_type = ds_uf2atype(user_account_control);
1374         if (account_type == 0) {
1375                 ldb_set_errstring(ldb, "samldb: Unrecognized account type!");
1376                 return LDB_ERR_UNWILLING_TO_PERFORM;
1377         }
1378         ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "sAMAccountType",
1379                                  account_type);
1380         if (ret != LDB_SUCCESS) {
1381                 return ret;
1382         }
1383         el = ldb_msg_find_element(ac->msg, "sAMAccountType");
1384         el->flags = LDB_FLAG_MOD_REPLACE;
1385
1386         /* "isCriticalSystemObject" might be set/changed */
1387         if (user_account_control
1388             & (UF_SERVER_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)) {
1389                 ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject",
1390                                          "TRUE");
1391                 if (ret != LDB_SUCCESS) {
1392                         return ret;
1393                 }
1394                 el = ldb_msg_find_element(ac->msg,
1395                                            "isCriticalSystemObject");
1396                 el->flags = LDB_FLAG_MOD_REPLACE;
1397         } else if (user_account_control & UF_WORKSTATION_TRUST_ACCOUNT) {
1398                 ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject",
1399                                          "FALSE");
1400                 if (ret != LDB_SUCCESS) {
1401                         return ret;
1402                 }
1403                 el = ldb_msg_find_element(ac->msg,
1404                                            "isCriticalSystemObject");
1405                 el->flags = LDB_FLAG_MOD_REPLACE;
1406         }
1407
1408         if (!ldb_msg_find_element(ac->msg, "primaryGroupID")) {
1409                 uint32_t rid = ds_uf2prim_group_rid(user_account_control);
1410
1411                 /* Older AD deployments don't know about the RODC group */
1412                 if (rid == DOMAIN_RID_READONLY_DCS) {
1413                         ret = samldb_prim_group_tester(ac, rid);
1414                         if (ret != LDB_SUCCESS) {
1415                                 return ret;
1416                         }
1417                 }
1418
1419                 ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
1420                                          "primaryGroupID", rid);
1421                 if (ret != LDB_SUCCESS) {
1422                         return ret;
1423                 }
1424                 el = ldb_msg_find_element(ac->msg,
1425                                            "primaryGroupID");
1426                 el->flags = LDB_FLAG_MOD_REPLACE;
1427         }
1428
1429         return LDB_SUCCESS;
1430 }
1431
1432 static int samldb_group_type_change(struct samldb_ctx *ac)
1433 {
1434         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1435         uint32_t group_type, old_group_type, account_type;
1436         struct ldb_message_element *el;
1437         struct ldb_message *tmp_msg;
1438         int ret;
1439         struct ldb_result *res;
1440         const char *attrs[] = { "groupType", NULL };
1441
1442         el = dsdb_get_single_valued_attr(ac->msg, "groupType",
1443                                          ac->req->operation);
1444         if (el == NULL) {
1445                 /* we are not affected */
1446                 return LDB_SUCCESS;
1447         }
1448
1449         /* Create a temporary message for fetching the "groupType" */
1450         tmp_msg = ldb_msg_new(ac->msg);
1451         if (tmp_msg == NULL) {
1452                 return ldb_module_oom(ac->module);
1453         }
1454         ret = ldb_msg_add(tmp_msg, el, 0);
1455         if (ret != LDB_SUCCESS) {
1456                 return ret;
1457         }
1458         group_type = ldb_msg_find_attr_as_uint(tmp_msg, "groupType", 0);
1459         talloc_free(tmp_msg);
1460
1461         ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, attrs,
1462                                     DSDB_FLAG_NEXT_MODULE |
1463                                     DSDB_SEARCH_SHOW_DELETED, ac->req);
1464         if (ret != LDB_SUCCESS) {
1465                 return ret;
1466         }
1467         old_group_type = ldb_msg_find_attr_as_uint(res->msgs[0], "groupType", 0);
1468         if (old_group_type == 0) {
1469                 return ldb_operr(ldb);
1470         }
1471
1472         /* Group type switching isn't so easy as it seems: We can only
1473          * change in this directions: global <-> universal <-> local
1474          * On each step also the group type itself
1475          * (security/distribution) is variable. */
1476
1477         if (ldb_request_get_control(ac->req, LDB_CONTROL_PROVISION_OID) == NULL) {
1478                 switch (group_type) {
1479                 case GTYPE_SECURITY_GLOBAL_GROUP:
1480                 case GTYPE_DISTRIBUTION_GLOBAL_GROUP:
1481                         /* change to "universal" allowed */
1482                         if ((old_group_type == GTYPE_SECURITY_DOMAIN_LOCAL_GROUP) ||
1483                         (old_group_type == GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)) {
1484                                 ldb_set_errstring(ldb,
1485                                         "samldb: Change from security/distribution local group forbidden!");
1486                                 return LDB_ERR_UNWILLING_TO_PERFORM;
1487                         }
1488                 break;
1489
1490                 case GTYPE_SECURITY_UNIVERSAL_GROUP:
1491                 case GTYPE_DISTRIBUTION_UNIVERSAL_GROUP:
1492                         /* each change allowed */
1493                 break;
1494                 case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
1495                 case GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP:
1496                         /* change to "universal" allowed */
1497                         if ((old_group_type == GTYPE_SECURITY_GLOBAL_GROUP) ||
1498                         (old_group_type == GTYPE_DISTRIBUTION_GLOBAL_GROUP)) {
1499                                 ldb_set_errstring(ldb,
1500                                         "samldb: Change from security/distribution global group forbidden!");
1501                                 return LDB_ERR_UNWILLING_TO_PERFORM;
1502                         }
1503                 break;
1504
1505                 case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
1506                 default:
1507                         /* we don't allow this "groupType" values */
1508                         return LDB_ERR_UNWILLING_TO_PERFORM;
1509                 break;
1510                 }
1511         }
1512
1513         account_type =  ds_gtype2atype(group_type);
1514         if (account_type == 0) {
1515                 ldb_set_errstring(ldb, "samldb: Unrecognized account type!");
1516                 return LDB_ERR_UNWILLING_TO_PERFORM;
1517         }
1518         ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "sAMAccountType",
1519                                  account_type);
1520         if (ret != LDB_SUCCESS) {
1521                 return ret;
1522         }
1523         el = ldb_msg_find_element(ac->msg, "sAMAccountType");
1524         el->flags = LDB_FLAG_MOD_REPLACE;
1525
1526         return LDB_SUCCESS;
1527 }
1528
1529 static int samldb_sam_accountname_check(struct samldb_ctx *ac)
1530 {
1531         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1532         const char *no_attrs[] = { NULL };
1533         struct ldb_result *res;
1534         const char *sam_accountname, *enc_str;
1535         struct ldb_message_element *el;
1536         struct ldb_message *tmp_msg;
1537         int ret;
1538
1539         el = dsdb_get_single_valued_attr(ac->msg, "sAMAccountName",
1540                                          ac->req->operation);
1541         if (el == NULL) {
1542                 /* we are not affected */
1543                 return LDB_SUCCESS;
1544         }
1545
1546         /* Create a temporary message for fetching the "sAMAccountName" */
1547         tmp_msg = ldb_msg_new(ac->msg);
1548         if (tmp_msg == NULL) {
1549                 return ldb_module_oom(ac->module);
1550         }
1551         ret = ldb_msg_add(tmp_msg, el, 0);
1552         if (ret != LDB_SUCCESS) {
1553                 return ret;
1554         }
1555         sam_accountname = talloc_steal(ac,
1556                                        ldb_msg_find_attr_as_string(tmp_msg, "sAMAccountName", NULL));
1557         talloc_free(tmp_msg);
1558
1559         if (sam_accountname == NULL) {
1560                 /* The "sAMAccountName" cannot be nothing */
1561                 ldb_set_errstring(ldb,
1562                                   "samldb: Empty account names aren't allowed!");
1563                 return LDB_ERR_UNWILLING_TO_PERFORM;
1564         }
1565
1566         enc_str = ldb_binary_encode_string(ac, sam_accountname);
1567         if (enc_str == NULL) {
1568                 return ldb_module_oom(ac->module);
1569         }
1570
1571         /* Make sure that a "sAMAccountName" is only used once */
1572
1573         ret = dsdb_module_search(ac->module, ac, &res,
1574                                  ldb_get_default_basedn(ldb),
1575                                  LDB_SCOPE_SUBTREE, no_attrs,
1576                                  DSDB_FLAG_NEXT_MODULE, ac->req,
1577                                  "(sAMAccountName=%s)", enc_str);
1578         if (ret != LDB_SUCCESS) {
1579                 return ret;
1580         }
1581         if (res->count > 1) {
1582                 return ldb_operr(ldb);
1583         } else if (res->count == 1) {
1584                 if (ldb_dn_compare(res->msgs[0]->dn, ac->msg->dn) != 0) {
1585                         ldb_asprintf_errstring(ldb,
1586                                                "samldb: Account name (sAMAccountName) '%s' already in use!",
1587                                                sam_accountname);
1588                         return LDB_ERR_ENTRY_ALREADY_EXISTS;
1589                 }
1590         }
1591         talloc_free(res);
1592
1593         return LDB_SUCCESS;
1594 }
1595
1596 static int samldb_member_check(struct samldb_ctx *ac)
1597 {
1598         static const char * const attrs[] = { "objectSid", "member", NULL };
1599         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1600         struct ldb_message_element *el;
1601         struct ldb_dn *member_dn;
1602         struct dom_sid *sid;
1603         struct ldb_result *res;
1604         struct dom_sid *group_sid;
1605         unsigned int i, j;
1606         int ret;
1607
1608         /* Fetch information from the existing object */
1609
1610         ret = dsdb_module_search(ac->module, ac, &res, ac->msg->dn, LDB_SCOPE_BASE, attrs,
1611                                  DSDB_FLAG_NEXT_MODULE, ac->req, NULL);
1612         if (ret != LDB_SUCCESS) {
1613                 return ret;
1614         }
1615         if (res->count != 1) {
1616                 return ldb_operr(ldb);
1617         }
1618
1619         group_sid = samdb_result_dom_sid(res, res->msgs[0], "objectSid");
1620         if (group_sid == NULL) {
1621                 return ldb_operr(ldb);
1622         }
1623
1624         /* We've to walk over all modification entries and consider the "member"
1625          * ones. */
1626         for (i = 0; i < ac->msg->num_elements; i++) {
1627                 if (ldb_attr_cmp(ac->msg->elements[i].name, "member") != 0) {
1628                         continue;
1629                 }
1630
1631                 el = &ac->msg->elements[i];
1632                 for (j = 0; j < el->num_values; j++) {
1633                         struct ldb_result *group_res;
1634                         const char *group_attrs[] = { "primaryGroupID" , NULL };
1635                         uint32_t prim_group_rid;
1636
1637                         if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE) {
1638                                 /* Deletes will be handled in
1639                                  * repl_meta_data, and deletes not
1640                                  * matching a member will return
1641                                  * LDB_ERR_UNWILLING_TO_PERFORM
1642                                  * there */
1643                                 continue;
1644                         }
1645
1646                         member_dn = ldb_dn_from_ldb_val(ac, ldb,
1647                                                         &el->values[j]);
1648                         if (!ldb_dn_validate(member_dn)) {
1649                                 return ldb_operr(ldb);
1650                         }
1651
1652                         /* Denies to add "member"s to groups which are primary
1653                          * ones for them - in this case return
1654                          * ERR_ENTRY_ALREADY_EXISTS. */
1655
1656                         ret = dsdb_module_search_dn(ac->module, ac, &group_res,
1657                                                     member_dn, group_attrs,
1658                                                     DSDB_FLAG_NEXT_MODULE, ac->req);
1659                         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1660                                 /* member DN doesn't exist yet */
1661                                 continue;
1662                         }
1663                         if (ret != LDB_SUCCESS) {
1664                                 return ret;
1665                         }
1666                         prim_group_rid = ldb_msg_find_attr_as_uint(group_res->msgs[0], "primaryGroupID", (uint32_t)-1);
1667                         if (prim_group_rid == (uint32_t) -1) {
1668                                 /* the member hasn't to be a user account ->
1669                                  * therefore no check needed in this case. */
1670                                 continue;
1671                         }
1672
1673                         sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb),
1674                                               prim_group_rid);
1675                         if (sid == NULL) {
1676                                 return ldb_operr(ldb);
1677                         }
1678
1679                         if (dom_sid_equal(group_sid, sid)) {
1680                                 ldb_asprintf_errstring(ldb,
1681                                                        "samldb: member %s already set via primaryGroupID %u",
1682                                                        ldb_dn_get_linearized(member_dn), prim_group_rid);
1683                                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
1684                         }
1685                 }
1686         }
1687
1688         talloc_free(res);
1689
1690         return LDB_SUCCESS;
1691 }
1692
1693 /* SAM objects have special rules regarding the "description" attribute on
1694  * modify operations. */
1695 static int samldb_description_check(struct samldb_ctx *ac, bool *modified)
1696 {
1697         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1698         const char * const attrs[] = { "objectClass", "description", NULL };
1699         struct ldb_result *res;
1700         unsigned int i;
1701         int ret;
1702
1703         /* Fetch information from the existing object */
1704         ret = dsdb_module_search(ac->module, ac, &res, ac->msg->dn, LDB_SCOPE_BASE, attrs,
1705                                  DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED, ac->req,
1706                                  "(|(objectclass=user)(objectclass=group)(objectclass=samDomain)(objectclass=samServer))");
1707         if (ret != LDB_SUCCESS) {
1708                 /* don't treat it specially ... let normal error codes
1709                    happen from other places */
1710                 ldb_reset_err_string(ldb);
1711                 return LDB_SUCCESS;
1712         }
1713         if (res->count == 0) {
1714                 /* we didn't match the filter */
1715                 talloc_free(res);
1716                 return LDB_SUCCESS;
1717         }
1718
1719         /* We've to walk over all modification entries and consider the
1720          * "description" ones. */
1721         for (i = 0; i < ac->msg->num_elements; i++) {
1722                 if (ldb_attr_cmp(ac->msg->elements[i].name, "description") == 0) {
1723                         ac->msg->elements[i].flags |= LDB_FLAG_INTERNAL_FORCE_SINGLE_VALUE_CHECK;
1724                         *modified = true;
1725                 }
1726         }
1727
1728         talloc_free(res);
1729
1730         return LDB_SUCCESS;
1731 }
1732
1733 /* This trigger adapts the "servicePrincipalName" attributes if the
1734  * "dNSHostName" and/or "sAMAccountName" attribute change(s) */
1735 static int samldb_service_principal_names_change(struct samldb_ctx *ac)
1736 {
1737         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1738         struct ldb_message_element *el = NULL, *el2 = NULL;
1739         struct ldb_message *msg;
1740         const char *attrs[] = { "servicePrincipalName", NULL };
1741         struct ldb_result *res;
1742         const char *dns_hostname = NULL, *old_dns_hostname = NULL,
1743                    *sam_accountname = NULL, *old_sam_accountname = NULL;
1744         unsigned int i;
1745         int ret;
1746
1747         el = dsdb_get_single_valued_attr(ac->msg, "dNSHostName",
1748                                          ac->req->operation);
1749         el2 = dsdb_get_single_valued_attr(ac->msg, "sAMAccountName",
1750                                           ac->req->operation);
1751         if ((el == NULL) && (el2 == NULL)) {
1752                 /* we are not affected */
1753                 return LDB_SUCCESS;
1754         }
1755
1756         /* Create a temporary message for fetching the "dNSHostName" */
1757         if (el != NULL) {
1758                 const char *dns_attrs[] = { "dNSHostName", NULL };
1759                 msg = ldb_msg_new(ac->msg);
1760                 if (msg == NULL) {
1761                         return ldb_module_oom(ac->module);
1762                 }
1763                 ret = ldb_msg_add(msg, el, 0);
1764                 if (ret != LDB_SUCCESS) {
1765                         return ret;
1766                 }
1767                 dns_hostname = talloc_steal(ac,
1768                                             ldb_msg_find_attr_as_string(msg, "dNSHostName", NULL));
1769                 talloc_free(msg);
1770
1771                 ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn,
1772                                             dns_attrs, DSDB_FLAG_NEXT_MODULE, ac->req);
1773                 if (ret == LDB_SUCCESS) {
1774                         old_dns_hostname = ldb_msg_find_attr_as_string(res->msgs[0], "dNSHostName", NULL);
1775                 }
1776         }
1777
1778         /* Create a temporary message for fetching the "sAMAccountName" */
1779         if (el2 != NULL) {
1780                 char *tempstr, *tempstr2;
1781                 const char *acct_attrs[] = { "sAMAccountName", NULL };
1782
1783                 msg = ldb_msg_new(ac->msg);
1784                 if (msg == NULL) {
1785                         return ldb_module_oom(ac->module);
1786                 }
1787                 ret = ldb_msg_add(msg, el2, 0);
1788                 if (ret != LDB_SUCCESS) {
1789                         return ret;
1790                 }
1791                 tempstr = talloc_strdup(ac,
1792                                         ldb_msg_find_attr_as_string(msg, "sAMAccountName", NULL));
1793                 talloc_free(msg);
1794
1795                 ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, acct_attrs,
1796                                             DSDB_FLAG_NEXT_MODULE, ac->req);
1797                 if (ret == LDB_SUCCESS) {
1798                         tempstr2 = talloc_strdup(ac,
1799                                                  ldb_msg_find_attr_as_string(res->msgs[0],
1800                                                                              "sAMAccountName", NULL));
1801                 }
1802
1803
1804                 /* The "sAMAccountName" needs some additional trimming: we need
1805                  * to remove the trailing "$"s if they exist. */
1806                 if ((tempstr != NULL) && (tempstr[0] != '\0') &&
1807                     (tempstr[strlen(tempstr) - 1] == '$')) {
1808                         tempstr[strlen(tempstr) - 1] = '\0';
1809                 }
1810                 if ((tempstr2 != NULL) && (tempstr2[0] != '\0') &&
1811                     (tempstr2[strlen(tempstr2) - 1] == '$')) {
1812                         tempstr2[strlen(tempstr2) - 1] = '\0';
1813                 }
1814                 sam_accountname = tempstr;
1815                 old_sam_accountname = tempstr2;
1816         }
1817
1818         if (old_dns_hostname == NULL) {
1819                 /* we cannot change when the old name is unknown */
1820                 dns_hostname = NULL;
1821         }
1822         if ((old_dns_hostname != NULL) && (dns_hostname != NULL) &&
1823             (strcasecmp(old_dns_hostname, dns_hostname) == 0)) {
1824                 /* The "dNSHostName" didn't change */
1825                 dns_hostname = NULL;
1826         }
1827
1828         if (old_sam_accountname == NULL) {
1829                 /* we cannot change when the old name is unknown */
1830                 sam_accountname = NULL;
1831         }
1832         if ((old_sam_accountname != NULL) && (sam_accountname != NULL) &&
1833             (strcasecmp(old_sam_accountname, sam_accountname) == 0)) {
1834                 /* The "sAMAccountName" didn't change */
1835                 sam_accountname = NULL;
1836         }
1837
1838         if ((dns_hostname == NULL) && (sam_accountname == NULL)) {
1839                 /* Well, there are information missing (old name(s)) or the
1840                  * names didn't change. We've nothing to do and can exit here */
1841                 return LDB_SUCCESS;
1842         }
1843
1844         /* Potential "servicePrincipalName" changes in the same request have to
1845          * be handled before the update (Windows behaviour). */
1846         el = ldb_msg_find_element(ac->msg, "servicePrincipalName");
1847         if (el != NULL) {
1848                 msg = ldb_msg_new(ac->msg);
1849                 if (msg == NULL) {
1850                         return ldb_module_oom(ac->module);
1851                 }
1852                 msg->dn = ac->msg->dn;
1853
1854                 do {
1855                         ret = ldb_msg_add(msg, el, el->flags);
1856                         if (ret != LDB_SUCCESS) {
1857                                 return ret;
1858                         }
1859
1860                         ldb_msg_remove_element(ac->msg, el);
1861
1862                         el = ldb_msg_find_element(ac->msg,
1863                                                   "servicePrincipalName");
1864                 } while (el != NULL);
1865
1866                 ret = dsdb_module_modify(ac->module, msg,
1867                                          DSDB_FLAG_NEXT_MODULE, ac->req);
1868                 if (ret != LDB_SUCCESS) {
1869                         return ret;
1870                 }
1871                 talloc_free(msg);
1872         }
1873
1874         /* Fetch the "servicePrincipalName"s if any */
1875         ret = dsdb_module_search(ac->module, ac, &res, ac->msg->dn, LDB_SCOPE_BASE, attrs,
1876                                  DSDB_FLAG_NEXT_MODULE, ac->req, NULL);
1877         if (ret != LDB_SUCCESS) {
1878                 return ret;
1879         }
1880         if ((res->count != 1) || (res->msgs[0]->num_elements > 1)) {
1881                 return ldb_operr(ldb);
1882         }
1883
1884         if (res->msgs[0]->num_elements == 1) {
1885                 /* Yes, we do have "servicePrincipalName"s. First we update them
1886                  * locally, that means we do always substitute the current
1887                  * "dNSHostName" with the new one and/or "sAMAccountName"
1888                  * without "$" with the new one and then we append this to the
1889                  * modification request (Windows behaviour). */
1890
1891                 for (i = 0; i < res->msgs[0]->elements[0].num_values; i++) {
1892                         char *old_str, *new_str, *pos;
1893                         const char *tok;
1894
1895                         old_str = (char *)
1896                                 res->msgs[0]->elements[0].values[i].data;
1897
1898                         new_str = talloc_strdup(ac->msg,
1899                                                 strtok_r(old_str, "/", &pos));
1900                         if (new_str == NULL) {
1901                                 return ldb_module_oom(ac->module);
1902                         }
1903
1904                         while ((tok = strtok_r(NULL, "/", &pos)) != NULL) {
1905                                 if ((dns_hostname != NULL) &&
1906                                     (strcasecmp(tok, old_dns_hostname) == 0)) {
1907                                         tok = dns_hostname;
1908                                 }
1909                                 if ((sam_accountname != NULL) &&
1910                                     (strcasecmp(tok, old_sam_accountname) == 0)) {
1911                                         tok = sam_accountname;
1912                                 }
1913
1914                                 new_str = talloc_asprintf(ac->msg, "%s/%s",
1915                                                           new_str, tok);
1916                                 if (new_str == NULL) {
1917                                         return ldb_module_oom(ac->module);
1918                                 }
1919                         }
1920
1921                         ret = ldb_msg_add_string(ac->msg,
1922                                                  "servicePrincipalName",
1923                                                  new_str);
1924                         if (ret != LDB_SUCCESS) {
1925                                 return ret;
1926                         }
1927                 }
1928
1929                 el = ldb_msg_find_element(ac->msg, "servicePrincipalName");
1930                 el->flags = LDB_FLAG_MOD_REPLACE;
1931         }
1932
1933         talloc_free(res);
1934
1935         return LDB_SUCCESS;
1936 }
1937
1938
1939 /* add */
1940 static int samldb_add(struct ldb_module *module, struct ldb_request *req)
1941 {
1942         struct ldb_context *ldb;
1943         struct samldb_ctx *ac;
1944         int ret;
1945
1946         ldb = ldb_module_get_ctx(module);
1947         ldb_debug(ldb, LDB_DEBUG_TRACE, "samldb_add\n");
1948
1949         /* do not manipulate our control entries */
1950         if (ldb_dn_is_special(req->op.add.message->dn)) {
1951                 return ldb_next_request(module, req);
1952         }
1953
1954         ac = samldb_ctx_init(module, req);
1955         if (ac == NULL) {
1956                 return ldb_operr(ldb);
1957         }
1958
1959         /* build the new msg */
1960         ac->msg = ldb_msg_copy_shallow(ac, req->op.add.message);
1961         if (ac->msg == NULL) {
1962                 talloc_free(ac);
1963                 ldb_debug(ldb, LDB_DEBUG_FATAL,
1964                           "samldb_add: ldb_msg_copy_shallow failed!\n");
1965                 return ldb_operr(ldb);
1966         }
1967
1968         if (samdb_find_attribute(ldb, ac->msg,
1969                                  "objectclass", "user") != NULL) {
1970                 ac->type = "user";
1971
1972                 ret = samldb_prim_group_trigger(ac);
1973                 if (ret != LDB_SUCCESS) {
1974                         return ret;
1975                 }
1976
1977                 ret = samldb_objectclass_trigger(ac);
1978                 if (ret != LDB_SUCCESS) {
1979                         return ret;
1980                 }
1981
1982                 return samldb_fill_object(ac);
1983         }
1984
1985         if (samdb_find_attribute(ldb, ac->msg,
1986                                  "objectclass", "group") != NULL) {
1987                 ac->type = "group";
1988
1989                 ret = samldb_objectclass_trigger(ac);
1990                 if (ret != LDB_SUCCESS) {
1991                         return ret;
1992                 }
1993
1994                 return samldb_fill_object(ac);
1995         }
1996
1997         /* perhaps a foreignSecurityPrincipal? */
1998         if (samdb_find_attribute(ldb, ac->msg,
1999                                  "objectclass",
2000                                  "foreignSecurityPrincipal") != NULL) {
2001                 return samldb_fill_foreignSecurityPrincipal_object(ac);
2002         }
2003
2004         if (samdb_find_attribute(ldb, ac->msg,
2005                                  "objectclass", "classSchema") != NULL) {
2006                 ret = samldb_schema_info_update(ac);
2007                 if (ret != LDB_SUCCESS) {
2008                         talloc_free(ac);
2009                         return ret;
2010                 }
2011
2012                 ac->type = "classSchema";
2013                 return samldb_fill_object(ac);
2014         }
2015
2016         if (samdb_find_attribute(ldb, ac->msg,
2017                                  "objectclass", "attributeSchema") != NULL) {
2018                 ret = samldb_schema_info_update(ac);
2019                 if (ret != LDB_SUCCESS) {
2020                         talloc_free(ac);
2021                         return ret;
2022                 }
2023
2024                 ac->type = "attributeSchema";
2025                 return samldb_fill_object(ac);
2026         }
2027
2028         talloc_free(ac);
2029
2030         /* nothing matched, go on */
2031         return ldb_next_request(module, req);
2032 }
2033
2034 /* modify */
2035 static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
2036 {
2037         struct ldb_context *ldb;
2038         struct samldb_ctx *ac;
2039         struct ldb_message_element *el, *el2;
2040         bool modified = false;
2041         int ret;
2042
2043         if (ldb_dn_is_special(req->op.mod.message->dn)) {
2044                 /* do not manipulate our control entries */
2045                 return ldb_next_request(module, req);
2046         }
2047
2048         ldb = ldb_module_get_ctx(module);
2049
2050         /* make sure that "objectSid" is not specified */
2051         el = ldb_msg_find_element(req->op.mod.message, "objectSid");
2052         if (el != NULL) {
2053                 if (ldb_request_get_control(req, LDB_CONTROL_PROVISION_OID) == NULL) {
2054                         ldb_set_errstring(ldb,
2055                                           "samldb: objectSid must not be specified!");
2056                         return LDB_ERR_UNWILLING_TO_PERFORM;
2057                 }
2058         }
2059         /* make sure that "sAMAccountType" is not specified */
2060         el = ldb_msg_find_element(req->op.mod.message, "sAMAccountType");
2061         if (el != NULL) {
2062                 ldb_set_errstring(ldb,
2063                                   "samldb: sAMAccountType must not be specified!");
2064                 return LDB_ERR_UNWILLING_TO_PERFORM;
2065         }
2066         /* make sure that "isCriticalSystemObject" is not specified */
2067         el = ldb_msg_find_element(req->op.mod.message, "isCriticalSystemObject");
2068         if (el != NULL) {
2069                 if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID) == NULL) {
2070                         ldb_set_errstring(ldb,
2071                                           "samldb: isCriticalSystemObject must not be specified!");
2072                         return LDB_ERR_UNWILLING_TO_PERFORM;
2073                 }
2074         }
2075
2076         /* msDS-IntId is not allowed to be modified
2077          * except when modification comes from replication */
2078         if (ldb_msg_find_element(req->op.mod.message, "msDS-IntId")) {
2079                 if (!ldb_request_get_control(req,
2080                                              DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
2081                         return LDB_ERR_CONSTRAINT_VIOLATION;
2082                 }
2083         }
2084
2085         ac = samldb_ctx_init(module, req);
2086         if (ac == NULL) {
2087                 return ldb_operr(ldb);
2088         }
2089
2090         /* build the new msg */
2091         ac->msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
2092         if (ac->msg == NULL) {
2093                 talloc_free(ac);
2094                 ldb_debug(ldb, LDB_DEBUG_FATAL,
2095                           "samldb_modify: ldb_msg_copy_shallow failed!\n");
2096                 return ldb_operr(ldb);
2097         }
2098
2099         el = ldb_msg_find_element(ac->msg, "primaryGroupID");
2100         if (el != NULL) {
2101                 ret = samldb_prim_group_trigger(ac);
2102                 if (ret != LDB_SUCCESS) {
2103                         return ret;
2104                 }
2105         }
2106
2107         el = ldb_msg_find_element(ac->msg, "userAccountControl");
2108         if (el != NULL) {
2109                 modified = true;
2110                 ret = samldb_user_account_control_change(ac);
2111                 if (ret != LDB_SUCCESS) {
2112                         return ret;
2113                 }
2114         }
2115
2116         el = ldb_msg_find_element(ac->msg, "groupType");
2117         if (el != NULL) {
2118                 modified = true;
2119                 ret = samldb_group_type_change(ac);
2120                 if (ret != LDB_SUCCESS) {
2121                         return ret;
2122                 }
2123         }
2124
2125         el = ldb_msg_find_element(ac->msg, "sAMAccountName");
2126         if (el != NULL) {
2127                 ret = samldb_sam_accountname_check(ac);
2128                 if (ret != LDB_SUCCESS) {
2129                         return ret;
2130                 }
2131         }
2132
2133         el = ldb_msg_find_element(ac->msg, "member");
2134         if (el != NULL) {
2135                 ret = samldb_member_check(ac);
2136                 if (ret != LDB_SUCCESS) {
2137                         return ret;
2138                 }
2139         }
2140
2141         el = ldb_msg_find_element(ac->msg, "description");
2142         if (el != NULL) {
2143                 ret = samldb_description_check(ac, &modified);
2144                 if (ret != LDB_SUCCESS) {
2145                         return ret;
2146                 }
2147         }
2148
2149         el = ldb_msg_find_element(ac->msg, "dNSHostName");
2150         el2 = ldb_msg_find_element(ac->msg, "sAMAccountName");
2151         if ((el != NULL) || (el2 != NULL)) {
2152                 modified = true;
2153                 ret = samldb_service_principal_names_change(ac);
2154                 if (ret != LDB_SUCCESS) {
2155                         return ret;
2156                 }
2157         }
2158
2159         if (modified) {
2160                 struct ldb_request *child_req;
2161
2162                 /* Now perform the real modifications as a child request */
2163                 ret = ldb_build_mod_req(&child_req, ldb, ac,
2164                                         ac->msg,
2165                                         req->controls,
2166                                         req, dsdb_next_callback,
2167                                         req);
2168                 LDB_REQ_SET_LOCATION(child_req);
2169                 if (ret != LDB_SUCCESS) {
2170                         return ret;
2171                 }
2172
2173                 return ldb_next_request(module, child_req);
2174         }
2175
2176         talloc_free(ac);
2177
2178         /* no change which interests us, go on */
2179         return ldb_next_request(module, req);
2180 }
2181
2182 /* delete */
2183
2184 static int samldb_prim_group_users_check(struct samldb_ctx *ac)
2185 {
2186         struct ldb_context *ldb;
2187         struct dom_sid *sid;
2188         uint32_t rid;
2189         NTSTATUS status;
2190         int ret;
2191         struct ldb_result *res;
2192         const char *attrs[] = { "objectSid", "isDeleted", NULL };
2193         const char *noattrs[] = { NULL };
2194
2195         ldb = ldb_module_get_ctx(ac->module);
2196
2197         /* Finds out the SID/RID of the SAM object */
2198         ret = dsdb_module_search_dn(ac->module, ac, &res, ac->req->op.del.dn,
2199                                         attrs,
2200                                         DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED,
2201                                         ac->req);
2202         if (ret != LDB_SUCCESS) {
2203                 return ret;
2204         }
2205
2206         if (ldb_msg_check_string_attribute(res->msgs[0], "isDeleted", "TRUE")) {
2207                 return LDB_SUCCESS;
2208         }
2209
2210         sid = samdb_result_dom_sid(ac, res->msgs[0], "objectSid");
2211         if (sid == NULL) {
2212                 /* No SID - it might not be a SAM object - therefore ok */
2213                 return LDB_SUCCESS;
2214         }
2215         status = dom_sid_split_rid(ac, sid, NULL, &rid);
2216         if (!NT_STATUS_IS_OK(status)) {
2217                 return ldb_operr(ldb);
2218         }
2219         if (rid == 0) {
2220                 /* Special object (security principal?) */
2221                 return LDB_SUCCESS;
2222         }
2223
2224         /* Deny delete requests from groups which are primary ones */
2225         ret = dsdb_module_search(ac->module, ac, &res,
2226                                  ldb_get_default_basedn(ldb),
2227                                  LDB_SCOPE_SUBTREE, noattrs,
2228                                  DSDB_FLAG_NEXT_MODULE,
2229                                  ac->req,
2230                                  "(&(primaryGroupID=%u)(objectClass=user))", rid);
2231         if (ret != LDB_SUCCESS) {
2232                 return ret;
2233         }
2234         if (res->count > 0) {
2235                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
2236         }
2237
2238         return LDB_SUCCESS;
2239 }
2240
2241 static int samldb_delete(struct ldb_module *module, struct ldb_request *req)
2242 {
2243         struct samldb_ctx *ac;
2244         int ret;
2245
2246         if (ldb_dn_is_special(req->op.del.dn)) {
2247                 /* do not manipulate our control entries */
2248                 return ldb_next_request(module, req);
2249         }
2250
2251         ac = samldb_ctx_init(module, req);
2252         if (ac == NULL) {
2253                 return ldb_operr(ldb_module_get_ctx(module));
2254         }
2255
2256         ret = samldb_prim_group_users_check(ac);
2257         if (ret != LDB_SUCCESS) {
2258                 return ret;
2259         }
2260
2261         talloc_free(ac);
2262
2263         return ldb_next_request(module, req);
2264 }
2265
2266 /* extended */
2267
2268 static int samldb_extended_allocate_rid_pool(struct ldb_module *module, struct ldb_request *req)
2269 {
2270         struct ldb_context *ldb = ldb_module_get_ctx(module);
2271         struct dsdb_fsmo_extended_op *exop;
2272         int ret;
2273
2274         exop = talloc_get_type(req->op.extended.data,
2275                                struct dsdb_fsmo_extended_op);
2276         if (!exop) {
2277                 ldb_set_errstring(ldb,
2278                                   "samldb_extended_allocate_rid_pool: invalid extended data");
2279                 return LDB_ERR_PROTOCOL_ERROR;
2280         }
2281
2282         ret = ridalloc_allocate_rid_pool_fsmo(module, exop, req);
2283         if (ret != LDB_SUCCESS) {
2284                 return ret;
2285         }
2286
2287         return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
2288 }
2289
2290 static int samldb_extended(struct ldb_module *module, struct ldb_request *req)
2291 {
2292         if (strcmp(req->op.extended.oid, DSDB_EXTENDED_ALLOCATE_RID_POOL) == 0) {
2293                 return samldb_extended_allocate_rid_pool(module, req);
2294         }
2295
2296         return ldb_next_request(module, req);
2297 }
2298
2299
2300 static const struct ldb_module_ops ldb_samldb_module_ops = {
2301         .name          = "samldb",
2302         .add           = samldb_add,
2303         .modify        = samldb_modify,
2304         .del           = samldb_delete,
2305         .extended      = samldb_extended
2306 };
2307
2308
2309 int ldb_samldb_module_init(const char *version)
2310 {
2311         LDB_MODULE_CHECK_VERSION(version);
2312         return ldb_register_module(&ldb_samldb_module_ops);
2313 }