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