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