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