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