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