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