r25068: Older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for every opcode on the
[Samba.git] / source / lib / ldb / ldb_tdb / ldb_cache.c
blobc90885bfab89bbf670a9a91b88f6570a8fa4f943
1 /*
2 ldb database library
4 Copyright (C) Andrew Tridgell 2004
6 ** NOTE! The following LGPL license applies to the ldb
7 ** library. This does NOT imply that all of Samba is released
8 ** under the LGPL
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2 of the License, or (at your option) any later version.
15 This library 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 GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 * Name: ldb
28 * Component: ldb tdb cache functions
30 * Description: cache special records in a ldb/tdb
32 * Author: Andrew Tridgell
35 #include "includes.h"
36 #include "ldb/include/includes.h"
38 #include "ldb/ldb_tdb/ldb_tdb.h"
40 #define LTDB_FLAG_CASE_INSENSITIVE (1<<0)
41 #define LTDB_FLAG_INTEGER (1<<1)
42 #define LTDB_FLAG_HIDDEN (1<<2)
43 #define LTDB_FLAG_OBJECTCLASS (1<<3)
45 int ltdb_attribute_flags(struct ldb_module *module, const char *attr_name);
47 /* valid attribute flags */
48 static const struct {
49 const char *name;
50 int value;
51 } ltdb_valid_attr_flags[] = {
52 { "CASE_INSENSITIVE", LTDB_FLAG_CASE_INSENSITIVE },
53 { "INTEGER", LTDB_FLAG_INTEGER },
54 { "HIDDEN", LTDB_FLAG_HIDDEN },
55 { "NONE", 0 },
56 { NULL, 0 }
61 de-register any special handlers for @ATTRIBUTES
63 static void ltdb_attributes_unload(struct ldb_module *module)
65 struct ltdb_private *ltdb =
66 (struct ltdb_private *)module->private_data;
67 struct ldb_message *msg;
68 int i;
70 if (ltdb->cache->attributes == NULL) {
71 /* no previously loaded attributes */
72 return;
75 msg = ltdb->cache->attributes;
76 for (i=0;i<msg->num_elements;i++) {
77 ldb_remove_attrib_handler(module->ldb, msg->elements[i].name);
80 talloc_free(ltdb->cache->attributes);
81 ltdb->cache->attributes = NULL;
85 add up the attrib flags for a @ATTRIBUTES element
87 static int ltdb_attributes_flags(struct ldb_message_element *el, unsigned *v)
89 int i;
90 unsigned value = 0;
91 for (i=0;i<el->num_values;i++) {
92 int j;
93 for (j=0;ltdb_valid_attr_flags[j].name;j++) {
94 if (strcmp(ltdb_valid_attr_flags[j].name,
95 (char *)el->values[i].data) == 0) {
96 value |= ltdb_valid_attr_flags[j].value;
97 break;
100 if (ltdb_valid_attr_flags[j].name == NULL) {
101 return -1;
104 *v = value;
105 return 0;
109 register any special handlers from @ATTRIBUTES
111 static int ltdb_attributes_load(struct ldb_module *module)
113 struct ltdb_private *ltdb =
114 (struct ltdb_private *)module->private_data;
115 struct ldb_message *msg = ltdb->cache->attributes;
116 struct ldb_dn *dn;
117 int i;
119 dn = ldb_dn_explode(module->ldb, LTDB_ATTRIBUTES);
120 if (dn == NULL) goto failed;
122 if (ltdb_search_dn1(module, dn, msg) == -1) {
123 talloc_free(dn);
124 goto failed;
126 talloc_free(dn);
127 /* mapping these flags onto ldap 'syntaxes' isn't strictly correct,
128 but its close enough for now */
129 for (i=0;i<msg->num_elements;i++) {
130 unsigned flags;
131 const char *syntax;
132 const struct ldb_attrib_handler *h;
133 struct ldb_attrib_handler h2;
135 if (ltdb_attributes_flags(&msg->elements[i], &flags) != 0) {
136 ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Invalid @ATTRIBUTES element for '%s'\n", msg->elements[i].name);
137 goto failed;
139 switch (flags & ~LTDB_FLAG_HIDDEN) {
140 case 0:
141 syntax = LDB_SYNTAX_OCTET_STRING;
142 break;
143 case LTDB_FLAG_CASE_INSENSITIVE:
144 syntax = LDB_SYNTAX_DIRECTORY_STRING;
145 break;
146 case LTDB_FLAG_INTEGER:
147 syntax = LDB_SYNTAX_INTEGER;
148 break;
149 default:
150 ldb_debug(module->ldb, LDB_DEBUG_ERROR,
151 "Invalid flag combination 0x%x for '%s' in @ATTRIBUTES\n",
152 flags, msg->elements[i].name);
153 goto failed;
156 h = ldb_attrib_handler_syntax(module->ldb, syntax);
157 if (h == NULL) {
158 ldb_debug(module->ldb, LDB_DEBUG_ERROR,
159 "Invalid attribute syntax '%s' for '%s' in @ATTRIBUTES\n",
160 syntax, msg->elements[i].name);
161 goto failed;
163 h2 = *h;
164 h2.attr = msg->elements[i].name;
165 h2.flags |= LDB_ATTR_FLAG_ALLOCATED;
166 if (ldb_set_attrib_handlers(module->ldb, &h2, 1) != 0) {
167 goto failed;
171 return 0;
172 failed:
173 return -1;
178 register any subclasses from @SUBCLASSES
180 static int ltdb_subclasses_load(struct ldb_module *module)
182 struct ltdb_private *ltdb =
183 (struct ltdb_private *)module->private_data;
184 struct ldb_message *msg = ltdb->cache->subclasses;
185 struct ldb_dn *dn;
186 int i, j;
188 dn = ldb_dn_explode(module->ldb, LTDB_SUBCLASSES);
189 if (dn == NULL) goto failed;
191 if (ltdb_search_dn1(module, dn, msg) == -1) {
192 talloc_free(dn);
193 goto failed;
195 talloc_free(dn);
197 for (i=0;i<msg->num_elements;i++) {
198 struct ldb_message_element *el = &msg->elements[i];
199 for (j=0;j<el->num_values;j++) {
200 if (ldb_subclass_add(module->ldb, el->name,
201 (char *)el->values[j].data) != 0) {
202 goto failed;
207 return 0;
208 failed:
209 return -1;
214 de-register any @SUBCLASSES
216 static void ltdb_subclasses_unload(struct ldb_module *module)
218 struct ltdb_private *ltdb =
219 (struct ltdb_private *)module->private_data;
220 struct ldb_message *msg;
221 int i;
223 if (ltdb->cache->subclasses == NULL) {
224 /* no previously loaded subclasses */
225 return;
228 msg = ltdb->cache->subclasses;
229 for (i=0;i<msg->num_elements;i++) {
230 ldb_subclass_remove(module->ldb, msg->elements[i].name);
233 talloc_free(ltdb->cache->subclasses);
234 ltdb->cache->subclasses = NULL;
239 initialise the baseinfo record
241 static int ltdb_baseinfo_init(struct ldb_module *module)
243 struct ltdb_private *ltdb =
244 (struct ltdb_private *)module->private_data;
245 struct ldb_message *msg;
246 struct ldb_message_element el;
247 struct ldb_val val;
248 int ret;
249 /* the initial sequence number must be different from the one
250 set in ltdb_cache_free(). Thanks to Jon for pointing this
251 out. */
252 const char *initial_sequence_number = "1";
254 ltdb->sequence_number = atof(initial_sequence_number);
256 msg = talloc(ltdb, struct ldb_message);
257 if (msg == NULL) {
258 goto failed;
261 msg->num_elements = 1;
262 msg->elements = &el;
263 msg->dn = ldb_dn_explode(msg, LTDB_BASEINFO);
264 if (!msg->dn) {
265 goto failed;
267 el.name = talloc_strdup(msg, LTDB_SEQUENCE_NUMBER);
268 if (!el.name) {
269 goto failed;
271 el.values = &val;
272 el.num_values = 1;
273 el.flags = 0;
274 val.data = (uint8_t *)talloc_strdup(msg, initial_sequence_number);
275 if (!val.data) {
276 goto failed;
278 val.length = 1;
280 ret = ltdb_store(module, msg, TDB_INSERT);
282 talloc_free(msg);
284 return ret;
286 failed:
287 talloc_free(msg);
288 errno = ENOMEM;
289 return -1;
293 free any cache records
295 static void ltdb_cache_free(struct ldb_module *module)
297 struct ltdb_private *ltdb =
298 (struct ltdb_private *)module->private_data;
300 ltdb->sequence_number = 0;
301 talloc_free(ltdb->cache);
302 ltdb->cache = NULL;
306 force a cache reload
308 int ltdb_cache_reload(struct ldb_module *module)
310 ltdb_attributes_unload(module);
311 ltdb_subclasses_unload(module);
312 ltdb_cache_free(module);
313 return ltdb_cache_load(module);
317 load the cache records
319 int ltdb_cache_load(struct ldb_module *module)
321 struct ltdb_private *ltdb =
322 (struct ltdb_private *)module->private_data;
323 struct ldb_dn *baseinfo_dn = NULL;
324 struct ldb_dn *indexlist_dn = NULL;
325 uint64_t seq;
326 struct ldb_message *baseinfo = NULL;
328 /* a very fast check to avoid extra database reads */
329 if (ltdb->cache != NULL &&
330 tdb_get_seqnum(ltdb->tdb) == ltdb->tdb_seqnum) {
331 return 0;
334 if (ltdb->cache == NULL) {
335 ltdb->cache = talloc_zero(ltdb, struct ltdb_cache);
336 if (ltdb->cache == NULL) goto failed;
337 ltdb->cache->indexlist = talloc_zero(ltdb->cache, struct ldb_message);
338 ltdb->cache->subclasses = talloc_zero(ltdb->cache, struct ldb_message);
339 ltdb->cache->attributes = talloc_zero(ltdb->cache, struct ldb_message);
340 if (ltdb->cache->indexlist == NULL ||
341 ltdb->cache->subclasses == NULL ||
342 ltdb->cache->attributes == NULL) {
343 goto failed;
347 baseinfo = talloc(ltdb->cache, struct ldb_message);
348 if (baseinfo == NULL) goto failed;
350 baseinfo_dn = ldb_dn_explode(module->ldb, LTDB_BASEINFO);
351 if (baseinfo_dn == NULL) goto failed;
353 if (ltdb_search_dn1(module, baseinfo_dn, baseinfo) == -1) {
354 goto failed;
357 /* possibly initialise the baseinfo */
358 if (!baseinfo->dn) {
359 if (ltdb_baseinfo_init(module) != 0) {
360 goto failed;
362 if (ltdb_search_dn1(module, baseinfo_dn, baseinfo) != 1) {
363 goto failed;
367 ltdb->tdb_seqnum = tdb_get_seqnum(ltdb->tdb);
369 /* if the current internal sequence number is the same as the one
370 in the database then assume the rest of the cache is OK */
371 seq = ldb_msg_find_attr_as_uint64(baseinfo, LTDB_SEQUENCE_NUMBER, 0);
372 if (seq == ltdb->sequence_number) {
373 goto done;
375 ltdb->sequence_number = seq;
377 talloc_free(ltdb->cache->last_attribute.name);
378 memset(&ltdb->cache->last_attribute, 0, sizeof(ltdb->cache->last_attribute));
380 ltdb_attributes_unload(module);
381 ltdb_subclasses_unload(module);
383 talloc_free(ltdb->cache->indexlist);
384 talloc_free(ltdb->cache->subclasses);
386 ltdb->cache->indexlist = talloc_zero(ltdb->cache, struct ldb_message);
387 ltdb->cache->subclasses = talloc_zero(ltdb->cache, struct ldb_message);
388 ltdb->cache->attributes = talloc_zero(ltdb->cache, struct ldb_message);
389 if (ltdb->cache->indexlist == NULL ||
390 ltdb->cache->subclasses == NULL ||
391 ltdb->cache->attributes == NULL) {
392 goto failed;
395 indexlist_dn = ldb_dn_explode(module->ldb, LTDB_INDEXLIST);
396 if (indexlist_dn == NULL) goto failed;
398 if (ltdb_search_dn1(module, indexlist_dn, ltdb->cache->indexlist) == -1) {
399 goto failed;
402 if (ltdb_attributes_load(module) == -1) {
403 goto failed;
405 if (ltdb_subclasses_load(module) == -1) {
406 goto failed;
409 done:
410 talloc_free(baseinfo);
411 talloc_free(baseinfo_dn);
412 talloc_free(indexlist_dn);
413 return 0;
415 failed:
416 talloc_free(baseinfo);
417 talloc_free(baseinfo_dn);
418 talloc_free(indexlist_dn);
419 return -1;
424 increase the sequence number to indicate a database change
426 int ltdb_increase_sequence_number(struct ldb_module *module)
428 struct ltdb_private *ltdb =
429 (struct ltdb_private *)module->private_data;
430 struct ldb_message *msg;
431 struct ldb_message_element el[2];
432 struct ldb_val val;
433 struct ldb_val val_time;
434 time_t t = time(NULL);
435 char *s = NULL;
436 int ret;
438 msg = talloc(ltdb, struct ldb_message);
439 if (msg == NULL) {
440 errno = ENOMEM;
441 return -1;
444 s = talloc_asprintf(msg, "%llu", ltdb->sequence_number+1);
445 if (!s) {
446 errno = ENOMEM;
447 return -1;
450 msg->num_elements = ARRAY_SIZE(el);
451 msg->elements = el;
452 msg->dn = ldb_dn_explode(msg, LTDB_BASEINFO);
453 if (msg->dn == NULL) {
454 talloc_free(msg);
455 errno = ENOMEM;
456 return -1;
458 el[0].name = talloc_strdup(msg, LTDB_SEQUENCE_NUMBER);
459 if (el[0].name == NULL) {
460 talloc_free(msg);
461 errno = ENOMEM;
462 return -1;
464 el[0].values = &val;
465 el[0].num_values = 1;
466 el[0].flags = LDB_FLAG_MOD_REPLACE;
467 val.data = (uint8_t *)s;
468 val.length = strlen(s);
470 el[1].name = talloc_strdup(msg, LTDB_MOD_TIMESTAMP);
471 if (el[1].name == NULL) {
472 talloc_free(msg);
473 errno = ENOMEM;
474 return -1;
476 el[1].values = &val_time;
477 el[1].num_values = 1;
478 el[1].flags = LDB_FLAG_MOD_REPLACE;
480 s = ldb_timestring(msg, t);
481 if (s == NULL) {
482 return -1;
485 val_time.data = (uint8_t *)s;
486 val_time.length = strlen(s);
488 ret = ltdb_modify_internal(module, msg);
490 talloc_free(msg);
492 if (ret == 0) {
493 ltdb->sequence_number += 1;
496 return ret;
501 return the attribute flags from the @ATTRIBUTES record
502 for the given attribute
504 int ltdb_attribute_flags(struct ldb_module *module, const char *attr_name)
506 struct ltdb_private *ltdb =
507 (struct ltdb_private *)module->private_data;
508 const struct ldb_message_element *attr_el;
509 int i, j, ret=0;
511 if (ltdb->cache->last_attribute.name &&
512 ldb_attr_cmp(ltdb->cache->last_attribute.name, attr_name) == 0) {
513 return ltdb->cache->last_attribute.flags;
516 /* objectclass is a special default case */
517 if (ldb_attr_cmp(attr_name, LTDB_OBJECTCLASS) == 0) {
518 ret = LTDB_FLAG_OBJECTCLASS | LTDB_FLAG_CASE_INSENSITIVE;
521 attr_el = ldb_msg_find_element(ltdb->cache->attributes, attr_name);
523 if (!attr_el) {
524 /* check if theres a wildcard attribute */
525 attr_el = ldb_msg_find_element(ltdb->cache->attributes, "*");
527 if (!attr_el) {
528 return ret;
532 for (i = 0; i < attr_el->num_values; i++) {
533 for (j=0; ltdb_valid_attr_flags[j].name; j++) {
534 if (strcmp(ltdb_valid_attr_flags[j].name,
535 (char *)attr_el->values[i].data) == 0) {
536 ret |= ltdb_valid_attr_flags[j].value;
541 talloc_free(ltdb->cache->last_attribute.name);
543 ltdb->cache->last_attribute.name = talloc_strdup(ltdb->cache, attr_name);
544 ltdb->cache->last_attribute.flags = ret;
546 return ret;
549 int ltdb_check_at_attributes_values(const struct ldb_val *value)
551 int i;
553 for (i = 0; ltdb_valid_attr_flags[i].name != NULL; i++) {
554 if ((strcmp(ltdb_valid_attr_flags[i].name, (char *)value->data) == 0)) {
555 return 0;
559 return -1;