s4:dsdb - substitute the "show_deleted" with the "show_recycled" control
[abartlet/samba.git/.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 recycled 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_RECYCLED_OID,
1161                                       false, NULL);
1162
1163         if (ret != LDB_SUCCESS) {
1164                 return ret;
1165         }
1166
1167         ac->step_fn = objectclass_do_rename;
1168
1169         return ldb_next_request(ac->module, search_req);
1170 }
1171
1172 static int objectclass_do_rename2(struct oc_context *ac);
1173
1174 static int objectclass_do_rename(struct oc_context *ac)
1175 {
1176         static const char * const attrs[] = { "objectClass", NULL };
1177         struct ldb_context *ldb;
1178         struct ldb_request *search_req;
1179         int ret;
1180
1181         ldb = ldb_module_get_ctx(ac->module);
1182
1183         /* Check if we have a valid parent - this check is needed since
1184          * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1185         if (ac->search_res == NULL) {
1186                 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, parent does not exist!",
1187                                        ldb_dn_get_linearized(ac->req->op.rename.olddn));
1188                 return LDB_ERR_OTHER;
1189         }
1190
1191         /* now assign "search_res2" to the parent entry to have "search_res"
1192          * free for another lookup */
1193         ac->search_res2 = ac->search_res;
1194         ac->search_res = NULL;
1195
1196         /* this looks up the real existing object for fetching some important
1197          * informations (objectclasses) */
1198         ret = ldb_build_search_req(&search_req, ldb,
1199                                    ac, ac->req->op.rename.olddn,
1200                                    LDB_SCOPE_BASE,
1201                                    "(objectClass=*)",
1202                                    attrs, NULL,
1203                                    ac, get_search_callback,
1204                                    ac->req);
1205         LDB_REQ_SET_LOCATION(search_req);
1206         if (ret != LDB_SUCCESS) {
1207                 return ret;
1208         }
1209
1210         ac->step_fn = objectclass_do_rename2;
1211
1212         return ldb_next_request(ac->module, search_req);
1213 }
1214
1215 static int objectclass_do_rename2(struct oc_context *ac)
1216 {
1217         struct ldb_context *ldb;
1218         struct ldb_request *rename_req;
1219         struct ldb_dn *fixed_dn;
1220         int ret;
1221
1222         ldb = ldb_module_get_ctx(ac->module);
1223
1224         /* Check if we have a valid entry - this check is needed since
1225          * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1226         if (ac->search_res == NULL) {
1227                 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, entry does not exist!",
1228                                        ldb_dn_get_linearized(ac->req->op.rename.olddn));
1229                 return LDB_ERR_NO_SUCH_OBJECT;
1230         }
1231
1232         if (ac->schema != NULL) {
1233                 struct ldb_message_element *oc_el_entry, *oc_el_parent;
1234                 const struct dsdb_class *objectclass;
1235                 const char *rdn_name;
1236                 bool allowed_class = false;
1237                 unsigned int i, j;
1238
1239                 oc_el_entry = ldb_msg_find_element(ac->search_res->message,
1240                                                    "objectClass");
1241                 if (oc_el_entry == NULL) {
1242                         /* existing entry without a valid object class? */
1243                         return ldb_operr(ldb);
1244                 }
1245                 objectclass = get_last_structural_class(ac->schema, oc_el_entry);
1246                 if (objectclass == NULL) {
1247                         /* existing entry without a valid object class? */
1248                         return ldb_operr(ldb);
1249                 }
1250
1251                 rdn_name = ldb_dn_get_rdn_name(ac->req->op.rename.newdn);
1252                 if ((objectclass->rDNAttID != NULL) &&
1253                     (ldb_attr_cmp(rdn_name, objectclass->rDNAttID) != 0)) {
1254                         ldb_asprintf_errstring(ldb,
1255                                                "objectclass: RDN %s is not correct for most specific structural objectclass %s, should be %s",
1256                                                rdn_name,
1257                                                objectclass->lDAPDisplayName,
1258                                                objectclass->rDNAttID);
1259                         return LDB_ERR_UNWILLING_TO_PERFORM;
1260                 }
1261
1262                 oc_el_parent = ldb_msg_find_element(ac->search_res2->message,
1263                                                     "objectClass");
1264                 if (oc_el_parent == NULL) {
1265                         /* existing entry without a valid object class? */
1266                         return ldb_operr(ldb);
1267                 }
1268
1269                 for (i=0; allowed_class == false && i < oc_el_parent->num_values; i++) {
1270                         const struct dsdb_class *sclass;
1271
1272                         sclass = dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
1273                                                                        &oc_el_parent->values[i]);
1274                         if (!sclass) {
1275                                 /* We don't know this class?  what is going on? */
1276                                 continue;
1277                         }
1278                         for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
1279                                 if (ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
1280                                         allowed_class = true;
1281                                         break;
1282                                 }
1283                         }
1284                 }
1285
1286                 if (!allowed_class) {
1287                         ldb_asprintf_errstring(ldb,
1288                                                "objectclass: structural objectClass %s is not a valid child class for %s",
1289                                                objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res2->message->dn));
1290                         return LDB_ERR_NAMING_VIOLATION;
1291                 }
1292         }
1293
1294         /* Ensure we are not trying to rename it to be a child of itself */
1295         if ((ldb_dn_compare_base(ac->req->op.rename.olddn,
1296                                  ac->req->op.rename.newdn) == 0)  &&
1297             (ldb_dn_compare(ac->req->op.rename.olddn,
1298                             ac->req->op.rename.newdn) != 0)) {
1299                 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s to be a child of itself",
1300                                        ldb_dn_get_linearized(ac->req->op.rename.olddn));
1301                 return LDB_ERR_UNWILLING_TO_PERFORM;
1302         }
1303
1304         /* Fix up the DN to be in the standard form, taking
1305          * particular care to match the parent DN */
1306         ret = fix_dn(ldb, ac,
1307                      ac->req->op.rename.newdn,
1308                      ac->search_res2->message->dn,
1309                      &fixed_dn);
1310         if (ret != LDB_SUCCESS) {
1311                 ldb_asprintf_errstring(ldb, "objectclass: Could not munge DN %s into normal form",
1312                                        ldb_dn_get_linearized(ac->req->op.rename.newdn));
1313                 return ret;
1314
1315         }
1316
1317         ret = ldb_build_rename_req(&rename_req, ldb, ac,
1318                                    ac->req->op.rename.olddn, fixed_dn,
1319                                    ac->req->controls,
1320                                    ac, oc_op_callback,
1321                                    ac->req);
1322         LDB_REQ_SET_LOCATION(rename_req);
1323         if (ret != LDB_SUCCESS) {
1324                 return ret;
1325         }
1326
1327         /* perform the rename */
1328         return ldb_next_request(ac->module, rename_req);
1329 }
1330
1331 static int objectclass_do_delete(struct oc_context *ac);
1332
1333 static int objectclass_delete(struct ldb_module *module, struct ldb_request *req)
1334 {
1335         static const char * const attrs[] = { "nCName", "objectClass",
1336                                               "systemFlags", NULL };
1337         struct ldb_context *ldb;
1338         struct ldb_request *search_req;
1339         struct oc_context *ac;
1340         int ret;
1341
1342         ldb = ldb_module_get_ctx(module);
1343
1344         ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_delete\n");
1345
1346         /* do not manipulate our control entries */
1347         if (ldb_dn_is_special(req->op.del.dn)) {
1348                 return ldb_next_request(module, req);
1349         }
1350
1351         /* Bypass the constraint checks when we do have the "RELAX" control
1352          * set. */
1353         if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID) != NULL) {
1354                 return ldb_next_request(module, req);
1355         }
1356
1357         ac = oc_init_context(module, req);
1358         if (ac == NULL) {
1359                 return ldb_operr(ldb);
1360         }
1361
1362         /* this looks up the entry object for fetching some important
1363          * informations (object classes, system flags...) */
1364         ret = ldb_build_search_req(&search_req, ldb,
1365                                    ac, req->op.del.dn, LDB_SCOPE_BASE,
1366                                    "(objectClass=*)",
1367                                    attrs, NULL,
1368                                    ac, get_search_callback,
1369                                    req);
1370         LDB_REQ_SET_LOCATION(search_req);
1371         if (ret != LDB_SUCCESS) {
1372                 return ret;
1373         }
1374
1375         ac->step_fn = objectclass_do_delete;
1376
1377         return ldb_next_request(ac->module, search_req);
1378 }
1379
1380 static int objectclass_do_delete(struct oc_context *ac)
1381 {
1382         struct ldb_context *ldb;
1383         struct ldb_dn *dn;
1384         int32_t systemFlags;
1385         int ret;
1386
1387         ldb = ldb_module_get_ctx(ac->module);
1388
1389         /* Check if we have a valid entry - this check is needed since
1390          * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1391         if (ac->search_res == NULL) {
1392                 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, entry does not exist!",
1393                                        ldb_dn_get_linearized(ac->req->op.del.dn));
1394                 return LDB_ERR_NO_SUCH_OBJECT;
1395         }
1396
1397         /* DC's ntDSDSA object */
1398         if (ldb_dn_compare(ac->req->op.del.dn, samdb_ntds_settings_dn(ldb)) == 0) {
1399                 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's the DC's ntDSDSA object!",
1400                                        ldb_dn_get_linearized(ac->req->op.del.dn));
1401                 return LDB_ERR_UNWILLING_TO_PERFORM;
1402         }
1403
1404         /* DC's rIDSet object */
1405         /* Perform this check only when it does exist - this is needed in order
1406          * to don't let existing provisions break. */
1407         ret = samdb_rid_set_dn(ldb, ac, &dn);
1408         if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
1409                 return ret;
1410         }
1411         if (ret == LDB_SUCCESS) {
1412                 if (ldb_dn_compare(ac->req->op.del.dn, dn) == 0) {
1413                         talloc_free(dn);
1414                         ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's the DC's rIDSet object!",
1415                                                ldb_dn_get_linearized(ac->req->op.del.dn));
1416                         return LDB_ERR_UNWILLING_TO_PERFORM;
1417                 }
1418                 talloc_free(dn);
1419         }
1420
1421         /* crossRef objects regarding config, schema and default domain NCs */
1422         if (samdb_find_attribute(ldb, ac->search_res->message, "objectClass",
1423                                  "crossRef") != NULL) {
1424                 dn = ldb_msg_find_attr_as_dn(ldb, ac, ac->search_res->message,
1425                                              "nCName");
1426                 if ((ldb_dn_compare(dn, ldb_get_default_basedn(ldb)) == 0) ||
1427                     (ldb_dn_compare(dn, ldb_get_config_basedn(ldb)) == 0)) {
1428                         talloc_free(dn);
1429
1430                         ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's a crossRef object to the main or configuration partition!",
1431                                                ldb_dn_get_linearized(ac->req->op.del.dn));
1432                         return LDB_ERR_NOT_ALLOWED_ON_NON_LEAF;
1433                 }
1434                 if (ldb_dn_compare(dn, ldb_get_schema_basedn(ldb)) == 0) {
1435                         talloc_free(dn);
1436
1437                         ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's a crossRef object to the schema partition!",
1438                                                ldb_dn_get_linearized(ac->req->op.del.dn));
1439                         return LDB_ERR_UNWILLING_TO_PERFORM;
1440                 }
1441                 talloc_free(dn);
1442         }
1443
1444         /* systemFlags */
1445
1446         systemFlags = ldb_msg_find_attr_as_int(ac->search_res->message,
1447                                                "systemFlags", 0);
1448         if ((systemFlags & SYSTEM_FLAG_DISALLOW_DELETE) != 0) {
1449                 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it isn't permitted!",
1450                                        ldb_dn_get_linearized(ac->req->op.del.dn));
1451                 return LDB_ERR_UNWILLING_TO_PERFORM;
1452         }
1453
1454         return ldb_next_request(ac->module, ac->req);
1455 }
1456
1457 static int objectclass_init(struct ldb_module *module)
1458 {
1459         struct ldb_context *ldb = ldb_module_get_ctx(module);
1460         int ret;
1461
1462         /* Init everything else */
1463         ret = ldb_next_init(module);
1464         if (ret != LDB_SUCCESS) {
1465                 return ret;
1466         }
1467         
1468         /* Look for the opaque to indicate we might have to cut down the DN of defaultObjectCategory */
1469         ldb_module_set_private(module, ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME));
1470
1471         return ret;
1472 }
1473
1474 _PUBLIC_ const struct ldb_module_ops ldb_objectclass_module_ops = {
1475         .name           = "objectclass",
1476         .add            = objectclass_add,
1477         .modify         = objectclass_modify,
1478         .rename         = objectclass_rename,
1479         .del            = objectclass_delete,
1480         .init_context   = objectclass_init
1481 };