r13258: Fix the talloc heirachy for ldb_tdb.
[abartlet/samba.git/.git] / source4 / lib / ldb / ldb_tdb / ldb_search.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 search functions
29  *
30  *  Description: functions to search ldb+tdb databases
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 /*
41   add one element to a message
42 */
43 static int msg_add_element(struct ldb_message *ret, 
44                            const struct ldb_message_element *el,
45                            int check_duplicates)
46 {
47         unsigned int i;
48         struct ldb_message_element *e2, *elnew;
49
50         if (check_duplicates && ldb_msg_find_element(ret, el->name)) {
51                 /* its already there */
52                 return 0;
53         }
54
55         e2 = talloc_realloc(ret, ret->elements, struct ldb_message_element, ret->num_elements+1);
56         if (!e2) {
57                 return -1;
58         }
59         ret->elements = e2;
60         
61         elnew = &e2[ret->num_elements];
62
63         elnew->name = talloc_strdup(ret->elements, el->name);
64         if (!elnew->name) {
65                 return -1;
66         }
67
68         if (el->num_values) {
69                 elnew->values = talloc_array(ret->elements, struct ldb_val, el->num_values);
70                 if (!elnew->values) {
71                         return -1;
72                 }
73         } else {
74                 elnew->values = NULL;
75         }
76
77         for (i=0;i<el->num_values;i++) {
78                 elnew->values[i] = ldb_val_dup(elnew->values, &el->values[i]);
79                 if (elnew->values[i].length != el->values[i].length) {
80                         return -1;
81                 }
82         }
83
84         elnew->num_values = el->num_values;
85
86         ret->num_elements++;
87
88         return 0;
89 }
90
91 /*
92   add the special distinguishedName element
93 */
94 static int msg_add_distinguished_name(struct ldb_message *msg)
95 {
96         struct ldb_message_element el;
97         struct ldb_val val;
98         int ret;
99
100         el.flags = 0;
101         el.name = "distinguishedName";
102         el.num_values = 1;
103         el.values = &val;
104         val.data = (uint8_t *)ldb_dn_linearize(msg, msg->dn);
105         val.length = strlen((char *)val.data);
106         
107         ret = msg_add_element(msg, &el, 1);
108         return ret;
109 }
110
111 /*
112   add all elements from one message into another
113  */
114 static int msg_add_all_elements(struct ldb_module *module, struct ldb_message *ret,
115                                 const struct ldb_message *msg)
116 {
117         struct ldb_context *ldb = module->ldb;
118         unsigned int i;
119         int check_duplicates = (ret->num_elements != 0);
120
121         if (msg_add_distinguished_name(ret) != 0) {
122                 return -1;
123         }
124
125         for (i=0;i<msg->num_elements;i++) {
126                 const struct ldb_attrib_handler *h;
127                 h = ldb_attrib_handler(ldb, msg->elements[i].name);
128                 if (h->flags & LDB_ATTR_FLAG_HIDDEN) {
129                         continue;
130                 }
131                 if (msg_add_element(ret, &msg->elements[i],
132                                     check_duplicates) != 0) {
133                         return -1;
134                 }
135         }
136
137         return 0;
138 }
139
140
141 /*
142   pull the specified list of attributes from a message
143  */
144 static struct ldb_message *ltdb_pull_attrs(struct ldb_module *module, 
145                                            TALLOC_CTX *mem_ctx, 
146                                            const struct ldb_message *msg, 
147                                            const char * const *attrs)
148 {
149         struct ldb_message *ret;
150         int i;
151
152         ret = talloc(mem_ctx, struct ldb_message);
153         if (!ret) {
154                 return NULL;
155         }
156
157         ret->dn = ldb_dn_copy(ret, msg->dn);
158         if (!ret->dn) {
159                 talloc_free(ret);
160                 return NULL;
161         }
162
163         ret->num_elements = 0;
164         ret->elements = NULL;
165
166         if (!attrs) {
167                 if (msg_add_all_elements(module, ret, msg) != 0) {
168                         talloc_free(ret);
169                         return NULL;
170                 }
171                 return ret;
172         }
173
174         for (i=0;attrs[i];i++) {
175                 struct ldb_message_element *el;
176
177                 if (strcmp(attrs[i], "*") == 0) {
178                         if (msg_add_all_elements(module, ret, msg) != 0) {
179                                 talloc_free(ret);
180                                 return NULL;
181                         }
182                         continue;
183                 }
184
185                 if (ldb_attr_cmp(attrs[i], "distinguishedName") == 0) {
186                         if (msg_add_distinguished_name(ret) != 0) {
187                                 return NULL;
188                         }
189                         continue;
190                 }
191
192                 el = ldb_msg_find_element(msg, attrs[i]);
193                 if (!el) {
194                         continue;
195                 }
196                 if (msg_add_element(ret, el, 1) != 0) {
197                         talloc_free(ret);
198                         return NULL;                            
199                 }
200         }
201
202         return ret;
203 }
204
205
206 /*
207   search the database for a single simple dn, returning all attributes
208   in a single message
209
210   return 1 on success, 0 on record-not-found and -1 on error
211 */
212 int ltdb_search_dn1(struct ldb_module *module, const struct ldb_dn *dn, struct ldb_message *msg)
213 {
214         struct ltdb_private *ltdb = module->private_data;
215         int ret;
216         TDB_DATA tdb_key, tdb_data, tdb_data2;
217
218         memset(msg, 0, sizeof(*msg));
219
220         /* form the key */
221         tdb_key = ltdb_key(module, dn);
222         if (!tdb_key.dptr) {
223                 return -1;
224         }
225
226         tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
227         talloc_free(tdb_key.dptr);
228         if (!tdb_data.dptr) {
229                 return 0;
230         }
231
232         tdb_data2.dptr = talloc_memdup(msg, tdb_data.dptr, tdb_data.dsize);
233         free(tdb_data.dptr);
234         if (!tdb_data2.dptr) {
235                 return -1;
236         }
237         tdb_data2.dsize = tdb_data.dsize;
238
239         msg->num_elements = 0;
240         msg->elements = NULL;
241
242         ret = ltdb_unpack_data(module, &tdb_data2, msg);
243         if (ret == -1) {
244                 talloc_free(tdb_data2.dptr);
245                 return -1;              
246         }
247
248         if (!msg->dn) {
249                 msg->dn = ldb_dn_copy(tdb_data2.dptr, dn);
250         }
251         if (!msg->dn) {
252                 talloc_free(tdb_data2.dptr);
253                 return -1;
254         }
255
256         return 1;
257 }
258
259 /* the lock key for search locking. Note that this is not a DN, its
260    just an arbitrary key to give to tdb. Also note that as we and
261    using transactions for all write operations and transactions take
262    care of their own locks, we don't need to do any locking anywhere
263    other than in ldb_search() */
264 #define LDBLOCK "INT_LDBLOCK"
265
266 /*
267   lock the database for read - use by ltdb_search
268 */
269 static int ltdb_lock_read(struct ldb_module *module)
270 {
271         struct ltdb_private *ltdb = module->private_data;
272         TDB_DATA key;
273
274         key.dptr = discard_const(LDBLOCK);
275         key.dsize = strlen(LDBLOCK);
276
277         return tdb_chainlock_read(ltdb->tdb, key);
278 }
279
280 /*
281   unlock the database after a ltdb_lock_read()
282 */
283 static int ltdb_unlock_read(struct ldb_module *module)
284 {
285         struct ltdb_private *ltdb = module->private_data;
286         TDB_DATA key;
287
288         key.dptr = discard_const(LDBLOCK);
289         key.dsize = strlen(LDBLOCK);
290
291         return tdb_chainunlock_read(ltdb->tdb, key);
292 }
293
294 /*
295   add a set of attributes from a record to a set of results
296   return 0 on success, -1 on failure
297 */
298 int ltdb_add_attr_results(struct ldb_module *module, 
299                           TALLOC_CTX *mem_ctx, 
300                           struct ldb_message *msg,
301                           const char * const attrs[], 
302                           unsigned int *count, 
303                           struct ldb_message ***res)
304 {
305         struct ldb_message *msg2;
306         struct ldb_message **res2;
307
308         /* pull the attributes that the user wants */
309         msg2 = ltdb_pull_attrs(module, mem_ctx, msg, attrs);
310         if (!msg2) {
311                 return -1;
312         }
313
314         /* add to the results list */
315         res2 = talloc_realloc(mem_ctx, *res, struct ldb_message *, (*count)+2);
316         if (!res2) {
317                 talloc_free(msg2);
318                 return -1;
319         }
320
321         (*res) = res2;
322
323         (*res)[*count] = talloc_steal(*res, msg2);
324         (*res)[(*count)+1] = NULL;
325         (*count)++;
326
327         return 0;
328 }
329
330
331 /*
332   internal search state during a full db search
333 */
334 struct ltdb_search_info {
335         struct ldb_module *module;
336         struct ldb_parse_tree *tree;
337         const struct ldb_dn *base;
338         enum ldb_scope scope;
339         const char * const *attrs;
340         struct ldb_message **msgs;
341         unsigned int failures;
342         unsigned int count;
343 };
344
345
346 /*
347   search function for a non-indexed search
348  */
349 static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
350 {
351         struct ltdb_search_info *sinfo = state;
352         struct ldb_message *msg;
353         int ret;
354
355         if (key.dsize < 4 || 
356             strncmp((char *)key.dptr, "DN=", 3) != 0) {
357                 return 0;
358         }
359
360         msg = talloc(sinfo, struct ldb_message);
361         if (msg == NULL) {
362                 return -1;
363         }
364
365         /* unpack the record */
366         ret = ltdb_unpack_data(sinfo->module, &data, msg);
367         if (ret == -1) {
368                 sinfo->failures++;
369                 talloc_free(msg);
370                 return 0;
371         }
372
373         if (!msg->dn) {
374                 msg->dn = ldb_dn_explode(msg, (char *)key.dptr + 3);
375                 if (msg->dn == NULL) {
376                         talloc_free(msg);
377                         return -1;
378                 }
379         }
380
381         /* see if it matches the given expression */
382         if (!ldb_match_msg(sinfo->module->ldb, msg, sinfo->tree, 
383                                sinfo->base, sinfo->scope)) {
384                 talloc_free(msg);
385                 return 0;
386         }
387
388         ret = ltdb_add_attr_results(sinfo->module, sinfo, msg, sinfo->attrs, &sinfo->count, &sinfo->msgs);
389
390         if (ret == -1) {
391                 sinfo->failures++;
392         }
393
394         talloc_free(msg);
395
396         return ret;
397 }
398
399
400 /*
401   search the database with a LDAP-like expression.
402   this is the "full search" non-indexed variant
403 */
404 static int ltdb_search_full(struct ldb_module *module, 
405                             const struct ldb_dn *base,
406                             enum ldb_scope scope,
407                             struct ldb_parse_tree *tree,
408                             const char * const attrs[], struct ldb_result **res)
409 {
410         struct ltdb_private *ltdb = module->private_data;
411         struct ldb_result *result;
412         int ret;
413         struct ltdb_search_info *sinfo;
414
415         result = talloc(ltdb, struct ldb_result);
416         if (result == NULL) {
417                 return LDB_ERR_OTHER;
418         }
419
420         sinfo = talloc(ltdb, struct ltdb_search_info);
421         if (sinfo == NULL) {
422                 talloc_free(result);
423                 return LDB_ERR_OTHER;
424         }
425
426         sinfo->tree = tree;
427         sinfo->module = module;
428         sinfo->scope = scope;
429         sinfo->base = base;
430         sinfo->attrs = attrs;
431         sinfo->msgs = NULL;
432         sinfo->count = 0;
433         sinfo->failures = 0;
434
435         ret = tdb_traverse_read(ltdb->tdb, search_func, sinfo);
436
437         if (ret == -1) {
438                 talloc_free(result);
439                 talloc_free(sinfo);
440                 return -1;
441         }
442
443         result->controls = NULL;
444         result->msgs = talloc_steal(result, sinfo->msgs);
445         result->count = sinfo->count;
446         *res = result;
447
448         talloc_free(sinfo);
449
450         return LDB_SUCCESS;
451 }
452
453
454 /*
455   search the database with a LDAP-like expression.
456   choses a search method
457 */
458 int ltdb_search_bytree(struct ldb_module *module, const struct ldb_dn *base,
459                        enum ldb_scope scope, struct ldb_parse_tree *tree,
460                        const char * const attrs[], struct ldb_result **res)
461 {
462         int ret;
463
464         if ((base == NULL || base->comp_num == 0) &&
465             (scope == LDB_SCOPE_BASE || scope == LDB_SCOPE_ONELEVEL)) return -1;
466
467         if (ltdb_lock_read(module) != 0) {
468                 return -1;
469         }
470
471         if (ltdb_cache_load(module) != 0) {
472                 ltdb_unlock_read(module);
473                 return -1;
474         }
475
476         *res = NULL;
477
478         ret = ltdb_search_indexed(module, base, scope, tree, attrs, res);
479         if (ret == -1) {
480                 ret = ltdb_search_full(module, base, scope, tree, attrs, res);
481         }
482
483         ltdb_unlock_read(module);
484
485         return ret;
486 }
487
488