Apply attributes (and their syntax) from the schema into ldb
[samba.git] / source / dsdb / schema / schema_set.c
1 /* 
2    Unix SMB/CIFS mplementation.
3    DSDB schema header
4    
5    Copyright (C) Stefan Metzmacher <metze@samba.org> 2006-2007
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2008
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20    
21 */
22
23 #include "includes.h"
24 #include "dsdb/samdb/samdb.h"
25 #include "lib/ldb/include/ldb_errors.h"
26 #include "lib/ldb/include/ldb_private.h"
27 #include "lib/util/dlinklist.h"
28 #include "param/param.h"
29
30
31 static int schema_set_attributes(struct ldb_context *ldb, struct dsdb_schema *schema)
32 {
33         int ret = LDB_SUCCESS;
34         
35         struct dsdb_attribute *attr;
36         
37         for (attr = schema->attributes; attr; attr = attr->next) {
38                 const struct ldb_schema_syntax *s;
39                 if (!attr->syntax) {
40                         continue;
41                 }
42                 if (attr->syntax->ldb_syntax) {
43                         ret = ldb_schema_attribute_add(ldb, attr->lDAPDisplayName, 0,
44                                                        attr->syntax->ldb_syntax);
45                 } else {
46                         s = ldb_standard_syntax_by_name(ldb, attr->syntax->ldap_oid);
47                         if (s) {
48                                 ret = ldb_schema_attribute_add_with_syntax(ldb, attr->lDAPDisplayName, 0, s);
49                         } else {
50                                 s = ldb_samba_syntax_by_name(ldb, attr->syntax->ldap_oid);
51                                 if (s) {
52                                         ret = ldb_schema_attribute_add_with_syntax(ldb, attr->lDAPDisplayName, 0, s);
53                                 } else {
54                                         ret = LDB_SUCCESS; /* Nothing to do here */
55                                 }
56                         }
57                 }
58                 if (ret != LDB_SUCCESS) {
59                         return ret;
60                 }
61         }
62
63         /* Now put back the hardcoded Samba special handlers */
64         return ldb_register_samba_handlers(ldb);
65 }
66
67
68 /**
69  * Attach the schema to an opaque pointer on the ldb, so ldb modules
70  * can find it 
71  */
72
73 int dsdb_set_schema(struct ldb_context *ldb, struct dsdb_schema *schema)
74 {
75         int ret;
76
77         ret = ldb_set_opaque(ldb, "dsdb_schema", schema);
78         if (ret != LDB_SUCCESS) {
79                 return ret;
80         }
81
82         ret = schema_set_attributes(ldb, schema);
83         if (ret != LDB_SUCCESS) {
84                 return ret;
85         }
86
87         talloc_steal(ldb, schema);
88
89         return LDB_SUCCESS;
90 }
91
92 /**
93  * Global variable to hold one copy of the schema, used to avoid memory bloat
94  */
95 static struct dsdb_schema *global_schema;
96
97 /**
98  * Make this ldb use the 'global' schema, setup to avoid having multiple copies in this process
99  */
100 int dsdb_set_global_schema(struct ldb_context *ldb)
101 {
102         int ret;
103         if (!global_schema) {
104                 return LDB_SUCCESS;
105         }
106         ret = ldb_set_opaque(ldb, "dsdb_schema", global_schema);
107         if (ret != LDB_SUCCESS) {
108                 return ret;
109         }
110
111         ret = schema_set_attributes(ldb, global_schema);
112         if (ret != LDB_SUCCESS) {
113                 return ret;
114         }
115
116         /* Keep a reference to this schema, just incase the global copy is replaced */
117         if (talloc_reference(ldb, global_schema) == NULL) {
118                 return LDB_ERR_OPERATIONS_ERROR;
119         }
120
121         return LDB_SUCCESS;
122 }
123
124 /**
125  * Find the schema object for this ldb
126  */
127
128 struct dsdb_schema *dsdb_get_schema(struct ldb_context *ldb)
129 {
130         const void *p;
131         struct dsdb_schema *schema;
132
133         /* see if we have a cached copy */
134         p = ldb_get_opaque(ldb, "dsdb_schema");
135         if (!p) {
136                 return NULL;
137         }
138
139         schema = talloc_get_type(p, struct dsdb_schema);
140         if (!schema) {
141                 return NULL;
142         }
143
144         return schema;
145 }
146
147 /**
148  * Make the schema found on this ldb the 'global' schema
149  */
150
151 void dsdb_make_schema_global(struct ldb_context *ldb)
152 {
153         struct dsdb_schema *schema = dsdb_get_schema(ldb);
154         if (!schema) {
155                 return;
156         }
157
158         if (global_schema) {
159                 talloc_unlink(talloc_autofree_context(), schema);
160         }
161
162         talloc_steal(talloc_autofree_context(), schema);
163         global_schema = schema;
164
165         dsdb_set_global_schema(ldb);
166 }
167
168
169 /**
170  * Rather than read a schema from the LDB itself, read it from an ldif
171  * file.  This allows schema to be loaded and used while adding the
172  * schema itself to the directory.
173  */
174
175 WERROR dsdb_attach_schema_from_ldif_file(struct ldb_context *ldb, const char *pf, const char *df)
176 {
177         struct ldb_ldif *ldif;
178         struct ldb_message *msg;
179         TALLOC_CTX *mem_ctx;
180         WERROR status;
181         int ret;
182         struct dsdb_schema *schema;
183         const struct ldb_val *prefix_val;
184         const struct ldb_val *info_val;
185         struct ldb_val info_val_default;
186
187         mem_ctx = talloc_new(ldb);
188         if (!mem_ctx) {
189                 goto nomem;
190         }
191
192         schema = dsdb_new_schema(mem_ctx, lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")));
193
194         schema->fsmo.we_are_master = true;
195         schema->fsmo.master_dn = ldb_dn_new_fmt(schema, ldb, "@PROVISION_SCHEMA_MASTER");
196         if (!schema->fsmo.master_dn) {
197                 goto nomem;
198         }
199
200         /*
201          * load the prefixMap attribute from pf
202          */
203         ldif = ldb_ldif_read_string(ldb, &pf);
204         if (!ldif) {
205                 status = WERR_INVALID_PARAM;
206                 goto failed;
207         }
208         talloc_steal(mem_ctx, ldif);
209
210         msg = ldb_msg_canonicalize(ldb, ldif->msg);
211         if (!msg) {
212                 goto nomem;
213         }
214         talloc_steal(mem_ctx, msg);
215         talloc_free(ldif);
216
217         prefix_val = ldb_msg_find_ldb_val(msg, "prefixMap");
218         if (!prefix_val) {
219                 status = WERR_INVALID_PARAM;
220                 goto failed;
221         }
222
223         info_val = ldb_msg_find_ldb_val(msg, "schemaInfo");
224         if (!info_val) {
225                 info_val_default = strhex_to_data_blob("FF0000000000000000000000000000000000000000");
226                 if (!info_val_default.data) {
227                         goto nomem;
228                 }
229                 talloc_steal(mem_ctx, info_val_default.data);
230                 info_val = &info_val_default;
231         }
232
233         status = dsdb_load_oid_mappings_ldb(schema, prefix_val, info_val);
234         if (!W_ERROR_IS_OK(status)) {
235                 goto failed;
236         }
237
238         /*
239          * load the attribute and class definitions outof df
240          */
241         while ((ldif = ldb_ldif_read_string(ldb, &df))) {
242                 bool is_sa;
243                 bool is_sc;
244
245                 talloc_steal(mem_ctx, ldif);
246
247                 msg = ldb_msg_canonicalize(ldb, ldif->msg);
248                 if (!msg) {
249                         goto nomem;
250                 }
251
252                 talloc_steal(mem_ctx, msg);
253                 talloc_free(ldif);
254
255                 is_sa = ldb_msg_check_string_attribute(msg, "objectClass", "attributeSchema");
256                 is_sc = ldb_msg_check_string_attribute(msg, "objectClass", "classSchema");
257
258                 if (is_sa) {
259                         struct dsdb_attribute *sa;
260
261                         sa = talloc_zero(schema, struct dsdb_attribute);
262                         if (!sa) {
263                                 goto nomem;
264                         }
265
266                         status = dsdb_attribute_from_ldb(schema, msg, sa, sa);
267                         if (!W_ERROR_IS_OK(status)) {
268                                 goto failed;
269                         }
270
271                         DLIST_ADD_END(schema->attributes, sa, struct dsdb_attribute *);
272                 } else if (is_sc) {
273                         struct dsdb_class *sc;
274
275                         sc = talloc_zero(schema, struct dsdb_class);
276                         if (!sc) {
277                                 goto nomem;
278                         }
279
280                         status = dsdb_class_from_ldb(schema, msg, sc, sc);
281                         if (!W_ERROR_IS_OK(status)) {
282                                 goto failed;
283                         }
284
285                         DLIST_ADD_END(schema->classes, sc, struct dsdb_class *);
286                 }
287         }
288
289         ret = dsdb_set_schema(ldb, schema);
290         if (ret != LDB_SUCCESS) {
291                 status = WERR_FOOBAR;
292                 goto failed;
293         }
294
295         goto done;
296
297 nomem:
298         status = WERR_NOMEM;
299 failed:
300 done:
301         talloc_free(mem_ctx);
302         return status;
303 }