lib: Remove tdb_compat
[nivanova/samba-autobuild/.git] / source4 / dsdb / samdb / ldb_modules / schema_load.c
1 /* 
2    Unix SMB/CIFS mplementation.
3
4    The module that handles the Schema FSMO Role Owner
5    checkings, it also loads the dsdb_schema.
6    
7    Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
8    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009-2010
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22    
23 */
24
25 #include "includes.h"
26 #include "ldb_module.h"
27 #include "dsdb/samdb/samdb.h"
28 #include "librpc/gen_ndr/ndr_misc.h"
29 #include "librpc/gen_ndr/ndr_drsuapi.h"
30 #include "librpc/gen_ndr/ndr_drsblobs.h"
31 #include "param/param.h"
32 #include <tdb.h>
33 #include "lib/tdb_wrap/tdb_wrap.h"
34 #include "dsdb/samdb/ldb_modules/util.h"
35
36 #include "system/filesys.h"
37 struct schema_load_private_data {
38         bool in_transaction;
39         struct tdb_wrap *metadata;
40 };
41
42 static int dsdb_schema_from_db(struct ldb_module *module,
43                                TALLOC_CTX *mem_ctx,
44                                uint64_t current_usn,
45                                uint64_t schema_seq_num,
46                                struct dsdb_schema **schema);
47
48 /*
49  * Open sam.ldb.d/metadata.tdb.
50  */
51 static int schema_metadata_open(struct ldb_module *module)
52 {
53         struct schema_load_private_data *data = talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data);
54         struct ldb_context *ldb = ldb_module_get_ctx(module);
55         TALLOC_CTX *tmp_ctx;
56         struct loadparm_context *lp_ctx;
57         const char *sam_name;
58         char *filename;
59         int open_flags;
60         struct stat statbuf;
61
62         if (!data) {
63                 return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR,
64                                         "schema_load: metadata not initialized");
65         }
66         data->metadata = NULL;
67
68         tmp_ctx = talloc_new(NULL);
69         if (tmp_ctx == NULL) {
70                 return ldb_module_oom(module);
71         }
72
73         sam_name = (const char *)ldb_get_opaque(ldb, "ldb_url");
74         if (!sam_name) {
75                 talloc_free(tmp_ctx);
76                 return ldb_operr(ldb);
77         }
78         if (strncmp("tdb://", sam_name, 6) == 0) {
79                 sam_name += 6;
80         }
81         filename = talloc_asprintf(tmp_ctx, "%s.d/metadata.tdb", sam_name);
82         if (!filename) {
83                 talloc_free(tmp_ctx);
84                 return ldb_oom(ldb);
85         }
86
87         open_flags = O_RDWR;
88         if (stat(filename, &statbuf) != 0) {
89                 talloc_free(tmp_ctx);
90                 return LDB_ERR_OPERATIONS_ERROR;
91         }
92
93         lp_ctx = talloc_get_type_abort(ldb_get_opaque(ldb, "loadparm"),
94                                        struct loadparm_context);
95
96         data->metadata = tdb_wrap_open(data, filename, 10,
97                                        lpcfg_tdb_flags(lp_ctx, TDB_DEFAULT),
98                                        open_flags, 0660);
99         if (data->metadata == NULL) {
100                 talloc_free(tmp_ctx);
101                 return LDB_ERR_OPERATIONS_ERROR;
102         }
103
104         talloc_free(tmp_ctx);
105         return LDB_SUCCESS;
106 }
107
108 static int schema_metadata_get_uint64(struct ldb_module *module,
109                                          const char *key, uint64_t *value,
110                                          uint64_t default_value)
111 {
112         struct schema_load_private_data *data = talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data);
113         struct tdb_context *tdb;
114         TDB_DATA tdb_key, tdb_data;
115         char *value_str;
116         TALLOC_CTX *tmp_ctx;
117
118         if (!data || !data->metadata) {
119                 *value = default_value;
120                 return LDB_SUCCESS;
121         }
122
123         tmp_ctx = talloc_new(NULL);
124         if (tmp_ctx == NULL) {
125                 return ldb_module_oom(module);
126         }
127
128         tdb = data->metadata->tdb;
129
130         tdb_key.dptr = (uint8_t *)discard_const_p(char, key);
131         tdb_key.dsize = strlen(key);
132
133         tdb_data = tdb_fetch(tdb, tdb_key);
134         if (!tdb_data.dptr) {
135                 if (tdb_error(tdb) == TDB_ERR_NOEXIST) {
136                         *value = default_value;
137                         talloc_free(tmp_ctx);
138                         return LDB_SUCCESS;
139                 } else {
140                         talloc_free(tmp_ctx);
141                         return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR,
142                                                 tdb_errorstr(tdb));
143                 }
144         }
145
146         value_str = talloc_strndup(tmp_ctx, (char *)tdb_data.dptr, tdb_data.dsize);
147         if (value_str == NULL) {
148                 SAFE_FREE(tdb_data.dptr);
149                 talloc_free(tmp_ctx);
150                 return ldb_module_oom(module);
151         }
152
153         *value = strtoull(value_str, NULL, 10);
154
155         SAFE_FREE(tdb_data.dptr);
156         talloc_free(tmp_ctx);
157
158         return LDB_SUCCESS;
159 }
160
161 static struct dsdb_schema *dsdb_schema_refresh(struct ldb_module *module, struct tevent_context *ev,
162                                                struct dsdb_schema *schema, bool is_global_schema)
163 {
164         TALLOC_CTX *mem_ctx;
165         uint64_t current_usn, schema_seq_num = 0;
166         int ret;
167         struct ldb_context *ldb = ldb_module_get_ctx(module);
168         struct dsdb_schema *new_schema;
169         struct ldb_dn *schema_dn = ldb_get_schema_basedn(ldb);
170         time_t ts, lastts;      
171         
172         struct schema_load_private_data *private_data = talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data);
173         if (!private_data) {
174                 /* We can't refresh until the init function has run */
175                 return schema;
176         }
177
178         /* We don't allow a schema reload during a transaction - nobody else can modify our schema behind our backs */
179         if (private_data->in_transaction) {
180                 return schema;
181         }
182
183         SMB_ASSERT(ev == ldb_get_event_context(ldb));
184
185         mem_ctx = talloc_new(module);
186         if (mem_ctx == NULL) {
187                 return NULL;
188         }
189
190         /*
191          * We update right now the last refresh timestamp so that if
192          * the schema partition hasn't change we don't keep on retrying.
193          * Otherwise if the timestamp was update only when the schema has
194          * actually changed (and therefor completely reloaded) we would
195          * continue to hit the database to get the highest USN.
196          */
197
198         ret = schema_metadata_get_uint64(module, DSDB_METADATA_SCHEMA_SEQ_NUM, &schema_seq_num, 0);
199
200         if (schema != NULL) {
201                 lastts = schema->last_refresh;
202                 ts = time(NULL);
203                 if (lastts > (ts - schema->refresh_interval)) {
204                         DEBUG(11, ("Less than %d seconds since last reload, "
205                                    "returning cached version ts = %d\n",
206                                    (int)schema->refresh_interval,
207                                    (int)lastts));
208                         TALLOC_FREE(mem_ctx);
209                         return schema;
210                 }
211
212                 if (ret == LDB_SUCCESS) {
213                         schema->metadata_usn = schema_seq_num;
214                 } else {
215                         /* From an old provision it can happen that the tdb didn't exists yet */
216                         DEBUG(0, ("Error while searching for the schema usn in the metadata ignoring: %d:%s:%s\n",
217                               ret, ldb_strerror(ret), ldb_errstring(ldb)));
218                         schema->metadata_usn = 0;
219                 }
220                 schema->last_refresh = ts;
221
222         }
223
224         ret = dsdb_module_load_partition_usn(module, schema_dn, &current_usn, NULL, NULL);
225         if (ret != LDB_SUCCESS || (schema && (current_usn == schema->loaded_usn))) {
226                 TALLOC_FREE(mem_ctx);
227                 return schema;
228         }
229
230         ret = dsdb_schema_from_db(module, mem_ctx, current_usn, schema_seq_num, &new_schema);
231         if (ret != LDB_SUCCESS) {
232                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
233                               "dsdb_schema_from_db() failed: %d:%s: %s",
234                               ret, ldb_strerror(ret), ldb_errstring(ldb));
235                 TALLOC_FREE(mem_ctx);
236                 return schema;
237         }
238
239         ret = dsdb_set_schema(ldb, new_schema);
240         if (ret != LDB_SUCCESS) {
241                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
242                               "dsdb_set_schema() failed: %d:%s: %s",
243                               ret, ldb_strerror(ret), ldb_errstring(ldb));
244                 TALLOC_FREE(mem_ctx);
245                 return schema;
246         }
247         if (is_global_schema) {
248                 dsdb_make_schema_global(ldb, new_schema);
249         }
250         TALLOC_FREE(mem_ctx);
251         return new_schema;
252 }
253
254
255 /*
256   Given an LDB module (pointing at the schema DB), and the DN, set the populated schema
257 */
258
259 static int dsdb_schema_from_db(struct ldb_module *module,
260                                TALLOC_CTX *mem_ctx,
261                                uint64_t current_usn,
262                                uint64_t schema_seq_num,
263                                struct dsdb_schema **schema)
264 {
265         struct ldb_context *ldb = ldb_module_get_ctx(module);
266         TALLOC_CTX *tmp_ctx;
267         char *error_string;
268         int ret;
269         struct ldb_dn *schema_dn = ldb_get_schema_basedn(ldb);
270         struct ldb_result *schema_res;
271         struct ldb_result *res;
272         static const char *schema_attrs[] = {
273                 "prefixMap",
274                 "schemaInfo",
275                 "fSMORoleOwner",
276                 NULL
277         };
278         unsigned flags;
279
280         tmp_ctx = talloc_new(module);
281         if (!tmp_ctx) {
282                 return ldb_oom(ldb);
283         }
284
285         /* we don't want to trace the schema load */
286         flags = ldb_get_flags(ldb);
287         ldb_set_flags(ldb, flags & ~LDB_FLG_ENABLE_TRACING);
288
289         /*
290          * setup the prefix mappings and schema info
291          */
292         ret = dsdb_module_search_dn(module, tmp_ctx, &schema_res,
293                                     schema_dn, schema_attrs,
294                                     DSDB_FLAG_NEXT_MODULE, NULL);
295         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
296                 ldb_reset_err_string(ldb);
297                 ldb_debug(ldb, LDB_DEBUG_WARNING,
298                           "schema_load_init: no schema head present: (skip schema loading)\n");
299                 goto failed;
300         } else if (ret != LDB_SUCCESS) {
301                 ldb_asprintf_errstring(ldb, 
302                                        "dsdb_schema: failed to search the schema head: %s",
303                                        ldb_errstring(ldb));
304                 goto failed;
305         }
306
307         /*
308          * load the attribute definitions
309          */
310         ret = dsdb_module_search(module, tmp_ctx, &res,
311                                  schema_dn, LDB_SCOPE_ONELEVEL, NULL,
312                                  DSDB_FLAG_NEXT_MODULE |
313                                  DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
314                                  NULL,
315                                  "(|(objectClass=attributeSchema)(objectClass=classSchema))");
316         if (ret != LDB_SUCCESS) {
317                 ldb_asprintf_errstring(ldb, 
318                                        "dsdb_schema: failed to search attributeSchema and classSchema objects: %s",
319                                        ldb_errstring(ldb));
320                 goto failed;
321         }
322
323         ret = dsdb_schema_from_ldb_results(tmp_ctx, ldb,
324                                            schema_res, res, schema, &error_string);
325         if (ret != LDB_SUCCESS) {
326                 ldb_asprintf_errstring(ldb, 
327                                        "dsdb_schema load failed: %s",
328                                        error_string);
329                 goto failed;
330         }
331
332         (*schema)->loaded_usn = current_usn;
333         (*schema)->metadata_usn = schema_seq_num;
334         (*schema)->last_refresh = time(NULL);
335
336         talloc_steal(mem_ctx, *schema);
337
338 failed:
339         if (flags & LDB_FLG_ENABLE_TRACING) {
340                 flags = ldb_get_flags(ldb);
341                 ldb_set_flags(ldb, flags | LDB_FLG_ENABLE_TRACING);
342         }
343         talloc_free(tmp_ctx);
344         return ret;
345 }       
346
347
348 static int schema_load_init(struct ldb_module *module)
349 {
350         struct schema_load_private_data *private_data;
351         struct ldb_context *ldb = ldb_module_get_ctx(module);
352         struct dsdb_schema *schema;
353         void *readOnlySchema;
354         int ret;
355
356         private_data = talloc_zero(module, struct schema_load_private_data);
357         if (private_data == NULL) {
358                 return ldb_oom(ldb);
359         }
360
361         ldb_module_set_private(module, private_data);
362
363         ret = ldb_next_init(module);
364         if (ret != LDB_SUCCESS) {
365                 return ret;
366         }
367
368         schema = dsdb_get_schema(ldb, NULL);
369
370         /* We might already have a schema */
371         if (schema != NULL) {
372                 /* Hook up the refresh function */
373                 if (dsdb_uses_global_schema(ldb)) {
374                         ret = dsdb_set_schema_refresh_function(ldb, dsdb_schema_refresh, module);
375
376                         if (ret != LDB_SUCCESS) {
377                                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
378                                               "schema_load_init: dsdb_set_schema_refresh_fns() failed: %d:%s: %s",
379                                               ret, ldb_strerror(ret), ldb_errstring(ldb));
380                                 return ret;
381                         }
382                 }
383
384                 return LDB_SUCCESS;
385         }
386
387         readOnlySchema = ldb_get_opaque(ldb, "readOnlySchema");
388
389         /* If we have the readOnlySchema opaque, then don't check for
390          * runtime schema updates, as they are not permitted (we would
391          * have to update the backend server schema too */
392         if (readOnlySchema != NULL) {
393                 struct dsdb_schema *new_schema;
394                 ret = dsdb_schema_from_db(module, private_data, 0, 0, &new_schema);
395                 if (ret != LDB_SUCCESS) {
396                         ldb_debug_set(ldb, LDB_DEBUG_FATAL,
397                                       "schema_load_init: dsdb_schema_from_db() failed: %d:%s: %s",
398                                       ret, ldb_strerror(ret), ldb_errstring(ldb));
399                         return ret;
400                 }
401
402                 /* "dsdb_set_schema()" steals schema into the ldb_context */
403                 ret = dsdb_set_schema(ldb, new_schema);
404                 if (ret != LDB_SUCCESS) {
405                         ldb_debug_set(ldb, LDB_DEBUG_FATAL,
406                                       "schema_load_init: dsdb_set_schema() failed: %d:%s: %s",
407                                       ret, ldb_strerror(ret), ldb_errstring(ldb));
408                         return ret;
409                 }
410
411         } else {
412                 ret = dsdb_set_schema_refresh_function(ldb, dsdb_schema_refresh, module);
413
414                 if (ret != LDB_SUCCESS) {
415                         ldb_debug_set(ldb, LDB_DEBUG_FATAL,
416                                       "schema_load_init: dsdb_set_schema_refresh_fns() failed: %d:%s: %s",
417                                       ret, ldb_strerror(ret), ldb_errstring(ldb));
418                         return ret;
419                 }
420         }
421
422         schema = dsdb_get_schema(ldb, NULL);
423
424         /* We do this, invoking the refresh handler, so we know that it works */
425         if (schema == NULL) {
426                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
427                               "schema_load_init: dsdb_get_schema failed");
428                 return LDB_ERR_OPERATIONS_ERROR;
429         }
430
431         return ret;
432 }
433
434 static int schema_search(struct ldb_module *module, struct ldb_request *req)
435 {
436         struct dsdb_schema *schema;
437         struct ldb_context *ldb = ldb_module_get_ctx(module);
438         uint64_t value;
439         int ret;
440         struct schema_load_private_data *private_data =
441                 talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data);
442
443         schema = dsdb_get_schema(ldb, NULL);
444         if (schema && private_data && !private_data->in_transaction) {
445                 ret = schema_metadata_get_uint64(module, DSDB_METADATA_SCHEMA_SEQ_NUM, &value, 0);
446                 if (ret == LDB_SUCCESS && schema->metadata_usn < value) {
447                         /* The usn of the schema was changed in the metadata,
448                         * this indicate that another process has modified the schema and
449                         * that a reload is needed.
450                         */
451                         schema->last_refresh = 0;
452                         schema = dsdb_get_schema(ldb, NULL);
453                 }
454         }
455
456         return ldb_next_request(module, req);
457 }
458
459 static int schema_load_start_transaction(struct ldb_module *module)
460 {
461         struct schema_load_private_data *private_data =
462                 talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data);
463         struct dsdb_schema *schema;
464         struct ldb_context *ldb = ldb_module_get_ctx(module);
465         uint64_t value;
466         int ret;
467
468         schema = dsdb_get_schema(ldb, NULL);
469         if (!private_data->metadata) {
470                 schema_metadata_open(module);
471         }
472         ret = schema_metadata_get_uint64(module, DSDB_METADATA_SCHEMA_SEQ_NUM, &value, 0);
473         if (ret == LDB_SUCCESS && schema->metadata_usn < value) {
474                 /* The usn of the schema was changed in the metadata,
475                  * this indicate that another process has modified the schema and
476                  * that a reload is needed.
477                  */
478                 schema->last_refresh = 0;
479                 schema = dsdb_get_schema(ldb, NULL);
480         }
481         private_data->in_transaction = true;
482
483         return ldb_next_start_trans(module);
484 }
485
486 static int schema_load_end_transaction(struct ldb_module *module)
487 {
488         struct schema_load_private_data *private_data =
489                 talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data);
490
491         private_data->in_transaction = false;
492
493         return ldb_next_end_trans(module);
494 }
495
496 static int schema_load_del_transaction(struct ldb_module *module)
497 {
498         struct schema_load_private_data *private_data =
499                 talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data);
500
501         private_data->in_transaction = false;
502
503         return ldb_next_del_trans(module);
504 }
505
506 static int schema_load_extended(struct ldb_module *module, struct ldb_request *req)
507 {
508         time_t *lastts;
509         struct ldb_context *ldb = ldb_module_get_ctx(module);
510         struct dsdb_schema *schema;
511
512         if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) != 0) {
513                 return ldb_next_request(module, req);
514         }
515         lastts = (time_t *)ldb_get_opaque(ldb, DSDB_OPAQUE_LAST_SCHEMA_UPDATE_MSG_OPAQUE_NAME);
516         if (!lastts) {
517                 lastts = talloc(ldb, time_t);
518         }
519         schema = dsdb_get_schema(ldb, NULL);
520         /* Force a refresh */
521         schema->last_refresh = 0;
522         *lastts = 0;
523         ldb_set_opaque(ldb, DSDB_OPAQUE_LAST_SCHEMA_UPDATE_MSG_OPAQUE_NAME, lastts);
524
525         /* Pass to next module, the partition one should finish the chain */
526         return ldb_next_request(module, req);
527 }
528
529
530 static const struct ldb_module_ops ldb_schema_load_module_ops = {
531         .name           = "schema_load",
532         .init_context   = schema_load_init,
533         .extended       = schema_load_extended,
534         .search         = schema_search,
535         .start_transaction = schema_load_start_transaction,
536         .end_transaction   = schema_load_end_transaction,
537         .del_transaction   = schema_load_del_transaction,
538 };
539
540 int ldb_schema_load_module_init(const char *version)
541 {
542         LDB_MODULE_CHECK_VERSION(version);
543         return ldb_register_module(&ldb_schema_load_module_ops);
544 }