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