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