• 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   Copyright (C) Stefan Metzmacher  2004
6   Copyright (C) Simo Sorce       2006
7
8
9     ** NOTE! The following LGPL license applies to the ldb
10     ** library. This does NOT imply that all of Samba is released
11     ** under the LGPL
12
13   This library is free software; you can redistribute it and/or
14   modify it under the terms of the GNU Lesser General Public
15   License as published by the Free Software Foundation; either
16   version 3 of the License, or (at your option) any later version.
17
18   This library is distributed in the hope that it will be useful,
19   but WITHOUT ANY WARRANTY; without even the implied warranty of
20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21   Lesser General Public License for more details.
22
23   You should have received a copy of the GNU Lesser General Public
24   License along with this library; if not, see <http://www.gnu.org/licenses/>.
25*/
26
27/*
28 *  Name: ldb_tdb
29 *
30 *  Component: ldb tdb backend
31 *
32 *  Description: core functions for tdb backend
33 *
34 *  Author: Andrew Tridgell
35 *  Author: Stefan Metzmacher
36 *
37 *  Modifications:
38 *
39 *  - description: make the module use asyncronous calls
40 *    date: Feb 2006
41 *    Author: Simo Sorce
42 */
43
44#include "includes.h"
45#include "ldb/include/includes.h"
46
47#include "ldb/ldb_tdb/ldb_tdb.h"
48
49int ltdb_check_special_dn(struct ldb_module *module, const struct ldb_message *msg);
50
51/*
52  map a tdb error code to a ldb error code
53*/
54static int ltdb_err_map(enum TDB_ERROR tdb_code)
55{
56	switch (tdb_code) {
57	case TDB_SUCCESS:
58		return LDB_SUCCESS;
59	case TDB_ERR_CORRUPT:
60	case TDB_ERR_OOM:
61	case TDB_ERR_EINVAL:
62		return LDB_ERR_OPERATIONS_ERROR;
63	case TDB_ERR_IO:
64		return LDB_ERR_PROTOCOL_ERROR;
65	case TDB_ERR_LOCK:
66	case TDB_ERR_NOLOCK:
67		return LDB_ERR_BUSY;
68	case TDB_ERR_LOCK_TIMEOUT:
69		return LDB_ERR_TIME_LIMIT_EXCEEDED;
70	case TDB_ERR_EXISTS:
71		return LDB_ERR_ENTRY_ALREADY_EXISTS;
72	case TDB_ERR_NOEXIST:
73		return LDB_ERR_NO_SUCH_OBJECT;
74	case TDB_ERR_RDONLY:
75		return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
76	}
77	return LDB_ERR_OTHER;
78}
79
80
81struct ldb_handle *init_ltdb_handle(struct ltdb_private *ltdb, struct ldb_module *module,
82				    struct ldb_request *req)
83{
84	struct ltdb_context *ac;
85	struct ldb_handle *h;
86
87	h = talloc_zero(req, struct ldb_handle);
88	if (h == NULL) {
89		ldb_set_errstring(module->ldb, "Out of Memory");
90		return NULL;
91	}
92
93	h->module = module;
94
95	ac = talloc_zero(h, struct ltdb_context);
96	if (ac == NULL) {
97		ldb_set_errstring(module->ldb, "Out of Memory");
98		talloc_free(h);
99		return NULL;
100	}
101
102	h->private_data = (void *)ac;
103
104	h->state = LDB_ASYNC_INIT;
105	h->status = LDB_SUCCESS;
106
107	ac->module = module;
108	ac->context = req->context;
109	ac->callback = req->callback;
110
111	return h;
112}
113
114/*
115  form a TDB_DATA for a record key
116  caller frees
117
118  note that the key for a record can depend on whether the
119  dn refers to a case sensitive index record or not
120*/
121struct TDB_DATA ltdb_key(struct ldb_module *module, const struct ldb_dn *dn)
122{
123	struct ldb_context *ldb = module->ldb;
124	TDB_DATA key;
125	char *key_str = NULL;
126	char *dn_folded = NULL;
127
128	/*
129	  most DNs are case insensitive. The exception is index DNs for
130	  case sensitive attributes
131
132	  there are 3 cases dealt with in this code:
133
134	  1) if the dn doesn't start with @ then uppercase the attribute
135             names and the attributes values of case insensitive attributes
136	  2) if the dn starts with @ then leave it alone - the indexing code handles
137	     the rest
138	*/
139
140	dn_folded = ldb_dn_linearize_casefold(ldb, ldb, dn);
141	if (!dn_folded) {
142		goto failed;
143	}
144
145	key_str = talloc_asprintf(ldb, "DN=%s", dn_folded);
146
147	talloc_free(dn_folded);
148
149	if (!key_str) {
150		goto failed;
151	}
152
153	key.dptr = (uint8_t *)key_str;
154	key.dsize = strlen(key_str) + 1;
155
156	return key;
157
158failed:
159	errno = ENOMEM;
160	key.dptr = NULL;
161	key.dsize = 0;
162	return key;
163}
164
165/*
166  check special dn's have valid attributes
167  currently only @ATTRIBUTES is checked
168*/
169int ltdb_check_special_dn(struct ldb_module *module, const struct ldb_message *msg)
170{
171	int i, j;
172
173	if (! ldb_dn_is_special(msg->dn) ||
174	    ! ldb_dn_check_special(msg->dn, LTDB_ATTRIBUTES)) {
175		return 0;
176	}
177
178	/* we have @ATTRIBUTES, let's check attributes are fine */
179	/* should we check that we deny multivalued attributes ? */
180	for (i = 0; i < msg->num_elements; i++) {
181		for (j = 0; j < msg->elements[i].num_values; j++) {
182			if (ltdb_check_at_attributes_values(&msg->elements[i].values[j]) != 0) {
183				ldb_set_errstring(module->ldb, "Invalid attribute value in an @ATTRIBUTES entry");
184				return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
185			}
186		}
187	}
188
189	return 0;
190}
191
192
193/*
194  we've made a modification to a dn - possibly reindex and
195  update sequence number
196*/
197static int ltdb_modified(struct ldb_module *module, const struct ldb_dn *dn)
198{
199	int ret = 0;
200
201	if (ldb_dn_is_special(dn) &&
202	    (ldb_dn_check_special(dn, LTDB_INDEXLIST) ||
203	     ldb_dn_check_special(dn, LTDB_ATTRIBUTES)) ) {
204		ret = ltdb_reindex(module);
205	}
206
207	if (ret == 0 &&
208	    !(ldb_dn_is_special(dn) &&
209	      ldb_dn_check_special(dn, LTDB_BASEINFO)) ) {
210		ret = ltdb_increase_sequence_number(module);
211	}
212
213	return ret;
214}
215
216/*
217  store a record into the db
218*/
219int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flgs)
220{
221	struct ltdb_private *ltdb =
222		talloc_get_type(module->private_data, struct ltdb_private);
223	TDB_DATA tdb_key, tdb_data;
224	int ret;
225
226	tdb_key = ltdb_key(module, msg->dn);
227	if (!tdb_key.dptr) {
228		return LDB_ERR_OTHER;
229	}
230
231	ret = ltdb_pack_data(module, msg, &tdb_data);
232	if (ret == -1) {
233		talloc_free(tdb_key.dptr);
234		return LDB_ERR_OTHER;
235	}
236
237	ret = tdb_store(ltdb->tdb, tdb_key, tdb_data, flgs);
238	if (ret == -1) {
239		ret = ltdb_err_map(tdb_error(ltdb->tdb));
240		goto done;
241	}
242
243	ret = ltdb_index_add(module, msg);
244	if (ret == -1) {
245		tdb_delete(ltdb->tdb, tdb_key);
246	}
247
248done:
249	talloc_free(tdb_key.dptr);
250	talloc_free(tdb_data.dptr);
251
252	return ret;
253}
254
255
256static int ltdb_add_internal(struct ldb_module *module, const struct ldb_message *msg)
257{
258	int ret;
259
260	ret = ltdb_check_special_dn(module, msg);
261	if (ret != LDB_SUCCESS) {
262		return ret;
263	}
264
265	if (ltdb_cache_load(module) != 0) {
266		return LDB_ERR_OPERATIONS_ERROR;
267	}
268
269	ret = ltdb_store(module, msg, TDB_INSERT);
270
271	if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
272		char *dn;
273
274		dn = ldb_dn_linearize(module, msg->dn);
275		if (!dn) {
276			return ret;
277		}
278		ldb_asprintf_errstring(module->ldb, "Entry %s already exists", dn);
279		talloc_free(dn);
280		return ret;
281	}
282
283	if (ret == LDB_SUCCESS) {
284		ret = ltdb_modified(module, msg->dn);
285		if (ret != LDB_SUCCESS) {
286			return LDB_ERR_OPERATIONS_ERROR;
287		}
288	}
289
290	return ret;
291}
292
293/*
294  add a record to the database
295*/
296static int ltdb_add(struct ldb_module *module, struct ldb_request *req)
297{
298	struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
299	struct ltdb_context *ltdb_ac;
300	int tret, ret = LDB_SUCCESS;
301
302	if (req->controls != NULL) {
303		ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
304		if (check_critical_controls(req->controls)) {
305			return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
306		}
307	}
308
309	req->handle = init_ltdb_handle(ltdb, module, req);
310	if (req->handle == NULL) {
311		return LDB_ERR_OPERATIONS_ERROR;
312	}
313	ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
314
315	tret = ltdb_add_internal(module, req->op.add.message);
316	if (tret != LDB_SUCCESS) {
317		req->handle->status = tret;
318		goto done;
319	}
320
321	if (ltdb_ac->callback) {
322		ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
323	}
324done:
325	req->handle->state = LDB_ASYNC_DONE;
326	return ret;
327}
328
329/*
330  delete a record from the database, not updating indexes (used for deleting
331  index records)
332*/
333int ltdb_delete_noindex(struct ldb_module *module, const struct ldb_dn *dn)
334{
335	struct ltdb_private *ltdb =
336		talloc_get_type(module->private_data, struct ltdb_private);
337	TDB_DATA tdb_key;
338	int ret;
339
340	tdb_key = ltdb_key(module, dn);
341	if (!tdb_key.dptr) {
342		return LDB_ERR_OTHER;
343	}
344
345	ret = tdb_delete(ltdb->tdb, tdb_key);
346	talloc_free(tdb_key.dptr);
347
348	if (ret != 0) {
349		ret = ltdb_err_map(tdb_error(ltdb->tdb));
350	}
351
352	return ret;
353}
354
355static int ltdb_delete_internal(struct ldb_module *module, const struct ldb_dn *dn)
356{
357	struct ldb_message *msg;
358	int ret;
359
360	msg = talloc(module, struct ldb_message);
361	if (msg == NULL) {
362		return LDB_ERR_OPERATIONS_ERROR;
363	}
364
365	/* in case any attribute of the message was indexed, we need
366	   to fetch the old record */
367	ret = ltdb_search_dn1(module, dn, msg);
368	if (ret != 1) {
369		/* not finding the old record is an error */
370		talloc_free(msg);
371		return LDB_ERR_NO_SUCH_OBJECT;
372	}
373
374	ret = ltdb_delete_noindex(module, dn);
375	if (ret != LDB_SUCCESS) {
376		talloc_free(msg);
377		return LDB_ERR_NO_SUCH_OBJECT;
378	}
379
380	/* remove any indexed attributes */
381	ret = ltdb_index_del(module, msg);
382	if (ret != LDB_SUCCESS) {
383		talloc_free(msg);
384		return LDB_ERR_OPERATIONS_ERROR;
385	}
386
387	ret = ltdb_modified(module, dn);
388	if (ret != LDB_SUCCESS) {
389		talloc_free(msg);
390		return LDB_ERR_OPERATIONS_ERROR;
391	}
392
393	talloc_free(msg);
394	return LDB_SUCCESS;
395}
396
397/*
398  delete a record from the database
399*/
400static int ltdb_delete(struct ldb_module *module, struct ldb_request *req)
401{
402	struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
403	struct ltdb_context *ltdb_ac;
404	int tret, ret = LDB_SUCCESS;
405
406	if (req->controls != NULL) {
407		ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
408		if (check_critical_controls(req->controls)) {
409			return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
410		}
411	}
412
413	req->handle = NULL;
414
415	if (ltdb_cache_load(module) != 0) {
416		return LDB_ERR_OPERATIONS_ERROR;
417	}
418
419	req->handle = init_ltdb_handle(ltdb, module, req);
420	if (req->handle == NULL) {
421		return LDB_ERR_OPERATIONS_ERROR;
422	}
423	ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
424
425	tret = ltdb_delete_internal(module, req->op.del.dn);
426	if (tret != LDB_SUCCESS) {
427		req->handle->status = tret;
428		goto done;
429	}
430
431	if (ltdb_ac->callback) {
432		ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
433	}
434done:
435	req->handle->state = LDB_ASYNC_DONE;
436	return ret;
437}
438
439/*
440  find an element by attribute name. At the moment this does a linear search, it should
441  be re-coded to use a binary search once all places that modify records guarantee
442  sorted order
443
444  return the index of the first matching element if found, otherwise -1
445*/
446static int find_element(const struct ldb_message *msg, const char *name)
447{
448	unsigned int i;
449	for (i=0;i<msg->num_elements;i++) {
450		if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
451			return i;
452		}
453	}
454	return -1;
455}
456
457
458/*
459  add an element to an existing record. Assumes a elements array that we
460  can call re-alloc on, and assumed that we can re-use the data pointers from the
461  passed in additional values. Use with care!
462
463  returns 0 on success, -1 on failure (and sets errno)
464*/
465static int msg_add_element(struct ldb_context *ldb,
466			   struct ldb_message *msg, struct ldb_message_element *el)
467{
468	struct ldb_message_element *e2;
469	unsigned int i;
470
471	e2 = talloc_realloc(msg, msg->elements, struct ldb_message_element,
472			      msg->num_elements+1);
473	if (!e2) {
474		errno = ENOMEM;
475		return -1;
476	}
477
478	msg->elements = e2;
479
480	e2 = &msg->elements[msg->num_elements];
481
482	e2->name = el->name;
483	e2->flags = el->flags;
484	e2->values = NULL;
485	if (el->num_values != 0) {
486		e2->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
487		if (!e2->values) {
488			errno = ENOMEM;
489			return -1;
490		}
491	}
492	for (i=0;i<el->num_values;i++) {
493		e2->values[i] = el->values[i];
494	}
495	e2->num_values = el->num_values;
496
497	msg->num_elements++;
498
499	return 0;
500}
501
502/*
503  delete all elements having a specified attribute name
504*/
505static int msg_delete_attribute(struct ldb_module *module,
506				struct ldb_context *ldb,
507				struct ldb_message *msg, const char *name)
508{
509	char *dn;
510	unsigned int i, j;
511
512	dn = ldb_dn_linearize(ldb, msg->dn);
513	if (dn == NULL) {
514		return -1;
515	}
516
517	for (i=0;i<msg->num_elements;i++) {
518		if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
519			for (j=0;j<msg->elements[i].num_values;j++) {
520				ltdb_index_del_value(module, dn, &msg->elements[i], j);
521			}
522			talloc_free(msg->elements[i].values);
523			if (msg->num_elements > (i+1)) {
524				memmove(&msg->elements[i],
525					&msg->elements[i+1],
526					sizeof(struct ldb_message_element)*
527					(msg->num_elements - (i+1)));
528			}
529			msg->num_elements--;
530			i--;
531			msg->elements = talloc_realloc(msg, msg->elements,
532							 struct ldb_message_element,
533							 msg->num_elements);
534		}
535	}
536
537	talloc_free(dn);
538	return 0;
539}
540
541/*
542  delete all elements matching an attribute name/value
543
544  return 0 on success, -1 on failure
545*/
546static int msg_delete_element(struct ldb_module *module,
547			      struct ldb_message *msg,
548			      const char *name,
549			      const struct ldb_val *val)
550{
551	struct ldb_context *ldb = module->ldb;
552	unsigned int i;
553	int found;
554	struct ldb_message_element *el;
555	const struct ldb_attrib_handler *h;
556
557	found = find_element(msg, name);
558	if (found == -1) {
559		return -1;
560	}
561
562	el = &msg->elements[found];
563
564	h = ldb_attrib_handler(ldb, el->name);
565
566	for (i=0;i<el->num_values;i++) {
567		if (h->comparison_fn(ldb, ldb, &el->values[i], val) == 0) {
568			if (i<el->num_values-1) {
569				memmove(&el->values[i], &el->values[i+1],
570					sizeof(el->values[i])*(el->num_values-(i+1)));
571			}
572			el->num_values--;
573			if (el->num_values == 0) {
574				return msg_delete_attribute(module, ldb, msg, name);
575			}
576			return 0;
577		}
578	}
579
580	return -1;
581}
582
583
584/*
585  modify a record - internal interface
586
587  yuck - this is O(n^2). Luckily n is usually small so we probably
588  get away with it, but if we ever have really large attribute lists
589  then we'll need to look at this again
590*/
591int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg)
592{
593	struct ldb_context *ldb = module->ldb;
594	struct ltdb_private *ltdb =
595		talloc_get_type(module->private_data, struct ltdb_private);
596	TDB_DATA tdb_key, tdb_data;
597	struct ldb_message *msg2;
598	unsigned i, j;
599	int ret;
600
601	tdb_key = ltdb_key(module, msg->dn);
602	if (!tdb_key.dptr) {
603		return LDB_ERR_OTHER;
604	}
605
606	tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
607	if (!tdb_data.dptr) {
608		talloc_free(tdb_key.dptr);
609		return ltdb_err_map(tdb_error(ltdb->tdb));
610	}
611
612	msg2 = talloc(tdb_key.dptr, struct ldb_message);
613	if (msg2 == NULL) {
614		talloc_free(tdb_key.dptr);
615		return LDB_ERR_OTHER;
616	}
617
618	ret = ltdb_unpack_data(module, &tdb_data, msg2);
619	if (ret == -1) {
620		ret = LDB_ERR_OTHER;
621		goto failed;
622	}
623
624	if (!msg2->dn) {
625		msg2->dn = msg->dn;
626	}
627
628	for (i=0;i<msg->num_elements;i++) {
629		struct ldb_message_element *el = &msg->elements[i];
630		struct ldb_message_element *el2;
631		struct ldb_val *vals;
632		char *dn;
633
634		switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
635
636		case LDB_FLAG_MOD_ADD:
637			/* add this element to the message. fail if it
638			   already exists */
639			ret = find_element(msg2, el->name);
640
641			if (ret == -1) {
642				if (msg_add_element(ldb, msg2, el) != 0) {
643					ret = LDB_ERR_OTHER;
644					goto failed;
645				}
646				continue;
647			}
648
649			el2 = &msg2->elements[ret];
650
651			/* An attribute with this name already exists, add all
652			 * values if they don't already exist. */
653
654			for (j=0;j<el->num_values;j++) {
655				if (ldb_msg_find_val(el2, &el->values[j])) {
656					ldb_set_errstring(module->ldb, "Type or value exists");
657					ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
658					goto failed;
659				}
660			}
661
662		        vals = talloc_realloc(msg2->elements, el2->values, struct ldb_val,
663						el2->num_values + el->num_values);
664
665			if (vals == NULL) {
666				ret = LDB_ERR_OTHER;
667				goto failed;
668			}
669
670			for (j=0;j<el->num_values;j++) {
671				vals[el2->num_values + j] =
672					ldb_val_dup(vals, &el->values[j]);
673			}
674
675			el2->values = vals;
676			el2->num_values += el->num_values;
677
678			break;
679
680		case LDB_FLAG_MOD_REPLACE:
681			/* replace all elements of this attribute name with the elements
682			   listed. The attribute not existing is not an error */
683			msg_delete_attribute(module, ldb, msg2, msg->elements[i].name);
684
685			/* add the replacement element, if not empty */
686			if (msg->elements[i].num_values != 0 &&
687			    msg_add_element(ldb, msg2, &msg->elements[i]) != 0) {
688				ret = LDB_ERR_OTHER;
689				goto failed;
690			}
691			break;
692
693		case LDB_FLAG_MOD_DELETE:
694
695			dn = ldb_dn_linearize(msg2, msg->dn);
696			if (dn == NULL) {
697				ret = LDB_ERR_OTHER;
698				goto failed;
699			}
700
701			/* we could be being asked to delete all
702			   values or just some values */
703			if (msg->elements[i].num_values == 0) {
704				if (msg_delete_attribute(module, ldb, msg2,
705							 msg->elements[i].name) != 0) {
706					ldb_asprintf_errstring(module->ldb, "No such attribute: %s for delete on %s", msg->elements[i].name, dn);
707					ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
708					goto failed;
709				}
710				break;
711			}
712			for (j=0;j<msg->elements[i].num_values;j++) {
713				if (msg_delete_element(module,
714						       msg2,
715						       msg->elements[i].name,
716						       &msg->elements[i].values[j]) != 0) {
717					ldb_asprintf_errstring(module->ldb, "No matching attribute value when deleting attribute: %s on %s", msg->elements[i].name, dn);
718					ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
719					goto failed;
720				}
721				if (ltdb_index_del_value(module, dn, &msg->elements[i], j) != 0) {
722					ret = LDB_ERR_OTHER;
723					goto failed;
724				}
725			}
726			break;
727		default:
728			ldb_asprintf_errstring(module->ldb, "Invalid ldb_modify flags on %s: 0x%x",
729							     msg->elements[i].name,
730							     msg->elements[i].flags & LDB_FLAG_MOD_MASK);
731			ret = LDB_ERR_PROTOCOL_ERROR;
732			goto failed;
733		}
734	}
735
736	/* we've made all the mods - save the modified record back into the database */
737	ret = ltdb_store(module, msg2, TDB_MODIFY);
738	if (ret != LDB_SUCCESS) {
739		goto failed;
740	}
741
742	if (ltdb_modified(module, msg->dn) != LDB_SUCCESS) {
743		ret = LDB_ERR_OPERATIONS_ERROR;
744		goto failed;
745	}
746
747	talloc_free(tdb_key.dptr);
748	free(tdb_data.dptr);
749	return ret;
750
751failed:
752	talloc_free(tdb_key.dptr);
753	free(tdb_data.dptr);
754	return ret;
755}
756
757/*
758  modify a record
759*/
760static int ltdb_modify(struct ldb_module *module, struct ldb_request *req)
761{
762	struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
763	struct ltdb_context *ltdb_ac;
764	int tret, ret = LDB_SUCCESS;
765
766	if (req->controls != NULL) {
767		ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
768		if (check_critical_controls(req->controls)) {
769			return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
770		}
771	}
772
773	req->handle = NULL;
774
775	req->handle = init_ltdb_handle(ltdb, module, req);
776	if (req->handle == NULL) {
777		return LDB_ERR_OPERATIONS_ERROR;
778	}
779	ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
780
781	tret = ltdb_check_special_dn(module, req->op.mod.message);
782	if (tret != LDB_SUCCESS) {
783		req->handle->status = tret;
784		goto done;
785	}
786
787	if (ltdb_cache_load(module) != 0) {
788		ret = LDB_ERR_OPERATIONS_ERROR;
789		goto done;
790	}
791
792	tret = ltdb_modify_internal(module, req->op.mod.message);
793	if (tret != LDB_SUCCESS) {
794		req->handle->status = tret;
795		goto done;
796	}
797
798	if (ltdb_ac->callback) {
799		ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
800	}
801done:
802	req->handle->state = LDB_ASYNC_DONE;
803	return ret;
804}
805
806/*
807  rename a record
808*/
809static int ltdb_rename(struct ldb_module *module, struct ldb_request *req)
810{
811	struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
812	struct ltdb_context *ltdb_ac;
813	struct ldb_message *msg;
814	int tret, ret = LDB_SUCCESS;
815
816	if (req->controls != NULL) {
817		ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
818		if (check_critical_controls(req->controls)) {
819			return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
820		}
821	}
822
823	req->handle = NULL;
824
825	if (ltdb_cache_load(module) != 0) {
826		return LDB_ERR_OPERATIONS_ERROR;
827	}
828
829	req->handle = init_ltdb_handle(ltdb, module, req);
830	if (req->handle == NULL) {
831		return LDB_ERR_OPERATIONS_ERROR;
832	}
833	ltdb_ac = talloc_get_type(req->handle->private_data, struct ltdb_context);
834
835	msg = talloc(ltdb_ac, struct ldb_message);
836	if (msg == NULL) {
837		ret = LDB_ERR_OPERATIONS_ERROR;
838		goto done;
839	}
840
841	/* in case any attribute of the message was indexed, we need
842	   to fetch the old record */
843	tret = ltdb_search_dn1(module, req->op.rename.olddn, msg);
844	if (tret != 1) {
845		/* not finding the old record is an error */
846		req->handle->status = LDB_ERR_NO_SUCH_OBJECT;
847		goto done;
848	}
849
850	msg->dn = ldb_dn_copy(msg, req->op.rename.newdn);
851	if (!msg->dn) {
852		ret = LDB_ERR_OPERATIONS_ERROR;
853		goto done;
854	}
855
856	tret = ltdb_add_internal(module, msg);
857	if (tret != LDB_SUCCESS) {
858		ret = LDB_ERR_OPERATIONS_ERROR;
859		goto done;
860	}
861
862	tret = ltdb_delete_internal(module, req->op.rename.olddn);
863	if (tret != LDB_SUCCESS) {
864		ltdb_delete_internal(module, req->op.rename.newdn);
865		ret = LDB_ERR_OPERATIONS_ERROR;
866		goto done;
867	}
868
869	if (ltdb_ac->callback) {
870		ret = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
871	}
872done:
873	req->handle->state = LDB_ASYNC_DONE;
874	return ret;
875}
876
877static int ltdb_start_trans(struct ldb_module *module)
878{
879	struct ltdb_private *ltdb =
880		talloc_get_type(module->private_data, struct ltdb_private);
881
882	if (tdb_transaction_start(ltdb->tdb) != 0) {
883		return ltdb_err_map(tdb_error(ltdb->tdb));
884	}
885
886	return LDB_SUCCESS;
887}
888
889static int ltdb_end_trans(struct ldb_module *module)
890{
891	struct ltdb_private *ltdb =
892		talloc_get_type(module->private_data, struct ltdb_private);
893
894	if (tdb_transaction_commit(ltdb->tdb) != 0) {
895		return ltdb_err_map(tdb_error(ltdb->tdb));
896	}
897
898	return LDB_SUCCESS;
899}
900
901static int ltdb_del_trans(struct ldb_module *module)
902{
903	struct ltdb_private *ltdb =
904		talloc_get_type(module->private_data, struct ltdb_private);
905
906	if (tdb_transaction_cancel(ltdb->tdb) != 0) {
907		return ltdb_err_map(tdb_error(ltdb->tdb));
908	}
909
910	return LDB_SUCCESS;
911}
912
913static int ltdb_wait(struct ldb_handle *handle, enum ldb_wait_type type)
914{
915	return handle->status;
916}
917
918static int ltdb_request(struct ldb_module *module, struct ldb_request *req)
919{
920	/* check for oustanding critical controls and return an error if found */
921	if (req->controls != NULL) {
922		ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
923		if (check_critical_controls(req->controls)) {
924			return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
925		}
926	}
927
928	/* search, add, modify, delete, rename are handled by their own, no other op supported */
929	return LDB_ERR_OPERATIONS_ERROR;
930}
931
932/*
933  return sequenceNumber from @BASEINFO
934*/
935static int ltdb_sequence_number(struct ldb_module *module, struct ldb_request *req)
936{
937	TALLOC_CTX *tmp_ctx = talloc_new(req);
938	struct ldb_message *msg = NULL;
939	struct ldb_dn *dn = ldb_dn_explode(tmp_ctx, LTDB_BASEINFO);
940	int tret;
941
942	if (tmp_ctx == NULL) {
943		talloc_free(tmp_ctx);
944		return LDB_ERR_OPERATIONS_ERROR;
945	}
946
947	msg = talloc(tmp_ctx, struct ldb_message);
948	if (msg == NULL) {
949		talloc_free(tmp_ctx);
950		return LDB_ERR_OPERATIONS_ERROR;
951	}
952
953	req->op.seq_num.flags = 0;
954
955	tret = ltdb_search_dn1(module, dn, msg);
956	if (tret != 1) {
957		talloc_free(tmp_ctx);
958		req->op.seq_num.seq_num = 0;
959		/* zero is as good as anything when we don't know */
960		return LDB_SUCCESS;
961	}
962
963	switch (req->op.seq_num.type) {
964	case LDB_SEQ_HIGHEST_SEQ:
965		req->op.seq_num.seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
966		break;
967	case LDB_SEQ_NEXT:
968		req->op.seq_num.seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
969		req->op.seq_num.seq_num++;
970		break;
971	case LDB_SEQ_HIGHEST_TIMESTAMP:
972	{
973		const char *date = ldb_msg_find_attr_as_string(msg, LTDB_MOD_TIMESTAMP, NULL);
974		if (date) {
975			req->op.seq_num.seq_num = ldb_string_to_time(date);
976		} else {
977			req->op.seq_num.seq_num = 0;
978			/* zero is as good as anything when we don't know */
979		}
980		break;
981	}
982	}
983	talloc_free(tmp_ctx);
984	return LDB_SUCCESS;
985}
986
987static const struct ldb_module_ops ltdb_ops = {
988	.name              = "tdb",
989	.search            = ltdb_search,
990	.add               = ltdb_add,
991	.modify            = ltdb_modify,
992	.del               = ltdb_delete,
993	.rename            = ltdb_rename,
994	.request           = ltdb_request,
995	.start_transaction = ltdb_start_trans,
996	.end_transaction   = ltdb_end_trans,
997	.del_transaction   = ltdb_del_trans,
998	.wait              = ltdb_wait,
999	.sequence_number   = ltdb_sequence_number
1000};
1001
1002/*
1003  connect to the database
1004*/
1005static int ltdb_connect(struct ldb_context *ldb, const char *url,
1006			unsigned int flags, const char *options[],
1007			struct ldb_module **module)
1008{
1009	const char *path;
1010	int tdb_flags, open_flags;
1011	struct ltdb_private *ltdb;
1012
1013	/* parse the url */
1014	if (strchr(url, ':')) {
1015		if (strncmp(url, "tdb://", 6) != 0) {
1016			ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid tdb URL '%s'", url);
1017			return -1;
1018		}
1019		path = url+6;
1020	} else {
1021		path = url;
1022	}
1023
1024	tdb_flags = TDB_DEFAULT | TDB_SEQNUM;
1025
1026	/* check for the 'nosync' option */
1027	if (flags & LDB_FLG_NOSYNC) {
1028		tdb_flags |= TDB_NOSYNC;
1029	}
1030
1031	/* and nommap option */
1032	if (flags & LDB_FLG_NOMMAP) {
1033		tdb_flags |= TDB_NOMMAP;
1034	}
1035
1036	if (flags & LDB_FLG_RDONLY) {
1037		open_flags = O_RDONLY;
1038	} else {
1039		open_flags = O_CREAT | O_RDWR;
1040	}
1041
1042	ltdb = talloc_zero(ldb, struct ltdb_private);
1043	if (!ltdb) {
1044		ldb_oom(ldb);
1045		return -1;
1046	}
1047
1048	/* note that we use quite a large default hash size */
1049	ltdb->tdb = ltdb_wrap_open(ltdb, path, 10000,
1050				   tdb_flags, open_flags,
1051				   ldb->create_perms, ldb);
1052	if (!ltdb->tdb) {
1053		ldb_debug(ldb, LDB_DEBUG_ERROR, "Unable to open tdb '%s'\n", path);
1054		talloc_free(ltdb);
1055		return -1;
1056	}
1057
1058	ltdb->sequence_number = 0;
1059
1060	*module = talloc(ldb, struct ldb_module);
1061	if ((*module) == NULL) {
1062		ldb_oom(ldb);
1063		talloc_free(ltdb);
1064		return -1;
1065	}
1066	talloc_set_name_const(*module, "ldb_tdb backend");
1067	(*module)->ldb = ldb;
1068	(*module)->prev = (*module)->next = NULL;
1069	(*module)->private_data = ltdb;
1070	(*module)->ops = &ltdb_ops;
1071
1072	if (ltdb_cache_load(*module) != 0) {
1073		talloc_free(*module);
1074		talloc_free(ltdb);
1075		return -1;
1076	}
1077
1078	return 0;
1079}
1080
1081int ldb_tdb_init(void)
1082{
1083	return ldb_register_backend("tdb", ltdb_connect);
1084}
1085