48813e5ac0d04cb3b7305ce6f07ef02fd1f4798f
[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 "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                         /* LSA-specific objectclasses per default not
569                          * allowed to be created over LDAP, so we need
570                          * to tell if this connection is LDAP (ie
571                          * marked as untrusted), and if the client is
572                          * adding these particular objectClass values
573                          * we must reject */
574
575                         /* Hongwei Sun from Microsoft explians:
576                            The constraint in 3.1.1.5.2.2 MS-ADTS means that the TDO
577                            cannot be added through LDAP interface, instead it can only be
578                            created through LSA Policy API.  This is also explained in
579                            7.1.6.9.7 MS-ADTS as follows:
580
581                            "Despite being replicated normally between peer DCs in a domain,
582                            the process of creating or manipulating TDOs is specifically
583                            restricted to the LSA Policy APIs, as detailed in [MS-LSAD] section
584                            3.1.1.5. Unlike other objects in the DS, TDOs may not be created or
585                            manipulated by client machines over the LDAPv3 transport."
586                         */
587
588                         if (ldb_req_is_untrusted(ac->req) &&
589                             ((strcasecmp(objectclass_name, "secret") == 0) ||
590                              (strcasecmp(objectclass_name, "trustedDomain") == 0))) {
591                                 ldb_asprintf_errstring(ldb,
592                                                        "objectclass: object class '%s' is LSA-specific, rejecting creation of '%s' over LDAP!",
593                                                        objectclass_name,
594                                                        ldb_dn_get_linearized(msg->dn));
595                                 talloc_free(mem_ctx);
596                                 return LDB_ERR_UNWILLING_TO_PERFORM;
597                         }
598
599                         ret = ldb_msg_add_string(msg, "objectClass", objectclass_name);
600                         if (ret != LDB_SUCCESS) {
601                                 ldb_set_errstring(ldb,
602                                                   "objectclass: could not re-add sorted "
603                                                   "objectclass to modify msg");
604                                 talloc_free(mem_ctx);
605                                 return ret;
606                         }
607                 }
608
609                 talloc_free(mem_ctx);
610
611                 /* Retrive the message again so get_last_structural_class works */
612                 objectclass_element = ldb_msg_find_element(msg, "objectClass");
613
614                 /* Make sure its valid to add an object of this type */
615                 objectclass = get_last_structural_class(ac->schema,
616                                                         objectclass_element);
617                 if(objectclass == NULL) {
618                         ldb_asprintf_errstring(ldb,
619                                                "Failed to find a structural class for %s",
620                                                ldb_dn_get_linearized(msg->dn));
621                         return LDB_ERR_UNWILLING_TO_PERFORM;
622                 }
623
624                 rdn_name = ldb_dn_get_rdn_name(msg->dn);
625                 if (rdn_name == NULL) {
626                         return ldb_operr(ldb);
627                 }
628                 found = false;
629                 for (i = 0; (!found) && (i < objectclass_element->num_values);
630                      i++) {
631                         const struct dsdb_class *tmp_class =
632                                 dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
633                                                                       &objectclass_element->values[i]);
634
635                         if (tmp_class == NULL) continue;
636
637                         if (ldb_attr_cmp(rdn_name, tmp_class->rDNAttID) == 0)
638                                 found = true;
639                 }
640                 if (!found) {
641                         ldb_asprintf_errstring(ldb,
642                                                "objectclass: Invalid RDN '%s' for objectclass '%s'!",
643                                                rdn_name, objectclass->lDAPDisplayName);
644                         return LDB_ERR_NAMING_VIOLATION;
645                 }
646
647                 if (objectclass->systemOnly &&
648                     !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) &&
649                     !check_rodc_ntdsdsa_add(ac, objectclass)) {
650                         ldb_asprintf_errstring(ldb,
651                                                "objectclass: object class '%s' is system-only, rejecting creation of '%s'!",
652                                                objectclass->lDAPDisplayName,
653                                                ldb_dn_get_linearized(msg->dn));
654                         return LDB_ERR_UNWILLING_TO_PERFORM;
655                 }
656
657                 if (ac->search_res && ac->search_res->message) {
658                         struct ldb_message_element *oc_el
659                                 = ldb_msg_find_element(ac->search_res->message, "objectClass");
660
661                         bool allowed_class = false;
662                         for (i=0; allowed_class == false && oc_el && i < oc_el->num_values; i++) {
663                                 const struct dsdb_class *sclass;
664
665                                 sclass = dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
666                                                                                &oc_el->values[i]);
667                                 if (!sclass) {
668                                         /* We don't know this class?  what is going on? */
669                                         continue;
670                                 }
671                                 for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
672                                         if (ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
673                                                 allowed_class = true;
674                                                 break;
675                                         }
676                                 }
677                         }
678
679                         if (!allowed_class) {
680                                 ldb_asprintf_errstring(ldb, "structural objectClass %s is not a valid child class for %s",
681                                                 objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res->message->dn));
682                                 return LDB_ERR_NAMING_VIOLATION;
683                         }
684                 }
685
686                 objectcategory = ldb_msg_find_attr_as_dn(ldb, ac, msg,
687                                                          "objectCategory");
688                 if (objectcategory == NULL) {
689                         struct dsdb_extended_dn_store_format *dn_format =
690                                         talloc_get_type(ldb_module_get_private(ac->module),
691                                                         struct dsdb_extended_dn_store_format);
692                         if (dn_format && dn_format->store_extended_dn_in_ldb == false) {
693                                 /* Strip off extended components */
694                                 struct ldb_dn *dn = ldb_dn_new(ac, ldb,
695                                                                objectclass->defaultObjectCategory);
696                                 value = ldb_dn_alloc_linearized(msg, dn);
697                                 talloc_free(dn);
698                         } else {
699                                 value = talloc_strdup(msg,
700                                                       objectclass->defaultObjectCategory);
701                         }
702                         if (value == NULL) {
703                                 return ldb_module_oom(ac->module);
704                         }
705
706                         ret = ldb_msg_add_string(msg, "objectCategory", value);
707                         if (ret != LDB_SUCCESS) {
708                                 return ret;
709                         }
710                 } else {
711                         const struct dsdb_class *ocClass =
712                                         dsdb_class_by_cn_ldb_val(ac->schema,
713                                                                  ldb_dn_get_rdn_val(objectcategory));
714                         if (ocClass != NULL) {
715                                 struct ldb_dn *dn = ldb_dn_new(ac, ldb,
716                                                                ocClass->defaultObjectCategory);
717                                 if (ldb_dn_compare(objectcategory, dn) != 0) {
718                                         ocClass = NULL;
719                                 }
720                         }
721                         talloc_free(objectcategory);
722                         if (ocClass == NULL) {
723                                 ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, 'objectCategory' attribute invalid!",
724                                                        ldb_dn_get_linearized(msg->dn));
725                                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
726                         }
727                 }
728
729                 if (!ldb_msg_find_element(msg, "showInAdvancedViewOnly") && (objectclass->defaultHidingValue == true)) {
730                         ldb_msg_add_string(msg, "showInAdvancedViewOnly",
731                                                 "TRUE");
732                 }
733
734                 /* There are very special rules for systemFlags, see MS-ADTS
735                  * MS-ADTS 3.1.1.5.2.4 */
736
737                 el = ldb_msg_find_element(msg, "systemFlags");
738                 if ((el != NULL) && (el->num_values > 1)) {
739                         ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, 'systemFlags' attribute multivalued!",
740                                                ldb_dn_get_linearized(msg->dn));
741                         return LDB_ERR_CONSTRAINT_VIOLATION;
742                 }
743
744                 systemFlags = ldb_msg_find_attr_as_int(msg, "systemFlags", 0);
745
746                 ldb_msg_remove_attr(msg, "systemFlags");
747
748                 /* Only the following flags may be set by a client */
749                 if (ldb_request_get_control(ac->req,
750                                             LDB_CONTROL_RELAX_OID) == NULL) {
751                         systemFlags &= ( SYSTEM_FLAG_CONFIG_ALLOW_RENAME
752                                        | SYSTEM_FLAG_CONFIG_ALLOW_MOVE
753                                        | SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE
754                                        | SYSTEM_FLAG_ATTR_IS_RDN );
755                 }
756
757                 /* But the last one ("ATTR_IS_RDN") is only allowed on
758                  * "attributeSchema" objects. So truncate if it does not fit. */
759                 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "attributeSchema") != 0) {
760                         systemFlags &= ~SYSTEM_FLAG_ATTR_IS_RDN;
761                 }
762
763                 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "server") == 0) {
764                         systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE | SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE);
765                 } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, "site") == 0
766                                 || ldb_attr_cmp(objectclass->lDAPDisplayName, "serversContainer") == 0
767                                 || ldb_attr_cmp(objectclass->lDAPDisplayName, "nTDSDSA") == 0) {
768                         systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
769
770                 } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLink") == 0
771                                 || ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLinkBridge") == 0
772                                 || ldb_attr_cmp(objectclass->lDAPDisplayName, "nTDSConnection") == 0) {
773                         systemFlags |= (int32_t)(SYSTEM_FLAG_CONFIG_ALLOW_RENAME);
774                 }
775
776                 /* TODO: If parent object is site or subnet, also add (SYSTEM_FLAG_CONFIG_ALLOW_RENAME) */
777
778                 if (el || systemFlags != 0) {
779                         ret = samdb_msg_add_int(ldb, msg, msg, "systemFlags",
780                                                 systemFlags);
781                         if (ret != LDB_SUCCESS) {
782                                 return ret;
783                         }
784                 }
785
786                 /* make sure that "isCriticalSystemObject" is not specified! */
787                 el = ldb_msg_find_element(msg, "isCriticalSystemObject");
788                 if ((el != NULL) &&
789                     !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
790                         ldb_set_errstring(ldb,
791                                           "objectclass: 'isCriticalSystemObject' must not be specified!");
792                         return LDB_ERR_UNWILLING_TO_PERFORM;
793                 }
794         }
795
796         ret = ldb_msg_sanity_check(ldb, msg);
797         if (ret != LDB_SUCCESS) {
798                 return ret;
799         }
800
801         ret = ldb_build_add_req(&add_req, ldb, ac,
802                                 msg,
803                                 ac->req->controls,
804                                 ac, oc_op_callback,
805                                 ac->req);
806         LDB_REQ_SET_LOCATION(add_req);
807         if (ret != LDB_SUCCESS) {
808                 return ret;
809         }
810
811         /* perform the add */
812         return ldb_next_request(ac->module, add_req);
813 }
814
815 static int oc_modify_callback(struct ldb_request *req,
816                                 struct ldb_reply *ares);
817 static int objectclass_do_mod(struct oc_context *ac);
818
819 static int objectclass_modify(struct ldb_module *module, struct ldb_request *req)
820 {
821         struct ldb_context *ldb = ldb_module_get_ctx(module);
822         struct ldb_message_element *objectclass_element;
823         struct ldb_message *msg;
824         struct ldb_request *down_req;
825         struct oc_context *ac;
826         bool oc_changes = false;
827         int ret;
828
829         ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_modify\n");
830
831         /* do not manipulate our control entries */
832         if (ldb_dn_is_special(req->op.mod.message->dn)) {
833                 return ldb_next_request(module, req);
834         }
835
836         /* As with the "real" AD we don't accept empty messages */
837         if (req->op.mod.message->num_elements == 0) {
838                 ldb_set_errstring(ldb, "objectclass: modify message must have "
839                                        "elements/attributes!");
840                 return LDB_ERR_UNWILLING_TO_PERFORM;
841         }
842
843         ac = oc_init_context(module, req);
844         if (ac == NULL) {
845                 return ldb_operr(ldb);
846         }
847
848         /* Without schema, there isn't much to do here */
849         if (ac->schema == NULL) {
850                 talloc_free(ac);
851                 return ldb_next_request(module, req);
852         }
853
854         msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
855         if (msg == NULL) {
856                 return ldb_module_oom(ac->module);
857         }
858
859         /* For now change everything except the objectclasses */
860
861         objectclass_element = ldb_msg_find_element(msg, "objectClass");
862         if (objectclass_element != NULL) {
863                 ldb_msg_remove_attr(msg, "objectClass");
864                 oc_changes = true;
865         }
866
867         /* MS-ADTS 3.1.1.5.3.5 - on a forest level < 2003 we do allow updates
868          * only on application NCs - not on the standard DCs */
869         if (oc_changes &&
870             (dsdb_forest_functional_level(ldb) < DS_DOMAIN_FUNCTION_2003)) {
871                 struct ldb_dn *nc_root;
872
873                 ret = dsdb_find_nc_root(ldb, ac, req->op.mod.message->dn,
874                                         &nc_root);
875                 if (ret != LDB_SUCCESS) {
876                         return ret;
877                 }
878
879                 if ((ldb_dn_compare(nc_root, ldb_get_default_basedn(ldb)) == 0) ||
880                     (ldb_dn_compare(nc_root, ldb_get_config_basedn(ldb)) == 0) ||
881                     (ldb_dn_compare(nc_root, ldb_get_schema_basedn(ldb)) == 0)) {
882                         ldb_set_errstring(ldb,
883                                           "objectclass: object class changes on objects under the standard name contexts not allowed!");
884                         return LDB_ERR_UNWILLING_TO_PERFORM;
885                 }
886
887                 talloc_free(nc_root);
888         }
889
890         ret = ldb_build_mod_req(&down_req, ldb, ac,
891                                 msg,
892                                 req->controls, ac,
893                                 oc_changes ? oc_modify_callback : oc_op_callback,
894                                 req);
895         LDB_REQ_SET_LOCATION(down_req);
896         if (ret != LDB_SUCCESS) {
897                 return ret;
898         }
899
900         return ldb_next_request(module, down_req);
901 }
902
903 static int oc_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
904 {
905         static const char * const attrs[] = { "objectClass", NULL };
906         struct ldb_context *ldb;
907         struct ldb_request *search_req;
908         struct oc_context *ac;
909         int ret;
910
911         ac = talloc_get_type(req->context, struct oc_context);
912         ldb = ldb_module_get_ctx(ac->module);
913
914         if (!ares) {
915                 return ldb_module_done(ac->req, NULL, NULL,
916                                         LDB_ERR_OPERATIONS_ERROR);
917         }
918
919         if (ares->type == LDB_REPLY_REFERRAL) {
920                 return ldb_module_send_referral(ac->req, ares->referral);
921         }
922
923         if (ares->error != LDB_SUCCESS) {
924                 return ldb_module_done(ac->req, ares->controls,
925                                         ares->response, ares->error);
926         }
927
928         if (ares->type != LDB_REPLY_DONE) {
929                 talloc_free(ares);
930                 return ldb_module_done(ac->req, NULL, NULL,
931                                         LDB_ERR_OPERATIONS_ERROR);
932         }
933
934         talloc_free(ares);
935
936         /* this looks up the real existing object for fetching some important
937          * informations (objectclasses) */
938         ret = ldb_build_search_req(&search_req, ldb,
939                                    ac, ac->req->op.mod.message->dn,
940                                    LDB_SCOPE_BASE,
941                                    "(objectClass=*)",
942                                    attrs, NULL, 
943                                    ac, get_search_callback,
944                                    ac->req);
945         LDB_REQ_SET_LOCATION(search_req);
946         if (ret != LDB_SUCCESS) {
947                 return ldb_module_done(ac->req, NULL, NULL, ret);
948         }
949
950         ac->step_fn = objectclass_do_mod;
951
952         ret = ldb_next_request(ac->module, search_req);
953         if (ret != LDB_SUCCESS) {
954                 return ldb_module_done(ac->req, NULL, NULL, ret);
955         }
956
957         return LDB_SUCCESS;
958 }
959
960 static int objectclass_do_mod(struct oc_context *ac)
961 {
962         struct ldb_context *ldb;
963         struct ldb_request *mod_req;
964         char *value;
965         struct ldb_message_element *oc_el_entry, *oc_el_change;
966         struct ldb_val *vals;
967         struct ldb_message *msg;
968         TALLOC_CTX *mem_ctx;
969         struct class_list *sorted, *current;
970         const struct dsdb_class *objectclass;
971         unsigned int i, j, k;
972         bool found, replace = false;
973         int ret;
974
975         ldb = ldb_module_get_ctx(ac->module);
976
977         /* we should always have a valid entry when we enter here */
978         if (ac->search_res == NULL) {
979                 return ldb_operr(ldb);
980         }
981
982         oc_el_entry = ldb_msg_find_element(ac->search_res->message,
983                                            "objectClass");
984         if (oc_el_entry == NULL) {
985                 /* existing entry without a valid object class? */
986                 return ldb_operr(ldb);
987         }
988
989         /* use a new message structure */
990         msg = ldb_msg_new(ac);
991         if (msg == NULL) {
992                 return ldb_module_oom(ac->module);
993         }
994
995         msg->dn = ac->req->op.mod.message->dn;
996
997         mem_ctx = talloc_new(ac);
998         if (mem_ctx == NULL) {
999                 return ldb_module_oom(ac->module);
1000         }
1001
1002         /* We've to walk over all "objectClass" message elements */
1003         for (k = 0; k < ac->req->op.mod.message->num_elements; k++) {
1004                 if (ldb_attr_cmp(ac->req->op.mod.message->elements[k].name,
1005                                  "objectClass") != 0) {
1006                         continue;
1007                 }
1008
1009                 oc_el_change = &ac->req->op.mod.message->elements[k];
1010
1011                 switch (oc_el_change->flags & LDB_FLAG_MOD_MASK) {
1012                 case LDB_FLAG_MOD_ADD:
1013                         /* Merge the two message elements */
1014                         for (i = 0; i < oc_el_change->num_values; i++) {
1015                                 for (j = 0; j < oc_el_entry->num_values; j++) {
1016                                         if (ldb_attr_cmp((char *)oc_el_change->values[i].data,
1017                                                          (char *)oc_el_entry->values[j].data) == 0) {
1018                                                 ldb_asprintf_errstring(ldb,
1019                                                                        "objectclass: cannot re-add an existing objectclass: '%.*s'!",
1020                                                                        (int)oc_el_change->values[i].length,
1021                                                                        (const char *)oc_el_change->values[i].data);
1022                                                 talloc_free(mem_ctx);
1023                                                 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
1024                                         }
1025                                 }
1026                                 /* append the new object class value - code was
1027                                  * copied from "ldb_msg_add_value" */
1028                                 vals = talloc_realloc(oc_el_entry, oc_el_entry->values,
1029                                                       struct ldb_val,
1030                                                       oc_el_entry->num_values + 1);
1031                                 if (vals == NULL) {
1032                                         talloc_free(mem_ctx);
1033                                         return ldb_module_oom(ac->module);
1034                                 }
1035                                 oc_el_entry->values = vals;
1036                                 oc_el_entry->values[oc_el_entry->num_values] =
1037                                                         oc_el_change->values[i];
1038                                 ++(oc_el_entry->num_values);
1039                         }
1040
1041                         objectclass = get_last_structural_class(ac->schema,
1042                                                                 oc_el_change);
1043                         if (objectclass != NULL) {
1044                                 ldb_asprintf_errstring(ldb,
1045                                                        "objectclass: cannot add a new top-most structural objectclass '%s'!",
1046                                                        objectclass->lDAPDisplayName);
1047                                 talloc_free(mem_ctx);
1048                                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1049                         }
1050
1051                         /* Now do the sorting */
1052                         ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
1053                                                oc_el_entry, &sorted);
1054                         if (ret != LDB_SUCCESS) {
1055                                 talloc_free(mem_ctx);
1056                                 return ret;
1057                         }
1058
1059                         break;
1060
1061                 case LDB_FLAG_MOD_REPLACE:
1062                         /* Do the sorting for the change message element */
1063                         ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
1064                                                oc_el_change, &sorted);
1065                         if (ret != LDB_SUCCESS) {
1066                                 talloc_free(mem_ctx);
1067                                 return ret;
1068                         }
1069
1070                         /* this is a replace */
1071                         replace = true;
1072
1073                         break;
1074
1075                 case LDB_FLAG_MOD_DELETE:
1076                         /* get the actual top-most structural objectclass */
1077                         objectclass = get_last_structural_class(ac->schema,
1078                                                                 oc_el_entry);
1079                         if (objectclass == NULL) {
1080                                 /* no structural objectclass? */
1081                                 talloc_free(mem_ctx);
1082                                 return ldb_operr(ldb);
1083                         }
1084
1085                         /* Merge the two message elements */
1086                         for (i = 0; i < oc_el_change->num_values; i++) {
1087                                 found = false;
1088                                 for (j = 0; j < oc_el_entry->num_values; j++) {
1089                                         if (ldb_attr_cmp((char *)oc_el_change->values[i].data,
1090                                                          (char *)oc_el_entry->values[j].data) == 0) {
1091                                                 found = true;
1092                                                 /* delete the object class value
1093                                                  * - code was copied from
1094                                                  * "ldb_msg_remove_element" */
1095                                                 if (j != oc_el_entry->num_values - 1) {
1096                                                         memmove(&oc_el_entry->values[j],
1097                                                                 &oc_el_entry->values[j+1],
1098                                                                 ((oc_el_entry->num_values-1) - j)*sizeof(struct ldb_val));
1099                                                 }
1100                                                 --(oc_el_entry->num_values);
1101                                                 break;
1102                                         }
1103                                 }
1104                                 if (!found) {
1105                                         /* we cannot delete a not existing
1106                                          * object class */
1107                                         ldb_asprintf_errstring(ldb,
1108                                                                "objectclass: cannot delete this objectclass: '%.*s'!",
1109                                                                (int)oc_el_change->values[i].length,
1110                                                                (const char *)oc_el_change->values[i].data);
1111                                         talloc_free(mem_ctx);
1112                                         return LDB_ERR_NO_SUCH_ATTRIBUTE;
1113                                 }
1114                         }
1115
1116                         /* Make sure that the top-most structural object class
1117                          * hasn't been deleted */
1118                         found = false;
1119                         for (i = 0; i < oc_el_entry->num_values; i++) {
1120                                 if (ldb_attr_cmp(objectclass->lDAPDisplayName,
1121                                                  (char *)oc_el_entry->values[i].data) == 0) {
1122                                         found = true;
1123                                         break;
1124                                 }
1125                         }
1126                         if (!found) {
1127                                 ldb_asprintf_errstring(ldb,
1128                                                        "objectclass: cannot delete the top-most structural objectclass '%s'!",
1129                                                        objectclass->lDAPDisplayName);
1130                                 talloc_free(mem_ctx);
1131                                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1132                         }
1133
1134                         /* Now do the sorting */
1135                         ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
1136                                                oc_el_entry, &sorted);
1137                         if (ret != LDB_SUCCESS) {
1138                                 talloc_free(mem_ctx);
1139                                 return ret;
1140                         }
1141
1142                         break;
1143                 }
1144
1145                 /* (Re)-add an empty "objectClass" attribute on the object
1146                  * classes change message "msg". */
1147                 ldb_msg_remove_attr(msg, "objectClass");
1148                 ret = ldb_msg_add_empty(msg, "objectClass",
1149                                         LDB_FLAG_MOD_REPLACE, &oc_el_change);
1150                 if (ret != LDB_SUCCESS) {
1151                         talloc_free(mem_ctx);
1152                         return ret;
1153                 }
1154
1155                 /* Move from the linked list back into an ldb msg */
1156                 for (current = sorted; current; current = current->next) {
1157                         value = talloc_strdup(msg,
1158                                               current->objectclass->lDAPDisplayName);
1159                         if (value == NULL) {
1160                                 talloc_free(mem_ctx);
1161                                 return ldb_module_oom(ac->module);
1162                         }
1163                         ret = ldb_msg_add_string(msg, "objectClass", value);
1164                         if (ret != LDB_SUCCESS) {
1165                                 ldb_set_errstring(ldb,
1166                                                   "objectclass: could not re-add sorted objectclasses!");
1167                                 talloc_free(mem_ctx);
1168                                 return ret;
1169                         }
1170                 }
1171
1172                 if (replace) {
1173                         /* Well, on replace we are nearly done: we have to test
1174                          * if the change and entry message element are identical
1175                          * ly. We can use "ldb_msg_element_compare" since now
1176                          * the specified objectclasses match for sure in case.
1177                          */
1178                         ret = ldb_msg_element_compare(oc_el_entry,
1179                                                       oc_el_change);
1180                         if (ret == 0) {
1181                                 ret = ldb_msg_element_compare(oc_el_change,
1182                                                               oc_el_entry);
1183                         }
1184                         if (ret == 0) {
1185                                 /* they are the same so we are done in this
1186                                  * case */
1187                                 talloc_free(mem_ctx);
1188                                 return ldb_module_done(ac->req, NULL, NULL,
1189                                                        LDB_SUCCESS);
1190                         } else {
1191                                 ldb_set_errstring(ldb,
1192                                                   "objectclass: the specified objectclasses are not exactly the same as on the entry!");
1193                                 talloc_free(mem_ctx);
1194                                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1195                         }
1196                 }
1197
1198                 /* Now we've applied all changes from "oc_el_change" to
1199                  * "oc_el_entry" therefore the new "oc_el_entry" will be
1200                  * "oc_el_change". */
1201                 oc_el_entry = oc_el_change;
1202         }
1203
1204         talloc_free(mem_ctx);
1205
1206         /* Now we have the real and definitive change left to do */
1207
1208         ret = ldb_build_mod_req(&mod_req, ldb, ac,
1209                                 msg,
1210                                 ac->req->controls,
1211                                 ac, oc_op_callback,
1212                                 ac->req);
1213         LDB_REQ_SET_LOCATION(mod_req);
1214         if (ret != LDB_SUCCESS) {
1215                 return ret;
1216         }
1217
1218         return ldb_next_request(ac->module, mod_req);
1219 }
1220
1221 static int objectclass_do_rename(struct oc_context *ac);
1222
1223 static int objectclass_rename(struct ldb_module *module, struct ldb_request *req)
1224 {
1225         static const char * const attrs[] = { "objectClass", NULL };
1226         struct ldb_context *ldb;
1227         struct ldb_request *search_req;
1228         struct oc_context *ac;
1229         struct ldb_dn *parent_dn;
1230         int ret;
1231
1232         ldb = ldb_module_get_ctx(module);
1233
1234         ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_rename\n");
1235
1236         /* do not manipulate our control entries */
1237         if (ldb_dn_is_special(req->op.rename.olddn)) {
1238                 return ldb_next_request(module, req);
1239         }
1240
1241         ac = oc_init_context(module, req);
1242         if (ac == NULL) {
1243                 return ldb_operr(ldb);
1244         }
1245
1246         parent_dn = ldb_dn_get_parent(ac, req->op.rename.newdn);
1247         if (parent_dn == NULL) {
1248                 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, the parent DN does not exist!",
1249                                        ldb_dn_get_linearized(req->op.rename.olddn));
1250                 return LDB_ERR_NO_SUCH_OBJECT;
1251         }
1252
1253         /* this looks up the parent object for fetching some important
1254          * informations (objectclasses, DN normalisation...) */
1255         ret = ldb_build_search_req(&search_req, ldb,
1256                                    ac, parent_dn, LDB_SCOPE_BASE,
1257                                    "(objectClass=*)",
1258                                    attrs, NULL,
1259                                    ac, get_search_callback,
1260                                    req);
1261         LDB_REQ_SET_LOCATION(search_req);
1262         if (ret != LDB_SUCCESS) {
1263                 return ret;
1264         }
1265
1266         /* we have to add the show recycled control, as otherwise DRS
1267            deletes will be refused as we will think the target parent
1268            does not exist */
1269         ret = ldb_request_add_control(search_req, LDB_CONTROL_SHOW_RECYCLED_OID,
1270                                       false, NULL);
1271
1272         if (ret != LDB_SUCCESS) {
1273                 return ret;
1274         }
1275
1276         ac->step_fn = objectclass_do_rename;
1277
1278         return ldb_next_request(ac->module, search_req);
1279 }
1280
1281 static int objectclass_do_rename2(struct oc_context *ac);
1282
1283 static int objectclass_do_rename(struct oc_context *ac)
1284 {
1285         static const char * const attrs[] = { "objectClass", NULL };
1286         struct ldb_context *ldb;
1287         struct ldb_request *search_req;
1288         int ret;
1289
1290         ldb = ldb_module_get_ctx(ac->module);
1291
1292         /* Check if we have a valid parent - this check is needed since
1293          * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1294         if (ac->search_res == NULL) {
1295                 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, parent does not exist!",
1296                                        ldb_dn_get_linearized(ac->req->op.rename.olddn));
1297                 return LDB_ERR_OTHER;
1298         }
1299
1300         /* now assign "search_res2" to the parent entry to have "search_res"
1301          * free for another lookup */
1302         ac->search_res2 = ac->search_res;
1303         ac->search_res = NULL;
1304
1305         /* this looks up the real existing object for fetching some important
1306          * informations (objectclasses) */
1307         ret = ldb_build_search_req(&search_req, ldb,
1308                                    ac, ac->req->op.rename.olddn,
1309                                    LDB_SCOPE_BASE,
1310                                    "(objectClass=*)",
1311                                    attrs, NULL,
1312                                    ac, get_search_callback,
1313                                    ac->req);
1314         LDB_REQ_SET_LOCATION(search_req);
1315         if (ret != LDB_SUCCESS) {
1316                 return ret;
1317         }
1318
1319         ac->step_fn = objectclass_do_rename2;
1320
1321         return ldb_next_request(ac->module, search_req);
1322 }
1323
1324 static int objectclass_do_rename2(struct oc_context *ac)
1325 {
1326         struct ldb_context *ldb;
1327         struct ldb_request *rename_req;
1328         struct ldb_dn *fixed_dn;
1329         int ret;
1330
1331         ldb = ldb_module_get_ctx(ac->module);
1332
1333         /* Check if we have a valid entry - this check is needed since
1334          * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1335         if (ac->search_res == NULL) {
1336                 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, entry does not exist!",
1337                                        ldb_dn_get_linearized(ac->req->op.rename.olddn));
1338                 return LDB_ERR_NO_SUCH_OBJECT;
1339         }
1340
1341         if (ac->schema != NULL) {
1342                 struct ldb_message_element *oc_el_entry, *oc_el_parent;
1343                 const struct dsdb_class *objectclass;
1344                 const char *rdn_name;
1345                 bool allowed_class = false;
1346                 unsigned int i, j;
1347                 bool found;
1348
1349                 oc_el_entry = ldb_msg_find_element(ac->search_res->message,
1350                                                    "objectClass");
1351                 if (oc_el_entry == NULL) {
1352                         /* existing entry without a valid object class? */
1353                         return ldb_operr(ldb);
1354                 }
1355                 objectclass = get_last_structural_class(ac->schema, oc_el_entry);
1356                 if (objectclass == NULL) {
1357                         /* existing entry without a valid object class? */
1358                         return ldb_operr(ldb);
1359                 }
1360
1361                 rdn_name = ldb_dn_get_rdn_name(ac->req->op.rename.newdn);
1362                 if (rdn_name == NULL) {
1363                         return ldb_operr(ldb);
1364                 }
1365                 found = false;
1366                 for (i = 0; (!found) && (i < oc_el_entry->num_values); i++) {
1367                         const struct dsdb_class *tmp_class =
1368                                 dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
1369                                                                       &oc_el_entry->values[i]);
1370
1371                         if (tmp_class == NULL) continue;
1372
1373                         if (ldb_attr_cmp(rdn_name, tmp_class->rDNAttID) == 0)
1374                                 found = true;
1375                 }
1376                 if (!found) {
1377                         ldb_asprintf_errstring(ldb,
1378                                                "objectclass: Invalid RDN '%s' for objectclass '%s'!",
1379                                                rdn_name, objectclass->lDAPDisplayName);
1380                         return LDB_ERR_UNWILLING_TO_PERFORM;
1381                 }
1382
1383                 oc_el_parent = ldb_msg_find_element(ac->search_res2->message,
1384                                                     "objectClass");
1385                 if (oc_el_parent == NULL) {
1386                         /* existing entry without a valid object class? */
1387                         return ldb_operr(ldb);
1388                 }
1389
1390                 for (i=0; allowed_class == false && i < oc_el_parent->num_values; i++) {
1391                         const struct dsdb_class *sclass;
1392
1393                         sclass = dsdb_class_by_lDAPDisplayName_ldb_val(ac->schema,
1394                                                                        &oc_el_parent->values[i]);
1395                         if (!sclass) {
1396                                 /* We don't know this class?  what is going on? */
1397                                 continue;
1398                         }
1399                         for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
1400                                 if (ldb_attr_cmp(objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
1401                                         allowed_class = true;
1402                                         break;
1403                                 }
1404                         }
1405                 }
1406
1407                 if (!allowed_class) {
1408                         ldb_asprintf_errstring(ldb,
1409                                                "objectclass: structural objectClass %s is not a valid child class for %s",
1410                                                objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res2->message->dn));
1411                         return LDB_ERR_NAMING_VIOLATION;
1412                 }
1413         }
1414
1415         /* Ensure we are not trying to rename it to be a child of itself */
1416         if ((ldb_dn_compare_base(ac->req->op.rename.olddn,
1417                                  ac->req->op.rename.newdn) == 0)  &&
1418             (ldb_dn_compare(ac->req->op.rename.olddn,
1419                             ac->req->op.rename.newdn) != 0)) {
1420                 ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s to be a child of itself",
1421                                        ldb_dn_get_linearized(ac->req->op.rename.olddn));
1422                 return LDB_ERR_UNWILLING_TO_PERFORM;
1423         }
1424
1425         /* Fix up the DN to be in the standard form, taking
1426          * particular care to match the parent DN */
1427         ret = fix_dn(ldb, ac,
1428                      ac->req->op.rename.newdn,
1429                      ac->search_res2->message->dn,
1430                      &fixed_dn);
1431         if (ret != LDB_SUCCESS) {
1432                 ldb_asprintf_errstring(ldb, "objectclass: Could not munge DN %s into normal form",
1433                                        ldb_dn_get_linearized(ac->req->op.rename.newdn));
1434                 return ret;
1435
1436         }
1437
1438         ret = ldb_build_rename_req(&rename_req, ldb, ac,
1439                                    ac->req->op.rename.olddn, fixed_dn,
1440                                    ac->req->controls,
1441                                    ac, oc_op_callback,
1442                                    ac->req);
1443         LDB_REQ_SET_LOCATION(rename_req);
1444         if (ret != LDB_SUCCESS) {
1445                 return ret;
1446         }
1447
1448         /* perform the rename */
1449         return ldb_next_request(ac->module, rename_req);
1450 }
1451
1452 static int objectclass_do_delete(struct oc_context *ac);
1453
1454 static int objectclass_delete(struct ldb_module *module, struct ldb_request *req)
1455 {
1456         static const char * const attrs[] = { "nCName", "objectClass",
1457                                               "systemFlags",
1458                                               "isCriticalSystemObject", NULL };
1459         struct ldb_context *ldb;
1460         struct ldb_request *search_req;
1461         struct oc_context *ac;
1462         int ret;
1463
1464         ldb = ldb_module_get_ctx(module);
1465
1466         ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_delete\n");
1467
1468         /* do not manipulate our control entries */
1469         if (ldb_dn_is_special(req->op.del.dn)) {
1470                 return ldb_next_request(module, req);
1471         }
1472
1473         /* Bypass the constraint checks when we do have the "RELAX" control
1474          * set. */
1475         if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID) != NULL) {
1476                 return ldb_next_request(module, req);
1477         }
1478
1479         ac = oc_init_context(module, req);
1480         if (ac == NULL) {
1481                 return ldb_operr(ldb);
1482         }
1483
1484         /* this looks up the entry object for fetching some important
1485          * informations (object classes, system flags...) */
1486         ret = ldb_build_search_req(&search_req, ldb,
1487                                    ac, req->op.del.dn, LDB_SCOPE_BASE,
1488                                    "(objectClass=*)",
1489                                    attrs, NULL,
1490                                    ac, get_search_callback,
1491                                    req);
1492         LDB_REQ_SET_LOCATION(search_req);
1493         if (ret != LDB_SUCCESS) {
1494                 return ret;
1495         }
1496
1497         ac->step_fn = objectclass_do_delete;
1498
1499         return ldb_next_request(ac->module, search_req);
1500 }
1501
1502 static int objectclass_do_delete(struct oc_context *ac)
1503 {
1504         struct ldb_context *ldb;
1505         struct ldb_dn *dn;
1506         int32_t systemFlags;
1507         bool isCriticalSystemObject;
1508         int ret;
1509
1510         ldb = ldb_module_get_ctx(ac->module);
1511
1512         /* Check if we have a valid entry - this check is needed since
1513          * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
1514         if (ac->search_res == NULL) {
1515                 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, entry does not exist!",
1516                                        ldb_dn_get_linearized(ac->req->op.del.dn));
1517                 return LDB_ERR_NO_SUCH_OBJECT;
1518         }
1519
1520         /* DC's ntDSDSA object */
1521         if (ldb_dn_compare(ac->req->op.del.dn, samdb_ntds_settings_dn(ldb)) == 0) {
1522                 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's the DC's ntDSDSA object!",
1523                                        ldb_dn_get_linearized(ac->req->op.del.dn));
1524                 return LDB_ERR_UNWILLING_TO_PERFORM;
1525         }
1526
1527         /* DC's rIDSet object */
1528         /* Perform this check only when it does exist - this is needed in order
1529          * to don't let existing provisions break. */
1530         ret = samdb_rid_set_dn(ldb, ac, &dn);
1531         if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
1532                 return ret;
1533         }
1534         if (ret == LDB_SUCCESS) {
1535                 if (ldb_dn_compare(ac->req->op.del.dn, dn) == 0) {
1536                         talloc_free(dn);
1537                         ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's the DC's rIDSet object!",
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         /* crossRef objects regarding config, schema and default domain NCs */
1545         if (samdb_find_attribute(ldb, ac->search_res->message, "objectClass",
1546                                  "crossRef") != NULL) {
1547                 dn = ldb_msg_find_attr_as_dn(ldb, ac, ac->search_res->message,
1548                                              "nCName");
1549                 if ((ldb_dn_compare(dn, ldb_get_default_basedn(ldb)) == 0) ||
1550                     (ldb_dn_compare(dn, ldb_get_config_basedn(ldb)) == 0)) {
1551                         talloc_free(dn);
1552
1553                         ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's a crossRef object to the main or configuration partition!",
1554                                                ldb_dn_get_linearized(ac->req->op.del.dn));
1555                         return LDB_ERR_NOT_ALLOWED_ON_NON_LEAF;
1556                 }
1557                 if (ldb_dn_compare(dn, ldb_get_schema_basedn(ldb)) == 0) {
1558                         talloc_free(dn);
1559
1560                         ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's a crossRef object to the schema partition!",
1561                                                ldb_dn_get_linearized(ac->req->op.del.dn));
1562                         return LDB_ERR_UNWILLING_TO_PERFORM;
1563                 }
1564                 talloc_free(dn);
1565         }
1566
1567         /* systemFlags */
1568
1569         systemFlags = ldb_msg_find_attr_as_int(ac->search_res->message,
1570                                                "systemFlags", 0);
1571         if ((systemFlags & SYSTEM_FLAG_DISALLOW_DELETE) != 0) {
1572                 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it isn't permitted!",
1573                                        ldb_dn_get_linearized(ac->req->op.del.dn));
1574                 return LDB_ERR_UNWILLING_TO_PERFORM;
1575         }
1576
1577         /* isCriticalSystemObject - but this only applies on tree delete
1578          * operations - MS-ADTS 3.1.1.5.5.7.2 */
1579         if (ldb_request_get_control(ac->req, LDB_CONTROL_TREE_DELETE_OID) != NULL) {
1580                 isCriticalSystemObject = ldb_msg_find_attr_as_bool(ac->search_res->message,
1581                                                                    "isCriticalSystemObject", false);
1582                 if (isCriticalSystemObject) {
1583                         ldb_asprintf_errstring(ldb,
1584                                                "objectclass: Cannot tree-delete %s, it's a critical system object!",
1585                                                ldb_dn_get_linearized(ac->req->op.del.dn));
1586                         return LDB_ERR_UNWILLING_TO_PERFORM;
1587                 }
1588         }
1589
1590         return ldb_next_request(ac->module, ac->req);
1591 }
1592
1593 static int objectclass_init(struct ldb_module *module)
1594 {
1595         struct ldb_context *ldb = ldb_module_get_ctx(module);
1596         int ret;
1597
1598         /* Init everything else */
1599         ret = ldb_next_init(module);
1600         if (ret != LDB_SUCCESS) {
1601                 return ret;
1602         }
1603         
1604         /* Look for the opaque to indicate we might have to cut down the DN of defaultObjectCategory */
1605         ldb_module_set_private(module, ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME));
1606
1607         ret = ldb_mod_register_control(module, LDB_CONTROL_RODC_DCPROMO_OID);
1608         if (ret != LDB_SUCCESS) {
1609                 ldb_debug(ldb, LDB_DEBUG_ERROR,
1610                           "objectclass_init: Unable to register control DCPROMO with rootdse\n");
1611                 return ldb_operr(ldb);
1612         }
1613
1614         return ret;
1615 }
1616
1617 static const struct ldb_module_ops ldb_objectclass_module_ops = {
1618         .name           = "objectclass",
1619         .add            = objectclass_add,
1620         .modify         = objectclass_modify,
1621         .rename         = objectclass_rename,
1622         .del            = objectclass_delete,
1623         .init_context   = objectclass_init
1624 };
1625
1626 int ldb_objectclass_module_init(const char *version)
1627 {
1628         LDB_MODULE_CHECK_VERSION(version);
1629         return ldb_register_module(&ldb_objectclass_module_ops);
1630 }