dsdb: improve debug message
[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, ac->req);
807         if (ret != LDB_SUCCESS) {
808                 ldb_asprintf_errstring(ldb,
809                                        "samldb_schema_info_update: dsdb_module_schema_info_update failed with %s",
810                                        ldb_errstring(ldb));
811                 return ret;
812         }
813
814         return LDB_SUCCESS;
815 }
816
817 static int samldb_prim_group_tester(struct samldb_ctx *ac, uint32_t rid);
818
819 /*
820  * "Objectclass" trigger (MS-SAMR 3.1.1.8.1)
821  *
822  * Has to be invoked on "add" and "modify" operations on "user", "computer" and
823  * "group" objects.
824  * ac->msg contains the "add"/"modify" message
825  * ac->type contains the object type (main objectclass)
826  */
827 static int samldb_objectclass_trigger(struct samldb_ctx *ac)
828 {
829         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
830         void *skip_allocate_sids = ldb_get_opaque(ldb,
831                                                   "skip_allocate_sids");
832         struct ldb_message_element *el, *el2;
833         struct dom_sid *sid;
834         int ret;
835
836         /* make sure that "sAMAccountType" is not specified */
837         el = ldb_msg_find_element(ac->msg, "sAMAccountType");
838         if (el != NULL) {
839                 ldb_set_errstring(ldb,
840                                   "samldb: sAMAccountType must not be specified!");
841                 return LDB_ERR_UNWILLING_TO_PERFORM;
842         }
843
844         /* Step 1: objectSid assignment */
845
846         /* Don't allow the objectSid to be changed. But beside the RELAX
847          * control we have also to guarantee that it can always be set with
848          * SYSTEM permissions. This is needed for the "samba3sam" backend. */
849         sid = samdb_result_dom_sid(ac, ac->msg, "objectSid");
850         if ((sid != NULL) && (!dsdb_module_am_system(ac->module)) &&
851             (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) == NULL)) {
852                 ldb_set_errstring(ldb,
853                                   "samldb: objectSid must not be specified!");
854                 return LDB_ERR_UNWILLING_TO_PERFORM;
855         }
856
857         /* but generate a new SID when we do have an add operations */
858         if ((sid == NULL) && (ac->req->operation == LDB_ADD) && !skip_allocate_sids) {
859                 ret = samldb_add_step(ac, samldb_allocate_sid);
860                 if (ret != LDB_SUCCESS) return ret;
861         }
862
863         if (strcmp(ac->type, "user") == 0) {
864                 bool uac_generated = false;
865
866                 /* Step 1.2: Default values */
867                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
868                         "accountExpires", "9223372036854775807");
869                 if (ret != LDB_SUCCESS) return ret;
870                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
871                         "badPasswordTime", "0");
872                 if (ret != LDB_SUCCESS) return ret;
873                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
874                         "badPwdCount", "0");
875                 if (ret != LDB_SUCCESS) return ret;
876                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
877                         "codePage", "0");
878                 if (ret != LDB_SUCCESS) return ret;
879                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
880                         "countryCode", "0");
881                 if (ret != LDB_SUCCESS) return ret;
882                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
883                         "lastLogoff", "0");
884                 if (ret != LDB_SUCCESS) return ret;
885                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
886                         "lastLogon", "0");
887                 if (ret != LDB_SUCCESS) return ret;
888                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
889                         "logonCount", "0");
890                 if (ret != LDB_SUCCESS) return ret;
891                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
892                         "pwdLastSet", "0");
893                 if (ret != LDB_SUCCESS) return ret;
894
895                 /* On add operations we might need to generate a
896                  * "userAccountControl" (if it isn't specified). */
897                 el = ldb_msg_find_element(ac->msg, "userAccountControl");
898                 if ((el == NULL) && (ac->req->operation == LDB_ADD)) {
899                         ret = samdb_msg_set_uint(ldb, ac->msg, ac->msg,
900                                                  "userAccountControl",
901                                                  UF_NORMAL_ACCOUNT);
902                         if (ret != LDB_SUCCESS) {
903                                 return ret;
904                         }
905                         uac_generated = true;
906                 }
907
908                 el = ldb_msg_find_element(ac->msg, "userAccountControl");
909                 if (el != NULL) {
910                         uint32_t user_account_control, account_type;
911
912                         /* Step 1.3: "userAccountControl" -> "sAMAccountType" mapping */
913                         user_account_control = ldb_msg_find_attr_as_uint(ac->msg,
914                                                                          "userAccountControl",
915                                                                          0);
916
917                         /* Temporary duplicate accounts aren't allowed */
918                         if ((user_account_control & UF_TEMP_DUPLICATE_ACCOUNT) != 0) {
919                                 return LDB_ERR_OTHER;
920                         }
921
922                         /* Workstation and (read-only) DC objects do need objectclass "computer" */
923                         if ((samdb_find_attribute(ldb, ac->msg,
924                                                   "objectclass", "computer") == NULL) &&
925                             (user_account_control &
926                              (UF_SERVER_TRUST_ACCOUNT | UF_WORKSTATION_TRUST_ACCOUNT))) {
927                                 ldb_set_errstring(ldb,
928                                                   "samldb: Requested account type does need objectclass 'computer'!");
929                                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
930                         }
931
932                         account_type = ds_uf2atype(user_account_control);
933                         if (account_type == 0) {
934                                 ldb_set_errstring(ldb, "samldb: Unrecognized account type!");
935                                 return LDB_ERR_UNWILLING_TO_PERFORM;
936                         }
937                         ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
938                                                  "sAMAccountType",
939                                                  account_type);
940                         if (ret != LDB_SUCCESS) {
941                                 return ret;
942                         }
943                         el2 = ldb_msg_find_element(ac->msg, "sAMAccountType");
944                         el2->flags = LDB_FLAG_MOD_REPLACE;
945
946                         /* "isCriticalSystemObject" might be set */
947                         if (user_account_control &
948                             (UF_SERVER_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)) {
949                                 ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject",
950                                                          "TRUE");
951                                 if (ret != LDB_SUCCESS) {
952                                         return ret;
953                                 }
954                                 el2 = ldb_msg_find_element(ac->msg,
955                                                            "isCriticalSystemObject");
956                                 el2->flags = LDB_FLAG_MOD_REPLACE;
957                         } else if (user_account_control & UF_WORKSTATION_TRUST_ACCOUNT) {
958                                 ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject",
959                                                          "FALSE");
960                                 if (ret != LDB_SUCCESS) {
961                                         return ret;
962                                 }
963                                 el2 = ldb_msg_find_element(ac->msg,
964                                                            "isCriticalSystemObject");
965                                 el2->flags = LDB_FLAG_MOD_REPLACE;
966                         }
967
968                         /* Step 1.4: "userAccountControl" -> "primaryGroupID" mapping */
969                         if (!ldb_msg_find_element(ac->msg, "primaryGroupID")) {
970                                 uint32_t rid = ds_uf2prim_group_rid(user_account_control);
971
972                                 /*
973                                  * Older AD deployments don't know about the
974                                  * RODC group
975                                  */
976                                 if (rid == DOMAIN_RID_READONLY_DCS) {
977                                         ret = samldb_prim_group_tester(ac, rid);
978                                         if (ret != LDB_SUCCESS) {
979                                                 return ret;
980                                         }
981                                 }
982
983                                 ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
984                                                          "primaryGroupID", rid);
985                                 if (ret != LDB_SUCCESS) {
986                                         return ret;
987                                 }
988                                 el2 = ldb_msg_find_element(ac->msg,
989                                                            "primaryGroupID");
990                                 el2->flags = LDB_FLAG_MOD_REPLACE;
991                         }
992
993                         /* Step 1.5: Add additional flags when needed */
994                         /* Obviously this is done when the "userAccountControl"
995                          * has been generated here (tested against Windows
996                          * Server) */
997                         if (uac_generated) {
998                                 user_account_control |= UF_ACCOUNTDISABLE;
999                                 user_account_control |= UF_PASSWD_NOTREQD;
1000
1001                                 ret = samdb_msg_set_uint(ldb, ac->msg, ac->msg,
1002                                                          "userAccountControl",
1003                                                          user_account_control);
1004                                 if (ret != LDB_SUCCESS) {
1005                                         return ret;
1006                                 }
1007                         }
1008                 }
1009
1010         } else if (strcmp(ac->type, "group") == 0) {
1011                 const char *tempstr;
1012
1013                 /* Step 2.2: Default values */
1014                 tempstr = talloc_asprintf(ac->msg, "%d",
1015                                           GTYPE_SECURITY_GLOBAL_GROUP);
1016                 if (tempstr == NULL) return ldb_operr(ldb);
1017                 ret = samdb_find_or_add_attribute(ldb, ac->msg,
1018                         "groupType", tempstr);
1019                 if (ret != LDB_SUCCESS) return ret;
1020
1021                 /* Step 2.3: "groupType" -> "sAMAccountType" */
1022                 el = ldb_msg_find_element(ac->msg, "groupType");
1023                 if (el != NULL) {
1024                         uint32_t group_type, account_type;
1025
1026                         group_type = ldb_msg_find_attr_as_uint(ac->msg,
1027                                                                "groupType", 0);
1028
1029                         /* The creation of builtin groups requires the
1030                          * RELAX control */
1031                         if (group_type == GTYPE_SECURITY_BUILTIN_LOCAL_GROUP) {
1032                                 if (ldb_request_get_control(ac->req,
1033                                                             LDB_CONTROL_RELAX_OID) == NULL) {
1034                                         return LDB_ERR_UNWILLING_TO_PERFORM;
1035                                 }
1036                         }
1037
1038                         account_type = ds_gtype2atype(group_type);
1039                         if (account_type == 0) {
1040                                 ldb_set_errstring(ldb, "samldb: Unrecognized account type!");
1041                                 return LDB_ERR_UNWILLING_TO_PERFORM;
1042                         }
1043                         ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
1044                                                  "sAMAccountType",
1045                                                  account_type);
1046                         if (ret != LDB_SUCCESS) {
1047                                 return ret;
1048                         }
1049                         el2 = ldb_msg_find_element(ac->msg, "sAMAccountType");
1050                         el2->flags = LDB_FLAG_MOD_REPLACE;
1051                 }
1052         }
1053
1054         return LDB_SUCCESS;
1055 }
1056
1057 /*
1058  * "Primary group ID" trigger (MS-SAMR 3.1.1.8.2)
1059  *
1060  * Has to be invoked on "add" and "modify" operations on "user" and "computer"
1061  * objects.
1062  * ac->msg contains the "add"/"modify" message
1063  */
1064
1065 static int samldb_prim_group_tester(struct samldb_ctx *ac, uint32_t rid)
1066 {
1067         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1068         struct dom_sid *sid;
1069         struct ldb_result *res;
1070         int ret;
1071         const char *noattrs[] = { NULL };
1072
1073         sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
1074         if (sid == NULL) {
1075                 return ldb_operr(ldb);
1076         }
1077
1078         ret = dsdb_module_search(ac->module, ac, &res,
1079                                  ldb_get_default_basedn(ldb),
1080                                  LDB_SCOPE_SUBTREE,
1081                                  noattrs, DSDB_FLAG_NEXT_MODULE,
1082                                  ac->req,
1083                                  "(objectSid=%s)",
1084                                  ldap_encode_ndr_dom_sid(ac, sid));
1085         if (ret != LDB_SUCCESS) {
1086                 return ret;
1087         }
1088         if (res->count != 1) {
1089                 talloc_free(res);
1090                 ldb_asprintf_errstring(ldb,
1091                                        "Failed to find primary group with RID %u!",
1092                                        rid);
1093                 return LDB_ERR_UNWILLING_TO_PERFORM;
1094         }
1095         talloc_free(res);
1096
1097         return LDB_SUCCESS;
1098 }
1099
1100 static int samldb_prim_group_set(struct samldb_ctx *ac)
1101 {
1102         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1103         uint32_t rid;
1104
1105         rid = ldb_msg_find_attr_as_uint(ac->msg, "primaryGroupID", (uint32_t) -1);
1106         if (rid == (uint32_t) -1) {
1107                 /* we aren't affected of any primary group set */
1108                 return LDB_SUCCESS;
1109
1110         } else if (!ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
1111                 ldb_set_errstring(ldb,
1112                                   "The primary group isn't settable on add operations!");
1113                 return LDB_ERR_UNWILLING_TO_PERFORM;
1114         }
1115
1116         return samldb_prim_group_tester(ac, rid);
1117 }
1118
1119 static int samldb_prim_group_change(struct samldb_ctx *ac)
1120 {
1121         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1122         const char * attrs[] = { "primaryGroupID", "memberOf", NULL };
1123         struct ldb_result *res, *group_res;
1124         struct ldb_message_element *el;
1125         struct ldb_message *msg;
1126         uint32_t prev_rid, new_rid;
1127         struct dom_sid *prev_sid, *new_sid;
1128         struct ldb_dn *prev_prim_group_dn, *new_prim_group_dn;
1129         int ret;
1130         const char *noattrs[] = { NULL };
1131
1132         el = dsdb_get_single_valued_attr(ac->msg, "primaryGroupID",
1133                                          ac->req->operation);
1134         if (el == NULL) {
1135                 /* we are not affected */
1136                 return LDB_SUCCESS;
1137         }
1138
1139         /* Fetch information from the existing object */
1140
1141         ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, attrs,
1142                                     DSDB_FLAG_NEXT_MODULE, ac->req);
1143         if (ret != LDB_SUCCESS) {
1144                 return ret;
1145         }
1146
1147         /* Finds out the DN of the old primary group */
1148
1149         prev_rid = ldb_msg_find_attr_as_uint(res->msgs[0], "primaryGroupID",
1150                                              (uint32_t) -1);
1151         if (prev_rid == (uint32_t) -1) {
1152                 /* User objects do always have a mandatory "primaryGroupID"
1153                  * attribute. If this doesn't exist then the object is of the
1154                  * wrong type. This is the exact Windows error code */
1155                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1156         }
1157
1158         prev_sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), prev_rid);
1159         if (prev_sid == NULL) {
1160                 return ldb_operr(ldb);
1161         }
1162
1163         /* Finds out the DN of the new primary group
1164          * Notice: in order to parse the primary group ID correctly we create
1165          * a temporary message here. */
1166
1167         msg = ldb_msg_new(ac->msg);
1168         if (msg == NULL) {
1169                 return ldb_module_oom(ac->module);
1170         }
1171         ret = ldb_msg_add(msg, el, 0);
1172         if (ret != LDB_SUCCESS) {
1173                 return ret;
1174         }
1175         new_rid = ldb_msg_find_attr_as_uint(msg, "primaryGroupID", (uint32_t) -1);
1176         talloc_free(msg);
1177         if (new_rid == (uint32_t) -1) {
1178                 /* we aren't affected of any primary group change */
1179                 return LDB_SUCCESS;
1180         }
1181
1182         if (prev_rid == new_rid) {
1183                 return LDB_SUCCESS;
1184         }
1185
1186         ret = dsdb_module_search(ac->module, ac, &group_res,
1187                                  ldb_get_default_basedn(ldb),
1188                                  LDB_SCOPE_SUBTREE,
1189                                  noattrs, DSDB_FLAG_NEXT_MODULE,
1190                                  ac->req,
1191                                  "(objectSid=%s)",
1192                                  ldap_encode_ndr_dom_sid(ac, prev_sid));
1193         if (ret != LDB_SUCCESS) {
1194                 return ret;
1195         }
1196         if (group_res->count != 1) {
1197                 return ldb_operr(ldb);
1198         }
1199         prev_prim_group_dn = group_res->msgs[0]->dn;
1200
1201         new_sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), new_rid);
1202         if (new_sid == NULL) {
1203                 return ldb_operr(ldb);
1204         }
1205
1206         ret = dsdb_module_search(ac->module, ac, &group_res,
1207                                  ldb_get_default_basedn(ldb),
1208                                  LDB_SCOPE_SUBTREE,
1209                                  noattrs, DSDB_FLAG_NEXT_MODULE,
1210                                  ac->req,
1211                                  "(objectSid=%s)",
1212                                  ldap_encode_ndr_dom_sid(ac, new_sid));
1213         if (ret != LDB_SUCCESS) {
1214                 return ret;
1215         }
1216         if (group_res->count != 1) {
1217                 /* Here we know if the specified new primary group candidate is
1218                  * valid or not. */
1219                 return LDB_ERR_UNWILLING_TO_PERFORM;
1220         }
1221         new_prim_group_dn = group_res->msgs[0]->dn;
1222
1223         /* We need to be already a normal member of the new primary
1224          * group in order to be successful. */
1225         el = samdb_find_attribute(ldb, res->msgs[0], "memberOf",
1226                                   ldb_dn_get_linearized(new_prim_group_dn));
1227         if (el == NULL) {
1228                 return LDB_ERR_UNWILLING_TO_PERFORM;
1229         }
1230
1231         /* Remove the "member" attribute on the new primary group */
1232         msg = ldb_msg_new(ac->msg);
1233         if (msg == NULL) {
1234                 return ldb_module_oom(ac->module);
1235         }
1236         msg->dn = new_prim_group_dn;
1237
1238         ret = samdb_msg_add_delval(ldb, msg, msg, "member",
1239                                    ldb_dn_get_linearized(ac->msg->dn));
1240         if (ret != LDB_SUCCESS) {
1241                 return ret;
1242         }
1243
1244         ret = dsdb_module_modify(ac->module, msg, DSDB_FLAG_NEXT_MODULE, ac->req);
1245         if (ret != LDB_SUCCESS) {
1246                 return ret;
1247         }
1248         talloc_free(msg);
1249
1250         /* Add a "member" attribute for the previous primary group */
1251         msg = ldb_msg_new(ac->msg);
1252         if (msg == NULL) {
1253                 return ldb_module_oom(ac->module);
1254         }
1255         msg->dn = prev_prim_group_dn;
1256
1257         ret = samdb_msg_add_addval(ldb, msg, msg, "member",
1258                                    ldb_dn_get_linearized(ac->msg->dn));
1259         if (ret != LDB_SUCCESS) {
1260                 return ret;
1261         }
1262
1263         ret = dsdb_module_modify(ac->module, msg, DSDB_FLAG_NEXT_MODULE, ac->req);
1264         if (ret != LDB_SUCCESS) {
1265                 return ret;
1266         }
1267         talloc_free(msg);
1268
1269         return LDB_SUCCESS;
1270 }
1271
1272 static int samldb_prim_group_trigger(struct samldb_ctx *ac)
1273 {
1274         int ret;
1275
1276         if (ac->req->operation == LDB_ADD) {
1277                 ret = samldb_prim_group_set(ac);
1278         } else {
1279                 ret = samldb_prim_group_change(ac);
1280         }
1281
1282         return ret;
1283 }
1284
1285
1286 /**
1287  * This function is called on LDB modify operations. It performs some additions/
1288  * replaces on the current LDB message when "userAccountControl" changes.
1289  */
1290 static int samldb_user_account_control_change(struct samldb_ctx *ac)
1291 {
1292         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1293         uint32_t user_account_control, old_user_account_control, account_type;
1294         struct ldb_message_element *el;
1295         struct ldb_message *tmp_msg;
1296         int ret;
1297         struct ldb_result *res;
1298         const char *attrs[] = { "userAccountControl", "objectClass", NULL };
1299         unsigned int i;
1300         bool is_computer = false;
1301
1302         el = dsdb_get_single_valued_attr(ac->msg, "userAccountControl",
1303                                          ac->req->operation);
1304         if (el == NULL) {
1305                 /* we are not affected */
1306                 return LDB_SUCCESS;
1307         }
1308
1309         /* Create a temporary message for fetching the "userAccountControl" */
1310         tmp_msg = ldb_msg_new(ac->msg);
1311         if (tmp_msg == NULL) {
1312                 return ldb_module_oom(ac->module);
1313         }
1314         ret = ldb_msg_add(tmp_msg, el, 0);
1315         if (ret != LDB_SUCCESS) {
1316                 return ret;
1317         }
1318         user_account_control = ldb_msg_find_attr_as_uint(tmp_msg,
1319                                                          "userAccountControl",
1320                                                          0);
1321         talloc_free(tmp_msg);
1322
1323         /* Temporary duplicate accounts aren't allowed */
1324         if ((user_account_control & UF_TEMP_DUPLICATE_ACCOUNT) != 0) {
1325                 return LDB_ERR_OTHER;
1326         }
1327
1328         /* Fetch the old "userAccountControl" and "objectClass" */
1329         ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, attrs,
1330                                     DSDB_FLAG_NEXT_MODULE, ac->req);
1331         if (ret != LDB_SUCCESS) {
1332                 return ret;
1333         }
1334         old_user_account_control = ldb_msg_find_attr_as_uint(res->msgs[0], "userAccountControl", 0);
1335         if (old_user_account_control == 0) {
1336                 return ldb_operr(ldb);
1337         }
1338         el = ldb_msg_find_element(res->msgs[0], "objectClass");
1339         if (el == NULL) {
1340                 return ldb_operr(ldb);
1341         }
1342
1343         /* When we do not have objectclass "computer" we cannot switch to a (read-only) DC */
1344         for (i = 0; i < el->num_values; i++) {
1345                 if (ldb_attr_cmp((char *)el->values[i].data, "computer") == 0) {
1346                         is_computer = true;
1347                         break;
1348                 }
1349         }
1350         if (!is_computer &&
1351             (user_account_control & (UF_SERVER_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT))) {
1352                 ldb_set_errstring(ldb,
1353                                   "samldb: Requested account type does need objectclass 'computer'!");
1354                 return LDB_ERR_UNWILLING_TO_PERFORM;
1355         }
1356
1357         /*
1358          * The functions "ds_uf2atype" and "ds_uf2prim_group_rid" are used as
1359          * detectors for account type changes.
1360          * So if the account type does change then we need to adjust the
1361          * "sAMAccountType", the "isCriticalSystemObject" and the
1362          * "primaryGroupID" attribute.
1363          */
1364         if ((ds_uf2atype(user_account_control)
1365              == ds_uf2atype(old_user_account_control)) &&
1366             (ds_uf2prim_group_rid(user_account_control)
1367              == ds_uf2prim_group_rid(old_user_account_control))) {
1368                 return LDB_SUCCESS;
1369         }
1370
1371         account_type = ds_uf2atype(user_account_control);
1372         if (account_type == 0) {
1373                 ldb_set_errstring(ldb, "samldb: Unrecognized account type!");
1374                 return LDB_ERR_UNWILLING_TO_PERFORM;
1375         }
1376         ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "sAMAccountType",
1377                                  account_type);
1378         if (ret != LDB_SUCCESS) {
1379                 return ret;
1380         }
1381         el = ldb_msg_find_element(ac->msg, "sAMAccountType");
1382         el->flags = LDB_FLAG_MOD_REPLACE;
1383
1384         /* "isCriticalSystemObject" might be set/changed */
1385         if (user_account_control
1386             & (UF_SERVER_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)) {
1387                 ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject",
1388                                          "TRUE");
1389                 if (ret != LDB_SUCCESS) {
1390                         return ret;
1391                 }
1392                 el = ldb_msg_find_element(ac->msg,
1393                                            "isCriticalSystemObject");
1394                 el->flags = LDB_FLAG_MOD_REPLACE;
1395         } else if (user_account_control & UF_WORKSTATION_TRUST_ACCOUNT) {
1396                 ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject",
1397                                          "FALSE");
1398                 if (ret != LDB_SUCCESS) {
1399                         return ret;
1400                 }
1401                 el = ldb_msg_find_element(ac->msg,
1402                                            "isCriticalSystemObject");
1403                 el->flags = LDB_FLAG_MOD_REPLACE;
1404         }
1405
1406         if (!ldb_msg_find_element(ac->msg, "primaryGroupID")) {
1407                 uint32_t rid = ds_uf2prim_group_rid(user_account_control);
1408
1409                 /* Older AD deployments don't know about the RODC group */
1410                 if (rid == DOMAIN_RID_READONLY_DCS) {
1411                         ret = samldb_prim_group_tester(ac, rid);
1412                         if (ret != LDB_SUCCESS) {
1413                                 return ret;
1414                         }
1415                 }
1416
1417                 ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
1418                                          "primaryGroupID", rid);
1419                 if (ret != LDB_SUCCESS) {
1420                         return ret;
1421                 }
1422                 el = ldb_msg_find_element(ac->msg,
1423                                            "primaryGroupID");
1424                 el->flags = LDB_FLAG_MOD_REPLACE;
1425         }
1426
1427         return LDB_SUCCESS;
1428 }
1429
1430 static int samldb_group_type_change(struct samldb_ctx *ac)
1431 {
1432         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1433         uint32_t group_type, old_group_type, account_type;
1434         struct ldb_message_element *el;
1435         struct ldb_message *tmp_msg;
1436         int ret;
1437         struct ldb_result *res;
1438         const char *attrs[] = { "groupType", NULL };
1439
1440         el = dsdb_get_single_valued_attr(ac->msg, "groupType",
1441                                          ac->req->operation);
1442         if (el == NULL) {
1443                 /* we are not affected */
1444                 return LDB_SUCCESS;
1445         }
1446
1447         /* Create a temporary message for fetching the "groupType" */
1448         tmp_msg = ldb_msg_new(ac->msg);
1449         if (tmp_msg == NULL) {
1450                 return ldb_module_oom(ac->module);
1451         }
1452         ret = ldb_msg_add(tmp_msg, el, 0);
1453         if (ret != LDB_SUCCESS) {
1454                 return ret;
1455         }
1456         group_type = ldb_msg_find_attr_as_uint(tmp_msg, "groupType", 0);
1457         talloc_free(tmp_msg);
1458
1459         ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, attrs,
1460                                     DSDB_FLAG_NEXT_MODULE |
1461                                     DSDB_SEARCH_SHOW_DELETED, ac->req);
1462         if (ret != LDB_SUCCESS) {
1463                 return ret;
1464         }
1465         old_group_type = ldb_msg_find_attr_as_uint(res->msgs[0], "groupType", 0);
1466         if (old_group_type == 0) {
1467                 return ldb_operr(ldb);
1468         }
1469
1470         /* Group type switching isn't so easy as it seems: We can only
1471          * change in this directions: global <-> universal <-> local
1472          * On each step also the group type itself
1473          * (security/distribution) is variable. */
1474
1475         if (ldb_request_get_control(ac->req, LDB_CONTROL_PROVISION_OID) == NULL) {
1476                 switch (group_type) {
1477                 case GTYPE_SECURITY_GLOBAL_GROUP:
1478                 case GTYPE_DISTRIBUTION_GLOBAL_GROUP:
1479                         /* change to "universal" allowed */
1480                         if ((old_group_type == GTYPE_SECURITY_DOMAIN_LOCAL_GROUP) ||
1481                         (old_group_type == GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)) {
1482                                 ldb_set_errstring(ldb,
1483                                         "samldb: Change from security/distribution local group forbidden!");
1484                                 return LDB_ERR_UNWILLING_TO_PERFORM;
1485                         }
1486                 break;
1487
1488                 case GTYPE_SECURITY_UNIVERSAL_GROUP:
1489                 case GTYPE_DISTRIBUTION_UNIVERSAL_GROUP:
1490                         /* each change allowed */
1491                 break;
1492                 case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
1493                 case GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP:
1494                         /* change to "universal" allowed */
1495                         if ((old_group_type == GTYPE_SECURITY_GLOBAL_GROUP) ||
1496                         (old_group_type == GTYPE_DISTRIBUTION_GLOBAL_GROUP)) {
1497                                 ldb_set_errstring(ldb,
1498                                         "samldb: Change from security/distribution global group forbidden!");
1499                                 return LDB_ERR_UNWILLING_TO_PERFORM;
1500                         }
1501                 break;
1502
1503                 case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
1504                 default:
1505                         /* we don't allow this "groupType" values */
1506                         return LDB_ERR_UNWILLING_TO_PERFORM;
1507                 break;
1508                 }
1509         }
1510
1511         account_type =  ds_gtype2atype(group_type);
1512         if (account_type == 0) {
1513                 ldb_set_errstring(ldb, "samldb: Unrecognized account type!");
1514                 return LDB_ERR_UNWILLING_TO_PERFORM;
1515         }
1516         ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "sAMAccountType",
1517                                  account_type);
1518         if (ret != LDB_SUCCESS) {
1519                 return ret;
1520         }
1521         el = ldb_msg_find_element(ac->msg, "sAMAccountType");
1522         el->flags = LDB_FLAG_MOD_REPLACE;
1523
1524         return LDB_SUCCESS;
1525 }
1526
1527 static int samldb_sam_accountname_check(struct samldb_ctx *ac)
1528 {
1529         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1530         const char *no_attrs[] = { NULL };
1531         struct ldb_result *res;
1532         const char *sam_accountname, *enc_str;
1533         struct ldb_message_element *el;
1534         struct ldb_message *tmp_msg;
1535         int ret;
1536
1537         el = dsdb_get_single_valued_attr(ac->msg, "sAMAccountName",
1538                                          ac->req->operation);
1539         if (el == NULL) {
1540                 /* we are not affected */
1541                 return LDB_SUCCESS;
1542         }
1543
1544         /* Create a temporary message for fetching the "sAMAccountName" */
1545         tmp_msg = ldb_msg_new(ac->msg);
1546         if (tmp_msg == NULL) {
1547                 return ldb_module_oom(ac->module);
1548         }
1549         ret = ldb_msg_add(tmp_msg, el, 0);
1550         if (ret != LDB_SUCCESS) {
1551                 return ret;
1552         }
1553         sam_accountname = talloc_steal(ac,
1554                                        ldb_msg_find_attr_as_string(tmp_msg, "sAMAccountName", NULL));
1555         talloc_free(tmp_msg);
1556
1557         if (sam_accountname == NULL) {
1558                 /* The "sAMAccountName" cannot be nothing */
1559                 ldb_set_errstring(ldb,
1560                                   "samldb: Empty account names aren't allowed!");
1561                 return LDB_ERR_UNWILLING_TO_PERFORM;
1562         }
1563
1564         enc_str = ldb_binary_encode_string(ac, sam_accountname);
1565         if (enc_str == NULL) {
1566                 return ldb_module_oom(ac->module);
1567         }
1568
1569         /* Make sure that a "sAMAccountName" is only used once */
1570
1571         ret = dsdb_module_search(ac->module, ac, &res,
1572                                  ldb_get_default_basedn(ldb),
1573                                  LDB_SCOPE_SUBTREE, no_attrs,
1574                                  DSDB_FLAG_NEXT_MODULE, ac->req,
1575                                  "(sAMAccountName=%s)", enc_str);
1576         if (ret != LDB_SUCCESS) {
1577                 return ret;
1578         }
1579         if (res->count > 1) {
1580                 return ldb_operr(ldb);
1581         } else if (res->count == 1) {
1582                 if (ldb_dn_compare(res->msgs[0]->dn, ac->msg->dn) != 0) {
1583                         ldb_asprintf_errstring(ldb,
1584                                                "samldb: Account name (sAMAccountName) '%s' already in use!",
1585                                                sam_accountname);
1586                         return LDB_ERR_ENTRY_ALREADY_EXISTS;
1587                 }
1588         }
1589         talloc_free(res);
1590
1591         return LDB_SUCCESS;
1592 }
1593
1594 static int samldb_member_check(struct samldb_ctx *ac)
1595 {
1596         static const char * const attrs[] = { "objectSid", "member", NULL };
1597         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1598         struct ldb_message_element *el;
1599         struct ldb_dn *member_dn;
1600         struct dom_sid *sid;
1601         struct ldb_result *res;
1602         struct dom_sid *group_sid;
1603         unsigned int i, j;
1604         int ret;
1605
1606         /* Fetch information from the existing object */
1607
1608         ret = dsdb_module_search(ac->module, ac, &res, ac->msg->dn, LDB_SCOPE_BASE, attrs,
1609                                  DSDB_FLAG_NEXT_MODULE, ac->req, NULL);
1610         if (ret != LDB_SUCCESS) {
1611                 return ret;
1612         }
1613         if (res->count != 1) {
1614                 return ldb_operr(ldb);
1615         }
1616
1617         group_sid = samdb_result_dom_sid(res, res->msgs[0], "objectSid");
1618         if (group_sid == NULL) {
1619                 return ldb_operr(ldb);
1620         }
1621
1622         /* We've to walk over all modification entries and consider the "member"
1623          * ones. */
1624         for (i = 0; i < ac->msg->num_elements; i++) {
1625                 if (ldb_attr_cmp(ac->msg->elements[i].name, "member") != 0) {
1626                         continue;
1627                 }
1628
1629                 el = &ac->msg->elements[i];
1630                 for (j = 0; j < el->num_values; j++) {
1631                         struct ldb_result *group_res;
1632                         const char *group_attrs[] = { "primaryGroupID" , NULL };
1633                         uint32_t prim_group_rid;
1634
1635                         if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE) {
1636                                 /* Deletes will be handled in
1637                                  * repl_meta_data, and deletes not
1638                                  * matching a member will return
1639                                  * LDB_ERR_UNWILLING_TO_PERFORM
1640                                  * there */
1641                                 continue;
1642                         }
1643
1644                         member_dn = ldb_dn_from_ldb_val(ac, ldb,
1645                                                         &el->values[j]);
1646                         if (!ldb_dn_validate(member_dn)) {
1647                                 return ldb_operr(ldb);
1648                         }
1649
1650                         /* Denies to add "member"s to groups which are primary
1651                          * ones for them - in this case return
1652                          * ERR_ENTRY_ALREADY_EXISTS. */
1653
1654                         ret = dsdb_module_search_dn(ac->module, ac, &group_res,
1655                                                     member_dn, group_attrs,
1656                                                     DSDB_FLAG_NEXT_MODULE, ac->req);
1657                         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1658                                 /* member DN doesn't exist yet */
1659                                 continue;
1660                         }
1661                         if (ret != LDB_SUCCESS) {
1662                                 return ret;
1663                         }
1664                         prim_group_rid = ldb_msg_find_attr_as_uint(group_res->msgs[0], "primaryGroupID", (uint32_t)-1);
1665                         if (prim_group_rid == (uint32_t) -1) {
1666                                 /* the member hasn't to be a user account ->
1667                                  * therefore no check needed in this case. */
1668                                 continue;
1669                         }
1670
1671                         sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb),
1672                                               prim_group_rid);
1673                         if (sid == NULL) {
1674                                 return ldb_operr(ldb);
1675                         }
1676
1677                         if (dom_sid_equal(group_sid, sid)) {
1678                                 ldb_asprintf_errstring(ldb,
1679                                                        "samldb: member %s already set via primaryGroupID %u",
1680                                                        ldb_dn_get_linearized(member_dn), prim_group_rid);
1681                                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
1682                         }
1683                 }
1684         }
1685
1686         talloc_free(res);
1687
1688         return LDB_SUCCESS;
1689 }
1690
1691 /* SAM objects have special rules regarding the "description" attribute on
1692  * modify operations. */
1693 static int samldb_description_check(struct samldb_ctx *ac, bool *modified)
1694 {
1695         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1696         const char * const attrs[] = { "objectClass", "description", NULL };
1697         struct ldb_result *res;
1698         unsigned int i;
1699         int ret;
1700
1701         /* Fetch information from the existing object */
1702         ret = dsdb_module_search(ac->module, ac, &res, ac->msg->dn, LDB_SCOPE_BASE, attrs,
1703                                  DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED, ac->req,
1704                                  "(|(objectclass=user)(objectclass=group)(objectclass=samDomain)(objectclass=samServer))");
1705         if (ret != LDB_SUCCESS) {
1706                 /* don't treat it specially ... let normal error codes
1707                    happen from other places */
1708                 ldb_reset_err_string(ldb);
1709                 return LDB_SUCCESS;
1710         }
1711         if (res->count == 0) {
1712                 /* we didn't match the filter */
1713                 talloc_free(res);
1714                 return LDB_SUCCESS;
1715         }
1716
1717         /* We've to walk over all modification entries and consider the
1718          * "description" ones. */
1719         for (i = 0; i < ac->msg->num_elements; i++) {
1720                 if (ldb_attr_cmp(ac->msg->elements[i].name, "description") == 0) {
1721                         ac->msg->elements[i].flags |= LDB_FLAG_INTERNAL_FORCE_SINGLE_VALUE_CHECK;
1722                         *modified = true;
1723                 }
1724         }
1725
1726         talloc_free(res);
1727
1728         return LDB_SUCCESS;
1729 }
1730
1731 /* This trigger adapts the "servicePrincipalName" attributes if the
1732  * "dNSHostName" and/or "sAMAccountName" attribute change(s) */
1733 static int samldb_service_principal_names_change(struct samldb_ctx *ac)
1734 {
1735         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1736         struct ldb_message_element *el = NULL, *el2 = NULL;
1737         struct ldb_message *msg;
1738         const char *attrs[] = { "servicePrincipalName", NULL };
1739         struct ldb_result *res;
1740         const char *dns_hostname = NULL, *old_dns_hostname = NULL,
1741                    *sam_accountname = NULL, *old_sam_accountname = NULL;
1742         unsigned int i;
1743         int ret;
1744
1745         el = dsdb_get_single_valued_attr(ac->msg, "dNSHostName",
1746                                          ac->req->operation);
1747         el2 = dsdb_get_single_valued_attr(ac->msg, "sAMAccountName",
1748                                           ac->req->operation);
1749         if ((el == NULL) && (el2 == NULL)) {
1750                 /* we are not affected */
1751                 return LDB_SUCCESS;
1752         }
1753
1754         /* Create a temporary message for fetching the "dNSHostName" */
1755         if (el != NULL) {
1756                 const char *dns_attrs[] = { "dNSHostName", NULL };
1757                 msg = ldb_msg_new(ac->msg);
1758                 if (msg == NULL) {
1759                         return ldb_module_oom(ac->module);
1760                 }
1761                 ret = ldb_msg_add(msg, el, 0);
1762                 if (ret != LDB_SUCCESS) {
1763                         return ret;
1764                 }
1765                 dns_hostname = talloc_steal(ac,
1766                                             ldb_msg_find_attr_as_string(msg, "dNSHostName", NULL));
1767                 talloc_free(msg);
1768
1769                 ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn,
1770                                             dns_attrs, DSDB_FLAG_NEXT_MODULE, ac->req);
1771                 if (ret == LDB_SUCCESS) {
1772                         old_dns_hostname = ldb_msg_find_attr_as_string(res->msgs[0], "dNSHostName", NULL);
1773                 }
1774         }
1775
1776         /* Create a temporary message for fetching the "sAMAccountName" */
1777         if (el2 != NULL) {
1778                 char *tempstr, *tempstr2;
1779                 const char *acct_attrs[] = { "sAMAccountName", NULL };
1780
1781                 msg = ldb_msg_new(ac->msg);
1782                 if (msg == NULL) {
1783                         return ldb_module_oom(ac->module);
1784                 }
1785                 ret = ldb_msg_add(msg, el2, 0);
1786                 if (ret != LDB_SUCCESS) {
1787                         return ret;
1788                 }
1789                 tempstr = talloc_strdup(ac,
1790                                         ldb_msg_find_attr_as_string(msg, "sAMAccountName", NULL));
1791                 talloc_free(msg);
1792
1793                 ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, acct_attrs,
1794                                             DSDB_FLAG_NEXT_MODULE, ac->req);
1795                 if (ret == LDB_SUCCESS) {
1796                         tempstr2 = talloc_strdup(ac,
1797                                                  ldb_msg_find_attr_as_string(res->msgs[0],
1798                                                                              "sAMAccountName", NULL));
1799                 }
1800
1801
1802                 /* The "sAMAccountName" needs some additional trimming: we need
1803                  * to remove the trailing "$"s if they exist. */
1804                 if ((tempstr != NULL) && (tempstr[0] != '\0') &&
1805                     (tempstr[strlen(tempstr) - 1] == '$')) {
1806                         tempstr[strlen(tempstr) - 1] = '\0';
1807                 }
1808                 if ((tempstr2 != NULL) && (tempstr2[0] != '\0') &&
1809                     (tempstr2[strlen(tempstr2) - 1] == '$')) {
1810                         tempstr2[strlen(tempstr2) - 1] = '\0';
1811                 }
1812                 sam_accountname = tempstr;
1813                 old_sam_accountname = tempstr2;
1814         }
1815
1816         if (old_dns_hostname == NULL) {
1817                 /* we cannot change when the old name is unknown */
1818                 dns_hostname = NULL;
1819         }
1820         if ((old_dns_hostname != NULL) && (dns_hostname != NULL) &&
1821             (strcasecmp(old_dns_hostname, dns_hostname) == 0)) {
1822                 /* The "dNSHostName" didn't change */
1823                 dns_hostname = NULL;
1824         }
1825
1826         if (old_sam_accountname == NULL) {
1827                 /* we cannot change when the old name is unknown */
1828                 sam_accountname = NULL;
1829         }
1830         if ((old_sam_accountname != NULL) && (sam_accountname != NULL) &&
1831             (strcasecmp(old_sam_accountname, sam_accountname) == 0)) {
1832                 /* The "sAMAccountName" didn't change */
1833                 sam_accountname = NULL;
1834         }
1835
1836         if ((dns_hostname == NULL) && (sam_accountname == NULL)) {
1837                 /* Well, there are information missing (old name(s)) or the
1838                  * names didn't change. We've nothing to do and can exit here */
1839                 return LDB_SUCCESS;
1840         }
1841
1842         /* Potential "servicePrincipalName" changes in the same request have to
1843          * be handled before the update (Windows behaviour). */
1844         el = ldb_msg_find_element(ac->msg, "servicePrincipalName");
1845         if (el != NULL) {
1846                 msg = ldb_msg_new(ac->msg);
1847                 if (msg == NULL) {
1848                         return ldb_module_oom(ac->module);
1849                 }
1850                 msg->dn = ac->msg->dn;
1851
1852                 do {
1853                         ret = ldb_msg_add(msg, el, el->flags);
1854                         if (ret != LDB_SUCCESS) {
1855                                 return ret;
1856                         }
1857
1858                         ldb_msg_remove_element(ac->msg, el);
1859
1860                         el = ldb_msg_find_element(ac->msg,
1861                                                   "servicePrincipalName");
1862                 } while (el != NULL);
1863
1864                 ret = dsdb_module_modify(ac->module, msg,
1865                                          DSDB_FLAG_NEXT_MODULE, ac->req);
1866                 if (ret != LDB_SUCCESS) {
1867                         return ret;
1868                 }
1869                 talloc_free(msg);
1870         }
1871
1872         /* Fetch the "servicePrincipalName"s if any */
1873         ret = dsdb_module_search(ac->module, ac, &res, ac->msg->dn, LDB_SCOPE_BASE, attrs,
1874                                  DSDB_FLAG_NEXT_MODULE, ac->req, NULL);
1875         if (ret != LDB_SUCCESS) {
1876                 return ret;
1877         }
1878         if ((res->count != 1) || (res->msgs[0]->num_elements > 1)) {
1879                 return ldb_operr(ldb);
1880         }
1881
1882         if (res->msgs[0]->num_elements == 1) {
1883                 /* Yes, we do have "servicePrincipalName"s. First we update them
1884                  * locally, that means we do always substitute the current
1885                  * "dNSHostName" with the new one and/or "sAMAccountName"
1886                  * without "$" with the new one and then we append this to the
1887                  * modification request (Windows behaviour). */
1888
1889                 for (i = 0; i < res->msgs[0]->elements[0].num_values; i++) {
1890                         char *old_str, *new_str, *pos;
1891                         const char *tok;
1892
1893                         old_str = (char *)
1894                                 res->msgs[0]->elements[0].values[i].data;
1895
1896                         new_str = talloc_strdup(ac->msg,
1897                                                 strtok_r(old_str, "/", &pos));
1898                         if (new_str == NULL) {
1899                                 return ldb_module_oom(ac->module);
1900                         }
1901
1902                         while ((tok = strtok_r(NULL, "/", &pos)) != NULL) {
1903                                 if ((dns_hostname != NULL) &&
1904                                     (strcasecmp(tok, old_dns_hostname) == 0)) {
1905                                         tok = dns_hostname;
1906                                 }
1907                                 if ((sam_accountname != NULL) &&
1908                                     (strcasecmp(tok, old_sam_accountname) == 0)) {
1909                                         tok = sam_accountname;
1910                                 }
1911
1912                                 new_str = talloc_asprintf(ac->msg, "%s/%s",
1913                                                           new_str, tok);
1914                                 if (new_str == NULL) {
1915                                         return ldb_module_oom(ac->module);
1916                                 }
1917                         }
1918
1919                         ret = ldb_msg_add_string(ac->msg,
1920                                                  "servicePrincipalName",
1921                                                  new_str);
1922                         if (ret != LDB_SUCCESS) {
1923                                 return ret;
1924                         }
1925                 }
1926
1927                 el = ldb_msg_find_element(ac->msg, "servicePrincipalName");
1928                 el->flags = LDB_FLAG_MOD_REPLACE;
1929         }
1930
1931         talloc_free(res);
1932
1933         return LDB_SUCCESS;
1934 }
1935
1936
1937 /* add */
1938 static int samldb_add(struct ldb_module *module, struct ldb_request *req)
1939 {
1940         struct ldb_context *ldb;
1941         struct samldb_ctx *ac;
1942         int ret;
1943
1944         ldb = ldb_module_get_ctx(module);
1945         ldb_debug(ldb, LDB_DEBUG_TRACE, "samldb_add\n");
1946
1947         /* do not manipulate our control entries */
1948         if (ldb_dn_is_special(req->op.add.message->dn)) {
1949                 return ldb_next_request(module, req);
1950         }
1951
1952         ac = samldb_ctx_init(module, req);
1953         if (ac == NULL) {
1954                 return ldb_operr(ldb);
1955         }
1956
1957         /* build the new msg */
1958         ac->msg = ldb_msg_copy_shallow(ac, req->op.add.message);
1959         if (ac->msg == NULL) {
1960                 talloc_free(ac);
1961                 ldb_debug(ldb, LDB_DEBUG_FATAL,
1962                           "samldb_add: ldb_msg_copy_shallow failed!\n");
1963                 return ldb_operr(ldb);
1964         }
1965
1966         if (samdb_find_attribute(ldb, ac->msg,
1967                                  "objectclass", "user") != NULL) {
1968                 ac->type = "user";
1969
1970                 ret = samldb_prim_group_trigger(ac);
1971                 if (ret != LDB_SUCCESS) {
1972                         return ret;
1973                 }
1974
1975                 ret = samldb_objectclass_trigger(ac);
1976                 if (ret != LDB_SUCCESS) {
1977                         return ret;
1978                 }
1979
1980                 return samldb_fill_object(ac);
1981         }
1982
1983         if (samdb_find_attribute(ldb, ac->msg,
1984                                  "objectclass", "group") != NULL) {
1985                 ac->type = "group";
1986
1987                 ret = samldb_objectclass_trigger(ac);
1988                 if (ret != LDB_SUCCESS) {
1989                         return ret;
1990                 }
1991
1992                 return samldb_fill_object(ac);
1993         }
1994
1995         /* perhaps a foreignSecurityPrincipal? */
1996         if (samdb_find_attribute(ldb, ac->msg,
1997                                  "objectclass",
1998                                  "foreignSecurityPrincipal") != NULL) {
1999                 return samldb_fill_foreignSecurityPrincipal_object(ac);
2000         }
2001
2002         if (samdb_find_attribute(ldb, ac->msg,
2003                                  "objectclass", "classSchema") != NULL) {
2004                 ret = samldb_schema_info_update(ac);
2005                 if (ret != LDB_SUCCESS) {
2006                         talloc_free(ac);
2007                         return ret;
2008                 }
2009
2010                 ac->type = "classSchema";
2011                 return samldb_fill_object(ac);
2012         }
2013
2014         if (samdb_find_attribute(ldb, ac->msg,
2015                                  "objectclass", "attributeSchema") != NULL) {
2016                 ret = samldb_schema_info_update(ac);
2017                 if (ret != LDB_SUCCESS) {
2018                         talloc_free(ac);
2019                         return ret;
2020                 }
2021
2022                 ac->type = "attributeSchema";
2023                 return samldb_fill_object(ac);
2024         }
2025
2026         talloc_free(ac);
2027
2028         /* nothing matched, go on */
2029         return ldb_next_request(module, req);
2030 }
2031
2032 /* modify */
2033 static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
2034 {
2035         struct ldb_context *ldb;
2036         struct samldb_ctx *ac;
2037         struct ldb_message_element *el, *el2;
2038         bool modified = false;
2039         int ret;
2040
2041         if (ldb_dn_is_special(req->op.mod.message->dn)) {
2042                 /* do not manipulate our control entries */
2043                 return ldb_next_request(module, req);
2044         }
2045
2046         ldb = ldb_module_get_ctx(module);
2047
2048         /* make sure that "objectSid" is not specified */
2049         el = ldb_msg_find_element(req->op.mod.message, "objectSid");
2050         if (el != NULL) {
2051                 if (ldb_request_get_control(req, LDB_CONTROL_PROVISION_OID) == NULL) {
2052                         ldb_set_errstring(ldb,
2053                                           "samldb: objectSid must not be specified!");
2054                         return LDB_ERR_UNWILLING_TO_PERFORM;
2055                 }
2056         }
2057         /* make sure that "sAMAccountType" is not specified */
2058         el = ldb_msg_find_element(req->op.mod.message, "sAMAccountType");
2059         if (el != NULL) {
2060                 ldb_set_errstring(ldb,
2061                                   "samldb: sAMAccountType must not be specified!");
2062                 return LDB_ERR_UNWILLING_TO_PERFORM;
2063         }
2064         /* make sure that "isCriticalSystemObject" is not specified */
2065         el = ldb_msg_find_element(req->op.mod.message, "isCriticalSystemObject");
2066         if (el != NULL) {
2067                 if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID) == NULL) {
2068                         ldb_set_errstring(ldb,
2069                                           "samldb: isCriticalSystemObject must not be specified!");
2070                         return LDB_ERR_UNWILLING_TO_PERFORM;
2071                 }
2072         }
2073
2074         /* msDS-IntId is not allowed to be modified
2075          * except when modification comes from replication */
2076         if (ldb_msg_find_element(req->op.mod.message, "msDS-IntId")) {
2077                 if (!ldb_request_get_control(req,
2078                                              DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
2079                         return LDB_ERR_CONSTRAINT_VIOLATION;
2080                 }
2081         }
2082
2083         ac = samldb_ctx_init(module, req);
2084         if (ac == NULL) {
2085                 return ldb_operr(ldb);
2086         }
2087
2088         /* build the new msg */
2089         ac->msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
2090         if (ac->msg == NULL) {
2091                 talloc_free(ac);
2092                 ldb_debug(ldb, LDB_DEBUG_FATAL,
2093                           "samldb_modify: ldb_msg_copy_shallow failed!\n");
2094                 return ldb_operr(ldb);
2095         }
2096
2097         el = ldb_msg_find_element(ac->msg, "primaryGroupID");
2098         if (el != NULL) {
2099                 ret = samldb_prim_group_trigger(ac);
2100                 if (ret != LDB_SUCCESS) {
2101                         return ret;
2102                 }
2103         }
2104
2105         el = ldb_msg_find_element(ac->msg, "userAccountControl");
2106         if (el != NULL) {
2107                 modified = true;
2108                 ret = samldb_user_account_control_change(ac);
2109                 if (ret != LDB_SUCCESS) {
2110                         return ret;
2111                 }
2112         }
2113
2114         el = ldb_msg_find_element(ac->msg, "groupType");
2115         if (el != NULL) {
2116                 modified = true;
2117                 ret = samldb_group_type_change(ac);
2118                 if (ret != LDB_SUCCESS) {
2119                         return ret;
2120                 }
2121         }
2122
2123         el = ldb_msg_find_element(ac->msg, "sAMAccountName");
2124         if (el != NULL) {
2125                 ret = samldb_sam_accountname_check(ac);
2126                 if (ret != LDB_SUCCESS) {
2127                         return ret;
2128                 }
2129         }
2130
2131         el = ldb_msg_find_element(ac->msg, "member");
2132         if (el != NULL) {
2133                 ret = samldb_member_check(ac);
2134                 if (ret != LDB_SUCCESS) {
2135                         return ret;
2136                 }
2137         }
2138
2139         el = ldb_msg_find_element(ac->msg, "description");
2140         if (el != NULL) {
2141                 ret = samldb_description_check(ac, &modified);
2142                 if (ret != LDB_SUCCESS) {
2143                         return ret;
2144                 }
2145         }
2146
2147         el = ldb_msg_find_element(ac->msg, "dNSHostName");
2148         el2 = ldb_msg_find_element(ac->msg, "sAMAccountName");
2149         if ((el != NULL) || (el2 != NULL)) {
2150                 modified = true;
2151                 ret = samldb_service_principal_names_change(ac);
2152                 if (ret != LDB_SUCCESS) {
2153                         return ret;
2154                 }
2155         }
2156
2157         if (modified) {
2158                 struct ldb_request *child_req;
2159
2160                 /* Now perform the real modifications as a child request */
2161                 ret = ldb_build_mod_req(&child_req, ldb, ac,
2162                                         ac->msg,
2163                                         req->controls,
2164                                         req, dsdb_next_callback,
2165                                         req);
2166                 LDB_REQ_SET_LOCATION(child_req);
2167                 if (ret != LDB_SUCCESS) {
2168                         return ret;
2169                 }
2170
2171                 return ldb_next_request(module, child_req);
2172         }
2173
2174         talloc_free(ac);
2175
2176         /* no change which interests us, go on */
2177         return ldb_next_request(module, req);
2178 }
2179
2180 /* delete */
2181
2182 static int samldb_prim_group_users_check(struct samldb_ctx *ac)
2183 {
2184         struct ldb_context *ldb;
2185         struct dom_sid *sid;
2186         uint32_t rid;
2187         NTSTATUS status;
2188         int ret;
2189         struct ldb_result *res;
2190         const char *attrs[] = { "objectSid", "isDeleted", NULL };
2191         const char *noattrs[] = { NULL };
2192
2193         ldb = ldb_module_get_ctx(ac->module);
2194
2195         /* Finds out the SID/RID of the SAM object */
2196         ret = dsdb_module_search_dn(ac->module, ac, &res, ac->req->op.del.dn,
2197                                         attrs,
2198                                         DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED,
2199                                         ac->req);
2200         if (ret != LDB_SUCCESS) {
2201                 return ret;
2202         }
2203
2204         if (ldb_msg_check_string_attribute(res->msgs[0], "isDeleted", "TRUE")) {
2205                 return LDB_SUCCESS;
2206         }
2207
2208         sid = samdb_result_dom_sid(ac, res->msgs[0], "objectSid");
2209         if (sid == NULL) {
2210                 /* No SID - it might not be a SAM object - therefore ok */
2211                 return LDB_SUCCESS;
2212         }
2213         status = dom_sid_split_rid(ac, sid, NULL, &rid);
2214         if (!NT_STATUS_IS_OK(status)) {
2215                 return ldb_operr(ldb);
2216         }
2217         if (rid == 0) {
2218                 /* Special object (security principal?) */
2219                 return LDB_SUCCESS;
2220         }
2221
2222         /* Deny delete requests from groups which are primary ones */
2223         ret = dsdb_module_search(ac->module, ac, &res,
2224                                  ldb_get_default_basedn(ldb),
2225                                  LDB_SCOPE_SUBTREE, noattrs,
2226                                  DSDB_FLAG_NEXT_MODULE,
2227                                  ac->req,
2228                                  "(&(primaryGroupID=%u)(objectClass=user))", rid);
2229         if (ret != LDB_SUCCESS) {
2230                 return ret;
2231         }
2232         if (res->count > 0) {
2233                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
2234         }
2235
2236         return LDB_SUCCESS;
2237 }
2238
2239 static int samldb_delete(struct ldb_module *module, struct ldb_request *req)
2240 {
2241         struct samldb_ctx *ac;
2242         int ret;
2243
2244         if (ldb_dn_is_special(req->op.del.dn)) {
2245                 /* do not manipulate our control entries */
2246                 return ldb_next_request(module, req);
2247         }
2248
2249         ac = samldb_ctx_init(module, req);
2250         if (ac == NULL) {
2251                 return ldb_operr(ldb_module_get_ctx(module));
2252         }
2253
2254         ret = samldb_prim_group_users_check(ac);
2255         if (ret != LDB_SUCCESS) {
2256                 return ret;
2257         }
2258
2259         talloc_free(ac);
2260
2261         return ldb_next_request(module, req);
2262 }
2263
2264 /* extended */
2265
2266 static int samldb_extended_allocate_rid_pool(struct ldb_module *module, struct ldb_request *req)
2267 {
2268         struct ldb_context *ldb = ldb_module_get_ctx(module);
2269         struct dsdb_fsmo_extended_op *exop;
2270         int ret;
2271
2272         exop = talloc_get_type(req->op.extended.data,
2273                                struct dsdb_fsmo_extended_op);
2274         if (!exop) {
2275                 ldb_set_errstring(ldb,
2276                                   "samldb_extended_allocate_rid_pool: invalid extended data");
2277                 return LDB_ERR_PROTOCOL_ERROR;
2278         }
2279
2280         ret = ridalloc_allocate_rid_pool_fsmo(module, exop, req);
2281         if (ret != LDB_SUCCESS) {
2282                 return ret;
2283         }
2284
2285         return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
2286 }
2287
2288 static int samldb_extended(struct ldb_module *module, struct ldb_request *req)
2289 {
2290         if (strcmp(req->op.extended.oid, DSDB_EXTENDED_ALLOCATE_RID_POOL) == 0) {
2291                 return samldb_extended_allocate_rid_pool(module, req);
2292         }
2293
2294         return ldb_next_request(module, req);
2295 }
2296
2297
2298 static const struct ldb_module_ops ldb_samldb_module_ops = {
2299         .name          = "samldb",
2300         .add           = samldb_add,
2301         .modify        = samldb_modify,
2302         .del           = samldb_delete,
2303         .extended      = samldb_extended
2304 };
2305
2306
2307 int ldb_samldb_module_init(const char *version)
2308 {
2309         LDB_MODULE_CHECK_VERSION(version);
2310         return ldb_register_module(&ldb_samldb_module_ops);
2311 }