36b7916e95f1ff0284da99704733b384f1ef4a0b
[kai/samba-autobuild/.git] / source4 / dsdb / samdb / ldb_modules / schema.c
1 /* 
2    ldb database library
3
4    Copyright (C) Simo Sorce  2004-2006
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 /*
22  *  Name: ldb
23  *
24  *  Component: ldb schema module
25  *
26  *  Description: add schema check functionality
27  *
28  *  Author: Simo Sorce
29  *
30  *  License: GNU GPL v2 or Later
31  */
32
33 #include "includes.h"
34 #include "libcli/ldap/ldap.h"
35 #include "ldb/include/ldb_errors.h"
36 #include "ldb/include/ldb_private.h"
37 #include "lib/util/dlinklist.h"
38 #include "schema_syntax.h"
39
40 /* Syntax-Table
41
42    see ldap_server/devdocs/AD-syntaxes.txt
43 */
44
45 enum schema_class_type {
46         SCHEMA_CT_88            = 0,
47         SCHEMA_CT_STRUCTURAL    = 1,
48         SCHEMA_CT_ABSTRACT      = 2,
49         SCHEMA_CT_AUXILIARY     = 3
50 };
51
52 struct schema_attribute {
53         char *OID;                              /* attributeID     */
54         char *name;                             /* lDAPDisplayName */
55         enum schema_internal_syntax syntax;     /* generated from attributeSyntax, oMSyntax, oMObjectClass */
56         bool single;                            /* isSingleValued  */
57         int min;                                /* rangeLower      */
58         int max;                                /* rangeUpper      */
59         int systemflag;                         /* systemFlag      */
60         int searchflag;                         /* searchFlag      */
61         bool isdefunct;                         /* isDefunct       */
62 };
63
64 struct schema_class {
65         char *OID;                              /* governsID             */
66         char *name;                             /* lDAPDisplayName       */
67         enum schema_class_type type;            /* objectClassCategory   */
68         bool systemOnly;                        /* systemOnly            */
69         bool isdefunct;                         /* isDefunct             */
70         int systemflag;                         /* systemFlag            */
71         char *defobjcat;                        /* defaultObjectCategory */
72         struct schema_class *parent;            /* subClassOf            */
73         struct schema_class **sysaux;           /* systemAuxiliaryClass  */
74         struct schema_class **aux;              /* auxiliaryClass        */
75         struct schema_class **sysposssup;       /* systemPossSuperiors   */
76         struct schema_class **posssup;          /* possSuperiors         */
77         struct schema_class **possinf;          /* possibleInferiors     */
78         struct schema_attribute **sysmust;      /* systemMustContain     */
79         struct schema_attribute **must;         /* MustContain           */
80         struct schema_attribute **sysmay;       /* systemMayContain      */
81         struct schema_attribute **may;          /* MayContain            */
82 };
83
84 /* TODO: ditcontentrules */
85
86 struct schema_private_data {
87         struct ldb_dn *schema_dn;
88         struct schema_attribute **attrs;
89         struct schema_store *attrs_store;
90         int num_attributes;
91         struct schema_class **class;
92         struct schema_store *class_store;
93         int num_classes;
94 };
95
96 struct schema_class_dlist {
97         struct schema_class *class;
98         struct schema_class_dlist *prev;
99         struct schema_class_dlist *next;
100         enum schema_class_type role;
101 };
102
103 struct schema_context {
104
105         enum sc_op { SC_ADD, SC_MOD, SC_DEL, SC_RENAME } op;
106         enum sc_step { SC_INIT, SC_ADD_CHECK_PARENT, SC_ADD_TEMP, SC_DEL_CHECK_CHILDREN } step;
107
108         struct schema_private_data *data;
109
110         struct ldb_module *module;
111         struct ldb_request *orig_req;
112         struct ldb_request *down_req;
113
114         struct ldb_request *parent_req;
115         struct ldb_reply *parent_res;
116
117         struct schema_class_dlist *class_list;
118         struct schema_class **sup_list;
119         struct schema_class **aux_list;
120 };
121
122 /* FIXME: I'd really like to use an hash table here */
123 struct schema_link {
124         const char *name;
125         void *object;
126 };
127
128 struct schema_store {
129         struct schema_link *store;
130         int num_links;
131 };
132
133 static struct schema_store *schema_store_new(TALLOC_CTX *mem_ctx)
134 {
135         struct schema_store *ht;
136         
137         ht = talloc(mem_ctx, struct schema_store);
138         if (!ht) return NULL;
139
140         ht->store = NULL;
141         ht->num_links = 0;
142
143         return ht;
144 }
145         
146 static int schema_store_add(struct schema_store *ht, const char *key, void *object)
147 {
148         ht->store = talloc_realloc(ht, ht->store, struct schema_link, ht->num_links + 1);
149         if (!ht->store) return LDB_ERR_OPERATIONS_ERROR;
150
151         ht->store[ht->num_links].name = key;
152         ht->store[ht->num_links].object = object;
153
154         ht->num_links++;
155
156         return LDB_SUCCESS;
157 }
158
159 static void *schema_store_find(struct schema_store *ht, const char *key)
160 {
161         int i;
162
163         for (i = 0; i < ht->num_links; i++) {
164                 if (strcasecmp(ht->store[i].name, key) == 0) {
165                         return ht->store[i].object;
166                 }
167         }
168
169         return NULL;
170 }
171
172 #define SCHEMA_CHECK_VALUE(mem, val, mod) \
173                 do { if (mem == val) { \
174                         ret = LDB_ERR_OPERATIONS_ERROR; \
175                         ldb_asprintf_errstring(mod->ldb, \
176                                 "schema module: Memory allocation or attribute error on %s", #mem); \
177                         goto done; } } while(0)
178
179 struct schema_class **schema_get_class_list(struct ldb_module *module,
180                                             struct schema_private_data *data,
181                                             struct ldb_message_element *el)
182 {
183         struct schema_class **list;
184         int i;
185         
186         list = talloc_array(data, struct schema_class *, el->num_values + 1);
187         if (!list) {
188                 ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Out of Memory");
189                 return NULL;
190         }
191         
192         for (i = 0; i < el->num_values; i++) {
193                 list[i] = (struct schema_class *)schema_store_find(data->class_store,
194                                                                   (char *)el->values[i].data);
195                 if (!list[i]) {
196                         ldb_debug_set(module->ldb,
197                                         LDB_DEBUG_ERROR,
198                                         "Class %s referenced but not found in schema\n",
199                                         (char *)el->values[i].data);
200                         return NULL;
201                 }
202         }
203         list[i] = NULL;
204
205         return list;
206 }
207
208 struct schema_attribute **schema_get_attrs_list(struct ldb_module *module,
209                                                 struct schema_private_data *data,
210                                                 struct ldb_message_element *el)
211 {
212         struct schema_attribute **list;
213         int i;
214
215         list = talloc_array(data, struct schema_attribute *, el->num_values + 1);
216         if (!list) {
217                 ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Out of Memory");
218                 return NULL;
219         }
220         
221         for (i = 0; i < el->num_values; i++) {
222                 list[i] = (struct schema_attribute *)schema_store_find(data->attrs_store,
223                                                                       (char *)el->values[i].data);
224                 if (!list[i]) {
225                         ldb_debug_set(module->ldb,
226                                         LDB_DEBUG_ERROR,
227                                         "Attriobute %s referenced but not found in schema\n",
228                                         (char *)el->values[i].data);
229                         return NULL;
230                 }
231         }
232         list[i] = NULL;
233
234         return list;
235 }
236
237 static int map_schema_syntax(uint32_t om_syntax, const char *attr_syntax, const struct ldb_val *om_class, enum schema_internal_syntax *syntax)
238 {
239         int ret;
240
241         ret = LDB_SUCCESS;
242
243         switch(om_syntax) {
244         case 1:
245                 *syntax = SCHEMA_AS_BOOLEAN;
246                 break;
247         case 2:
248                 *syntax = SCHEMA_AS_INTEGER;
249                 break;
250         case 4:
251                 if (strcmp(attr_syntax, "2.5.5.10") == 0) {
252                         *syntax = SCHEMA_AS_OCTET_STRING;
253                         break;
254                 }
255                 if (strcmp(attr_syntax, "2.5.5.17") == 0) {
256                         *syntax = SCHEMA_AS_SID;
257                         break;
258                 }
259                 ret = LDB_ERR_OPERATIONS_ERROR;
260                 break;
261         case 6:
262                 *syntax = SCHEMA_AS_OID;
263                 break;
264         case 10:
265                 *syntax = SCHEMA_AS_ENUMERATION;
266                 break;
267         case 18:
268                 *syntax = SCHEMA_AS_NUMERIC_STRING;
269                 break;
270         case 19:
271                 *syntax = SCHEMA_AS_PRINTABLE_STRING;
272                 break;
273         case 20:
274                 *syntax = SCHEMA_AS_CASE_IGNORE_STRING;
275                 break;
276         case 22:
277                 *syntax = SCHEMA_AS_IA5_STRING;
278                 break;
279         case 23:
280                 *syntax = SCHEMA_AS_UTC_TIME;
281                 break;
282         case 24:
283                 *syntax = SCHEMA_AS_GENERALIZED_TIME;
284                 break;
285         case 27:
286                 *syntax = SCHEMA_AS_CASE_SENSITIVE_STRING;
287                 break;
288         case 64:
289                 *syntax = SCHEMA_AS_DIRECTORY_STRING;
290                 break;
291         case 65:
292                 *syntax = SCHEMA_AS_LARGE_INTEGER;
293                 break;
294         case 66:
295                 *syntax = SCHEMA_AS_OBJECT_SECURITY_DESCRIPTOR;
296                 break;
297         case 127:
298                 if (!om_class) {
299                         ret = LDB_ERR_OPERATIONS_ERROR;
300                         break;
301                 }
302                 
303                 if (memcmp(om_class->data, "\x2b\x0c\x02\x87\x73\x1c\x00\x85\x4a\x00", MIN(om_class->length, 10)) == 0) {
304                         *syntax = SCHEMA_AS_DN;
305                         break;
306                 }
307                 if (memcmp(om_class->data, "\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0b", MIN(om_class->length, 10)) == 0) {
308                         *syntax = SCHEMA_AS_DN_BINARY;
309                         break;
310                 }
311                 if (memcmp(om_class->data, "\x56\x06\x01\x02\x05\x0b\x1d\x00\x00\x00", MIN(om_class->length, 10)) == 0) {
312                         *syntax = SCHEMA_AS_OR_NAME;
313                         break;
314                 }
315                 if (memcmp(om_class->data, "\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x06", MIN(om_class->length, 10)) == 0) {
316                         *syntax = SCHEMA_AS_REPLICA_LINK;
317                         break;
318                 }
319                 if (memcmp(om_class->data, "\x2b\x0c\x02\x87\x73\x1c\x00\x85\x5c\x00", MIN(om_class->length, 10)) == 0) {
320                         *syntax = SCHEMA_AS_PRESENTATION_ADDRESS;
321                         break;
322                 }
323                 if (memcmp(om_class->data, "\x2b\x0c\x02\x87\x73\x1c\x00\x85\x3e\x00", MIN(om_class->length, 10)) == 0) {
324                         *syntax = SCHEMA_AS_ACCESS_POINT;
325                         break;
326                 }
327                 if (memcmp(om_class->data, "\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0c", MIN(om_class->length, 10)) == 0) {
328                         *syntax = SCHEMA_AS_DN_STRING;
329                         break;
330                 }
331                 /* not found will error in default: */
332         default:
333                 ret = LDB_ERR_OPERATIONS_ERROR;
334         }
335
336         return ret;
337 }
338
339 static int schema_init_attrs(struct ldb_module *module, struct schema_private_data *data)
340 {
341         static const char *schema_attrs[] = {   "attributeID",
342                                                 "lDAPDisplayName",
343                                                 "attributeSyntax",
344                                                 "oMSyntax",
345                                                 "oMObjectClass",
346                                                 "isSingleValued",
347                                                 "rangeLower",
348                                                 "rangeUpper",
349                                                 "searchFlag",
350                                                 "systemFlag",
351                                                 "isDefunct",
352                                                 NULL };
353         struct ldb_result *res;
354         int ret, i;
355
356         ret = ldb_search(module->ldb,
357                          data->schema_dn,
358                          LDB_SCOPE_SUBTREE,
359                          "(objectClass=attributeSchema)",
360                          schema_attrs,
361                          &res);
362
363         if (ret != LDB_SUCCESS) {
364                 goto done;
365         }
366
367         data->num_attributes = res->count;
368         data->attrs = talloc_array(data, struct schema_attribute *, res->count);
369         SCHEMA_CHECK_VALUE(data->attrs, NULL, module);
370
371         data->attrs_store = schema_store_new(data);
372         SCHEMA_CHECK_VALUE(data->attrs_store, NULL, module);
373         
374         for (i = 0; i < res->count; i++) {
375                 const char *tmp_single;
376                 const char *attr_syntax;
377                 uint32_t om_syntax;
378                 const struct ldb_val *om_class;
379
380                 data->attrs[i] = talloc(data->attrs, struct schema_attribute);
381                 SCHEMA_CHECK_VALUE(data->attrs[i], NULL, module);
382
383                 data->attrs[i]->OID = talloc_strdup(data->attrs[i],
384                                                 ldb_msg_find_attr_as_string(res->msgs[i], "attributeID", NULL));
385                 SCHEMA_CHECK_VALUE(data->attrs[i]->OID, NULL, module);
386                 
387                 data->attrs[i]->name = talloc_strdup(data->attrs[i],
388                                                 ldb_msg_find_attr_as_string(res->msgs[i], "lDAPDisplayName", NULL));
389                 SCHEMA_CHECK_VALUE(data->attrs[i]->name, NULL, module);
390
391                 /* once we have both the OID and the attribute name, add the pointer to the store */
392                 schema_store_add(data->attrs_store, data->attrs[i]->OID, data->attrs[i]);
393                 schema_store_add(data->attrs_store, data->attrs[i]->name, data->attrs[i]);
394
395                 attr_syntax = ldb_msg_find_attr_as_string(res->msgs[i], "attributeSyntax", NULL);
396                 SCHEMA_CHECK_VALUE(attr_syntax, NULL, module);
397                 
398                 om_syntax = ldb_msg_find_attr_as_uint(res->msgs[i], "oMSyntax", 0);
399                 /* 0 is not a valid oMSyntax */
400                 SCHEMA_CHECK_VALUE(om_syntax, 0, module);
401
402                 om_class = ldb_msg_find_ldb_val(res->msgs[i], "oMObjectClass");
403
404                 ret = map_schema_syntax(om_syntax, attr_syntax, om_class, &data->attrs[i]->syntax);
405                 if (ret != LDB_SUCCESS) {
406                         ldb_asprintf_errstring(module->ldb,
407                                 "schema module: invalid om syntax value on %s",
408                                 data->attrs[i]->name);
409                         goto done;
410                 }
411                 
412                 tmp_single = ldb_msg_find_attr_as_string(res->msgs[i], "isSingleValued", NULL);
413                 SCHEMA_CHECK_VALUE(tmp_single, NULL, module);
414                 if (strcmp(tmp_single, "TRUE") == 0) {
415                         data->attrs[i]->single = 1;
416                 } else {
417                         data->attrs[i]->single = 0;
418                 }
419
420                 /* the following are optional */
421                 data->attrs[i]->min = ldb_msg_find_attr_as_int(res->msgs[i], "rangeLower", INT_MIN);
422                 data->attrs[i]->max = ldb_msg_find_attr_as_int(res->msgs[i], "rangeUpper", INT_MAX);
423                 data->attrs[i]->systemflag = ldb_msg_find_attr_as_int(res->msgs[i], "systemFlag", 0);
424                 data->attrs[i]->searchflag = ldb_msg_find_attr_as_int(res->msgs[i], "searchFlag", 0);
425                 data->attrs[i]->isdefunct = ldb_msg_find_attr_as_bool(res->msgs[i], "isDefunct", False);
426         }
427
428 done:
429         talloc_free(res);
430         return ret;
431 }
432
433 static int schema_init_classes(struct ldb_module *module, struct schema_private_data *data)
434 {
435         static const char *schema_attrs[] = {   "governsID",
436                                                 "lDAPDisplayName",
437                                                 "objectClassCategory",
438                                                 "defaultObjectCategory"
439                                                 "systemOnly",
440                                                 "systemFlag",
441                                                 "isDefunct",
442                                                 "subClassOf",
443                                                 "systemAuxiliaryClass",
444                                                 "auxiliaryClass",
445                                                 "systemPossSuperiors",
446                                                 "possSuperiors",
447                                                 "possibleInferiors",
448                                                 "systemMustContain",
449                                                 "MustContain", 
450                                                 "systemMayContain",
451                                                 "MayContain",
452                                                 NULL };
453         struct ldb_result *res;
454         int ret, i;
455
456         ret = ldb_search(module->ldb,
457                          data->schema_dn,
458                          LDB_SCOPE_SUBTREE,
459                          "(objectClass=classSchema)",
460                          schema_attrs,
461                          &res);
462
463         if (ret != LDB_SUCCESS) {
464                 goto done;
465         }
466
467         data->num_classes = res->count;
468         data->class = talloc_array(data, struct schema_class *, res->count);
469         SCHEMA_CHECK_VALUE(data->class, NULL, module);
470
471         data->class_store = schema_store_new(data);
472         SCHEMA_CHECK_VALUE(data->class_store, NULL, module);
473
474         for (i = 0; i < res->count; i++) {
475                 struct ldb_message_element *el;
476
477                 data->class[i] = talloc(data->class, struct schema_class);
478                 SCHEMA_CHECK_VALUE(data->class[i], NULL, module);
479
480                 data->class[i]->OID = talloc_strdup(data->class[i],
481                                                 ldb_msg_find_attr_as_string(res->msgs[i], "governsID", NULL));
482                 SCHEMA_CHECK_VALUE(data->class[i]->OID, NULL, module);
483
484                 data->class[i]->name = talloc_strdup(data->class[i],
485                                                 ldb_msg_find_attr_as_string(res->msgs[i], "lDAPDisplayName", NULL));
486                 SCHEMA_CHECK_VALUE(data->class[i]->name, NULL, module);
487
488                 /* once we have both the OID and the class name, add the pointer to the store */
489                 schema_store_add(data->class_store, data->class[i]->OID, data->class[i]);
490                 schema_store_add(data->class_store, data->class[i]->name, data->class[i]);
491
492                 data->class[i]->type = ldb_msg_find_attr_as_int(res->msgs[i], "objectClassCategory", -1);
493                 /* 0 should not be a valid value, but turn out it is so test with -1 */
494                 SCHEMA_CHECK_VALUE(data->class[i]->type, -1, module);
495
496                 data->class[i]->defobjcat = talloc_strdup(data->class[i],
497                                                 ldb_msg_find_attr_as_string(res->msgs[i],
498                                                                         "defaultObjectCategory", NULL));
499                 SCHEMA_CHECK_VALUE(data->class[i]->defobjcat, NULL, module);
500
501                 /* the following attributes are all optional */
502
503                 data->class[i]->systemOnly = ldb_msg_find_attr_as_bool(res->msgs[i], "systemOnly", False);
504                 data->class[i]->systemflag = ldb_msg_find_attr_as_int(res->msgs[i], "systemFlag", 0);
505                 data->class[i]->isdefunct = ldb_msg_find_attr_as_bool(res->msgs[i], "isDefunct", False);
506
507                 /* attributes are loaded first, so we can just go an query the attributes repo */
508                 
509                 el = ldb_msg_find_element(res->msgs[i], "systemMustContain");
510                 if (el) {
511                         data->class[i]->sysmust = schema_get_attrs_list(module, data, el);
512                         SCHEMA_CHECK_VALUE(data->class[i]->sysmust, NULL, module);
513                 }
514
515                 el = ldb_msg_find_element(res->msgs[i], "MustContain");
516                 if (el) {
517                         data->class[i]->must = schema_get_attrs_list(module, data, el);
518                         SCHEMA_CHECK_VALUE(data->class[i]->must, NULL, module);
519                 }
520
521                 el = ldb_msg_find_element(res->msgs[i], "systemMayContain");
522                 if (el) {
523                         data->class[i]->sysmay = schema_get_attrs_list(module, data, el);
524                         SCHEMA_CHECK_VALUE(data->class[i]->sysmay, NULL, module);
525                 }
526
527                 el = ldb_msg_find_element(res->msgs[i], "MayContain");
528                 if (el) {
529                         data->class[i]->may = schema_get_attrs_list(module, data, el);
530                         SCHEMA_CHECK_VALUE(data->class[i]->may, NULL, module);
531                 }
532
533         }
534
535         /* subClassOf, systemAuxiliaryClass, auxiliaryClass, systemPossSuperiors
536          * must be filled in a second loop, when all class objects are allocated
537          * or we may not find a class that has not yet been parsed */
538         for (i = 0; i < res->count; i++) {
539                 struct ldb_message_element *el;
540                 const char *attr;
541
542                 /* this is single valued anyway */
543                 attr = ldb_msg_find_attr_as_string(res->msgs[i], "subClassOf", NULL);
544                 SCHEMA_CHECK_VALUE(attr, NULL, module);
545                 data->class[i]->parent = schema_store_find(data->class_store, attr);
546                 SCHEMA_CHECK_VALUE(data->class[i]->parent, NULL, module);
547
548                 /* the following attributes are all optional */
549
550                 data->class[i]->sysaux = NULL;
551                 el = ldb_msg_find_element(res->msgs[i], "systemAuxiliaryClass");
552                 if (el) {
553                         data->class[i]->sysaux = schema_get_class_list(module, data, el); 
554                         SCHEMA_CHECK_VALUE(data->class[i]->sysaux, NULL, module);
555                 }
556
557                 data->class[i]->aux = NULL;
558                 el = ldb_msg_find_element(res->msgs[i], "auxiliaryClass");
559                 if (el) {
560                         data->class[i]->aux = schema_get_class_list(module, data, el); 
561                         SCHEMA_CHECK_VALUE(data->class[i]->aux, NULL, module);
562                 }
563
564                 data->class[i]->sysposssup = NULL;
565                 el = ldb_msg_find_element(res->msgs[i], "systemPossSuperiors");
566                 if (el) {
567                         data->class[i]->sysposssup = schema_get_class_list(module, data, el); 
568                         SCHEMA_CHECK_VALUE(data->class[i]->sysposssup, NULL, module);
569                 }
570
571                 data->class[i]->posssup = NULL;
572                 el = ldb_msg_find_element(res->msgs[i], "possSuperiors");
573                 if (el) {
574                         data->class[i]->posssup = schema_get_class_list(module, data, el); 
575                         SCHEMA_CHECK_VALUE(data->class[i]->posssup, NULL, module);
576                 }
577
578                 data->class[i]->possinf = NULL;
579                 el = ldb_msg_find_element(res->msgs[i], "possibleInferiors");
580                 if (el) {
581                         data->class[i]->possinf = schema_get_class_list(module, data, el); 
582                         SCHEMA_CHECK_VALUE(data->class[i]->possinf, NULL, module);
583                 }
584         }
585
586 done:
587         talloc_free(res);
588         return ret;
589 }
590
591 static struct ldb_handle *schema_init_handle(struct ldb_request *req, struct ldb_module *module, enum sc_op op)
592 {
593         struct schema_context *sctx;
594         struct ldb_handle *h;
595
596         h = talloc_zero(req, struct ldb_handle);
597         if (h == NULL) {
598                 ldb_set_errstring(module->ldb, "Out of Memory");
599                 return NULL;
600         }
601
602         h->module = module;
603
604         sctx = talloc_zero(h, struct schema_context);
605         if (sctx == NULL) {
606                 ldb_set_errstring(module->ldb, "Out of Memory");
607                 talloc_free(h);
608                 return NULL;
609         }
610
611         h->private_data = (void *)sctx;
612
613         h->state = LDB_ASYNC_INIT;
614         h->status = LDB_SUCCESS;
615
616         sctx->op = op;
617         sctx->step = SC_INIT;
618         sctx->data = module->private_data;
619         sctx->module = module;
620         sctx->orig_req = req;
621
622         return h;
623 }
624
625 static int schema_add_check_parent(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
626 {
627         struct schema_context *sctx;
628
629         if (!context || !ares) {
630                 ldb_set_errstring(ldb, "NULL Context or Result in callback");
631                 return LDB_ERR_OPERATIONS_ERROR;
632         }
633
634         sctx = talloc_get_type(context, struct schema_context);
635
636         /* we are interested only in the single reply (base search) we receive here */
637         if (ares->type == LDB_REPLY_ENTRY) {
638                 if (sctx->parent_res != NULL) {
639                         ldb_set_errstring(ldb, "Too many results");
640                         talloc_free(ares);
641                         return LDB_ERR_OPERATIONS_ERROR;
642                 }
643                 sctx->parent_res = talloc_steal(sctx, ares);
644         } else {
645                 talloc_free(ares);
646         }
647
648         return LDB_SUCCESS;
649 }
650
651 static int schema_add_build_parent_req(struct schema_context *sctx)
652 {
653         static const char * const parent_attrs[] = { "objectClass", NULL };
654         int ret;
655
656         sctx->parent_req = talloc_zero(sctx, struct ldb_request);
657         if (sctx->parent_req == NULL) {
658                 ldb_debug(sctx->module->ldb, LDB_DEBUG_ERROR, "Out of Memory!\n");
659                 return LDB_ERR_OPERATIONS_ERROR;
660         }
661
662         sctx->parent_req->operation = LDB_SEARCH;
663         sctx->parent_req->op.search.scope = LDB_SCOPE_BASE;
664         sctx->parent_req->op.search.base = ldb_dn_get_parent(sctx->parent_req, sctx->orig_req->op.add.message->dn);
665         sctx->parent_req->op.search.tree = ldb_parse_tree(sctx->module->ldb, "(objectClass=*)");
666         sctx->parent_req->op.search.attrs = parent_attrs;
667         sctx->parent_req->controls = NULL;
668         sctx->parent_req->context = sctx;
669         sctx->parent_req->callback = schema_add_check_parent;
670         ret = ldb_set_timeout_from_prev_req(sctx->module->ldb, sctx->orig_req, sctx->parent_req);
671
672         return ret;
673 }
674
675 static struct schema_class_dlist *schema_add_get_dlist_entry_with_class(struct schema_class_dlist *list, struct schema_class *class)
676 {
677         struct schema_class_dlist *temp;
678
679         for (temp = list; temp && (temp->class != class); temp = temp->next) /* noop */ ;
680         return temp;
681 }
682
683 static int schema_add_class_to_dlist(struct schema_class_dlist *list, struct schema_class *class, enum schema_class_type role)
684 {
685         struct schema_class_dlist *entry;
686         struct schema_class_dlist *temp;
687         int ret;
688
689         /* see if this class is usable */
690         if (class->isdefunct) {
691                 return LDB_ERR_NO_SUCH_ATTRIBUTE;
692         }
693
694         /* see if this class already exist in the class list */
695         if (schema_add_get_dlist_entry_with_class(list, class)) {
696                 return LDB_SUCCESS;
697         }
698
699         /* this is a new class go on and add to the list */
700         entry = talloc_zero(list, struct schema_class_dlist);
701         if (!entry) return LDB_ERR_OPERATIONS_ERROR;
702         entry->class = class;
703         entry->role = class->type;
704
705         /* If parent is top (list is guaranteed to start always with top) */
706         if (class->parent == list->class) {
707                 /* if the hierarchy role is structural try to add it just after top */
708                 if (role == SCHEMA_CT_STRUCTURAL) {
709                         /* but check no other class at after top has a structural role */
710                         if (list->next && (list->next->role == SCHEMA_CT_STRUCTURAL)) {
711                                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
712                         }
713                         DLIST_ADD_AFTER(list, entry, list);
714                 } else {
715                         DLIST_ADD_END(list, entry, struct schema_class_dlist *);
716                 }
717                 return LDB_SUCCESS;
718         }
719
720         /* search if parent has already been added */
721         temp = schema_add_get_dlist_entry_with_class(list->next, class->parent);
722         if (temp == NULL) {
723                 ret = schema_add_class_to_dlist(list, class->parent, role);
724                 if (ret != LDB_SUCCESS) {
725                         return ret;
726                 }
727                 temp = schema_add_get_dlist_entry_with_class(list->next, class->parent);
728         }
729         if (!temp) { /* parent not found !? */
730                 return LDB_ERR_OPERATIONS_ERROR;
731         }
732
733         DLIST_ADD_AFTER(list, entry, temp);
734         if (role == SCHEMA_CT_STRUCTURAL || role == SCHEMA_CT_AUXILIARY) {
735                 temp = entry;
736                 do {
737                         temp->role = role;
738                         temp = temp->prev;
739                         /* stop when hierarchy base is met or when base class parent is top */
740                 } while (temp->class == temp->next->class->parent &&
741                          temp->next->class->parent != list->class);
742
743                 /* if we have not reached the head of the list
744                  * and role is structural */
745                 if (temp != list && role == SCHEMA_CT_STRUCTURAL) {
746                         struct schema_class_dlist *hfirst, *hlast;
747
748                         /* check if the list second entry is structural */
749                         if (list->next->role == SCHEMA_CT_STRUCTURAL) {
750                                 /* we have a confilict here */
751                                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
752                         }
753                         /* we have to move this hierarchy of classes
754                          * so that the base of the structural hierarchy is right after top */
755                          
756                         hfirst = temp->next;
757                         hlast = entry;
758                         /* now hfirst - hlast are the boundaries of the structural hierarchy */
759                         
760                         /* extract the structural hierachy from the list */
761                         hfirst->prev->next = hlast->next;
762                         if (hlast->next) hlast->next->prev = hfirst->prev;
763                         
764                         /* insert the structural hierarchy just after top */
765                         list->next->prev = hlast;
766                         hlast->next = list->next;
767                         list->next = hfirst;
768                         hfirst->prev = list;
769                 }       
770         }
771
772         return LDB_SUCCESS;
773 }
774
775 /* merge source list into dest list and remove duplicates */
776 static int schema_merge_class_list(TALLOC_CTX *mem_ctx, struct schema_class ***dest, struct schema_class **source)
777 {
778         struct schema_class **list = *dest;
779         int i, j, n, f;
780
781         n = 0;  
782         if (list) for (n = 0; list[n]; n++) /* noop */ ;
783         f = n;
784
785         for (i = 0; source[i]; i++) {
786                 for (j = 0; j < f; j++) {
787                         if (list[j] == source[i]) {
788                                 break;
789                         }
790                 }
791                 if (j < f) { /* duplicate found */
792                         continue;
793                 }
794
795                 list = talloc_realloc(mem_ctx, list, struct schema_class *, n + 2);
796                 if (!list) {
797                         return LDB_ERR_OPERATIONS_ERROR;
798                 }
799                 list[n] = source[i];
800                 n++;
801                 list[n] = NULL;
802         }
803
804         *dest = list;
805
806         return LDB_SUCCESS;
807 }
808
809 /* validate and modify the objectclass attribute to sort and add parents */
810 static int schema_add_build_objectclass_list(struct schema_context *sctx)
811 {
812         struct schema_class_dlist *temp;
813         struct ldb_message_element * el;
814         struct schema_class *class;
815         int ret, i, an;
816
817         /* First of all initialize list, it must start with class top */
818         sctx->class_list = talloc_zero(sctx, struct schema_class_dlist);
819         if (!sctx->class_list) return LDB_ERR_OPERATIONS_ERROR;
820
821         sctx->class_list->class = schema_store_find(sctx->data->class_store, "top");
822         if (!sctx->class_list->class) return LDB_ERR_OPERATIONS_ERROR;
823
824         el = ldb_msg_find_element(sctx->orig_req->op.add.message, "objectClass");
825         if (!el) {
826                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
827         }
828
829         for (i = 0; i < el->num_values; i++) {
830
831                 class = schema_store_find(sctx->data->class_store, (char *)el->values[i].data);
832                 if (!class) {
833                         return LDB_ERR_NO_SUCH_ATTRIBUTE;
834                 }
835                 
836                 ret = schema_add_class_to_dlist(sctx->class_list, class, class->type);
837                 if (ret != LDB_SUCCESS) {
838                         return ret;
839                 }
840         }
841
842         /* now check if there is any class role that is still not STRUCTURAL or AUXILIARY */
843         /* build also the auxiliary class list and the possible superiors list */ 
844         temp = sctx->class_list->next; /* top is special, skip it */
845         an = 0;
846
847         while (temp) {
848                 if (temp->role == SCHEMA_CT_ABSTRACT || temp->role == SCHEMA_CT_88) {
849                         return LDB_ERR_OBJECT_CLASS_VIOLATION;
850                 }
851                 if (temp->class->sysaux) {
852                         ret = schema_merge_class_list(sctx, &sctx->aux_list, temp->class->sysaux);
853                         if (ret != LDB_SUCCESS) {
854                                 return LDB_ERR_OPERATIONS_ERROR;
855                         }
856                 }
857                 if (temp->class->aux) {
858                         ret = schema_merge_class_list(sctx, &sctx->aux_list, temp->class->aux);
859                         if (ret != LDB_SUCCESS) {
860                                 return LDB_ERR_OPERATIONS_ERROR;
861                         }
862                 }
863                 if (temp->class->sysposssup) {
864                         ret = schema_merge_class_list(sctx, &sctx->sup_list, temp->class->sysposssup);
865                         if (ret != LDB_SUCCESS) {
866                                 return LDB_ERR_OPERATIONS_ERROR;
867                         }
868                 }
869                 if (temp->class->posssup) {
870                         ret = schema_merge_class_list(sctx, &sctx->sup_list, temp->class->posssup);
871                         if (ret != LDB_SUCCESS) {
872                                 return LDB_ERR_OPERATIONS_ERROR;
873                         }
874                 }
875                 temp = temp->next;
876         }
877
878         /* complete sup_list with material from the aux classes */
879         for (i = 0; sctx->aux_list && sctx->aux_list[i]; i++) {
880                 if (sctx->aux_list[i]->sysposssup) {
881                         ret = schema_merge_class_list(sctx, &sctx->sup_list, sctx->aux_list[i]->sysposssup);
882                         if (ret != LDB_SUCCESS) {
883                                 return LDB_ERR_OPERATIONS_ERROR;
884                         }
885                 }
886                 if (sctx->aux_list[i]->posssup) {
887                         ret = schema_merge_class_list(sctx, &sctx->sup_list, sctx->aux_list[i]->posssup);
888                         if (ret != LDB_SUCCESS) {
889                                 return LDB_ERR_OPERATIONS_ERROR;
890                         }
891                 }
892         }
893
894         if (!sctx->sup_list) return LDB_ERR_NAMING_VIOLATION;
895
896         return LDB_SUCCESS;
897 }
898
899 static int schema_add_check_container_constraints(struct schema_context *sctx)
900 {
901         struct schema_class **parent_possinf = NULL;
902         struct schema_class **parent_classes;
903         struct schema_class_dlist *temp;
904         struct ldb_message_element *el;
905         int i, j, ret;
906
907         el = ldb_msg_find_element(sctx->parent_res->message, "objectClass");
908         if (!el) {
909                 /* what the .. */
910                 return LDB_ERR_OPERATIONS_ERROR;
911         }
912
913         parent_classes = talloc_array(sctx, struct schema_class *, el->num_values + 1);
914
915         for (i = 0; i < el->num_values; i++) {
916
917                 parent_classes[i] = schema_store_find(sctx->data->class_store, (const char *)el->values[i].data);
918                 if (!parent_classes[i]) { /* should not be possible */
919                         return LDB_ERR_OPERATIONS_ERROR;
920                 }
921
922                 if (parent_classes[i]->possinf) {
923                         ret = schema_merge_class_list(sctx, &parent_possinf, parent_classes[i]->possinf);
924                         if (ret != LDB_SUCCESS) {
925                                 return LDB_ERR_OPERATIONS_ERROR;
926                         }
927                 }
928
929                 /* check also embedded auxiliary classes possinf */
930                 for (j = 0; parent_classes[i]->sysaux && parent_classes[i]->sysaux[j]; j++) {
931                         if (parent_classes[i]->sysaux[j]->possinf) {
932                                 ret = schema_merge_class_list(sctx, &parent_possinf, parent_classes[i]->sysaux[j]->possinf);
933                                 if (ret != LDB_SUCCESS) {
934                                         return LDB_ERR_OPERATIONS_ERROR;
935                                 }
936                         }
937                 }
938                 for (j = 0; parent_classes[i]->aux && parent_classes[i]->aux[j]; j++) {
939                         if (parent_classes[i]->aux[j]->possinf) {
940                                 ret = schema_merge_class_list(sctx, &parent_possinf, parent_classes[i]->aux[j]->possinf);
941                                 if (ret != LDB_SUCCESS) {
942                                         return LDB_ERR_OPERATIONS_ERROR;
943                                 }
944                         }
945                 }
946         }
947
948         /* foreach parent objectclass,
949          *   check parent possible inferiors match all of the child objectclasses
950          *    and that
951          *   poss Superiors of the child objectclasses mathes one of the parent classes
952          */
953
954         temp = sctx->class_list->next; /* skip top it is special */
955         while (temp) {
956
957                 for (i = 0; parent_possinf[i]; i++) {
958                         if (temp->class == parent_possinf[i]) {
959                                 break;
960                         }
961                 }
962                 if (parent_possinf[i] == NULL) {
963                         /* class not found in possible inferiors */
964                         return LDB_ERR_NAMING_VIOLATION;
965                 }
966
967                 temp = temp->next;
968         }
969
970         for (i = 0; parent_classes[i]; i++) {
971                 for (j = 0; sctx->sup_list[j]; j++) {
972                         if (sctx->sup_list[j] == parent_classes[i]) {
973                                 break;
974                         }
975                 }
976                 if (sctx->sup_list[j]) { /* possible Superiors match one of the parent classes */
977                         return LDB_SUCCESS;
978                 }
979         }
980
981         /* no parent classes matched superiors */
982         return LDB_ERR_NAMING_VIOLATION;
983 }
984
985 static int schema_add_build_down_req(struct schema_context *sctx)
986 {
987         struct schema_class_dlist *temp;
988         struct ldb_message *msg;
989         char *oc;
990         int ret;
991
992         sctx->down_req = talloc(sctx, struct ldb_request);
993         if (!sctx->down_req) {
994                 ldb_set_errstring(sctx->module->ldb, "Out of memory!");
995                 return LDB_ERR_OPERATIONS_ERROR;
996         }
997
998         *(sctx->down_req) = *(sctx->orig_req); /* copy the request */
999         msg = ldb_msg_copy_shallow(sctx->down_req, sctx->orig_req->op.add.message);
1000         if (!msg) {
1001                 ldb_set_errstring(sctx->module->ldb, "Out of memory!");
1002                 return LDB_ERR_OPERATIONS_ERROR;
1003         }
1004
1005         /* rebuild the objectclass list */
1006         ldb_msg_remove_attr(msg, "objectClass");
1007         ret = ldb_msg_add_empty(msg, "objectClass", 0);
1008         if (ret != LDB_SUCCESS) {
1009                 return ret;
1010         }
1011
1012         /* Add the complete list of classes back to the message */
1013         for (temp = sctx->class_list; temp; temp = temp->next) {
1014                 ret = ldb_msg_add_string(msg, "objectClass", temp->class->name);
1015                 if (ret != LDB_SUCCESS) {
1016                         return ret;
1017                 }
1018         }
1019
1020         /* objectCategory can be set only by the system */
1021         if (ldb_msg_find_element(msg, "objectCategory")) {
1022                 return LDB_ERR_CONSTRAINT_VIOLATION;
1023         }
1024
1025         /* the OC is mandatory, every class defines it */
1026         /* use the one defined in the structural class that defines the object */
1027         for (temp = sctx->class_list->next; temp; temp = temp->next) {
1028                 if (!temp->next) break;
1029                 if (temp->next->role != SCHEMA_CT_STRUCTURAL) break;
1030         }
1031         oc = talloc_strdup(msg, temp->class->defobjcat);
1032         ret = ldb_msg_add_string(msg, "objectCategory", oc);
1033
1034         sctx->down_req->op.add.message = msg;
1035
1036         return LDB_SUCCESS;
1037 }
1038
1039 static int schema_add_continue(struct ldb_handle *h)
1040 {
1041         struct schema_context *sctx;
1042         int ret;
1043
1044         sctx = talloc_get_type(h->private_data, struct schema_context);
1045
1046         switch (sctx->step) {
1047         case SC_INIT:
1048
1049                 /* First of all check that a parent exists for this entry */
1050                 ret = schema_add_build_parent_req(sctx);
1051                 if (ret != LDB_SUCCESS) {
1052                         break;
1053                 }
1054
1055                 sctx->step = SC_ADD_CHECK_PARENT;
1056                 return ldb_next_request(sctx->module, sctx->parent_req);
1057
1058         case SC_ADD_CHECK_PARENT:
1059
1060                 /* parent search done, check result and go on */
1061                 if (sctx->parent_res == NULL) {
1062                         /* we must have a parent */
1063                         ret = LDB_ERR_NO_SUCH_OBJECT;
1064                         break;
1065                 }
1066
1067                 /* Check objectclasses are ok */
1068                 ret = schema_add_build_objectclass_list(sctx);
1069                 if (ret != LDB_SUCCESS) {
1070                         break;
1071                 }
1072
1073                 /* check the parent is of the right type for this object */
1074                 ret = schema_add_check_container_constraints(sctx);
1075                 if (ret != LDB_SUCCESS) {
1076                         break;
1077                 }
1078
1079                 /* check attributes syntax */
1080                 /*
1081                 ret = schema_check_attributes_syntax(sctx);
1082                 if (ret != LDB_SUCCESS) {
1083                         break;
1084                 }
1085                 */
1086
1087                 ret = schema_add_build_down_req(sctx);
1088                 if (ret != LDB_SUCCESS) {
1089                         break;
1090                 }
1091                 sctx->step = SC_ADD_TEMP;
1092
1093                 return ldb_next_request(sctx->module, sctx->down_req);
1094
1095         default:
1096                 ret = LDB_ERR_OPERATIONS_ERROR;
1097                 break;
1098         }
1099
1100         /* this is reached only in case of error */
1101         /* FIXME: fire an async reply ? */
1102         h->status = ret;
1103         h->state = LDB_ASYNC_DONE;
1104         return ret;
1105 }
1106
1107 static int schema_add(struct ldb_module *module, struct ldb_request *req)
1108 {
1109         struct schema_context *sctx;
1110         struct ldb_handle *h;
1111
1112         if (ldb_dn_is_special(req->op.add.message->dn)) { /* do not manipulate our control entries */
1113                 return ldb_next_request(module, req);
1114         }
1115
1116         h = schema_init_handle(req, module, SC_ADD);
1117         if (!h) {
1118                 return LDB_ERR_OPERATIONS_ERROR;
1119         }
1120
1121         sctx = talloc_get_type(h->private_data, struct schema_context);
1122         sctx->orig_req->handle = h;
1123         return schema_add_continue(h);
1124 }
1125
1126
1127 static int schema_modify(struct ldb_module *module, struct ldb_request *req)
1128 {
1129         struct ldb_handle *h;
1130         struct schema_context *sctx;
1131
1132         if (ldb_dn_is_special(req->op.mod.message->dn)) { /* do not manipulate our control entries */
1133                 return ldb_next_request(module, req);
1134         }
1135
1136         return ldb_next_request(module, req);   
1137 }
1138
1139 static int schema_delete(struct ldb_module *module, struct ldb_request *req)
1140 {
1141         struct ldb_handle *h;
1142         struct schema_context *sctx;
1143
1144         if (ldb_dn_is_special(req->op.del.dn)) { /* do not manipulate our control entries */
1145                 return ldb_next_request(module, req);
1146         }
1147         
1148         /* First of all check no children exists for this entry */
1149
1150         return ldb_next_request(module, req);
1151 }
1152
1153 static int schema_rename(struct ldb_module *module, struct ldb_request *req)
1154 {
1155         struct ldb_handle *h;
1156         struct schema_context *sctx;
1157
1158         if (ldb_dn_is_special(req->op.rename.olddn) &&
1159             ldb_dn_is_special(req->op.rename.newdn)) { /* do not manipulate our control entries */
1160                 return ldb_next_request(module, req);
1161         }
1162
1163         return ldb_next_request(module, req);
1164 }
1165
1166 static int schema_wait_loop(struct ldb_handle *handle) {
1167         struct schema_context *sctx;
1168         int ret;
1169     
1170         if (!handle || !handle->private_data) {
1171                 return LDB_ERR_OPERATIONS_ERROR;
1172         }
1173
1174         if (handle->state == LDB_ASYNC_DONE) {
1175                 return handle->status;
1176         }
1177
1178         handle->state = LDB_ASYNC_PENDING;
1179         handle->status = LDB_SUCCESS;
1180
1181         sctx = talloc_get_type(handle->private_data, struct schema_context);
1182
1183         switch (sctx->step) {
1184         case SC_ADD_CHECK_PARENT:
1185                 ret = ldb_wait(sctx->parent_req->handle, LDB_WAIT_NONE);
1186
1187                 if (ret != LDB_SUCCESS) {
1188                         handle->status = ret;
1189                         goto done;
1190                 }
1191                 if (sctx->parent_req->handle->status != LDB_SUCCESS) {
1192                         handle->status = sctx->parent_req->handle->status;
1193                         goto done;
1194                 }
1195
1196                 if (sctx->parent_req->handle->state != LDB_ASYNC_DONE) {
1197                         return LDB_SUCCESS;
1198                 }
1199
1200                 return schema_add_continue(handle);
1201
1202         case SC_ADD_TEMP:
1203                 ret = ldb_wait(sctx->down_req->handle, LDB_WAIT_NONE);
1204
1205                 if (ret != LDB_SUCCESS) {
1206                         handle->status = ret;
1207                         goto done;
1208                 }
1209                 if (sctx->down_req->handle->status != LDB_SUCCESS) {
1210                         handle->status = sctx->down_req->handle->status;
1211                         goto done;
1212                 }
1213
1214                 if (sctx->down_req->handle->state != LDB_ASYNC_DONE) {
1215                         return LDB_SUCCESS;
1216                 }
1217
1218                 break;
1219
1220         default:
1221                 ret = LDB_ERR_OPERATIONS_ERROR;
1222                 goto done;
1223         }
1224
1225         ret = LDB_SUCCESS;
1226
1227 done:
1228         handle->state = LDB_ASYNC_DONE;
1229         return ret;
1230 }
1231
1232 static int schema_wait_all(struct ldb_handle *handle) {
1233
1234         int ret;
1235
1236         while (handle->state != LDB_ASYNC_DONE) {
1237                 ret = schema_wait_loop(handle);
1238                 if (ret != LDB_SUCCESS) {
1239                         return ret;
1240                 }
1241         }
1242
1243         return handle->status;
1244 }
1245
1246 static int schema_wait(struct ldb_handle *handle, enum ldb_wait_type type)
1247 {
1248         if (type == LDB_WAIT_ALL) {
1249                 return schema_wait_all(handle);
1250         } else {
1251                 return schema_wait_loop(handle);
1252         }
1253 }
1254
1255 static int schema_init(struct ldb_module *module)
1256 {
1257         static const char *schema_attrs[] = { "schemaNamingContext", NULL };
1258         struct schema_private_data *data;
1259         struct ldb_result *res;
1260         int ret;
1261
1262         /* need to let the partiorion module to register first */
1263         ret = ldb_next_init(module);
1264         if (ret != LDB_SUCCESS) {
1265                 return ret;
1266         }
1267
1268         data = talloc_zero(module, struct schema_private_data);
1269         if (data == NULL) {
1270                 return LDB_ERR_OPERATIONS_ERROR;
1271         }
1272
1273         /* find the schema partition */
1274         ret = ldb_search(module->ldb,
1275                          ldb_dn_new(module),
1276                          LDB_SCOPE_BASE,
1277                          "(objectClass=*)",
1278                          schema_attrs,
1279                          &res);
1280
1281         if (res->count != 1) {
1282                 /* FIXME: return a clear error string */
1283                 talloc_free(data);
1284                 talloc_free(res);
1285                 return LDB_ERR_OPERATIONS_ERROR;
1286         }
1287
1288         data->schema_dn = ldb_msg_find_attr_as_dn(data, res->msgs[0], "schemaNamingContext");
1289         if (data->schema_dn == NULL) {
1290                 /* FIXME: return a clear error string */
1291                 talloc_free(data);
1292                 talloc_free(res);
1293                 return LDB_ERR_OPERATIONS_ERROR;
1294         }
1295
1296         talloc_free(res);
1297
1298         ret = schema_init_attrs(module, data);
1299         if (ret != LDB_SUCCESS) {
1300                 talloc_free(data);
1301                 return ret;
1302         }
1303
1304         ret = schema_init_classes(module, data);
1305         if (ret != LDB_SUCCESS) {
1306                 talloc_free(data);
1307                 return ret;
1308         }
1309
1310         module->private_data = data;
1311         return LDB_SUCCESS;
1312 }
1313
1314 static const struct ldb_module_ops schema_ops = {
1315         .name          = "schema",
1316         .init_context  = schema_init,
1317         .add           = schema_add,
1318         .modify        = schema_modify,
1319         .del           = schema_delete,
1320         .rename        = schema_rename,
1321         .wait          = schema_wait
1322 };
1323
1324 int ldb_schema_init(void)
1325 {
1326         return ldb_register_module(&schema_ops);
1327 }