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