r25762: This test belongs best with the other checks for a valid parent, in
[sfrench/samba-autobuild/.git] / source4 / dsdb / samdb / ldb_modules / objectclass.c
1 /* 
2    ldb database library
3
4    Copyright (C) Simo Sorce  2006
5    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2007
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 /*
22  *  Name: ldb
23  *
24  *  Component: objectClass sorting module
25  *
26  *  Description: 
27  *  - sort the objectClass attribute into the class
28  *    hierarchy, 
29  *  - fix DNs and attributes into 'standard' case
30  *  - Add objectCategory and ntSecurityDescriptor defaults
31  *
32  *  Author: Andrew Bartlett
33  */
34
35
36 #include "includes.h"
37 #include "ldb/include/ldb.h"
38 #include "ldb/include/ldb_errors.h"
39 #include "ldb/include/ldb_private.h"
40 #include "dsdb/samdb/samdb.h"
41 #include "lib/util/dlinklist.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
47 struct oc_context {
48
49         enum oc_step {OC_DO_REQ, OC_SEARCH_SELF, OC_DO_MOD, 
50                       OC_SEARCH_ADD_PARENT, OC_DO_ADD, 
51                       OC_SEARCH_RENAME_PARENT, OC_DO_RENAME} step;
52
53         struct ldb_module *module;
54         struct ldb_request *orig_req;
55
56         struct ldb_request *down_req;
57
58         struct ldb_request *search_req;
59         struct ldb_reply *search_res;
60
61         struct ldb_request *add_req;
62         struct ldb_request *mod_req;
63         struct ldb_request *rename_req;
64 };
65
66 struct class_list {
67         struct class_list *prev, *next;
68         const struct dsdb_class *objectclass;
69 };
70
71 static struct ldb_handle *oc_init_handle(struct ldb_request *req, struct ldb_module *module)
72 {
73         struct oc_context *ac;
74         struct ldb_handle *h;
75
76         h = talloc_zero(req, struct ldb_handle);
77         if (h == NULL) {
78                 ldb_set_errstring(module->ldb, "Out of Memory");
79                 return NULL;
80         }
81
82         h->module = module;
83
84         ac = talloc_zero(h, struct oc_context);
85         if (ac == NULL) {
86                 ldb_set_errstring(module->ldb, "Out of Memory");
87                 talloc_free(h);
88                 return NULL;
89         }
90
91         h->private_data = (void *)ac;
92
93         h->state = LDB_ASYNC_INIT;
94         h->status = LDB_SUCCESS;
95
96         ac->module = module;
97         ac->orig_req = req;
98
99         return h;
100 }
101
102 /* Sort objectClasses into correct order, and validate that all
103  * objectClasses specified actually exist in the schema
104  */
105
106 static int objectclass_sort(struct ldb_module *module,
107                             const struct dsdb_schema *schema,
108                             struct ldb_message *msg, /* so that when we create new elements, we put it on the right parent */
109                             TALLOC_CTX *mem_ctx,
110                             struct ldb_message_element *objectclass_element,
111                             struct class_list **sorted_out) 
112 {
113         int i;
114         int layer;
115         struct class_list *sorted = NULL, *parent_class = NULL,
116                 *subclass = NULL, *unsorted = NULL, *current, *poss_subclass, *poss_parent, *new_parent;
117         /* DESIGN:
118          *
119          * We work on 4 different 'bins' (implemented here as linked lists):
120          *
121          * * sorted:       the eventual list, in the order we wish to push
122          *                 into the database.  This is the only ordered list.
123          *
124          * * parent_class: The current parent class 'bin' we are
125          *                 trying to find subclasses for
126          *
127          * * subclass:     The subclasses we have found so far
128          *
129          * * unsorted:     The remaining objectClasses
130          *
131          * The process is a matter of filtering objectClasses up from
132          * unsorted into sorted.  Order is irrelevent in the later 3 'bins'.
133          * 
134          * We start with 'top' (found and promoted to parent_class
135          * initially).  Then we find (in unsorted) all the direct
136          * subclasses of 'top'.  parent_classes is concatenated onto
137          * the end of 'sorted', and subclass becomes the list in
138          * parent_class.
139          *
140          * We then repeat, until we find no more subclasses.  Any left
141          * over classes are added to the end.
142          *
143          */
144
145         /* Firstly, dump all the objectClass elements into the
146          * unsorted bin, except for 'top', which is special */
147         for (i=0; i < objectclass_element->num_values; i++) {
148                 current = talloc(mem_ctx, struct class_list);
149                 if (!current) {
150                         ldb_set_errstring(module->ldb, "objectclass: out of memory allocating objectclass list");
151                         talloc_free(mem_ctx);
152                         return LDB_ERR_OPERATIONS_ERROR;
153                 }
154                 current->objectclass = dsdb_class_by_lDAPDisplayName(schema, (const char *)objectclass_element->values[i].data);
155                 if (!current->objectclass) {
156                         ldb_asprintf_errstring(module->ldb, "objectclass %s is not a valid objectClass in schema", (const char *)objectclass_element->values[i].data);
157                         return LDB_ERR_OBJECT_CLASS_VIOLATION;
158                 }
159
160                 /* this is the root of the tree.  We will start
161                  * looking for subclasses from here */
162                 if (ldb_attr_cmp("top", current->objectclass->lDAPDisplayName) == 0) {
163                         DLIST_ADD_END(parent_class, current, struct class_list *);
164                 } else {
165                         DLIST_ADD_END(unsorted, current, struct class_list *);
166                 }
167         }
168
169         if (parent_class == NULL) {
170                 current = talloc(mem_ctx, struct class_list);
171                 current->objectclass = dsdb_class_by_lDAPDisplayName(schema, "top");
172                 DLIST_ADD_END(parent_class, current, struct class_list *);
173         }
174
175         /* For each object:  find parent chain */
176         for (current = unsorted; schema && current; current = current->next) {
177                 for (poss_parent = unsorted; poss_parent; poss_parent = poss_parent->next) {
178                         if (ldb_attr_cmp(poss_parent->objectclass->lDAPDisplayName, current->objectclass->subClassOf) == 0) {
179                                 break;
180                         }
181                 }
182                 /* If we didn't get to the end of the list, we need to add this parent */
183                 if (poss_parent || (ldb_attr_cmp("top", current->objectclass->subClassOf) == 0)) {
184                         continue;
185                 }
186
187                 new_parent = talloc(mem_ctx, struct class_list);
188                 new_parent->objectclass = dsdb_class_by_lDAPDisplayName(schema, current->objectclass->subClassOf);
189                 DLIST_ADD_END(unsorted, new_parent, struct class_list *);
190         }
191
192         /* DEBUGGING aid:  how many layers are we down now? */
193         layer = 0;
194         do {
195                 layer++;
196                 /* Find all the subclasses of classes in the
197                  * parent_classes.  Push them onto the subclass list */
198
199                 /* Ensure we don't bother if there are no unsorted entries left */
200                 for (current = parent_class; schema && unsorted && current; current = current->next) {
201                         /* Walk the list of possible subclasses in unsorted */
202                         for (poss_subclass = unsorted; poss_subclass; ) {
203                                 struct class_list *next;
204                                 
205                                 /* Save the next pointer, as the DLIST_ macros will change poss_subclass->next */
206                                 next = poss_subclass->next;
207
208                                 if (ldb_attr_cmp(poss_subclass->objectclass->subClassOf, current->objectclass->lDAPDisplayName) == 0) {
209                                         DLIST_REMOVE(unsorted, poss_subclass);
210                                         DLIST_ADD(subclass, poss_subclass);
211                                         
212                                         break;
213                                 }
214                                 poss_subclass = next;
215                         }
216                 }
217
218                 /* Now push the parent_classes as sorted, we are done with
219                 these.  Add to the END of the list by concatenation */
220                 DLIST_CONCATENATE(sorted, parent_class, struct class_list *);
221
222                 /* and now find subclasses of these */
223                 parent_class = subclass;
224                 subclass = NULL;
225
226                 /* If we didn't find any subclasses we will fall out
227                  * the bottom here */
228         } while (parent_class);
229
230         if (!unsorted) {
231                 *sorted_out = sorted;
232                 return LDB_SUCCESS;
233         }
234
235         if (!schema) {
236                 /* If we don't have schema yet, then just merge the lists again */
237                 DLIST_CONCATENATE(sorted, unsorted, struct class_list *);
238                 *sorted_out = sorted;
239                 return LDB_SUCCESS;
240         }
241
242         /* This shouldn't happen, and would break MMC, perhaps there
243          * was no 'top', a conflict in the objectClasses or some other
244          * schema error?
245          */
246         ldb_asprintf_errstring(module->ldb, "objectclass %s is not a valid objectClass in objectClass chain", unsorted->objectclass->lDAPDisplayName);
247         return LDB_ERR_OBJECT_CLASS_VIOLATION;
248 }
249
250 static DATA_BLOB *get_sd(struct ldb_module *module, TALLOC_CTX *mem_ctx, 
251                          const struct dsdb_class *objectclass) 
252 {
253         NTSTATUS status;
254         DATA_BLOB *linear_sd;
255         struct auth_session_info *session_info
256                 = ldb_get_opaque(module->ldb, "sessionInfo");
257         struct security_descriptor *sd
258                 = sddl_decode(mem_ctx, 
259                               objectclass->defaultSecurityDescriptor,
260                               samdb_domain_sid(module->ldb));
261
262         if (!session_info || !session_info->security_token) {
263                 return NULL;
264         }
265         
266         sd->owner_sid = session_info->security_token->user_sid;
267         sd->group_sid = session_info->security_token->group_sid;
268         
269         linear_sd = talloc(mem_ctx, DATA_BLOB);
270         if (!linear_sd) {
271                 return NULL;
272         }
273
274         status = ndr_push_struct_blob(linear_sd, mem_ctx, sd, 
275                                       (ndr_push_flags_fn_t)ndr_push_security_descriptor);
276
277         if (!NT_STATUS_IS_OK(status)) {
278                 return NULL;
279         }
280         
281         return linear_sd;
282
283 }
284
285 static int get_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
286 {
287         struct oc_context *ac;
288
289         ac = talloc_get_type(context, struct oc_context);
290
291         /* we are interested only in the single reply (base search) we receive here */
292         if (ares->type == LDB_REPLY_ENTRY) {
293                 if (ac->search_res != NULL) {
294                         ldb_set_errstring(ldb, "Too many results");
295                         talloc_free(ares);
296                         return LDB_ERR_OPERATIONS_ERROR;
297                 }
298
299                 ac->search_res = talloc_move(ac, &ares);
300         } else {
301                 talloc_free(ares);
302         }
303
304         return LDB_SUCCESS;
305 }
306
307 /* Fix up the DN to be in the standard form, taking particular care to match the parent DN
308
309    This should mean that if the parent is:
310     CN=Users,DC=samba,DC=example,DC=com
311    and a proposed child is
312     cn=Admins ,cn=USERS,dc=Samba,dc=example,dc=COM
313
314    The resulting DN should be:
315
316     CN=Admins,CN=Users,DC=samba,DC=example,DC=com
317    
318  */
319 static int fix_dn(TALLOC_CTX *mem_ctx, 
320                   struct ldb_dn *newdn, struct ldb_dn *parent_dn, 
321                   struct ldb_dn **fixed_dn) 
322 {
323         char *upper_rdn_attr;
324         /* Fix up the DN to be in the standard form, taking particular care to match the parent DN */
325         *fixed_dn = ldb_dn_copy(mem_ctx, parent_dn);
326
327         /* We need the attribute name in upper case */
328         upper_rdn_attr = strupper_talloc(*fixed_dn, 
329                                          ldb_dn_get_rdn_name(newdn));
330         if (!upper_rdn_attr) {
331                 return LDB_ERR_OPERATIONS_ERROR;
332         }
333                                                
334         /* Create a new child */
335         if (ldb_dn_add_child_fmt(*fixed_dn, "X=X") == false) {
336                 return LDB_ERR_OPERATIONS_ERROR;
337         }
338
339         /* And replace it with CN=foo (we need the attribute in upper case */
340         return ldb_dn_set_component(*fixed_dn, 0, upper_rdn_attr,
341                                     *ldb_dn_get_rdn_val(newdn));
342 }
343
344 /* Fix all attribute names to be in the correct case, and check they are all valid per the schema */
345 static int fix_attributes(struct ldb_context *ldb, const struct dsdb_schema *schema, struct ldb_message *msg) 
346 {
347         int i;
348         for (i=0; i < msg->num_elements; i++) {
349                 const struct dsdb_attribute *attribute = dsdb_attribute_by_lDAPDisplayName(schema, msg->elements[i].name);
350                 if (!attribute) {
351                         ldb_asprintf_errstring(ldb, "objectclass %s is not a valid objectClass in schema", msg->elements[i].name);
352                         return LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE;
353                 }
354                 msg->elements[i].name = attribute->lDAPDisplayName;
355         }
356
357         return LDB_SUCCESS;
358 }
359
360 static int objectclass_add(struct ldb_module *module, struct ldb_request *req)
361 {
362
363         static const char * const attrs[] = { NULL };
364
365         struct ldb_handle *h;
366         struct oc_context *ac;
367         struct ldb_dn *parent_dn;
368         int ret;
369         
370         ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectclass_add\n");
371
372         /* do not manipulate our control entries */
373         if (ldb_dn_is_special(req->op.add.message->dn)) {
374                 return ldb_next_request(module, req);
375         }
376
377         /* Need to object to this, but cn=rootdse doesn't hae an objectClass... */
378         if (ldb_msg_find_element(req->op.add.message, 
379                                  "objectClass") == NULL) {
380                 return ldb_next_request(module, req);
381         }
382
383         h = oc_init_handle(req, module);
384         if (!h) {
385                 return LDB_ERR_OPERATIONS_ERROR;
386         }
387         ac = talloc_get_type(h->private_data, struct oc_context);
388         
389         /* return or own handle to deal with this call */
390         req->handle = h;
391
392         parent_dn = ldb_dn_get_parent(ac, ac->orig_req->op.mod.message->dn);
393         if (parent_dn == NULL) {
394                 ldb_oom(module->ldb);
395                 return LDB_ERR_OPERATIONS_ERROR;
396         }
397         ret = ldb_build_search_req(&ac->search_req, module->ldb,
398                                    ac, parent_dn, LDB_SCOPE_BASE,
399                                    "(objectClass=*)",
400                                    attrs, NULL, 
401                                    ac, get_search_callback);
402         if (ret != LDB_SUCCESS) {
403                 return ret;
404         }
405
406         talloc_steal(ac->search_req, parent_dn);
407
408         ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->search_req);
409
410         ac->step = OC_SEARCH_ADD_PARENT;
411
412         return ldb_next_request(ac->module, ac->search_req);
413 }
414
415 static int objectclass_do_add(struct ldb_handle *h) 
416 {
417         const struct dsdb_schema *schema;
418         struct oc_context *ac;
419         struct ldb_message_element *objectclass_element;
420         struct ldb_message *msg;
421         TALLOC_CTX *mem_ctx;
422         struct class_list *sorted, *current;
423         int ret;
424       
425         ac = talloc_get_type(h->private_data, struct oc_context);
426         schema = dsdb_get_schema(ac->module->ldb);
427
428         mem_ctx = talloc_new(ac);
429         if (mem_ctx == NULL) {
430                 return LDB_ERR_OPERATIONS_ERROR;
431         }
432
433         ac->add_req = talloc(ac, struct ldb_request);
434         if (ac->add_req == NULL) {
435                 talloc_free(mem_ctx);
436                 return LDB_ERR_OPERATIONS_ERROR;
437         }
438
439         *ac->add_req = *ac->orig_req;
440
441         ac->add_req->op.add.message = msg = ldb_msg_copy_shallow(ac->add_req, ac->orig_req->op.add.message);
442
443         ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->add_req);
444         
445         /* Check we have a valid parent */
446         if (ac->search_res == NULL) {
447                 if (ldb_dn_get_comp_num(ac->orig_req->op.add.message->dn) <= 1) {
448                         /* Allow cn=rootdse and cn=templates for now... */
449                 } else if (ldb_dn_compare(ldb_get_root_basedn(ac->module->ldb), ac->orig_req->op.add.message->dn) == 0) {
450                         /* Allow the tree to be started */
451                 } else {
452                         ldb_asprintf_errstring(ac->module->ldb, "objectclass: Cannot add %s, parent does not exist!", 
453                                                ldb_dn_get_linearized(ac->orig_req->op.add.message->dn));
454                         return LDB_ERR_UNWILLING_TO_PERFORM;
455                 }
456         } else {
457                 
458                 /* Fix up the DN to be in the standard form, taking particular care to match the parent DN */
459                 ret = fix_dn(msg, 
460                              ac->orig_req->op.add.message->dn,
461                              ac->search_res->message->dn,
462                              &msg->dn);
463
464                 if (ret != LDB_SUCCESS) {
465                         return ret;
466                 }
467
468                 /* TODO: Check this is a valid child to this parent,
469                  * by reading the allowedChildClasses and
470                  * allowedChildClasssesEffective attributes */
471
472         }
473
474         if (schema) {
475                 ret = fix_attributes(ac->module->ldb, schema, msg);
476                 if (ret != LDB_SUCCESS) {
477                         talloc_free(mem_ctx);
478                         return ret;
479                 }
480
481                 /* This is now the objectClass list from the database */
482                 objectclass_element = ldb_msg_find_element(msg, "objectClass");
483                 
484                 if (!objectclass_element) {
485                         /* Where did it go?  bail now... */
486                         talloc_free(mem_ctx);
487                         return LDB_ERR_OPERATIONS_ERROR;
488                 }
489                 ret = objectclass_sort(ac->module, schema, msg, mem_ctx, objectclass_element, &sorted);
490                 if (ret != LDB_SUCCESS) {
491                         talloc_free(mem_ctx);
492                         return ret;
493                 }
494                 
495                 ldb_msg_remove_attr(msg, "objectClass");
496                 ret = ldb_msg_add_empty(msg, "objectClass", 0, NULL);
497                 
498                 if (ret != LDB_SUCCESS) {
499                         talloc_free(mem_ctx);
500                         return ret;
501                 }
502                 
503                 /* We must completely replace the existing objectClass entry,
504                  * because we need it sorted */
505                 
506                 /* Move from the linked list back into an ldb msg */
507                 for (current = sorted; current; current = current->next) {
508                         ret = ldb_msg_add_string(msg, "objectClass", current->objectclass->lDAPDisplayName);
509                         if (ret != LDB_SUCCESS) {
510                                 ldb_set_errstring(ac->module->ldb, 
511                                                   "objectclass: could not re-add sorted "
512                                                   "objectclass to modify msg");
513                                 talloc_free(mem_ctx);
514                                 return ret;
515                         }
516                         /* Last one is the critical one */
517                         if (!current->next) {
518                                 if (!ldb_msg_find_element(msg, "objectCategory")) {
519                                         ldb_msg_add_string(msg, "objectCategory", 
520                                                            current->objectclass->defaultObjectCategory);
521                                 }
522                                 if (!ldb_msg_find_element(msg, "nTSecurityDescriptor")) {
523                                         DATA_BLOB *sd = get_sd(ac->module, mem_ctx, current->objectclass);
524                                         ldb_msg_add_steal_value(msg, "nTSecurityDescriptor", sd);
525                                 }
526                         }
527                 }
528         }
529
530         talloc_free(mem_ctx);
531         ret = ldb_msg_sanity_check(ac->module->ldb, msg);
532
533
534         if (ret != LDB_SUCCESS) {
535                 return ret;
536         }
537
538         h->state = LDB_ASYNC_INIT;
539         h->status = LDB_SUCCESS;
540
541         ac->step = OC_DO_ADD;
542
543         /* perform the add */
544         return ldb_next_request(ac->module, ac->add_req);
545 }
546
547 static int objectclass_modify(struct ldb_module *module, struct ldb_request *req)
548 {
549         struct ldb_message_element *objectclass_element;
550         struct ldb_message *msg;
551         const struct dsdb_schema *schema = dsdb_get_schema(module->ldb);
552         int ret;
553
554         ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectclass_modify\n");
555
556         /* do not manipulate our control entries */
557         if (ldb_dn_is_special(req->op.mod.message->dn)) {
558                 return ldb_next_request(module, req);
559         }
560         
561         /* Without schema, there isn't much to do here */
562         if (!schema) {
563                 return ldb_next_request(module, req);
564         }
565         objectclass_element = ldb_msg_find_element(req->op.mod.message, "objectClass");
566
567         /* If no part of this touches the objectClass, then we don't
568          * need to make any changes.  */
569
570         /* If the only operation is the deletion of the objectClass
571          * then go on with just fixing the attribute case */
572         if (!objectclass_element) {
573                 struct ldb_request *down_req = talloc(req, struct ldb_request);
574                 if (down_req == NULL) {
575                         ldb_set_errstring(module->ldb, "Out of memory!");
576                         return LDB_ERR_OPERATIONS_ERROR;
577                 }
578                 
579                 *down_req = *req; /* copy the request */
580                 
581                 down_req->op.mod.message = msg = ldb_msg_copy_shallow(down_req, req->op.mod.message);
582                 
583                 if (down_req->op.mod.message == NULL) {
584                         return LDB_ERR_OPERATIONS_ERROR;
585                 }
586                 
587                 ret = fix_attributes(module->ldb, schema, msg);
588                 if (ret != LDB_SUCCESS) {
589                         return ret;
590                 }
591
592                 /* go on with the call chain */
593                 ret = ldb_next_request(module, down_req);
594                 
595                 /* do not free down_req as the call results may be linked to it,
596                  * it will be freed when the upper level request get freed */
597                 if (ret == LDB_SUCCESS) {
598                         req->handle = down_req->handle;
599                 }
600                 return ret;
601         }
602
603         switch (objectclass_element->flags & LDB_FLAG_MOD_MASK) {
604         case LDB_FLAG_MOD_DELETE:
605                 return LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED;
606                 break;
607         case LDB_FLAG_MOD_REPLACE:
608         {
609                 struct ldb_request *down_req;
610                 struct class_list *sorted, *current;
611                 TALLOC_CTX *mem_ctx;
612                 mem_ctx = talloc_new(req);
613                 if (mem_ctx == NULL) {
614                         return LDB_ERR_OPERATIONS_ERROR;
615                 }
616
617                 /* prepare the first operation */
618                 down_req = talloc(req, struct ldb_request);
619                 if (down_req == NULL) {
620                         ldb_set_errstring(module->ldb, "Out of memory!");
621                         talloc_free(mem_ctx);
622                         return LDB_ERR_OPERATIONS_ERROR;
623                 }
624                 
625                 *down_req = *req; /* copy the request */
626                 
627                 down_req->op.mod.message = msg = ldb_msg_copy_shallow(down_req, req->op.mod.message);
628                 
629                 if (down_req->op.mod.message == NULL) {
630                         talloc_free(mem_ctx);
631                         return LDB_ERR_OPERATIONS_ERROR;
632                 }
633                 
634                 ret = fix_attributes(module->ldb, schema, msg);
635                 if (ret != LDB_SUCCESS) {
636                         talloc_free(mem_ctx);
637                         return ret;
638                 }
639
640                 ret = objectclass_sort(module, schema, msg, mem_ctx, objectclass_element, &sorted);
641                 if (ret != LDB_SUCCESS) {
642                         return ret;
643                 }
644
645                 /* We must completely replace the existing objectClass entry,
646                  * because we need it sorted */
647                 
648                 ldb_msg_remove_attr(msg, "objectClass");
649                 ret = ldb_msg_add_empty(msg, "objectClass", LDB_FLAG_MOD_REPLACE, NULL);
650                 
651                 if (ret != LDB_SUCCESS) {
652                         talloc_free(mem_ctx);
653                         return ret;
654                 }
655
656                 /* Move from the linked list back into an ldb msg */
657                 for (current = sorted; current; current = current->next) {
658                         ret = ldb_msg_add_string(msg, "objectClass", current->objectclass->lDAPDisplayName);
659                         if (ret != LDB_SUCCESS) {
660                                 ldb_set_errstring(module->ldb, "objectclass: could not re-add sorted objectclass to modify msg");
661                                 talloc_free(mem_ctx);
662                                 return ret;
663                         }
664                 }
665                 
666                 talloc_free(mem_ctx);
667
668                 ret = ldb_msg_sanity_check(module->ldb, msg);
669                 if (ret != LDB_SUCCESS) {
670                         talloc_free(mem_ctx);
671                         return ret;
672                 }
673                 
674                 /* go on with the call chain */
675                 ret = ldb_next_request(module, down_req);
676                 
677                 /* do not free down_req as the call results may be linked to it,
678                  * it will be freed when the upper level request get freed */
679                 if (ret == LDB_SUCCESS) {
680                         req->handle = down_req->handle;
681                 }
682                 return ret;
683         }
684         }
685
686         /* This isn't the default branch of the switch, but a 'in any
687          * other case'.  When a delete isn't for all objectClasses for
688          * example
689          */
690         {
691                 struct ldb_handle *h;
692                 struct oc_context *ac;
693                 
694                 h = oc_init_handle(req, module);
695                 if (!h) {
696                         return LDB_ERR_OPERATIONS_ERROR;
697                 }
698                 ac = talloc_get_type(h->private_data, struct oc_context);
699                 
700                 /* return or own handle to deal with this call */
701                 req->handle = h;
702                 
703                 /* prepare the first operation */
704                 ac->down_req = talloc(ac, struct ldb_request);
705                 if (ac->down_req == NULL) {
706                         ldb_oom(ac->module->ldb);
707                         return LDB_ERR_OPERATIONS_ERROR;
708                 }
709                 
710                 *(ac->down_req) = *req; /* copy the request */
711                 
712                 ac->down_req->op.mod.message = msg = ldb_msg_copy_shallow(ac->down_req, req->op.mod.message);
713                 
714                 if (ac->down_req->op.mod.message == NULL) {
715                         ldb_oom(ac->module->ldb);
716                         return LDB_ERR_OPERATIONS_ERROR;
717                 }
718                 
719                 ret = fix_attributes(ac->module->ldb, schema, msg);
720                 if (ret != LDB_SUCCESS) {
721                         ldb_oom(ac->module->ldb);
722                         return ret;
723                 }
724
725                 ac->down_req->context = NULL;
726                 ac->down_req->callback = NULL;
727                 ldb_set_timeout_from_prev_req(module->ldb, req, ac->down_req);
728                 
729                 ac->step = OC_DO_REQ;
730
731                 return ldb_next_request(module, ac->down_req);
732         }
733 }
734
735 static int objectclass_search_self(struct ldb_handle *h) 
736 {
737         int ret;
738         struct oc_context *ac;
739         static const char * const attrs[] = { "objectClass", NULL };
740
741         ac = talloc_get_type(h->private_data, struct oc_context);
742
743         ret = ldb_build_search_req(&ac->search_req, ac->module->ldb,
744                                    ac, ac->orig_req->op.mod.message->dn, LDB_SCOPE_BASE,
745                                    "(objectClass=*)",
746                                    attrs, NULL, 
747                                    ac, get_search_callback);
748
749         if (ret != LDB_SUCCESS) {
750                 return ret;
751         }
752
753         ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->search_req);
754
755         ac->step = OC_SEARCH_SELF;
756
757         return ldb_next_request(ac->module, ac->search_req);
758 }
759
760 static int objectclass_do_mod(struct ldb_handle *h) {
761
762         const struct dsdb_schema *schema;
763         struct oc_context *ac;
764         struct ldb_message_element *objectclass_element;
765         struct ldb_message *msg;
766         TALLOC_CTX *mem_ctx;
767         struct class_list *sorted, *current;
768         int ret;
769       
770         ac = talloc_get_type(h->private_data, struct oc_context);
771         schema = dsdb_get_schema(ac->module->ldb);
772
773         mem_ctx = talloc_new(ac);
774         if (mem_ctx == NULL) {
775                 return LDB_ERR_OPERATIONS_ERROR;
776         }
777
778         ac->mod_req = talloc(ac, struct ldb_request);
779         if (ac->mod_req == NULL) {
780                 talloc_free(mem_ctx);
781                 return LDB_ERR_OPERATIONS_ERROR;
782         }
783
784         ac->mod_req->operation = LDB_MODIFY;
785         ac->mod_req->controls = NULL;
786         ac->mod_req->context = ac;
787         ac->mod_req->callback = NULL;
788         ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->mod_req);
789         
790         /* use a new message structure */
791         ac->mod_req->op.mod.message = msg = ldb_msg_new(ac->mod_req);
792         if (msg == NULL) {
793                 ldb_set_errstring(ac->module->ldb, "objectclass: could not create new modify msg");
794                 talloc_free(mem_ctx);
795                 return LDB_ERR_OPERATIONS_ERROR;
796         }
797
798         /* This is now the objectClass list from the database */
799         objectclass_element = ldb_msg_find_element(ac->search_res->message, 
800                                                    "objectClass");
801         if (!objectclass_element) {
802                 /* Where did it go?  bail now... */
803                 talloc_free(mem_ctx);
804                 return LDB_ERR_OPERATIONS_ERROR;
805         }
806         
807         /* modify dn */
808         msg->dn = ac->orig_req->op.mod.message->dn;
809
810         ret = objectclass_sort(ac->module, schema, msg, mem_ctx, objectclass_element, &sorted);
811         if (ret != LDB_SUCCESS) {
812                 return ret;
813         }
814
815         /* We must completely replace the existing objectClass entry.
816          * We could do a constrained add/del, but we are meant to be
817          * in a transaction... */
818
819         ret = ldb_msg_add_empty(msg, "objectClass", LDB_FLAG_MOD_REPLACE, NULL);
820         if (ret != LDB_SUCCESS) {
821                 ldb_set_errstring(ac->module->ldb, "objectclass: could not clear objectclass in modify msg");
822                 talloc_free(mem_ctx);
823                 return ret;
824         }
825         
826         /* Move from the linked list back into an ldb msg */
827         for (current = sorted; current; current = current->next) {
828                 ret = ldb_msg_add_string(msg, "objectClass", current->objectclass->lDAPDisplayName);
829                 if (ret != LDB_SUCCESS) {
830                         ldb_set_errstring(ac->module->ldb, "objectclass: could not re-add sorted objectclass to modify msg");
831                         talloc_free(mem_ctx);
832                         return ret;
833                 }
834         }
835
836         ret = ldb_msg_sanity_check(ac->module->ldb, msg);
837         if (ret != LDB_SUCCESS) {
838                 talloc_free(mem_ctx);
839                 return ret;
840         }
841
842
843         h->state = LDB_ASYNC_INIT;
844         h->status = LDB_SUCCESS;
845
846         ac->step = OC_DO_MOD;
847
848         talloc_free(mem_ctx);
849         /* perform the search */
850         return ldb_next_request(ac->module, ac->mod_req);
851 }
852
853 static int objectclass_rename(struct ldb_module *module, struct ldb_request *req)
854 {
855
856         static const char * const attrs[] = { NULL };
857
858         struct ldb_handle *h;
859         struct oc_context *ac;
860         struct ldb_dn *parent_dn;
861         int ret;
862         
863         ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectclass_rename\n");
864
865         if (ldb_dn_is_special(req->op.rename.newdn)) { /* do not manipulate our control entries */
866                 return ldb_next_request(module, req);
867         }
868         
869         /* Firstly ensure we are not trying to rename it to be a child of itself */
870         if ((ldb_dn_compare_base(req->op.rename.olddn, req->op.rename.newdn) == 0) 
871             && (ldb_dn_compare(req->op.rename.olddn, req->op.rename.newdn) != 0)) {
872                 ldb_asprintf_errstring(module->ldb, "Cannot rename %s to be a child of itself",
873                                        ldb_dn_get_linearized(req->op.rename.olddn));
874                 return LDB_ERR_UNWILLING_TO_PERFORM;
875         }
876
877         h = oc_init_handle(req, module);
878         if (!h) {
879                 return LDB_ERR_OPERATIONS_ERROR;
880         }
881         ac = talloc_get_type(h->private_data, struct oc_context);
882         
883         /* return or own handle to deal with this call */
884         req->handle = h;
885
886         parent_dn = ldb_dn_get_parent(ac, ac->orig_req->op.rename.newdn);
887         if (parent_dn == NULL) {
888                 ldb_oom(module->ldb);
889                 return LDB_ERR_OPERATIONS_ERROR;
890         }
891         ret = ldb_build_search_req(&ac->search_req, module->ldb,
892                                    ac, parent_dn, LDB_SCOPE_BASE,
893                                    "(objectClass=*)",
894                                    attrs, NULL, 
895                                    ac, get_search_callback);
896         if (ret != LDB_SUCCESS) {
897                 return ret;
898         }
899         talloc_steal(ac->search_req, parent_dn);
900         ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->search_req);
901
902         ac->step = OC_SEARCH_RENAME_PARENT;
903
904         return ldb_next_request(ac->module, ac->search_req);
905 }
906
907 static int objectclass_do_rename(struct ldb_handle *h) 
908 {
909         struct oc_context *ac;
910         int ret;
911       
912         ac = talloc_get_type(h->private_data, struct oc_context);
913
914         ac->rename_req = talloc(ac, struct ldb_request);
915         if (ac->rename_req == NULL) {
916                 return LDB_ERR_OPERATIONS_ERROR;
917         }
918
919         *ac->rename_req = *ac->orig_req;
920
921         ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->rename_req);
922         
923         /* Check we have a valid parent */
924         if (ac->search_res == NULL) {
925                 ldb_asprintf_errstring(ac->module->ldb, "objectclass: Cannot rename %s, parent does not exist!", 
926                                        ldb_dn_get_linearized(ac->orig_req->op.rename.newdn));
927                 return LDB_ERR_UNWILLING_TO_PERFORM;
928         }
929         
930         /* Fix up the DN to be in the standard form, taking particular care to match the parent DN */
931         ret = fix_dn(ac->rename_req, 
932                      ac->orig_req->op.rename.newdn, 
933                      ac->search_res->message->dn, 
934                      &ac->rename_req->op.rename.newdn);
935
936         if (ret != LDB_SUCCESS) {
937                 return ret;
938         }
939
940         /* TODO: Check this is a valid child to this parent,
941          * by reading the allowedChildClasses and
942          * allowedChildClasssesEffective attributes */
943
944         h->state = LDB_ASYNC_INIT;
945         h->status = LDB_SUCCESS;
946
947         ac->step = OC_DO_RENAME;
948
949         /* perform the rename */
950         return ldb_next_request(ac->module, ac->rename_req);
951 }
952
953 static int oc_wait(struct ldb_handle *handle) {
954         struct oc_context *ac;
955         int ret;
956     
957         if (!handle || !handle->private_data) {
958                 return LDB_ERR_OPERATIONS_ERROR;
959         }
960
961         if (handle->state == LDB_ASYNC_DONE) {
962                 return handle->status;
963         }
964
965         handle->state = LDB_ASYNC_PENDING;
966         handle->status = LDB_SUCCESS;
967
968         ac = talloc_get_type(handle->private_data, struct oc_context);
969
970         switch (ac->step) {
971         case OC_DO_REQ:
972                 ret = ldb_wait(ac->down_req->handle, LDB_WAIT_NONE);
973
974                 if (ret != LDB_SUCCESS) {
975                         handle->status = ret;
976                         goto done;
977                 }
978                 if (ac->down_req->handle->status != LDB_SUCCESS) {
979                         handle->status = ac->down_req->handle->status;
980                         goto done;
981                 }
982
983                 if (ac->down_req->handle->state != LDB_ASYNC_DONE) {
984                         return LDB_SUCCESS;
985                 }
986
987                 /* mods done, go on */
988                 return objectclass_search_self(handle);
989
990         case OC_SEARCH_SELF:
991                 ret = ldb_wait(ac->search_req->handle, LDB_WAIT_NONE);
992
993                 if (ret != LDB_SUCCESS) {
994                         handle->status = ret;
995                         goto done;
996                 }
997                 if (ac->search_req->handle->status != LDB_SUCCESS) {
998                         handle->status = ac->search_req->handle->status;
999                         goto done;
1000                 }
1001
1002                 if (ac->search_req->handle->state != LDB_ASYNC_DONE) {
1003                         return LDB_SUCCESS;
1004                 }
1005
1006                 /* self search done, go on */
1007                 return objectclass_do_mod(handle);
1008
1009         case OC_DO_MOD:
1010                 ret = ldb_wait(ac->mod_req->handle, LDB_WAIT_NONE);
1011
1012                 if (ret != LDB_SUCCESS) {
1013                         handle->status = ret;
1014                         goto done;
1015                 }
1016                 if (ac->mod_req->handle->status != LDB_SUCCESS) {
1017                         handle->status = ac->mod_req->handle->status;
1018                         goto done;
1019                 }
1020
1021                 if (ac->mod_req->handle->state != LDB_ASYNC_DONE) {
1022                         return LDB_SUCCESS;
1023                 }
1024
1025                 break;
1026                 
1027         case OC_SEARCH_ADD_PARENT:
1028                 ret = ldb_wait(ac->search_req->handle, LDB_WAIT_NONE);
1029
1030                 if (ret != LDB_SUCCESS) {
1031                         handle->status = ret;
1032                         goto done;
1033                 }
1034                 if (ac->search_req->handle->status != LDB_SUCCESS) {
1035                         handle->status = ac->search_req->handle->status;
1036                         goto done;
1037                 }
1038
1039                 if (ac->search_req->handle->state != LDB_ASYNC_DONE) {
1040                         return LDB_SUCCESS;
1041                 }
1042
1043                 /* parent search done, go on */
1044                 return objectclass_do_add(handle);
1045
1046         case OC_DO_ADD:
1047                 ret = ldb_wait(ac->add_req->handle, LDB_WAIT_NONE);
1048
1049                 if (ret != LDB_SUCCESS) {
1050                         handle->status = ret;
1051                         goto done;
1052                 }
1053                 if (ac->add_req->handle->status != LDB_SUCCESS) {
1054                         handle->status = ac->add_req->handle->status;
1055                         goto done;
1056                 }
1057
1058                 if (ac->add_req->handle->state != LDB_ASYNC_DONE) {
1059                         return LDB_SUCCESS;
1060                 }
1061
1062                 break;
1063                 
1064         case OC_SEARCH_RENAME_PARENT:
1065                 ret = ldb_wait(ac->search_req->handle, LDB_WAIT_NONE);
1066
1067                 if (ret != LDB_SUCCESS) {
1068                         handle->status = ret;
1069                         goto done;
1070                 }
1071                 if (ac->search_req->handle->status != LDB_SUCCESS) {
1072                         handle->status = ac->search_req->handle->status;
1073                         goto done;
1074                 }
1075
1076                 if (ac->search_req->handle->state != LDB_ASYNC_DONE) {
1077                         return LDB_SUCCESS;
1078                 }
1079
1080                 /* parent search done, go on */
1081                 return objectclass_do_rename(handle);
1082
1083         case OC_DO_RENAME:
1084                 ret = ldb_wait(ac->rename_req->handle, LDB_WAIT_NONE);
1085
1086                 if (ret != LDB_SUCCESS) {
1087                         handle->status = ret;
1088                         goto done;
1089                 }
1090                 if (ac->rename_req->handle->status != LDB_SUCCESS) {
1091                         handle->status = ac->rename_req->handle->status;
1092                         goto done;
1093                 }
1094
1095                 if (ac->rename_req->handle->state != LDB_ASYNC_DONE) {
1096                         return LDB_SUCCESS;
1097                 }
1098
1099                 break;
1100                 
1101         default:
1102                 ret = LDB_ERR_OPERATIONS_ERROR;
1103                 goto done;
1104         }
1105
1106         ret = LDB_SUCCESS;
1107
1108 done:
1109         handle->state = LDB_ASYNC_DONE;
1110         return ret;
1111 }
1112
1113 static int oc_wait_all(struct ldb_handle *handle) {
1114
1115         int ret;
1116
1117         while (handle->state != LDB_ASYNC_DONE) {
1118                 ret = oc_wait(handle);
1119                 if (ret != LDB_SUCCESS) {
1120                         return ret;
1121                 }
1122         }
1123
1124         return handle->status;
1125 }
1126
1127 static int objectclass_wait(struct ldb_handle *handle, enum ldb_wait_type type)
1128 {
1129         if (type == LDB_WAIT_ALL) {
1130                 return oc_wait_all(handle);
1131         } else {
1132                 return oc_wait(handle);
1133         }
1134 }
1135
1136 static const struct ldb_module_ops objectclass_ops = {
1137         .name              = "objectclass",
1138         .add           = objectclass_add,
1139         .modify        = objectclass_modify,
1140         .rename        = objectclass_rename,
1141         .wait          = objectclass_wait
1142 };
1143
1144 int ldb_objectclass_init(void)
1145 {
1146         return ldb_register_module(&objectclass_ops);
1147 }
1148