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
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 3 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, see <http://www.gnu.org/licenses/>.
27 * Component: ldb tdb cache functions
29 * Description: cache special records in a ldb/tdb
31 * Author: Andrew Tridgell
35 #include "ldb_private.h"
37 #define LTDB_FLAG_CASE_INSENSITIVE (1<<0)
38 #define LTDB_FLAG_INTEGER (1<<1)
39 #define LTDB_FLAG_HIDDEN (1<<2)
41 /* valid attribute flags */
45 } ltdb_valid_attr_flags
[] = {
46 { "CASE_INSENSITIVE", LTDB_FLAG_CASE_INSENSITIVE
},
47 { "INTEGER", LTDB_FLAG_INTEGER
},
48 { "HIDDEN", LTDB_FLAG_HIDDEN
},
55 de-register any special handlers for @ATTRIBUTES
57 static void ltdb_attributes_unload(struct ldb_module
*module
)
59 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
61 ldb_schema_attribute_remove_flagged(ldb
, LDB_ATTR_FLAG_FROM_DB
);
66 add up the attrib flags for a @ATTRIBUTES element
68 static int ltdb_attributes_flags(struct ldb_message_element
*el
, unsigned *v
)
72 for (i
=0;i
<el
->num_values
;i
++) {
74 for (j
=0;ltdb_valid_attr_flags
[j
].name
;j
++) {
75 if (strcmp(ltdb_valid_attr_flags
[j
].name
,
76 (char *)el
->values
[i
].data
) == 0) {
77 value
|= ltdb_valid_attr_flags
[j
].value
;
81 if (ltdb_valid_attr_flags
[j
].name
== NULL
) {
89 static int ldb_schema_attribute_compare(const void *p1
, const void *p2
)
91 const struct ldb_schema_attribute
*sa1
= (const struct ldb_schema_attribute
*)p1
;
92 const struct ldb_schema_attribute
*sa2
= (const struct ldb_schema_attribute
*)p2
;
93 return ldb_attr_cmp(sa1
->name
, sa2
->name
);
97 register any special handlers from @ATTRIBUTES
99 static int ltdb_attributes_load(struct ldb_module
*module
)
101 struct ldb_schema_attribute
*attrs
;
102 struct ldb_context
*ldb
;
103 struct ldb_message
*attrs_msg
= NULL
;
106 unsigned int num_loaded_attrs
= 0;
109 ldb
= ldb_module_get_ctx(module
);
111 if (ldb
->schema
.attribute_handler_override
) {
112 /* we skip loading the @ATTRIBUTES record when a module is supplying
113 its own attribute handling */
117 attrs_msg
= ldb_msg_new(module
);
118 if (attrs_msg
== NULL
) {
122 dn
= ldb_dn_new(module
, ldb
, LTDB_ATTRIBUTES
);
123 if (dn
== NULL
) goto failed
;
125 r
= ltdb_search_dn1(module
, dn
, attrs_msg
,
126 LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC
127 |LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC
128 |LDB_UNPACK_DATA_FLAG_NO_DN
);
130 if (r
!= LDB_SUCCESS
&& r
!= LDB_ERR_NO_SUCH_OBJECT
) {
133 if (r
== LDB_ERR_NO_SUCH_OBJECT
|| attrs_msg
->num_elements
== 0) {
134 TALLOC_FREE(attrs_msg
);
138 attrs
= talloc_array(attrs_msg
,
139 struct ldb_schema_attribute
,
140 attrs_msg
->num_elements
141 + ldb
->schema
.num_attributes
);
147 ldb
->schema
.attributes
,
148 sizeof(ldb
->schema
.attributes
[0]) * ldb
->schema
.num_attributes
);
150 /* mapping these flags onto ldap 'syntaxes' isn't strictly correct,
151 but its close enough for now */
152 for (i
=0;i
<attrs_msg
->num_elements
;i
++) {
155 const struct ldb_schema_syntax
*s
;
156 const struct ldb_schema_attribute
*a
=
157 ldb_schema_attribute_by_name(ldb
,
158 attrs_msg
->elements
[i
].name
);
159 if (a
!= NULL
&& a
->flags
& LDB_ATTR_FLAG_FIXED
) {
160 /* Must already be set in the array, and kept */
164 if (ltdb_attributes_flags(&attrs_msg
->elements
[i
], &flags
) != 0) {
165 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
166 "Invalid @ATTRIBUTES element for '%s'",
167 attrs_msg
->elements
[i
].name
);
170 switch (flags
& ~LTDB_FLAG_HIDDEN
) {
172 syntax
= LDB_SYNTAX_OCTET_STRING
;
174 case LTDB_FLAG_CASE_INSENSITIVE
:
175 syntax
= LDB_SYNTAX_DIRECTORY_STRING
;
177 case LTDB_FLAG_INTEGER
:
178 syntax
= LDB_SYNTAX_INTEGER
;
181 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
182 "Invalid flag combination 0x%x for '%s' "
184 flags
, attrs_msg
->elements
[i
].name
);
188 s
= ldb_standard_syntax_by_name(ldb
, syntax
);
190 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
191 "Invalid attribute syntax '%s' for '%s' "
193 syntax
, attrs_msg
->elements
[i
].name
);
197 flags
|= LDB_ATTR_FLAG_ALLOCATED
| LDB_ATTR_FLAG_FROM_DB
;
199 r
= ldb_schema_attribute_fill_with_syntax(ldb
,
201 attrs_msg
->elements
[i
].name
,
203 &attrs
[num_loaded_attrs
+ ldb
->schema
.num_attributes
]);
210 attrs
= talloc_realloc(attrs_msg
,
211 attrs
, struct ldb_schema_attribute
,
212 num_loaded_attrs
+ ldb
->schema
.num_attributes
);
216 TYPESAFE_QSORT(attrs
, num_loaded_attrs
+ ldb
->schema
.num_attributes
,
217 ldb_schema_attribute_compare
);
218 talloc_unlink(ldb
, ldb
->schema
.attributes
);
219 ldb
->schema
.attributes
= talloc_steal(ldb
, attrs
);
220 ldb
->schema
.num_attributes
= num_loaded_attrs
+ ldb
->schema
.num_attributes
;
221 TALLOC_FREE(attrs_msg
);
225 TALLOC_FREE(attrs_msg
);
230 register any index records we find for the DB
232 static int ltdb_index_load(struct ldb_module
*module
,
233 struct ltdb_private
*ltdb
)
235 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
236 struct ldb_dn
*indexlist_dn
;
239 if (ldb
->schema
.index_handler_override
) {
241 * we skip loading the @INDEXLIST record when a module is
242 * supplying its own attribute handling
244 ltdb
->cache
->attribute_indexes
= true;
245 ltdb
->cache
->one_level_indexes
= ldb
->schema
.one_level_indexes
;
249 talloc_free(ltdb
->cache
->indexlist
);
251 ltdb
->cache
->indexlist
= ldb_msg_new(ltdb
->cache
);
252 if (ltdb
->cache
->indexlist
== NULL
) {
255 ltdb
->cache
->one_level_indexes
= false;
256 ltdb
->cache
->attribute_indexes
= false;
258 indexlist_dn
= ldb_dn_new(ltdb
, ldb
, LTDB_INDEXLIST
);
259 if (indexlist_dn
== NULL
) {
263 r
= ltdb_search_dn1(module
, indexlist_dn
, ltdb
->cache
->indexlist
,
264 LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC
265 |LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC
266 |LDB_UNPACK_DATA_FLAG_NO_DN
);
267 TALLOC_FREE(indexlist_dn
);
269 if (r
!= LDB_SUCCESS
&& r
!= LDB_ERR_NO_SUCH_OBJECT
) {
273 if (ldb_msg_find_element(ltdb
->cache
->indexlist
, LTDB_IDXONE
) != NULL
) {
274 ltdb
->cache
->one_level_indexes
= true;
276 if (ldb_msg_find_element(ltdb
->cache
->indexlist
, LTDB_IDXATTR
) != NULL
) {
277 ltdb
->cache
->attribute_indexes
= true;
284 initialise the baseinfo record
286 static int ltdb_baseinfo_init(struct ldb_module
*module
)
288 struct ldb_context
*ldb
;
289 void *data
= ldb_module_get_private(module
);
290 struct ltdb_private
*ltdb
= talloc_get_type(data
, struct ltdb_private
);
291 struct ldb_message
*msg
;
292 struct ldb_message_element el
;
295 /* the initial sequence number must be different from the one
296 set in ltdb_cache_free(). Thanks to Jon for pointing this
298 const char *initial_sequence_number
= "1";
300 ldb
= ldb_module_get_ctx(module
);
302 ltdb
->sequence_number
= atof(initial_sequence_number
);
304 msg
= ldb_msg_new(ltdb
);
309 msg
->num_elements
= 1;
311 msg
->dn
= ldb_dn_new(msg
, ldb
, LTDB_BASEINFO
);
315 el
.name
= talloc_strdup(msg
, LTDB_SEQUENCE_NUMBER
);
322 val
.data
= (uint8_t *)talloc_strdup(msg
, initial_sequence_number
);
328 ret
= ltdb_store(module
, msg
, TDB_INSERT
);
337 return LDB_ERR_OPERATIONS_ERROR
;
341 free any cache records
343 static void ltdb_cache_free(struct ldb_module
*module
)
345 void *data
= ldb_module_get_private(module
);
346 struct ltdb_private
*ltdb
= talloc_get_type(data
, struct ltdb_private
);
348 ltdb
->sequence_number
= 0;
349 talloc_free(ltdb
->cache
);
356 int ltdb_cache_reload(struct ldb_module
*module
)
358 ltdb_attributes_unload(module
);
359 ltdb_cache_free(module
);
360 return ltdb_cache_load(module
);
364 load the cache records
366 int ltdb_cache_load(struct ldb_module
*module
)
368 struct ldb_context
*ldb
;
369 void *data
= ldb_module_get_private(module
);
370 struct ltdb_private
*ltdb
= talloc_get_type(data
, struct ltdb_private
);
371 struct ldb_dn
*baseinfo_dn
= NULL
, *options_dn
= NULL
;
373 struct ldb_message
*baseinfo
= NULL
, *options
= NULL
;
376 ldb
= ldb_module_get_ctx(module
);
378 /* a very fast check to avoid extra database reads */
379 if (ltdb
->cache
!= NULL
&&
380 tdb_get_seqnum(ltdb
->tdb
) == ltdb
->tdb_seqnum
) {
384 if (ltdb
->cache
== NULL
) {
385 ltdb
->cache
= talloc_zero(ltdb
, struct ltdb_cache
);
386 if (ltdb
->cache
== NULL
) goto failed
;
389 baseinfo
= ldb_msg_new(ltdb
->cache
);
390 if (baseinfo
== NULL
) goto failed
;
392 baseinfo_dn
= ldb_dn_new(baseinfo
, ldb
, LTDB_BASEINFO
);
393 if (baseinfo_dn
== NULL
) goto failed
;
395 r
= ltdb_search_dn1(module
, baseinfo_dn
, baseinfo
, 0);
396 if (r
!= LDB_SUCCESS
&& r
!= LDB_ERR_NO_SUCH_OBJECT
) {
400 /* possibly initialise the baseinfo */
401 if (r
== LDB_ERR_NO_SUCH_OBJECT
) {
403 if (tdb_transaction_start(ltdb
->tdb
) != 0) {
407 /* error handling for ltdb_baseinfo_init() is by
408 looking for the record again. */
409 ltdb_baseinfo_init(module
);
411 tdb_transaction_commit(ltdb
->tdb
);
413 if (ltdb_search_dn1(module
, baseinfo_dn
, baseinfo
, 0) != LDB_SUCCESS
) {
418 ltdb
->tdb_seqnum
= tdb_get_seqnum(ltdb
->tdb
);
420 /* if the current internal sequence number is the same as the one
421 in the database then assume the rest of the cache is OK */
422 seq
= ldb_msg_find_attr_as_uint64(baseinfo
, LTDB_SEQUENCE_NUMBER
, 0);
423 if (seq
== ltdb
->sequence_number
) {
426 ltdb
->sequence_number
= seq
;
428 /* Read an interpret database options */
429 options
= ldb_msg_new(ltdb
->cache
);
430 if (options
== NULL
) goto failed
;
432 options_dn
= ldb_dn_new(options
, ldb
, LTDB_OPTIONS
);
433 if (options_dn
== NULL
) goto failed
;
435 r
= ltdb_search_dn1(module
, options_dn
, options
, 0);
436 talloc_free(options_dn
);
437 if (r
!= LDB_SUCCESS
&& r
!= LDB_ERR_NO_SUCH_OBJECT
) {
441 /* set flags if they do exist */
442 if (r
== LDB_SUCCESS
) {
443 ltdb
->check_base
= ldb_msg_find_attr_as_bool(options
,
446 ltdb
->disallow_dn_filter
= ldb_msg_find_attr_as_bool(options
,
447 LTDB_DISALLOW_DN_FILTER
,
450 ltdb
->check_base
= false;
451 ltdb
->disallow_dn_filter
= false;
455 * ltdb_attributes_unload() calls internally talloc_free() on
456 * any non-fixed elemnts in ldb->schema.attributes.
458 * NOTE WELL: This is per-ldb, not per module, so overwrites
459 * the handlers across all databases when used under Samba's
462 ltdb_attributes_unload(module
);
464 if (ltdb_index_load(module
, ltdb
) == -1) {
469 * NOTE WELL: This is per-ldb, not per module, so overwrites
470 * the handlers across all databases when used under Samba's
473 if (ltdb_attributes_load(module
) == -1) {
478 talloc_free(options
);
479 talloc_free(baseinfo
);
483 talloc_free(options
);
484 talloc_free(baseinfo
);
490 increase the sequence number to indicate a database change
492 int ltdb_increase_sequence_number(struct ldb_module
*module
)
494 struct ldb_context
*ldb
;
495 void *data
= ldb_module_get_private(module
);
496 struct ltdb_private
*ltdb
= talloc_get_type(data
, struct ltdb_private
);
497 struct ldb_message
*msg
;
498 struct ldb_message_element el
[2];
500 struct ldb_val val_time
;
501 time_t t
= time(NULL
);
505 ldb
= ldb_module_get_ctx(module
);
507 msg
= ldb_msg_new(ltdb
);
510 return LDB_ERR_OPERATIONS_ERROR
;
513 s
= talloc_asprintf(msg
, "%llu", ltdb
->sequence_number
+1);
517 return LDB_ERR_OPERATIONS_ERROR
;
520 msg
->num_elements
= ARRAY_SIZE(el
);
522 msg
->dn
= ldb_dn_new(msg
, ldb
, LTDB_BASEINFO
);
523 if (msg
->dn
== NULL
) {
526 return LDB_ERR_OPERATIONS_ERROR
;
528 el
[0].name
= talloc_strdup(msg
, LTDB_SEQUENCE_NUMBER
);
529 if (el
[0].name
== NULL
) {
532 return LDB_ERR_OPERATIONS_ERROR
;
535 el
[0].num_values
= 1;
536 el
[0].flags
= LDB_FLAG_MOD_REPLACE
;
537 val
.data
= (uint8_t *)s
;
538 val
.length
= strlen(s
);
540 el
[1].name
= talloc_strdup(msg
, LTDB_MOD_TIMESTAMP
);
541 if (el
[1].name
== NULL
) {
544 return LDB_ERR_OPERATIONS_ERROR
;
546 el
[1].values
= &val_time
;
547 el
[1].num_values
= 1;
548 el
[1].flags
= LDB_FLAG_MOD_REPLACE
;
550 s
= ldb_timestring(msg
, t
);
553 return LDB_ERR_OPERATIONS_ERROR
;
556 val_time
.data
= (uint8_t *)s
;
557 val_time
.length
= strlen(s
);
559 ret
= ltdb_modify_internal(module
, msg
, NULL
);
563 if (ret
== LDB_SUCCESS
) {
564 ltdb
->sequence_number
+= 1;
567 /* updating the tdb_seqnum here avoids us reloading the cache
568 records due to our own modification */
569 ltdb
->tdb_seqnum
= tdb_get_seqnum(ltdb
->tdb
);
574 int ltdb_check_at_attributes_values(const struct ldb_val
*value
)
578 for (i
= 0; ltdb_valid_attr_flags
[i
].name
!= NULL
; i
++) {
579 if ((strcmp(ltdb_valid_attr_flags
[i
].name
, (char *)value
->data
) == 0)) {