r19430: merge recent ldb changes from Samba4. This includes memory leak fixes
[kai/samba-autobuild/.git] / source3 / 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 2 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, write to the Free Software
22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 */
24
25 /*
26  *  Name: ldb
27  *
28  *  Component: ldb tdb cache functions
29  *
30  *  Description: cache special records in a ldb/tdb
31  *
32  *  Author: Andrew Tridgell
33  */
34
35 #include "includes.h"
36 #include "ldb/include/includes.h"
37
38 #include "ldb/ldb_tdb/ldb_tdb.h"
39
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)
44
45 /* valid attribute flags */
46 static const struct {
47         const char *name;
48         int value;
49 } ltdb_valid_attr_flags[] = {
50         { "CASE_INSENSITIVE", LTDB_FLAG_CASE_INSENSITIVE },
51         { "INTEGER", LTDB_FLAG_INTEGER },
52         { "HIDDEN", LTDB_FLAG_HIDDEN },
53         { "NONE", 0 },
54         { NULL, 0 }
55 };
56
57
58 /*
59   de-register any special handlers for @ATTRIBUTES
60 */
61 static void ltdb_attributes_unload(struct ldb_module *module)
62 {
63         struct ltdb_private *ltdb = module->private_data;
64         struct ldb_message *msg;
65         int i;
66
67         if (ltdb->cache->attributes == NULL) {
68                 /* no previously loaded attributes */
69                 return;
70         }
71
72         msg = ltdb->cache->attributes;
73         for (i=0;i<msg->num_elements;i++) {
74                 ldb_remove_attrib_handler(module->ldb, msg->elements[i].name);
75         }
76
77         talloc_free(ltdb->cache->attributes);
78         ltdb->cache->attributes = NULL;
79 }
80
81 /*
82   add up the attrib flags for a @ATTRIBUTES element
83 */
84 static int ltdb_attributes_flags(struct ldb_message_element *el, unsigned *v)
85 {
86         int i;
87         unsigned value = 0;
88         for (i=0;i<el->num_values;i++) {
89                 int j;
90                 for (j=0;ltdb_valid_attr_flags[j].name;j++) {
91                         if (strcmp(ltdb_valid_attr_flags[j].name, 
92                                    (char *)el->values[i].data) == 0) {
93                                 value |= ltdb_valid_attr_flags[j].value;
94                                 break;
95                         }
96                 }
97                 if (ltdb_valid_attr_flags[j].name == NULL) {
98                         return -1;
99                 }
100         }
101         *v = value;
102         return 0;
103 }
104
105 /*
106   register any special handlers from @ATTRIBUTES
107 */
108 static int ltdb_attributes_load(struct ldb_module *module)
109 {
110         struct ltdb_private *ltdb = module->private_data;
111         struct ldb_message *msg = ltdb->cache->attributes;
112         struct ldb_dn *dn;
113         int i;
114
115         dn = ldb_dn_explode(module->ldb, LTDB_ATTRIBUTES);
116         if (dn == NULL) goto failed;
117
118         if (ltdb_search_dn1(module, dn, msg) == -1) {
119                 talloc_free(dn);
120                 goto failed;
121         }
122         talloc_free(dn);
123         /* mapping these flags onto ldap 'syntaxes' isn't strictly correct,
124            but its close enough for now */
125         for (i=0;i<msg->num_elements;i++) {
126                 unsigned flags;
127                 const char *syntax;
128                 const struct ldb_attrib_handler *h;
129                 struct ldb_attrib_handler h2;
130
131                 if (ltdb_attributes_flags(&msg->elements[i], &flags) != 0) {
132                         ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Invalid @ATTRIBUTES element for '%s'\n", msg->elements[i].name);
133                         goto failed;
134                 }
135                 switch (flags & ~LTDB_FLAG_HIDDEN) {
136                 case 0:
137                         syntax = LDB_SYNTAX_OCTET_STRING;
138                         break;
139                 case LTDB_FLAG_CASE_INSENSITIVE:
140                         syntax = LDB_SYNTAX_DIRECTORY_STRING;
141                         break;
142                 case LTDB_FLAG_INTEGER:
143                         syntax = LDB_SYNTAX_INTEGER;
144                         break;
145                 default:
146                         ldb_debug(module->ldb, LDB_DEBUG_ERROR, 
147                                   "Invalid flag combination 0x%x for '%s' in @ATTRIBUTES\n",
148                                   flags, msg->elements[i].name);
149                         goto failed;
150                 }
151
152                 h = ldb_attrib_handler_syntax(module->ldb, syntax);
153                 if (h == NULL) {
154                         ldb_debug(module->ldb, LDB_DEBUG_ERROR, 
155                                   "Invalid attribute syntax '%s' for '%s' in @ATTRIBUTES\n",
156                                   syntax, msg->elements[i].name);
157                         goto failed;
158                 }
159                 h2 = *h;
160                 h2.attr = msg->elements[i].name;
161                 h2.flags |= LDB_ATTR_FLAG_ALLOCATED;
162                 if (ldb_set_attrib_handlers(module->ldb, &h2, 1) != 0) {
163                         goto failed;
164                 }
165         }
166
167         return 0;
168 failed:
169         return -1;
170 }
171
172
173 /*
174   register any subclasses from @SUBCLASSES
175 */
176 static int ltdb_subclasses_load(struct ldb_module *module)
177 {
178         struct ltdb_private *ltdb = module->private_data;
179         struct ldb_message *msg = ltdb->cache->subclasses;
180         struct ldb_dn *dn;
181         int i, j;
182
183         dn = ldb_dn_explode(module->ldb, LTDB_SUBCLASSES);
184         if (dn == NULL) goto failed;
185
186         if (ltdb_search_dn1(module, dn, msg) == -1) {
187                 talloc_free(dn);
188                 goto failed;
189         }
190         talloc_free(dn);
191
192         for (i=0;i<msg->num_elements;i++) {
193                 struct ldb_message_element *el = &msg->elements[i];
194                 for (j=0;j<el->num_values;j++) {
195                         if (ldb_subclass_add(module->ldb, el->name, 
196                                              (char *)el->values[j].data) != 0) {
197                                 goto failed;
198                         }
199                 }
200         }
201
202         return 0;
203 failed:
204         return -1;
205 }
206
207
208 /*
209   de-register any @SUBCLASSES
210 */
211 static void ltdb_subclasses_unload(struct ldb_module *module)
212 {
213         struct ltdb_private *ltdb = module->private_data;
214         struct ldb_message *msg;
215         int i;
216
217         if (ltdb->cache->subclasses == NULL) {
218                 /* no previously loaded subclasses */
219                 return;
220         }
221
222         msg = ltdb->cache->subclasses;
223         for (i=0;i<msg->num_elements;i++) {
224                 ldb_subclass_remove(module->ldb, msg->elements[i].name);
225         }
226
227         talloc_free(ltdb->cache->subclasses);
228         ltdb->cache->subclasses = NULL;
229 }
230
231
232 /*
233   initialise the baseinfo record
234 */
235 static int ltdb_baseinfo_init(struct ldb_module *module)
236 {
237         struct ltdb_private *ltdb = module->private_data;
238         struct ldb_message *msg;
239         struct ldb_message_element el;
240         struct ldb_val val;
241         int ret;
242         /* the initial sequence number must be different from the one
243            set in ltdb_cache_free(). Thanks to Jon for pointing this
244            out. */
245         const char *initial_sequence_number = "1";
246
247         ltdb->sequence_number = atof(initial_sequence_number);
248
249         msg = talloc(ltdb, struct ldb_message);
250         if (msg == NULL) {
251                 goto failed;
252         }
253
254         msg->num_elements = 1;
255         msg->elements = &el;
256         msg->dn = ldb_dn_explode(msg, LTDB_BASEINFO);
257         if (!msg->dn) {
258                 goto failed;
259         }
260         el.name = talloc_strdup(msg, LTDB_SEQUENCE_NUMBER);
261         if (!el.name) {
262                 goto failed;
263         }
264         el.values = &val;
265         el.num_values = 1;
266         el.flags = 0;
267         val.data = (uint8_t *)talloc_strdup(msg, initial_sequence_number);
268         if (!val.data) {
269                 goto failed;
270         }
271         val.length = 1;
272         
273         ret = ltdb_store(module, msg, TDB_INSERT);
274
275         talloc_free(msg);
276
277         return ret;
278
279 failed:
280         talloc_free(msg);
281         errno = ENOMEM;
282         return -1;
283 }
284
285 /*
286   free any cache records
287  */
288 static void ltdb_cache_free(struct ldb_module *module)
289 {
290         struct ltdb_private *ltdb = module->private_data;
291
292         ltdb->sequence_number = 0;
293         talloc_free(ltdb->cache);
294         ltdb->cache = NULL;
295 }
296
297 /*
298   force a cache reload
299 */
300 int ltdb_cache_reload(struct ldb_module *module)
301 {
302         ltdb_attributes_unload(module);
303         ltdb_subclasses_unload(module);
304         ltdb_cache_free(module);
305         return ltdb_cache_load(module);
306 }
307
308 /*
309   load the cache records
310 */
311 int ltdb_cache_load(struct ldb_module *module)
312 {
313         struct ltdb_private *ltdb = module->private_data;
314         struct ldb_dn *baseinfo_dn = NULL;
315         struct ldb_dn *indexlist_dn = NULL;
316         uint64_t seq;
317         struct ldb_message *baseinfo;
318
319         /* a very fast check to avoid extra database reads */
320         if (ltdb->cache != NULL && 
321             tdb_get_seqnum(ltdb->tdb) == ltdb->tdb_seqnum) {
322                 return 0;
323         }
324
325         if (ltdb->cache == NULL) {
326                 ltdb->cache = talloc_zero(ltdb, struct ltdb_cache);
327                 if (ltdb->cache == NULL) goto failed;
328                 ltdb->cache->indexlist = talloc_zero(ltdb->cache, struct ldb_message);
329                 ltdb->cache->subclasses = talloc_zero(ltdb->cache, struct ldb_message);
330                 ltdb->cache->attributes = talloc_zero(ltdb->cache, struct ldb_message);
331                 if (ltdb->cache->indexlist == NULL ||
332                     ltdb->cache->subclasses == NULL ||
333                     ltdb->cache->attributes == NULL) {
334                         goto failed;
335                 }
336         }
337
338         baseinfo = talloc(ltdb->cache, struct ldb_message);
339         if (baseinfo == NULL) goto failed;
340
341         baseinfo_dn = ldb_dn_explode(module->ldb, LTDB_BASEINFO);
342         if (baseinfo_dn == NULL) goto failed;
343
344         if (ltdb_search_dn1(module, baseinfo_dn, baseinfo) == -1) {
345                 goto failed;
346         }
347         
348         /* possibly initialise the baseinfo */
349         if (!baseinfo->dn) {
350                 if (ltdb_baseinfo_init(module) != 0) {
351                         goto failed;
352                 }
353                 if (ltdb_search_dn1(module, baseinfo_dn, baseinfo) != 1) {
354                         goto failed;
355                 }
356         }
357
358         ltdb->tdb_seqnum = tdb_get_seqnum(ltdb->tdb);
359
360         /* if the current internal sequence number is the same as the one
361            in the database then assume the rest of the cache is OK */
362         seq = ldb_msg_find_attr_as_uint64(baseinfo, LTDB_SEQUENCE_NUMBER, 0);
363         if (seq == ltdb->sequence_number) {
364                 goto done;
365         }
366         ltdb->sequence_number = seq;
367
368         talloc_free(ltdb->cache->last_attribute.name);
369         memset(&ltdb->cache->last_attribute, 0, sizeof(ltdb->cache->last_attribute));
370
371         ltdb_attributes_unload(module);
372         ltdb_subclasses_unload(module);
373
374         talloc_free(ltdb->cache->indexlist);
375         talloc_free(ltdb->cache->subclasses);
376
377         ltdb->cache->indexlist = talloc_zero(ltdb->cache, struct ldb_message);
378         ltdb->cache->subclasses = talloc_zero(ltdb->cache, struct ldb_message);
379         ltdb->cache->attributes = talloc_zero(ltdb->cache, struct ldb_message);
380         if (ltdb->cache->indexlist == NULL ||
381             ltdb->cache->subclasses == NULL ||
382             ltdb->cache->attributes == NULL) {
383                 goto failed;
384         }
385             
386         indexlist_dn = ldb_dn_explode(module->ldb, LTDB_INDEXLIST);
387         if (indexlist_dn == NULL) goto failed;
388
389         if (ltdb_search_dn1(module, indexlist_dn, ltdb->cache->indexlist) == -1) {
390                 goto failed;
391         }
392
393         if (ltdb_attributes_load(module) == -1) {
394                 goto failed;
395         }
396         if (ltdb_subclasses_load(module) == -1) {
397                 goto failed;
398         }
399
400 done:
401         talloc_free(baseinfo);
402         talloc_free(baseinfo_dn);
403         talloc_free(indexlist_dn);
404         return 0;
405
406 failed:
407         talloc_free(baseinfo);
408         talloc_free(baseinfo_dn);
409         talloc_free(indexlist_dn);
410         return -1;
411 }
412
413
414 /*
415   increase the sequence number to indicate a database change
416 */
417 int ltdb_increase_sequence_number(struct ldb_module *module)
418 {
419         struct ltdb_private *ltdb = module->private_data;
420         struct ldb_message *msg;
421         struct ldb_message_element el[2];
422         struct ldb_val val;
423         struct ldb_val val_time;
424         time_t t = time(NULL);
425         char *s = NULL;
426         int ret;
427
428         msg = talloc(ltdb, struct ldb_message);
429         if (msg == NULL) {
430                 errno = ENOMEM;
431                 return -1;
432         }
433
434         s = talloc_asprintf(msg, "%llu", ltdb->sequence_number+1);
435         if (!s) {
436                 errno = ENOMEM;
437                 return -1;
438         }
439
440         msg->num_elements = ARRAY_SIZE(el);
441         msg->elements = el;
442         msg->dn = ldb_dn_explode(msg, LTDB_BASEINFO);
443         if (msg->dn == NULL) {
444                 talloc_free(msg);
445                 errno = ENOMEM;
446                 return -1;
447         }
448         el[0].name = talloc_strdup(msg, LTDB_SEQUENCE_NUMBER);
449         if (el[0].name == NULL) {
450                 talloc_free(msg);
451                 errno = ENOMEM;
452                 return -1;
453         }
454         el[0].values = &val;
455         el[0].num_values = 1;
456         el[0].flags = LDB_FLAG_MOD_REPLACE;
457         val.data = (uint8_t *)s;
458         val.length = strlen(s);
459
460         el[1].name = talloc_strdup(msg, LTDB_MOD_TIMESTAMP);
461         if (el[1].name == NULL) {
462                 talloc_free(msg);
463                 errno = ENOMEM;
464                 return -1;
465         }
466         el[1].values = &val_time;
467         el[1].num_values = 1;
468         el[1].flags = LDB_FLAG_MOD_REPLACE;
469
470         s = ldb_timestring(msg, t);
471         if (s == NULL) {
472                 return -1;
473         }
474
475         val_time.data = (uint8_t *)s;
476         val_time.length = strlen(s);
477
478         ret = ltdb_modify_internal(module, msg);
479
480         talloc_free(msg);
481
482         if (ret == 0) {
483                 ltdb->sequence_number += 1;
484         }
485
486         return ret;
487 }
488
489
490 /*
491   return the attribute flags from the @ATTRIBUTES record 
492   for the given attribute
493 */
494 int ltdb_attribute_flags(struct ldb_module *module, const char *attr_name)
495 {
496         struct ltdb_private *ltdb = module->private_data;
497         const struct ldb_message_element *attr_el;
498         int i, j, ret=0;
499
500         if (ltdb->cache->last_attribute.name &&
501             ldb_attr_cmp(ltdb->cache->last_attribute.name, attr_name) == 0) {
502                 return ltdb->cache->last_attribute.flags;
503         }
504
505         /* objectclass is a special default case */
506         if (ldb_attr_cmp(attr_name, LTDB_OBJECTCLASS) == 0) {
507                 ret = LTDB_FLAG_OBJECTCLASS | LTDB_FLAG_CASE_INSENSITIVE;
508         }
509
510         attr_el = ldb_msg_find_element(ltdb->cache->attributes, attr_name);
511
512         if (!attr_el) {
513                 /* check if theres a wildcard attribute */
514                 attr_el = ldb_msg_find_element(ltdb->cache->attributes, "*");
515
516                 if (!attr_el) {
517                         return ret;
518                 }
519         }
520
521         for (i = 0; i < attr_el->num_values; i++) {
522                 for (j=0; ltdb_valid_attr_flags[j].name; j++) {
523                         if (strcmp(ltdb_valid_attr_flags[j].name, 
524                                    (char *)attr_el->values[i].data) == 0) {
525                                 ret |= ltdb_valid_attr_flags[j].value;
526                         }
527                 }
528         }
529
530         talloc_free(ltdb->cache->last_attribute.name);
531
532         ltdb->cache->last_attribute.name = talloc_strdup(ltdb->cache, attr_name);
533         ltdb->cache->last_attribute.flags = ret;
534
535         return ret;
536 }
537
538 int ltdb_check_at_attributes_values(const struct ldb_val *value)
539 {
540         int i;
541
542         for (i = 0; ltdb_valid_attr_flags[i].name != NULL; i++) {
543                 if ((strcmp(ltdb_valid_attr_flags[i].name, (char *)value->data) == 0)) {
544                         return 0;
545                 }
546         }
547
548         return -1;
549 }
550