s4-dsdb: Relax the conditions where we can't do a subtree delete
[mat/samba.git] / source4 / dsdb / samdb / ldb_modules / objectclass.c
1 /* 
2    ldb database library
3
4    Copyright (C) Simo Sorce  2006-2008
5    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2009
6    Copyright (C) Matthias Dieter Wallnöfer 2010-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: objectClass sorting and constraint checking module
26  *
27  *  Description: 
28  *  - sort the objectClass attribute into the class
29  *    hierarchy and perform constraint checks (correct RDN name,
30  *    valid parent),
31  *  - fix DNs into 'standard' case
32  *  - Add objectCategory and some other attribute defaults
33  *
34  *  Author: Andrew Bartlett
35  */
36
37
38 #include "includes.h"
39 #include "ldb_module.h"
40 #include "util/dlinklist.h"
41 #include "dsdb/samdb/samdb.h"
42 #include "librpc/ndr/libndr.h"
43 #include "librpc/gen_ndr/ndr_security.h"
44 #include "libcli/security/security.h"
45 #include "auth/auth.h"
46 #include "param/param.h"
47 #include "../libds/common/flags.h"
48 #include "dsdb/samdb/ldb_modules/schema.h"
49 #include "dsdb/samdb/ldb_modules/util.h"
50
51 struct oc_context {
52
53         struct ldb_module *module;
54         struct ldb_request *req;
55         const struct dsdb_schema *schema;
56
57         struct ldb_reply *search_res;
58         struct ldb_reply *search_res2;
59
60         int (*step_fn)(struct oc_context *);
61 };
62
63 struct class_list {
64         struct class_list *prev, *next;
65         const struct dsdb_class *objectclass;
66 };
67
68 static struct oc_context *oc_init_context(struct ldb_module *module,
69                                           struct ldb_request *req)
70 {
71         struct ldb_context *ldb;
72         struct oc_context *ac;
73
74         ldb = ldb_module_get_ctx(module);
75
76         ac = talloc_zero(req, struct oc_context);
77         if (ac == NULL) {
78                 ldb_oom(ldb);
79                 return NULL;
80         }
81
82         ac->module = module;
83         ac->req = req;
84         ac->schema = dsdb_get_schema(ldb, ac);
85
86         return ac;
87 }
88
89 static int objectclass_do_add(struct oc_context *ac);
90
91 /* Sort objectClasses into correct order, and validate that all
92  * objectClasses specified actually exist in the schema
93  */
94
95 static int objectclass_sort(struct ldb_module *module,
96                             const struct dsdb_schema *schema,
97                             TALLOC_CTX *mem_ctx,
98                             struct ldb_message_element *objectclass_element,
99                             struct class_list **sorted_out) 
100 {
101         struct ldb_context *ldb;
102         unsigned int i, lowest;
103         struct class_list *unsorted = NULL, *sorted = NULL, *current = NULL, *poss_parent = NULL, *new_parent = NULL, *current_lowest = NULL;
104
105         ldb = ldb_module_get_ctx(module);
106
107         /* DESIGN:
108          *
109          * We work on 4 different 'bins' (implemented here as linked lists):
110          *
111          * * sorted:       the eventual list, in the order we wish to push
112          *                 into the database.  This is the only ordered list.
113          *
114          * * parent_class: The current parent class 'bin' we are
115          *                 trying to find subclasses for
116          *
117          * * subclass:     The subclasses we have found so far
118          *
119          * * unsorted:     The remaining objectClasses
120          *
121          * The process is a matter of filtering objectClasses up from
122          * unsorted into sorted.  Order is irrelevent in the later 3 'bins'.
123          * 
124          * We start with 'top' (found and promoted to parent_class
125          * initially).  Then we find (in unsorted) all the direct
126          * subclasses of 'top'.  parent_classes is concatenated onto
127          * the end of 'sorted', and subclass becomes the list in
128          * parent_class.
129          *
130          * We then repeat, until we find no more subclasses.  Any left
131          * over classes are added to the end.
132          *
133          */
134
135         /* Firstly, dump all the objectClass elements into the
136          * unsorted bin, except for 'top', which is special */
137         for (i=0; i < objectclass_element->num_values; i++) {
138                 current = talloc(mem_ctx, struct class_list);
139                 if (!current) {
140                         return ldb_oom(ldb);
141                 }
142                 current->objectclass = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &objectclass_element->values[i]);
143                 if (!current->objectclass) {
144                         ldb_asprintf_errstring(ldb, "objectclass %.*s is not a valid objectClass in schema", 
145                                                (int)objectclass_element->values[i].length, (const char *)objectclass_element->values[i].data);
146                         /* This looks weird, but windows apparently returns this for invalid objectClass values */
147                         return LDB_ERR_NO_SUCH_ATTRIBUTE;
148                 } else if (current->objectclass->isDefunct) {
149                         ldb_asprintf_errstring(ldb, "objectclass %.*s marked as isDefunct objectClass in schema - not valid for new objects", 
150                                                (int)objectclass_element->values[i].length, (const char *)objectclass_element->values[i].data);
151                         /* This looks weird, but windows apparently returns this for invalid objectClass values */
152                         return LDB_ERR_NO_SUCH_ATTRIBUTE;
153                 }
154
155                 /* Don't add top to list, we will do that later */
156                 if (ldb_attr_cmp("top", current->objectclass->lDAPDisplayName) != 0) {
157                         DLIST_ADD_END(unsorted, current, struct class_list *);
158                 }
159         }
160
161         /* Add top here, to prevent duplicates */
162         current = talloc(mem_ctx, struct class_list);
163         current->objectclass = dsdb_class_by_lDAPDisplayName(schema, "top");
164         DLIST_ADD_END(sorted, current, struct class_list *);
165
166
167         /* For each object:  find parent chain */
168         for (current = unsorted; schema && current; current = current->next) {
169                 for (poss_parent = unsorted; poss_parent; poss_parent = poss_parent->next) {
170                         if (ldb_attr_cmp(poss_parent->objectclass->lDAPDisplayName, current->objectclass->subClassOf) == 0) {
171                                 break;
172                         }
173                 }
174                 /* If we didn't get to the end of the list, we need to add this parent */
175                 if (poss_parent || (ldb_attr_cmp("top", current->objectclass->subClassOf) == 0)) {
176                         continue;
177                 }
178
179                 new_parent = talloc(mem_ctx, struct class_list);
180                 new_parent->objectclass = dsdb_class_by_lDAPDisplayName(schema, current->objectclass->subClassOf);
181                 DLIST_ADD_END(unsorted, new_parent, struct class_list *);
182         }
183
184         do
185         {
186                 lowest = UINT_MAX;
187                 current_lowest = NULL;
188                 for (current = unsorted; schema && current; current = current->next) {
189                         if(current->objectclass->subClass_order < lowest) {
190                                 current_lowest = current;
191                                 lowest = current->objectclass->subClass_order;
192                         }
193                 }
194
195                 if(current_lowest != NULL) {
196                         DLIST_REMOVE(unsorted,current_lowest);
197                         DLIST_ADD_END(sorted,current_lowest, struct class_list *);
198                 }
199         } while(unsorted);
200
201
202         if (!unsorted) {
203                 *sorted_out = sorted;
204                 return LDB_SUCCESS;
205         }
206
207         if (!schema) {
208                 /* If we don't have schema yet, then just merge the lists again */
209                 DLIST_CONCATENATE(sorted, unsorted, struct class_list *);
210                 *sorted_out = sorted;
211                 return LDB_SUCCESS;
212         }
213
214         /* This shouldn't happen, and would break MMC, perhaps there
215          * was no 'top', a conflict in the objectClasses or some other
216          * schema error?
217          */
218         ldb_asprintf_errstring(ldb, "objectclass %s is not a valid objectClass in objectClass chain", unsorted->objectclass->lDAPDisplayName);
219         return LDB_ERR_OBJECT_CLASS_VIOLATION;
220 }
221
222 /*
223  * This checks if we have unrelated object classes in our entry's "objectClass"
224  * attribute. That means "unsatisfied" abstract classes (no concrete subclass)
225  * or two or more disjunct structural ones.
226  * If one of these conditions are true, blame.
227  */
228 static int check_unrelated_objectclasses(struct ldb_module *module,
229                                         const struct dsdb_schema *schema,
230                                         const struct dsdb_class *struct_objectclass,
231                                         struct ldb_message_element *objectclass_element)
232 {
233         struct ldb_context *ldb = ldb_module_get_ctx(module);
234         unsigned int i;
235         bool found;
236
237         if (schema == NULL) {
238                 return LDB_SUCCESS;
239         }
240
241         for (i = 0; i < objectclass_element->num_values; i++) {
242                 const struct dsdb_class *tmp_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema,
243                                                                                            &objectclass_element->values[i]);
244                 const struct dsdb_class *tmp_class2 = struct_objectclass;
245
246                 /* Pointer comparison can be used due to the same schema str. */
247                 if (tmp_class == NULL ||
248                     tmp_class == struct_objectclass ||
249                     tmp_class->objectClassCategory > 2 ||
250                     ldb_attr_cmp(tmp_class->lDAPDisplayName, "top") == 0) {
251                         continue;
252                 }
253
254                 found = false;
255                 while (!found &&
256                        ldb_attr_cmp(tmp_class2->lDAPDisplayName, "top") != 0) {
257                         tmp_class2 = dsdb_class_by_lDAPDisplayName(schema,
258                                                                    tmp_class2->subClassOf);
259                         if (tmp_class2 == tmp_class) {
260                                 found = true;
261                         }
262                 }
263                 if (found) {
264                         continue;
265                 }
266
267                 ldb_asprintf_errstring(ldb,
268                                        "objectclass: the objectclass '%s' seems to be unrelated to the entry!",
269                                        tmp_class->lDAPDisplayName);
270                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
271         }
272
273         return LDB_SUCCESS;
274 }
275
276 static int get_search_callback(struct ldb_request *req, struct ldb_reply *ares)
277 {
278         struct ldb_context *ldb;
279         struct oc_context *ac;
280         int ret;
281
282         ac = talloc_get_type(req->context, struct oc_context);
283         ldb = ldb_module_get_ctx(ac->module);
284
285         if (!ares) {
286                 return ldb_module_done(ac->req, NULL, NULL,
287                                         LDB_ERR_OPERATIONS_ERROR);
288         }
289         if (ares->error != LDB_SUCCESS &&
290             ares->error != LDB_ERR_NO_SUCH_OBJECT) {
291                 return ldb_module_done(ac->req, ares->controls,
292                                         ares->response, ares->error);
293         }
294
295         ldb_reset_err_string(ldb);
296
297         switch (ares->type) {
298         case LDB_REPLY_ENTRY:
299                 if (ac->search_res != NULL) {
300                         ldb_set_errstring(ldb, "Too many results");
301                         talloc_free(ares);
302                         return ldb_module_done(ac->req, NULL, NULL,
303                                                 LDB_ERR_OPERATIONS_ERROR);
304                 }
305
306                 ac->search_res = talloc_steal(ac, ares);
307                 break;
308
309         case LDB_REPLY_REFERRAL:
310                 /* ignore */
311                 talloc_free(ares);
312                 break;
313
314         case LDB_REPLY_DONE:
315                 talloc_free(ares);
316                 ret = ac->step_fn(ac);
317                 if (ret != LDB_SUCCESS) {
318                         return ldb_module_done(ac->req, NULL, NULL, ret);
319                 }
320                 break;
321         }
322
323         return LDB_SUCCESS;
324 }
325
326 static int oc_op_callback(struct ldb_request *req, struct ldb_reply *ares)
327 {
328         struct oc_context *ac;
329
330         ac = talloc_get_type(req->context, struct oc_context);
331
332         if (!ares) {
333                 return ldb_module_done(ac->req, NULL, NULL,
334                                         LDB_ERR_OPERATIONS_ERROR);
335         }
336
337         if (ares->type == LDB_REPLY_REFERRAL) {
338                 return ldb_module_send_referral(ac->req, ares->referral);
339         }
340
341         if (ares->error != LDB_SUCCESS) {
342                 return ldb_module_done(ac->req, ares->controls,
343                                         ares->response, ares->error);
344         }
345
346         if (ares->type != LDB_REPLY_DONE) {
347                 talloc_free(ares);
348                 return ldb_module_done(ac->req, NULL, NULL,
349                                         LDB_ERR_OPERATIONS_ERROR);
350         }
351
352         return ldb_module_done(ac->req, ares->controls,
353                                 ares->response, ares->error);
354 }
355
356 /* Fix up the DN to be in the standard form, taking particular care to match the parent DN
357
358    This should mean that if the parent is:
359     CN=Users,DC=samba,DC=example,DC=com
360    and a proposed child is
361     cn=Admins ,cn=USERS,dc=Samba,dc=example,dc=COM
362
363    The resulting DN should be:
364
365     CN=Admins,CN=Users,DC=samba,DC=example,DC=com
366    
367  */
368 static int fix_dn(struct ldb_context *ldb,
369                   TALLOC_CTX *mem_ctx,
370                   struct ldb_dn *newdn, struct ldb_dn *parent_dn, 
371                   struct ldb_dn **fixed_dn) 
372 {
373         char *upper_rdn_attr;
374         const struct ldb_val *rdn_val;
375
376         /* Fix up the DN to be in the standard form, taking particular care to
377          * match the parent DN */
378         *fixed_dn = ldb_dn_copy(mem_ctx, parent_dn);
379         if (*fixed_dn == NULL) {
380                 return ldb_oom(ldb);
381         }
382
383         /* We need the attribute name in upper case */
384         upper_rdn_attr = strupper_talloc(*fixed_dn, 
385                                          ldb_dn_get_rdn_name(newdn));
386         if (upper_rdn_attr == NULL) {
387                 return ldb_oom(ldb);
388         }
389
390         /* Create a new child */
391         if (ldb_dn_add_child_fmt(*fixed_dn, "X=X") == false) {
392                 return ldb_operr(ldb);
393         }
394
395         rdn_val = ldb_dn_get_rdn_val(newdn);
396         if (rdn_val == NULL) {
397                 return ldb_operr(ldb);
398         }
399
400 #if 0
401         /* the rules for rDN length constraints are more complex than
402         this. Until we understand them we need to leave this
403         constraint out. Otherwise we break replication, as windows
404         does sometimes send us rDNs longer than 64 */
405         if (!rdn_val || rdn_val->length > 64) {
406                 DEBUG(2,(__location__ ": WARNING: rDN longer than 64 limit for '%s'\n", ldb_dn_get_linearized(newdn)));
407         }
408 #endif
409
410
411         /* And replace it with CN=foo (we need the attribute in upper case) */
412         return ldb_dn_set_component(*fixed_dn, 0, upper_rdn_attr, *rdn_val);
413 }
414
415
416 static int objectclass_do_add(struct oc_context *ac);
417
418 static int objectclass_add(struct ldb_module *module, struct ldb_request *req)
419 {
420         struct ldb_context *ldb;
421         struct ldb_request *search_req;
422         struct oc_context *ac;
423         struct ldb_dn *parent_dn;
424         const struct ldb_val *val;
425         int ret;
426         static const char * const parent_attrs[] = { "objectClass", NULL };
427
428         ldb = ldb_module_get_ctx(module);
429
430         ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_add\n");
431
432         /* do not manipulate our control entries */
433         if (ldb_dn_is_special(req->op.add.message->dn)) {
434                 return ldb_next_request(module, req);
435         }
436
437         /* An add operation on the basedn without "NC-add" operation isn't
438          * allowed. */
439         if (ldb_dn_compare(ldb_get_default_basedn(ldb), req->op.add.message->dn) == 0) {
440                 unsigned int instanceType;
441
442                 instanceType = ldb_msg_find_attr_as_uint(req->op.add.message,
443                                                          "instanceType", 0);
444                 if (!(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
445                         char *referral_uri;
446                         /* When we are trying to readd the root basedn then
447                          * this is denied, but with an interesting mechanism:
448                          * there is generated a referral with the last
449                          * component value as hostname. */
450                         val = ldb_dn_get_component_val(req->op.add.message->dn,
451                                                        ldb_dn_get_comp_num(req->op.add.message->dn) - 1);
452                         if (val == NULL) {
453                                 return ldb_operr(ldb);
454                         }
455                         referral_uri = talloc_asprintf(req, "ldap://%s/%s", val->data,
456                                                        ldb_dn_get_linearized(req->op.add.message->dn));
457                         if (referral_uri == NULL) {
458                                 return ldb_module_oom(module);
459                         }
460
461                         return ldb_module_send_referral(req, referral_uri);
462                 }
463         }
464
465         ac = oc_init_context(module, req);
466         if (ac == NULL) {
467                 return ldb_operr(ldb);
468         }
469
470         /* If there isn't a parent, just go on to the add processing */
471         if (ldb_dn_get_comp_num(ac->req->op.add.message->dn) == 1) {
472                 return objectclass_do_add(ac);
473         }
474
475         /* get copy of parent DN */
476         parent_dn = ldb_dn_get_parent(ac, ac->req->op.add.message->dn);
477         if (parent_dn == NULL) {
478                 return ldb_operr(ldb);
479         }
480
481         ret = ldb_build_search_req(&search_req, ldb,
482                                    ac, parent_dn, LDB_SCOPE_BASE,
483                                    "(objectClass=*)", parent_attrs,
484                                    NULL,
485                                    ac, get_search_callback,
486                                    req);
487         LDB_REQ_SET_LOCATION(search_req);
488         if (ret != LDB_SUCCESS) {
489                 return ret;
490         }
491
492         ac->step_fn = objectclass_do_add;
493
494         return ldb_next_request(ac->module, search_req);
495 }
496
497
498 /*
499   check if this is a special RODC nTDSDSA add
500  */
501 static bool check_rodc_ntdsdsa_add(struct oc_context *ac,
502                                    const struct dsdb_class *objectclass)
503 {
504         struct ldb_control *rodc_control;
505
506         if (ldb_attr_cmp(objectclass->lDAPDisplayName, "nTDSDSA") != 0) {
507                 return false;
508         }
509         rodc_control = ldb_request_get_control(ac->req, LDB_CONTROL_RODC_DCPROMO_OID);
510         if (!rodc_control) {
511                 return false;
512         }
513
514         rodc_control->critical = false;
515         return true;
516 }
517
518 static int objectclass_do_add(struct oc_context *ac)
519 {
520         struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
521         struct ldb_request *add_req;
522         struct ldb_message_element *objectclass_element, *el;
523         struct ldb_message *msg;
524         TALLOC_CTX *mem_ctx;
525         struct class_list *sorted, *current;
526         const char *rdn_name = NULL;
527         char *value;
528         const struct dsdb_class *objectclass;
529         struct ldb_dn *objectcategory;
530         int32_t systemFlags = 0;
531         unsigned int i, j;
532         bool found;
533         int ret;
534
535         msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message);
536         if (msg == NULL) {
537                 return ldb_module_oom(ac->module);
538         }
539
540         /* Check if we have a valid parent - this check is needed since
541          * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
542         if (ac->search_res == NULL) {
543                 unsigned int instanceType;
544
545                 /* An add operation on partition DNs without "NC-add" operation
546                  * isn't allowed. */
547                 instanceType = ldb_msg_find_attr_as_uint(msg, "instanceType",
548                                                          0);
549                 if (!(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
550                         ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, parent does not exist!", 
551                                                ldb_dn_get_linearized(msg->dn));
552                         return LDB_ERR_NO_SUCH_OBJECT;
553                 }
554
555                 /* Don't keep any error messages - we've to add a partition */
556                 ldb_set_errstring(ldb, NULL);
557         } else {
558                 /* Fix up the DN to be in the standard form, taking
559                  * particular care to match the parent DN */
560                 ret = fix_dn(ldb, msg,
561                              ac->req->op.add.message->dn,
562                              ac->search_res->message->dn,
563                              &msg->dn);
564                 if (ret != LDB_SUCCESS) {
565                         ldb_asprintf_errstring(ldb, "objectclass: Could not munge DN %s into normal form",
566                                                ldb_dn_get_linearized(ac->req->op.add.message->dn));
567                         return ret;
568                 }
569         }
570
571         if (ac->schema != NULL) {
572                 objectclass_element = ldb_msg_find_element(msg, "objectClass");
573                 if (!objectclass_element) {
574                         ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, no objectclass specified!",
575                                                ldb_dn_get_linearized(msg->dn));
576                         return LDB_ERR_OBJECT_CLASS_VIOLATION;
577                 }
578                 if (objectclass_element->num_values == 0) {
579                         ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, at least one (structural) objectclass has to be specified!",
580                                                ldb_dn_get_linearized(msg->dn));
581                         return LDB_ERR_CONSTRAINT_VIOLATION;
582                 }
583
584                 mem_ctx = talloc_new(ac);
585                 if (mem_ctx == NULL) {
586                         return ldb_module_oom(ac->module);
587                 }
588
589                 /* Here we do now get the "objectClass" list from the
590                  * database. */
591                 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
592                                        objectclass_element, &sorted);
593                 if (ret != LDB_SUCCESS) {
594                         talloc_free(mem_ctx);
595                         return ret;
596                 }
597                 
598                 ldb_msg_remove_element(msg, objectclass_element);
599
600                 /* Well, now we shouldn't find any additional "objectClass"
601                  * message element (required by the AD specification). */
602                 objectclass_element = ldb_msg_find_element(msg, "objectClass");
603                 if (objectclass_element != NULL) {
604                         ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, only one 'objectclass' attribute specification is allowed!",
605                                                ldb_dn_get_linearized(msg->dn));
606                         talloc_free(mem_ctx);
607                         return LDB_ERR_OBJECT_CLASS_VIOLATION;
608                 }
609
610                 /* We must completely replace the existing objectClass entry,
611                  * because we need it sorted. */
612                 ret = ldb_msg_add_empty(msg, "objectClass", 0,
613                                         &objectclass_element);
614                 if (ret != LDB_SUCCESS) {
615                         talloc_free(mem_ctx);
616                         return ret;
617                 }
618
619                 /* Move from the linked list back into an ldb msg */
620                 for (current = sorted; current; current = current->next) {
621                         const char *objectclass_name = current->objectclass->lDAPDisplayName;
622
623                         ret = ldb_msg_add_string(msg, "objectClass", objectclass_name);
624                         if (ret != LDB_SUCCESS) {
625                                 ldb_set_errstring(ldb,
626                                                   "objectclass: could not re-add sorted "
627                                                   "objectclass to modify msg");
628                                 talloc_free(mem_ctx);
629                                 return ret;
630                         }
631                 }
632
633                 talloc_free(mem_ctx);
634
635                 /* Make sure its valid to add an object of this type */
636                 objectclass = get_last_structural_class(ac->schema,
637                                                         objectclass_element, ac->req);
638                 if(objectclass == NULL) {
639                         ldb_asprintf_errstring(ldb,
640                                                "Failed to find a structural class for %s",
641                                                ldb_dn_get_linearized(msg->dn));
642                         return LDB_ERR_UNWILLING_TO_PERFORM;
643                 }
644
645                 ret = check_unrelated_objectclasses(ac->module, ac->schema,
646                                                     objectclass,
647                                                     objectclass_element);
648                 if (ret != LDB_SUCCESS) {
649                         return ret;
650                 }
651
652                 rdn_name = ldb_dn_get_rdn_name(msg->dn);
653                 if (rdn_name == NULL) {
654                         return ldb_operr(ldb);
655                 }
656                 found = false;
657                 for (i = 0; (!found) && (i < objectclass_element->num_values);
658                      i++) {
659                         const struct dsdb_class *tmp_class =
660                                 dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
661                                                                       &objectclass_element->values[i]);
662
663                         if (tmp_class == NULL) continue;
664
665                         if (ldb_attr_cmp(rdn_name, tmp_class->rDNAttID) == 0)
666                                 found = true;
667                 }
668                 if (!found) {
669                         ldb_asprintf_errstring(ldb,
670                                                "objectclass: Invalid RDN '%s' for objectclass '%s'!",
671                                                rdn_name, objectclass->lDAPDisplayName);
672                         return LDB_ERR_NAMING_VIOLATION;
673                 }
674
675                 if (objectclass->systemOnly &&
676                     !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) &&
677                     !check_rodc_ntdsdsa_add(ac, objectclass)) {
678                         ldb_asprintf_errstring(ldb,
679                                                "objectclass: object class '%s' is system-only, rejecting creation of '%s'!",
680                                                objectclass->lDAPDisplayName,
681                                                ldb_dn_get_linearized(msg->dn));
682                         return LDB_ERR_UNWILLING_TO_PERFORM;
683                 }
684
685                 if (ac->search_res && ac->search_res->message) {
686                         struct ldb_message_element *oc_el
687                                 = ldb_msg_find_element(ac->search_res->message, "objectClass");
688
689                         bool allowed_class = false;
690                         for (i=0; allowed_class == false && oc_el && i < oc_el->num_values; i++) {
691                                 const struct dsdb_class *sclass;
692
693                                 sclass = dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
694                                                                                &oc_el->values[i]);
695                                 if (!sclass) {
696                                         /* We don't know this class?  what is going on? */
697                                         continue;
698                                 }
699                                 for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
700                                         if (ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
701                                                 allowed_class = true;
702                                                 break;
703                                         }
704                                 }
705                         }
706
707                         if (!allowed_class) {
708                                 ldb_asprintf_errstring(ldb, "structural objectClass %s is not a valid child class for %s",
709                                                 objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res->message->dn));
710                                 return LDB_ERR_NAMING_VIOLATION;
711                         }
712                 }
713
714                 objectcategory = ldb_msg_find_attr_as_dn(ldb, ac, msg,
715                                                          "objectCategory");
716                 if (objectcategory == NULL) {
717                         struct dsdb_extended_dn_store_format *dn_format =
718                                         talloc_get_type(ldb_module_get_private(ac->module),
719                                                         struct dsdb_extended_dn_store_format);
720                         if (dn_format && dn_format->store_extended_dn_in_ldb == false) {
721                                 /* Strip off extended components */
722                                 struct ldb_dn *dn = ldb_dn_new(ac, ldb,
723                                                                objectclass->defaultObjectCategory);
724                                 value = ldb_dn_alloc_linearized(msg, dn);
725                                 talloc_free(dn);
726                         } else {
727                                 value = talloc_strdup(msg,
728                                                       objectclass->defaultObjectCategory);
729                         }
730                         if (value == NULL) {
731                                 return ldb_module_oom(ac->module);
732                         }
733
734                         ret = ldb_msg_add_string(msg, "objectCategory", value);
735                         if (ret != LDB_SUCCESS) {
736                                 return ret;
737                         }
738                 } else {
739                         const struct dsdb_class *ocClass =
740                                         dsdb_class_by_cn_ldb_val(ac->schema,
741                                                                  ldb_dn_get_rdn_val(objectcategory));
742                         if (ocClass != NULL) {
743                                 struct ldb_dn *dn = ldb_dn_new(ac, ldb,
744                                                                ocClass->defaultObjectCategory);
745                                 if (ldb_dn_compare(objectcategory, dn) != 0) {
746                                         ocClass = NULL;
747                                 }
748                         }
749                         talloc_free(objectcategory);
750                         if (ocClass == NULL) {
751                                 ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, 'objectCategory' attribute invalid!",
752                                                        ldb_dn_get_linearized(msg->dn));
753                                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
754                         }
755                 }
756
757                 if (!ldb_msg_find_element(msg, "showInAdvancedViewOnly") && (objectclass->defaultHidingValue == true)) {
758                         ldb_msg_add_string(msg, "showInAdvancedViewOnly",
759                                                 "TRUE");
760                 }
761
762                 /* There are very special rules for systemFlags, see MS-ADTS
763                  * MS-ADTS 3.1.1.5.2.4 */
764
765                 el = ldb_msg_find_element(msg, "systemFlags");
766                 if ((el != NULL) && (el->num_values > 1)) {
767                         ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, 'systemFlags' attribute multivalued!",
768                                                ldb_dn_get_linearized(msg->dn));
769                         return LDB_ERR_CONSTRAINT_VIOLATION;
770                 }
771
772                 systemFlags = ldb_msg_find_attr_as_int(msg, "systemFlags", 0);
773
774                 ldb_msg_remove_attr(msg, "systemFlags");
775
776                 /* Only the following flags may be set by a client */
777                 if (ldb_request_get_control(ac->req,
778                                             LDB_CONTROL_RELAX_OID) == NULL) {
779                         systemFlags &= ( SYSTEM_FLAG_CONFIG_ALLOW_RENAME
780                                        | SYSTEM_FLAG_CONFIG_ALLOW_MOVE
781                                        | SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE
782                                        | SYSTEM_FLAG_ATTR_IS_RDN );
783                 }
784
785                 /* But the last one ("ATTR_IS_RDN") is only allowed on
786                  * "attributeSchema" objects. So truncate if it does not fit. */
787                 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "attributeSchema") != 0) {
788                         systemFlags &= ~SYSTEM_FLAG_ATTR_IS_RDN;
789                 }
790
791                 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "server") == 0) {
792                         systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE | SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE);
793                 } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, "site") == 0
794                                 || ldb_attr_cmp(objectclass->lDAPDisplayName, "serversContainer") == 0
795                                 || ldb_attr_cmp(objectclass->lDAPDisplayName, "nTDSDSA") == 0) {
796                         if (ldb_attr_cmp(objectclass->lDAPDisplayName, "site") == 0)
797                                 systemFlags |= (int32_t)(SYSTEM_FLAG_CONFIG_ALLOW_RENAME);
798                         systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
799                 } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLink") == 0
800                                 || ldb_attr_cmp(objectclass->lDAPDisplayName, "subnet") == 0
801                                 || ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLinkBridge") == 0
802                                 || ldb_attr_cmp(objectclass->lDAPDisplayName, "nTDSConnection") == 0) {
803                         systemFlags |= (int32_t)(SYSTEM_FLAG_CONFIG_ALLOW_RENAME);
804                 }
805                 /* TODO: If parent object is site or subnet, also add (SYSTEM_FLAG_CONFIG_ALLOW_RENAME) */
806
807                 if (el || systemFlags != 0) {
808                         ret = samdb_msg_add_int(ldb, msg, msg, "systemFlags",
809                                                 systemFlags);
810                         if (ret != LDB_SUCCESS) {
811                                 return ret;
812                         }
813                 }
814
815                 /* make sure that "isCriticalSystemObject" is not specified! */
816                 el = ldb_msg_find_element(msg, "isCriticalSystemObject");
817                 if ((el != NULL) &&
818                     !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
819                         ldb_set_errstring(ldb,
820                                           "objectclass: 'isCriticalSystemObject' must not be specified!");
821                         return LDB_ERR_UNWILLING_TO_PERFORM;
822                 }
823         }
824
825         ret = ldb_build_add_req(&add_req, ldb, ac,
826                                 msg,
827                                 ac->req->controls,
828                                 ac, oc_op_callback,
829                                 ac->req);
830         LDB_REQ_SET_LOCATION(add_req);
831         if (ret != LDB_SUCCESS) {
832                 return ret;
833         }
834
835         /* perform the add */
836         return ldb_next_request(ac->module, add_req);
837 }
838
839 static int oc_modify_callback(struct ldb_request *req,
840                                 struct ldb_reply *ares);
841 static int objectclass_do_mod(struct oc_context *ac);
842
843 static int objectclass_modify(struct ldb_module *module, struct ldb_request *req)
844 {
845         struct ldb_context *ldb = ldb_module_get_ctx(module);
846         struct ldb_message_element *objectclass_element;
847         struct ldb_message *msg;
848         struct ldb_request *down_req;
849         struct oc_context *ac;
850         bool oc_changes = false;
851         int ret;
852
853         ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_modify\n");
854
855         /* do not manipulate our control entries */
856         if (ldb_dn_is_special(req->op.mod.message->dn)) {
857                 return ldb_next_request(module, req);
858         }
859
860         /* As with the "real" AD we don't accept empty messages */
861         if (req->op.mod.message->num_elements == 0) {
862                 ldb_set_errstring(ldb, "objectclass: modify message must have "
863                                        "elements/attributes!");
864                 return LDB_ERR_UNWILLING_TO_PERFORM;
865         }
866
867         ac = oc_init_context(module, req);
868         if (ac == NULL) {
869                 return ldb_operr(ldb);
870         }
871
872         /* Without schema, there isn't much to do here */
873         if (ac->schema == NULL) {
874                 talloc_free(ac);
875                 return ldb_next_request(module, req);
876         }
877
878         msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
879         if (msg == NULL) {
880                 return ldb_module_oom(ac->module);
881         }
882
883         /* For now change everything except the objectclasses */
884
885         objectclass_element = ldb_msg_find_element(msg, "objectClass");
886         if (objectclass_element != NULL) {
887                 ldb_msg_remove_attr(msg, "objectClass");
888                 oc_changes = true;
889         }
890
891         /* MS-ADTS 3.1.1.5.3.5 - on a forest level < 2003 we do allow updates
892          * only on application NCs - not on the default ones */
893         if (oc_changes &&
894             (dsdb_forest_functional_level(ldb) < DS_DOMAIN_FUNCTION_2003)) {
895                 struct ldb_dn *nc_root;
896
897                 ret = dsdb_find_nc_root(ldb, ac, req->op.mod.message->dn,
898                                         &nc_root);
899                 if (ret != LDB_SUCCESS) {
900                         return ret;
901                 }
902
903                 if ((ldb_dn_compare(nc_root, ldb_get_default_basedn(ldb)) == 0) ||
904                     (ldb_dn_compare(nc_root, ldb_get_config_basedn(ldb)) == 0) ||
905                     (ldb_dn_compare(nc_root, ldb_get_schema_basedn(ldb)) == 0)) {
906                         ldb_set_errstring(ldb,
907                                           "objectclass: object class changes on objects under the standard name contexts not allowed!");
908                         return LDB_ERR_UNWILLING_TO_PERFORM;
909                 }
910
911                 talloc_free(nc_root);
912         }
913
914         ret = ldb_build_mod_req(&down_req, ldb, ac,
915                                 msg,
916                                 req->controls, ac,
917                                 oc_changes ? oc_modify_callback : oc_op_callback,
918                                 req);
919         LDB_REQ_SET_LOCATION(down_req);
920         if (ret != LDB_SUCCESS) {
921                 return ret;
922         }
923
924         return ldb_next_request(module, down_req);
925 }
926
927 static int oc_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
928 {
929         static const char * const attrs[] = { "objectClass", NULL };
930         struct ldb_context *ldb;
931         struct ldb_request *search_req;
932         struct oc_context *ac;
933         int ret;
934
935         ac = talloc_get_type(req->context, struct oc_context);
936         ldb = ldb_module_get_ctx(ac->module);
937
938         if (!ares) {
939                 return ldb_module_done(ac->req, NULL, NULL,
940                                         LDB_ERR_OPERATIONS_ERROR);
941         }
942
943         if (ares->type == LDB_REPLY_REFERRAL) {
944                 return ldb_module_send_referral(ac->req, ares->referral);
945         }
946
947         if (ares->error != LDB_SUCCESS) {
948                 return ldb_module_done(ac->req, ares->controls,
949                                         ares->response, ares->error);
950         }
951
952         if (ares->type != LDB_REPLY_DONE) {
953                 talloc_free(ares);
954                 return ldb_module_done(ac->req, NULL, NULL,
955                                         LDB_ERR_OPERATIONS_ERROR);
956         }
957
958         talloc_free(ares);
959
960         /* this looks up the real existing object for fetching some important
961          * information (objectclasses) */
962         ret = ldb_build_search_req(&search_req, ldb,
963                                    ac, ac->req->op.mod.message->dn,
964                                    LDB_SCOPE_BASE,
965                                    "(objectClass=*)",
966                                    attrs, NULL, 
967                                    ac, get_search_callback,
968                                    ac->req);
969         LDB_REQ_SET_LOCATION(search_req);
970         if (ret != LDB_SUCCESS) {
971                 return ldb_module_done(ac->req, NULL, NULL, ret);
972         }
973
974         ac->step_fn = objectclass_do_mod;
975
976         ret = ldb_next_request(ac->module, search_req);
977         if (ret != LDB_SUCCESS) {
978                 return ldb_module_done(ac->req, NULL, NULL, ret);
979         }
980
981         return LDB_SUCCESS;
982 }
983
984 static int objectclass_do_mod(struct oc_context *ac)
985 {
986         struct ldb_context *ldb;
987         struct ldb_request *mod_req;
988         struct ldb_message_element *oc_el_entry, *oc_el_change;
989         struct ldb_val *vals;
990         struct ldb_message *msg;
991         TALLOC_CTX *mem_ctx;
992         struct class_list *sorted, *current;
993         const struct dsdb_class *objectclass;
994         unsigned int i, j, k;
995         bool found;
996         int ret;
997
998         ldb = ldb_module_get_ctx(ac->module);
999
1000         /* we should always have a valid entry when we enter here */
1001         if (ac->search_res == NULL) {
1002                 return ldb_operr(ldb);
1003         }
1004
1005         oc_el_entry = ldb_msg_find_element(ac->search_res->message,
1006                                            "objectClass");
1007         if (oc_el_entry == NULL) {
1008                 /* existing entry without a valid object class? */
1009                 return ldb_operr(ldb);
1010         }
1011
1012         /* use a new message structure */
1013         msg = ldb_msg_new(ac);
1014         if (msg == NULL) {
1015                 return ldb_module_oom(ac->module);
1016         }
1017
1018         msg->dn = ac->req->op.mod.message->dn;
1019
1020         mem_ctx = talloc_new(ac);
1021         if (mem_ctx == NULL) {
1022                 return ldb_module_oom(ac->module);
1023         }
1024
1025         /* We've to walk over all "objectClass" message elements */
1026         for (k = 0; k < ac->req->op.mod.message->num_elements; k++) {
1027                 if (ldb_attr_cmp(ac->req->op.mod.message->elements[k].name,
1028                                  "objectClass") != 0) {
1029                         continue;
1030                 }
1031
1032                 oc_el_change = &ac->req->op.mod.message->elements[k];
1033
1034                 switch (oc_el_change->flags & LDB_FLAG_MOD_MASK) {
1035                 case LDB_FLAG_MOD_ADD:
1036                         /* Merge the two message elements */
1037                         for (i = 0; i < oc_el_change->num_values; i++) {
1038                                 for (j = 0; j < oc_el_entry->num_values; j++) {
1039                                         if (ldb_attr_cmp((char *)oc_el_change->values[i].data,
1040                                                          (char *)oc_el_entry->values[j].data) == 0) {
1041                                                 ldb_asprintf_errstring(ldb,
1042                                                                        "objectclass: cannot re-add an existing objectclass: '%.*s'!",
1043                                                                        (int)oc_el_change->values[i].length,
1044                                                                        (const char *)oc_el_change->values[i].data);
1045                                                 talloc_free(mem_ctx);
1046                                                 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
1047                                         }
1048                                 }
1049                                 /* append the new object class value - code was
1050                                  * copied from "ldb_msg_add_value" */
1051                                 vals = talloc_realloc(oc_el_entry, oc_el_entry->values,
1052                                                       struct ldb_val,
1053                                                       oc_el_entry->num_values + 1);
1054                                 if (vals == NULL) {
1055                                         talloc_free(mem_ctx);
1056                                         return ldb_module_oom(ac->module);
1057                                 }
1058                                 oc_el_entry->values = vals;
1059                                 oc_el_entry->values[oc_el_entry->num_values] =
1060                                                         oc_el_change->values[i];
1061                                 ++(oc_el_entry->num_values);
1062                         }
1063
1064                         break;
1065
1066                 case LDB_FLAG_MOD_REPLACE:
1067                         /*
1068                          * In this case the new "oc_el_entry" is simply
1069                          * "oc_el_change"
1070                          */
1071                         oc_el_entry = oc_el_change;
1072
1073                         break;
1074
1075                 case LDB_FLAG_MOD_DELETE:
1076                         /* Merge the two message elements */
1077                         for (i = 0; i < oc_el_change->num_values; i++) {
1078                                 found = false;
1079                                 for (j = 0; j < oc_el_entry->num_values; j++) {
1080                                         if (ldb_attr_cmp((char *)oc_el_change->values[i].data,
1081                                                          (char *)oc_el_entry->values[j].data) == 0) {
1082                                                 found = true;
1083                                                 /* delete the object class value
1084                                                  * - code was copied from
1085                                                  * "ldb_msg_remove_element" */
1086                                                 if (j != oc_el_entry->num_values - 1) {
1087                                                         memmove(&oc_el_entry->values[j],
1088                                                                 &oc_el_entry->values[j+1],
1089                                                                 ((oc_el_entry->num_values-1) - j)*sizeof(struct ldb_val));
1090                                                 }
1091                                                 --(oc_el_entry->num_values);
1092                                                 break;
1093                                         }
1094                                 }
1095                                 if (!found) {
1096                                         /* we cannot delete a not existing
1097                                          * object class */
1098                                         ldb_asprintf_errstring(ldb,
1099                                                                "objectclass: cannot delete this objectclass: '%.*s'!",
1100                                                                (int)oc_el_change->values[i].length,
1101                                                                (const char *)oc_el_change->values[i].data);
1102                                         talloc_free(mem_ctx);
1103                                         return LDB_ERR_NO_SUCH_ATTRIBUTE;
1104                                 }
1105                         }
1106
1107                         break;
1108                 }
1109
1110                 /* Get the new top-most structural object class */
1111                 objectclass = get_last_structural_class(ac->schema, oc_el_entry,
1112                                                         ac->req);
1113                 if (objectclass == NULL) {
1114                         ldb_set_errstring(ldb,
1115                                           "objectclass: cannot delete all structural objectclasses!");
1116                         talloc_free(mem_ctx);
1117                         return LDB_ERR_OBJECT_CLASS_VIOLATION;
1118                 }
1119
1120                 ret = check_unrelated_objectclasses(ac->module, ac->schema,
1121                                                     objectclass,
1122                                                     oc_el_entry);
1123                 if (ret != LDB_SUCCESS) {
1124                         talloc_free(mem_ctx);
1125                         return ret;
1126                 }
1127
1128                 /* Now do the sorting */
1129                 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
1130                                        oc_el_entry, &sorted);
1131                 if (ret != LDB_SUCCESS) {
1132                         talloc_free(mem_ctx);
1133                         return ret;
1134                 }
1135
1136                 /* (Re)-add an empty "objectClass" attribute on the object
1137                  * classes change message "msg". */
1138                 ldb_msg_remove_attr(msg, "objectClass");
1139                 ret = ldb_msg_add_empty(msg, "objectClass",
1140                                         LDB_FLAG_MOD_REPLACE, &oc_el_entry);
1141                 if (ret != LDB_SUCCESS) {
1142                         talloc_free(mem_ctx);
1143                         return ret;
1144                 }
1145
1146                 /* Move from the linked list back into an ldb msg */
1147                 for (current = sorted; current; current = current->next) {
1148                         const char *objectclass_name = current->objectclass->lDAPDisplayName;
1149
1150                         ret = ldb_msg_add_string(msg, "objectClass",
1151                                                  objectclass_name);
1152                         if (ret != LDB_SUCCESS) {
1153                                 ldb_set_errstring(ldb,
1154                                                   "objectclass: could not re-add sorted objectclasses!");
1155                                 talloc_free(mem_ctx);
1156                                 return ret;
1157                         }
1158                 }
1159         }
1160
1161         talloc_free(mem_ctx);
1162
1163         /* Now we have the real and definitive change left to do */
1164
1165         ret = ldb_build_mod_req(&mod_req, ldb, ac,
1166                                 msg,
1167                                 ac->req->controls,
1168                                 ac, oc_op_callback,
1169                                 ac->req);
1170         LDB_REQ_SET_LOCATION(mod_req);
1171         if (ret != LDB_SUCCESS) {
1172                 return ret;
1173         }
1174
1175         return ldb_next_request(ac->module, mod_req);
1176 }
1177
1178 static int objectclass_do_rename(struct oc_context *ac);
1179
1180 static int objectclass_rename(struct ldb_module *module, struct ldb_request *req)
1181 {
1182         static const char * const attrs[] = { "objectClass", NULL };
1183         struct ldb_context *ldb;
1184         struct ldb_request *search_req;
1185         struct oc_context *ac;
1186         struct ldb_dn *parent_dn;
1187         int ret;
1188
1189         ldb = ldb_module_get_ctx(module);
1190
1191         ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_rename\n");
1192
1193         /* do not manipulate our control entries */
1194         if (ldb_dn_is_special(req->op.rename.olddn)) {
1195                 return ldb_next_request(module, req);
1196         }
1197
1198         ac = oc_init_context(module, req);
1199         if (ac == NULL) {
1200                 return ldb_operr(ldb);
1201         }
1202
1203         parent_dn = ldb_dn_get_parent(ac, req->op.rename.newdn);
1204         if (parent_dn == NULL) {
1205                 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, the parent DN does not exist!",
1206                                        ldb_dn_get_linearized(req->op.rename.olddn));
1207                 return LDB_ERR_NO_SUCH_OBJECT;
1208         }
1209
1210         /* this looks up the parent object for fetching some important
1211          * information (objectclasses, DN normalisation...) */
1212         ret = ldb_build_search_req(&search_req, ldb,
1213                                    ac, parent_dn, LDB_SCOPE_BASE,
1214                                    "(objectClass=*)",
1215                                    attrs, NULL,
1216                                    ac, get_search_callback,
1217                                    req);
1218         LDB_REQ_SET_LOCATION(search_req);
1219         if (ret != LDB_SUCCESS) {
1220                 return ret;
1221         }
1222
1223         /* we have to add the show recycled control, as otherwise DRS
1224            deletes will be refused as we will think the target parent
1225            does not exist */
1226         ret = ldb_request_add_control(search_req, LDB_CONTROL_SHOW_RECYCLED_OID,
1227                                       false, NULL);
1228
1229         if (ret != LDB_SUCCESS) {
1230                 return ret;
1231         }
1232
1233         ac->step_fn = objectclass_do_rename;
1234
1235         return ldb_next_request(ac->module, search_req);
1236 }
1237
1238 static int objectclass_do_rename2(struct oc_context *ac);
1239
1240 static int objectclass_do_rename(struct oc_context *ac)
1241 {
1242         static const char * const attrs[] = { "objectClass", NULL };
1243         struct ldb_context *ldb;
1244         struct ldb_request *search_req;
1245         int ret;
1246
1247         ldb = ldb_module_get_ctx(ac->module);
1248
1249         /* Check if we have a valid parent - this check is needed since
1250          * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1251         if (ac->search_res == NULL) {
1252                 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, parent does not exist!",
1253                                        ldb_dn_get_linearized(ac->req->op.rename.olddn));
1254                 return LDB_ERR_OTHER;
1255         }
1256
1257         /* now assign "search_res2" to the parent entry to have "search_res"
1258          * free for another lookup */
1259         ac->search_res2 = ac->search_res;
1260         ac->search_res = NULL;
1261
1262         /* this looks up the real existing object for fetching some important
1263          * information (objectclasses) */
1264         ret = ldb_build_search_req(&search_req, ldb,
1265                                    ac, ac->req->op.rename.olddn,
1266                                    LDB_SCOPE_BASE,
1267                                    "(objectClass=*)",
1268                                    attrs, NULL,
1269                                    ac, get_search_callback,
1270                                    ac->req);
1271         LDB_REQ_SET_LOCATION(search_req);
1272         if (ret != LDB_SUCCESS) {
1273                 return ret;
1274         }
1275
1276         ac->step_fn = objectclass_do_rename2;
1277
1278         return ldb_next_request(ac->module, search_req);
1279 }
1280
1281 static int objectclass_do_rename2(struct oc_context *ac)
1282 {
1283         struct ldb_context *ldb;
1284         struct ldb_request *rename_req;
1285         struct ldb_dn *fixed_dn;
1286         int ret;
1287
1288         ldb = ldb_module_get_ctx(ac->module);
1289
1290         /* Check if we have a valid entry - this check is needed since
1291          * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1292         if (ac->search_res == NULL) {
1293                 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, entry does not exist!",
1294                                        ldb_dn_get_linearized(ac->req->op.rename.olddn));
1295                 return LDB_ERR_NO_SUCH_OBJECT;
1296         }
1297
1298         if (ac->schema != NULL) {
1299                 struct ldb_message_element *oc_el_entry, *oc_el_parent;
1300                 const struct dsdb_class *objectclass;
1301                 const char *rdn_name;
1302                 bool allowed_class = false;
1303                 unsigned int i, j;
1304                 bool found;
1305
1306                 oc_el_entry = ldb_msg_find_element(ac->search_res->message,
1307                                                    "objectClass");
1308                 if (oc_el_entry == NULL) {
1309                         /* existing entry without a valid object class? */
1310                         return ldb_operr(ldb);
1311                 }
1312                 objectclass = get_last_structural_class(ac->schema, oc_el_entry, ac->req);
1313                 if (objectclass == NULL) {
1314                         /* existing entry without a valid object class? */
1315                         return ldb_operr(ldb);
1316                 }
1317
1318                 rdn_name = ldb_dn_get_rdn_name(ac->req->op.rename.newdn);
1319                 if (rdn_name == NULL) {
1320                         return ldb_operr(ldb);
1321                 }
1322                 found = false;
1323                 for (i = 0; (!found) && (i < oc_el_entry->num_values); i++) {
1324                         const struct dsdb_class *tmp_class =
1325                                 dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
1326                                                                       &oc_el_entry->values[i]);
1327
1328                         if (tmp_class == NULL) continue;
1329
1330                         if (ldb_attr_cmp(rdn_name, tmp_class->rDNAttID) == 0)
1331                                 found = true;
1332                 }
1333                 if (!found) {
1334                         ldb_asprintf_errstring(ldb,
1335                                                "objectclass: Invalid RDN '%s' for objectclass '%s'!",
1336                                                rdn_name, objectclass->lDAPDisplayName);
1337                         return LDB_ERR_UNWILLING_TO_PERFORM;
1338                 }
1339
1340                 oc_el_parent = ldb_msg_find_element(ac->search_res2->message,
1341                                                     "objectClass");
1342                 if (oc_el_parent == NULL) {
1343                         /* existing entry without a valid object class? */
1344                         return ldb_operr(ldb);
1345                 }
1346
1347                 for (i=0; allowed_class == false && i < oc_el_parent->num_values; i++) {
1348                         const struct dsdb_class *sclass;
1349
1350                         sclass = dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
1351                                                                        &oc_el_parent->values[i]);
1352                         if (!sclass) {
1353                                 /* We don't know this class?  what is going on? */
1354                                 continue;
1355                         }
1356                         for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
1357                                 if (ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
1358                                         allowed_class = true;
1359                                         break;
1360                                 }
1361                         }
1362                 }
1363
1364                 if (!allowed_class) {
1365                         ldb_asprintf_errstring(ldb,
1366                                                "objectclass: structural objectClass %s is not a valid child class for %s",
1367                                                objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res2->message->dn));
1368                         return LDB_ERR_NAMING_VIOLATION;
1369                 }
1370         }
1371
1372         /* Ensure we are not trying to rename it to be a child of itself */
1373         if ((ldb_dn_compare_base(ac->req->op.rename.olddn,
1374                                  ac->req->op.rename.newdn) == 0)  &&
1375             (ldb_dn_compare(ac->req->op.rename.olddn,
1376                             ac->req->op.rename.newdn) != 0)) {
1377                 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s to be a child of itself",
1378                                        ldb_dn_get_linearized(ac->req->op.rename.olddn));
1379                 return LDB_ERR_UNWILLING_TO_PERFORM;
1380         }
1381
1382         /* Fix up the DN to be in the standard form, taking
1383          * particular care to match the parent DN */
1384         ret = fix_dn(ldb, ac,
1385                      ac->req->op.rename.newdn,
1386                      ac->search_res2->message->dn,
1387                      &fixed_dn);
1388         if (ret != LDB_SUCCESS) {
1389                 ldb_asprintf_errstring(ldb, "objectclass: Could not munge DN %s into normal form",
1390                                        ldb_dn_get_linearized(ac->req->op.rename.newdn));
1391                 return ret;
1392
1393         }
1394
1395         ret = ldb_build_rename_req(&rename_req, ldb, ac,
1396                                    ac->req->op.rename.olddn, fixed_dn,
1397                                    ac->req->controls,
1398                                    ac, oc_op_callback,
1399                                    ac->req);
1400         LDB_REQ_SET_LOCATION(rename_req);
1401         if (ret != LDB_SUCCESS) {
1402                 return ret;
1403         }
1404
1405         /* perform the rename */
1406         return ldb_next_request(ac->module, rename_req);
1407 }
1408
1409 static int objectclass_do_delete(struct oc_context *ac);
1410
1411 static int objectclass_delete(struct ldb_module *module, struct ldb_request *req)
1412 {
1413         static const char * const attrs[] = { "nCName", "objectClass",
1414                                               "systemFlags",
1415                                               "isDeleted",
1416                                               "isCriticalSystemObject", NULL };
1417         struct ldb_context *ldb;
1418         struct ldb_request *search_req;
1419         struct oc_context *ac;
1420         int ret;
1421
1422         ldb = ldb_module_get_ctx(module);
1423
1424         ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_delete\n");
1425
1426         /* do not manipulate our control entries */
1427         if (ldb_dn_is_special(req->op.del.dn)) {
1428                 return ldb_next_request(module, req);
1429         }
1430
1431         /* Bypass the constraint checks when we do have the "RELAX" control
1432          * set. */
1433         if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID) != NULL) {
1434                 return ldb_next_request(module, req);
1435         }
1436
1437         ac = oc_init_context(module, req);
1438         if (ac == NULL) {
1439                 return ldb_operr(ldb);
1440         }
1441
1442         /* this looks up the entry object for fetching some important
1443          * information (object classes, system flags...) */
1444         ret = ldb_build_search_req(&search_req, ldb,
1445                                    ac, req->op.del.dn, LDB_SCOPE_BASE,
1446                                    "(objectClass=*)",
1447                                    attrs, req->controls,
1448                                    ac, get_search_callback,
1449                                    req);
1450         LDB_REQ_SET_LOCATION(search_req);
1451         if (ret != LDB_SUCCESS) {
1452                 return ret;
1453         }
1454
1455         ac->step_fn = objectclass_do_delete;
1456
1457         return ldb_next_request(ac->module, search_req);
1458 }
1459
1460 static int objectclass_do_delete(struct oc_context *ac)
1461 {
1462         struct ldb_context *ldb;
1463         struct ldb_dn *dn;
1464         int32_t systemFlags;
1465         bool isCriticalSystemObject;
1466         int ret;
1467
1468         ldb = ldb_module_get_ctx(ac->module);
1469
1470         /* Check if we have a valid entry - this check is needed since
1471          * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1472         if (ac->search_res == NULL) {
1473                 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, entry does not exist!",
1474                                        ldb_dn_get_linearized(ac->req->op.del.dn));
1475                 return LDB_ERR_NO_SUCH_OBJECT;
1476         }
1477
1478         /* DC's ntDSDSA object */
1479         if (ldb_dn_compare(ac->req->op.del.dn, samdb_ntds_settings_dn(ldb)) == 0) {
1480                 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's the DC's ntDSDSA object!",
1481                                        ldb_dn_get_linearized(ac->req->op.del.dn));
1482                 return LDB_ERR_UNWILLING_TO_PERFORM;
1483         }
1484
1485         /* DC's rIDSet object */
1486         /* Perform this check only when it does exist - this is needed in order
1487          * to don't let existing provisions break. */
1488         ret = samdb_rid_set_dn(ldb, ac, &dn);
1489         if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
1490                 return ret;
1491         }
1492         if (ret == LDB_SUCCESS) {
1493                 if (ldb_dn_compare(ac->req->op.del.dn, dn) == 0) {
1494                         talloc_free(dn);
1495                         ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's the DC's rIDSet object!",
1496                                                ldb_dn_get_linearized(ac->req->op.del.dn));
1497                         return LDB_ERR_UNWILLING_TO_PERFORM;
1498                 }
1499                 talloc_free(dn);
1500         }
1501
1502         /* Only trusted request from system account are allowed to delete
1503          * deleted objects.
1504          */
1505         if (ldb_msg_check_string_attribute(ac->search_res->message, "isDeleted", "TRUE") &&
1506                         (ldb_req_is_untrusted(ac->req) ||
1507                                 !dsdb_module_am_system(ac->module))) {
1508                 ldb_asprintf_errstring(ldb, "Delete of '%s' failed",
1509                                                 ldb_dn_get_linearized(ac->req->op.del.dn));
1510                 return LDB_ERR_UNWILLING_TO_PERFORM;
1511         }
1512
1513         /* crossRef objects regarding config, schema and default domain NCs */
1514         if (samdb_find_attribute(ldb, ac->search_res->message, "objectClass",
1515                                  "crossRef") != NULL) {
1516                 dn = ldb_msg_find_attr_as_dn(ldb, ac, ac->search_res->message,
1517                                              "nCName");
1518                 if ((ldb_dn_compare(dn, ldb_get_default_basedn(ldb)) == 0) ||
1519                     (ldb_dn_compare(dn, ldb_get_config_basedn(ldb)) == 0)) {
1520                         talloc_free(dn);
1521
1522                         ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's a crossRef object to the main or configuration partition!",
1523                                                ldb_dn_get_linearized(ac->req->op.del.dn));
1524                         return LDB_ERR_NOT_ALLOWED_ON_NON_LEAF;
1525                 }
1526                 if (ldb_dn_compare(dn, ldb_get_schema_basedn(ldb)) == 0) {
1527                         talloc_free(dn);
1528
1529                         ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's a crossRef object to the schema partition!",
1530                                                ldb_dn_get_linearized(ac->req->op.del.dn));
1531                         return LDB_ERR_UNWILLING_TO_PERFORM;
1532                 }
1533                 talloc_free(dn);
1534         }
1535
1536         /* systemFlags */
1537
1538         systemFlags = ldb_msg_find_attr_as_int(ac->search_res->message,
1539                                                "systemFlags", 0);
1540         if ((systemFlags & SYSTEM_FLAG_DISALLOW_DELETE) != 0) {
1541                 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it isn't permitted!",
1542                                        ldb_dn_get_linearized(ac->req->op.del.dn));
1543                 return LDB_ERR_UNWILLING_TO_PERFORM;
1544         }
1545
1546         /* isCriticalSystemObject - but this only applies on tree delete
1547          * operations - MS-ADTS 3.1.1.5.5.7.2 */
1548         if (ldb_request_get_control(ac->req, LDB_CONTROL_TREE_DELETE_OID) != NULL) {
1549                 isCriticalSystemObject = ldb_msg_find_attr_as_bool(ac->search_res->message,
1550                                                                    "isCriticalSystemObject", false);
1551                 if (isCriticalSystemObject) {
1552                         /*
1553                          * Following the explaination from Microsoft
1554                          * https://lists.samba.org/archive/cifs-protocol/2011-August/002046.html
1555                          * "I finished the investigation on this behavior.
1556                          * As per MS-ADTS 3.1.5.5.7.2 , when a tree deletion is performed ,
1557                          * every object in the tree will be checked to see if it has isCriticalSystemObject
1558                          * set to TRUE, including the root node on which the delete operation is performed
1559                          * But there is an exception  if the root object is a SAM specific objects(3.1.1.5.2.3 MS-ADTS)
1560                          * Its deletion is done through SAM manger and isCriticalSystemObject attribute is not checked
1561                          * The root node of the tree delete in your case is CN=ARES,OU=Domain Controllers,DC=w2k8r2,DC=home,DC=matws,DC=net
1562                          * which is a SAM object  with  user class.  Therefore the tree deletion is performed without any error
1563                          */
1564
1565                         if (samdb_find_attribute(ldb, ac->search_res->message, "objectClass", "group") == NULL &&
1566                             samdb_find_attribute(ldb, ac->search_res->message, "objectClass", "samDomain") == NULL &&
1567                             samdb_find_attribute(ldb, ac->search_res->message, "objectClass", "samServer") == NULL &&
1568                             samdb_find_attribute(ldb, ac->search_res->message, "objectClass", "user") == NULL) {
1569                                         ldb_asprintf_errstring(ldb,
1570                                                "objectclass: Cannot tree-delete %s, it's a critical system object!",
1571                                                ldb_dn_get_linearized(ac->req->op.del.dn));
1572                         return LDB_ERR_UNWILLING_TO_PERFORM;
1573                         }
1574                 }
1575         }
1576
1577         return ldb_next_request(ac->module, ac->req);
1578 }
1579
1580 static int objectclass_init(struct ldb_module *module)
1581 {
1582         struct ldb_context *ldb = ldb_module_get_ctx(module);
1583         int ret;
1584
1585         /* Init everything else */
1586         ret = ldb_next_init(module);
1587         if (ret != LDB_SUCCESS) {
1588                 return ret;
1589         }
1590         
1591         /* Look for the opaque to indicate we might have to cut down the DN of defaultObjectCategory */
1592         ldb_module_set_private(module, ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME));
1593
1594         ret = ldb_mod_register_control(module, LDB_CONTROL_RODC_DCPROMO_OID);
1595         if (ret != LDB_SUCCESS) {
1596                 ldb_debug(ldb, LDB_DEBUG_ERROR,
1597                           "objectclass_init: Unable to register control DCPROMO with rootdse\n");
1598                 return ldb_operr(ldb);
1599         }
1600
1601         return ret;
1602 }
1603
1604 static const struct ldb_module_ops ldb_objectclass_module_ops = {
1605         .name           = "objectclass",
1606         .add            = objectclass_add,
1607         .modify         = objectclass_modify,
1608         .rename         = objectclass_rename,
1609         .del            = objectclass_delete,
1610         .init_context   = objectclass_init
1611 };
1612
1613 int ldb_objectclass_module_init(const char *version)
1614 {
1615         LDB_MODULE_CHECK_VERSION(version);
1616         return ldb_register_module(&ldb_objectclass_module_ops);
1617 }