Fix the mess with ldb includes.
[metze/samba/wip.git] / source4 / lib / ldb / ldb_tdb / ldb_cache.c
1 /* 
2    ldb database library
3
4    Copyright (C) Andrew Tridgell  2004
5
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
9    
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.
14
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.
19
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/>.
22 */
23
24 /*
25  *  Name: ldb
26  *
27  *  Component: ldb tdb cache functions
28  *
29  *  Description: cache special records in a ldb/tdb
30  *
31  *  Author: Andrew Tridgell
32  */
33
34 #include "ldb_tdb.h"
35
36 #define LTDB_FLAG_CASE_INSENSITIVE (1<<0)
37 #define LTDB_FLAG_INTEGER          (1<<1)
38 #define LTDB_FLAG_HIDDEN           (1<<2)
39
40 /* valid attribute flags */
41 static const struct {
42         const char *name;
43         int value;
44 } ltdb_valid_attr_flags[] = {
45         { "CASE_INSENSITIVE", LTDB_FLAG_CASE_INSENSITIVE },
46         { "INTEGER", LTDB_FLAG_INTEGER },
47         { "HIDDEN", LTDB_FLAG_HIDDEN },
48         { "NONE", 0 },
49         { NULL, 0 }
50 };
51
52
53 /*
54   de-register any special handlers for @ATTRIBUTES
55 */
56 static void ltdb_attributes_unload(struct ldb_module *module)
57 {
58         struct ldb_context *ldb;
59         void *data = ldb_module_get_private(module);
60         struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
61         struct ldb_message *msg;
62         int i;
63
64         ldb = ldb_module_get_ctx(module);
65
66         if (ltdb->cache->attributes == NULL) {
67                 /* no previously loaded attributes */
68                 return;
69         }
70
71         msg = ltdb->cache->attributes;
72         for (i=0;i<msg->num_elements;i++) {
73                 ldb_schema_attribute_remove(ldb, msg->elements[i].name);
74         }
75
76         talloc_free(ltdb->cache->attributes);
77         ltdb->cache->attributes = NULL;
78 }
79
80 /*
81   add up the attrib flags for a @ATTRIBUTES element
82 */
83 static int ltdb_attributes_flags(struct ldb_message_element *el, unsigned *v)
84 {
85         int i;
86         unsigned value = 0;
87         for (i=0;i<el->num_values;i++) {
88                 int j;
89                 for (j=0;ltdb_valid_attr_flags[j].name;j++) {
90                         if (strcmp(ltdb_valid_attr_flags[j].name, 
91                                    (char *)el->values[i].data) == 0) {
92                                 value |= ltdb_valid_attr_flags[j].value;
93                                 break;
94                         }
95                 }
96                 if (ltdb_valid_attr_flags[j].name == NULL) {
97                         return -1;
98                 }
99         }
100         *v = value;
101         return 0;
102 }
103
104 /*
105   register any special handlers from @ATTRIBUTES
106 */
107 static int ltdb_attributes_load(struct ldb_module *module)
108 {
109         struct ldb_context *ldb;
110         void *data = ldb_module_get_private(module);
111         struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
112         struct ldb_message *msg = ltdb->cache->attributes;
113         struct ldb_dn *dn;
114         int i, r;
115
116         ldb = ldb_module_get_ctx(module);
117
118         dn = ldb_dn_new(module, ldb, LTDB_ATTRIBUTES);
119         if (dn == NULL) goto failed;
120
121         r = ltdb_search_dn1(module, dn, msg);
122         talloc_free(dn);
123         if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) {
124                 goto failed;
125         }
126         if (r == LDB_ERR_NO_SUCH_OBJECT) {
127                 return 0;
128         }
129         /* mapping these flags onto ldap 'syntaxes' isn't strictly correct,
130            but its close enough for now */
131         for (i=0;i<msg->num_elements;i++) {
132                 unsigned flags;
133                 const char *syntax;
134                 const struct ldb_schema_syntax *s;
135
136                 if (ltdb_attributes_flags(&msg->elements[i], &flags) != 0) {
137                         ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid @ATTRIBUTES element for '%s'\n", msg->elements[i].name);
138                         goto failed;
139                 }
140                 switch (flags & ~LTDB_FLAG_HIDDEN) {
141                 case 0:
142                         syntax = LDB_SYNTAX_OCTET_STRING;
143                         break;
144                 case LTDB_FLAG_CASE_INSENSITIVE:
145                         syntax = LDB_SYNTAX_DIRECTORY_STRING;
146                         break;
147                 case LTDB_FLAG_INTEGER:
148                         syntax = LDB_SYNTAX_INTEGER;
149                         break;
150                 default:
151                         ldb_debug(ldb, LDB_DEBUG_ERROR, 
152                                   "Invalid flag combination 0x%x for '%s' in @ATTRIBUTES\n",
153                                   flags, msg->elements[i].name);
154                         goto failed;
155                 }
156
157                 s = ldb_standard_syntax_by_name(ldb, syntax);
158                 if (s == NULL) {
159                         ldb_debug(ldb, LDB_DEBUG_ERROR, 
160                                   "Invalid attribute syntax '%s' for '%s' in @ATTRIBUTES\n",
161                                   syntax, msg->elements[i].name);
162                         goto failed;
163                 }
164
165                 flags |= LDB_ATTR_FLAG_ALLOCATED;
166                 if (ldb_schema_attribute_add_with_syntax(ldb, msg->elements[i].name, flags, s) != 0) {
167                         goto failed;
168                 }
169         }
170
171         return 0;
172 failed:
173         return -1;
174 }
175
176
177 /*
178   initialise the baseinfo record
179 */
180 static int ltdb_baseinfo_init(struct ldb_module *module)
181 {
182         struct ldb_context *ldb;
183         void *data = ldb_module_get_private(module);
184         struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
185         struct ldb_message *msg;
186         struct ldb_message_element el;
187         struct ldb_val val;
188         int ret;
189         /* the initial sequence number must be different from the one
190            set in ltdb_cache_free(). Thanks to Jon for pointing this
191            out. */
192         const char *initial_sequence_number = "1";
193
194         ldb = ldb_module_get_ctx(module);
195
196         ltdb->sequence_number = atof(initial_sequence_number);
197
198         msg = talloc(ltdb, struct ldb_message);
199         if (msg == NULL) {
200                 goto failed;
201         }
202
203         msg->num_elements = 1;
204         msg->elements = &el;
205         msg->dn = ldb_dn_new(msg, ldb, LTDB_BASEINFO);
206         if (!msg->dn) {
207                 goto failed;
208         }
209         el.name = talloc_strdup(msg, LTDB_SEQUENCE_NUMBER);
210         if (!el.name) {
211                 goto failed;
212         }
213         el.values = &val;
214         el.num_values = 1;
215         el.flags = 0;
216         val.data = (uint8_t *)talloc_strdup(msg, initial_sequence_number);
217         if (!val.data) {
218                 goto failed;
219         }
220         val.length = 1;
221         
222         ret = ltdb_store(module, msg, TDB_INSERT);
223
224         talloc_free(msg);
225
226         return ret;
227
228 failed:
229         talloc_free(msg);
230         errno = ENOMEM;
231         return LDB_ERR_OPERATIONS_ERROR;
232 }
233
234 /*
235   free any cache records
236  */
237 static void ltdb_cache_free(struct ldb_module *module)
238 {
239         void *data = ldb_module_get_private(module);
240         struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
241
242         ltdb->sequence_number = 0;
243         talloc_free(ltdb->cache);
244         ltdb->cache = NULL;
245 }
246
247 /*
248   force a cache reload
249 */
250 int ltdb_cache_reload(struct ldb_module *module)
251 {
252         ltdb_attributes_unload(module);
253         ltdb_cache_free(module);
254         return ltdb_cache_load(module);
255 }
256
257 /*
258   load the cache records
259 */
260 int ltdb_cache_load(struct ldb_module *module)
261 {
262         struct ldb_context *ldb;
263         void *data = ldb_module_get_private(module);
264         struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
265         struct ldb_dn *baseinfo_dn = NULL, *options_dn = NULL;
266         struct ldb_dn *indexlist_dn = NULL;
267         uint64_t seq;
268         struct ldb_message *baseinfo = NULL, *options = NULL;
269         int r;
270
271         ldb = ldb_module_get_ctx(module);
272
273         /* a very fast check to avoid extra database reads */
274         if (ltdb->cache != NULL && 
275             tdb_get_seqnum(ltdb->tdb) == ltdb->tdb_seqnum) {
276                 return 0;
277         }
278
279         if (ltdb->cache == NULL) {
280                 ltdb->cache = talloc_zero(ltdb, struct ltdb_cache);
281                 if (ltdb->cache == NULL) goto failed;
282                 ltdb->cache->indexlist = talloc_zero(ltdb->cache, struct ldb_message);
283                 ltdb->cache->attributes = talloc_zero(ltdb->cache, struct ldb_message);
284                 if (ltdb->cache->indexlist == NULL ||
285                     ltdb->cache->attributes == NULL) {
286                         goto failed;
287                 }
288         }
289
290         baseinfo = talloc(ltdb->cache, struct ldb_message);
291         if (baseinfo == NULL) goto failed;
292
293         baseinfo_dn = ldb_dn_new(module, ldb, LTDB_BASEINFO);
294         if (baseinfo_dn == NULL) goto failed;
295
296         r= ltdb_search_dn1(module, baseinfo_dn, baseinfo);
297         if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) {
298                 goto failed;
299         }
300         
301         /* possibly initialise the baseinfo */
302         if (r == LDB_ERR_NO_SUCH_OBJECT) {
303                 if (ltdb_baseinfo_init(module) != LDB_SUCCESS) {
304                         goto failed;
305                 }
306                 if (ltdb_search_dn1(module, baseinfo_dn, baseinfo) != LDB_SUCCESS) {
307                         goto failed;
308                 }
309         }
310
311         ltdb->tdb_seqnum = tdb_get_seqnum(ltdb->tdb);
312
313         /* if the current internal sequence number is the same as the one
314            in the database then assume the rest of the cache is OK */
315         seq = ldb_msg_find_attr_as_uint64(baseinfo, LTDB_SEQUENCE_NUMBER, 0);
316         if (seq == ltdb->sequence_number) {
317                 goto done;
318         }
319         ltdb->sequence_number = seq;
320
321         /* Read an interpret database options */
322         options = talloc(ltdb->cache, struct ldb_message);
323         if (options == NULL) goto failed;
324
325         options_dn = ldb_dn_new(options, ldb, LTDB_OPTIONS);
326         if (options_dn == NULL) goto failed;
327
328         r= ltdb_search_dn1(module, options_dn, options);
329         if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) {
330                 goto failed;
331         }
332         
333         /* set flag for checking base DN on searches */
334         if (r == LDB_SUCCESS) {
335                 ltdb->check_base = ldb_msg_find_attr_as_bool(options, LTDB_CHECK_BASE, false);
336         } else {
337                 ltdb->check_base = false;
338         }
339
340         talloc_free(ltdb->cache->last_attribute.name);
341         memset(&ltdb->cache->last_attribute, 0, sizeof(ltdb->cache->last_attribute));
342
343         ltdb_attributes_unload(module);
344
345         talloc_free(ltdb->cache->indexlist);
346
347         ltdb->cache->indexlist = talloc_zero(ltdb->cache, struct ldb_message);
348         ltdb->cache->attributes = talloc_zero(ltdb->cache, struct ldb_message);
349         if (ltdb->cache->indexlist == NULL ||
350             ltdb->cache->attributes == NULL) {
351                 goto failed;
352         }
353             
354         indexlist_dn = ldb_dn_new(module, ldb, LTDB_INDEXLIST);
355         if (indexlist_dn == NULL) goto failed;
356
357         r = ltdb_search_dn1(module, indexlist_dn, ltdb->cache->indexlist);
358         if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) {
359                 goto failed;
360         }
361
362         if (ltdb_attributes_load(module) == -1) {
363                 goto failed;
364         }
365
366 done:
367         talloc_free(options);
368         talloc_free(baseinfo);
369         talloc_free(baseinfo_dn);
370         talloc_free(indexlist_dn);
371         return 0;
372
373 failed:
374         talloc_free(options);
375         talloc_free(baseinfo);
376         talloc_free(baseinfo_dn);
377         talloc_free(indexlist_dn);
378         return -1;
379 }
380
381
382 /*
383   increase the sequence number to indicate a database change
384 */
385 int ltdb_increase_sequence_number(struct ldb_module *module)
386 {
387         struct ldb_context *ldb;
388         void *data = ldb_module_get_private(module);
389         struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
390         struct ldb_message *msg;
391         struct ldb_message_element el[2];
392         struct ldb_val val;
393         struct ldb_val val_time;
394         time_t t = time(NULL);
395         char *s = NULL;
396         int ret;
397
398         ldb = ldb_module_get_ctx(module);
399
400         msg = talloc(ltdb, struct ldb_message);
401         if (msg == NULL) {
402                 errno = ENOMEM;
403                 return LDB_ERR_OPERATIONS_ERROR;
404         }
405
406         s = talloc_asprintf(msg, "%llu", ltdb->sequence_number+1);
407         if (!s) {
408                 errno = ENOMEM;
409                 return LDB_ERR_OPERATIONS_ERROR;
410         }
411
412         msg->num_elements = ARRAY_SIZE(el);
413         msg->elements = el;
414         msg->dn = ldb_dn_new(msg, ldb, LTDB_BASEINFO);
415         if (msg->dn == NULL) {
416                 talloc_free(msg);
417                 errno = ENOMEM;
418                 return LDB_ERR_OPERATIONS_ERROR;
419         }
420         el[0].name = talloc_strdup(msg, LTDB_SEQUENCE_NUMBER);
421         if (el[0].name == NULL) {
422                 talloc_free(msg);
423                 errno = ENOMEM;
424                 return LDB_ERR_OPERATIONS_ERROR;
425         }
426         el[0].values = &val;
427         el[0].num_values = 1;
428         el[0].flags = LDB_FLAG_MOD_REPLACE;
429         val.data = (uint8_t *)s;
430         val.length = strlen(s);
431
432         el[1].name = talloc_strdup(msg, LTDB_MOD_TIMESTAMP);
433         if (el[1].name == NULL) {
434                 talloc_free(msg);
435                 errno = ENOMEM;
436                 return LDB_ERR_OPERATIONS_ERROR;
437         }
438         el[1].values = &val_time;
439         el[1].num_values = 1;
440         el[1].flags = LDB_FLAG_MOD_REPLACE;
441
442         s = ldb_timestring(msg, t);
443         if (s == NULL) {
444                 return LDB_ERR_OPERATIONS_ERROR;
445         }
446
447         val_time.data = (uint8_t *)s;
448         val_time.length = strlen(s);
449
450         ret = ltdb_modify_internal(module, msg);
451
452         talloc_free(msg);
453
454         if (ret == LDB_SUCCESS) {
455                 ltdb->sequence_number += 1;
456         }
457
458         /* updating the tdb_seqnum here avoids us reloading the cache
459            records due to our own modification */
460         ltdb->tdb_seqnum = tdb_get_seqnum(ltdb->tdb);
461
462         return ret;
463 }
464
465 int ltdb_check_at_attributes_values(const struct ldb_val *value)
466 {
467         int i;
468
469         for (i = 0; ltdb_valid_attr_flags[i].name != NULL; i++) {
470                 if ((strcmp(ltdb_valid_attr_flags[i].name, (char *)value->data) == 0)) {
471                         return 0;
472                 }
473         }
474
475         return -1;
476 }
477