r12829: fix ldb headers, to not include '<...>' files in .c files
[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_context *ldb, 
44                            struct ldb_message *ret, 
45                            const struct ldb_message_element *el,
46                            int check_duplicates)
47 {
48         unsigned int i;
49         struct ldb_message_element *e2, *elnew;
50
51         if (check_duplicates && ldb_msg_find_element(ret, el->name)) {
52                 /* its already there */
53                 return 0;
54         }
55
56         e2 = talloc_realloc(ret, ret->elements, struct ldb_message_element, ret->num_elements+1);
57         if (!e2) {
58                 return -1;
59         }
60         ret->elements = e2;
61         
62         elnew = &e2[ret->num_elements];
63
64         elnew->name = talloc_strdup(ret->elements, el->name);
65         if (!elnew->name) {
66                 return -1;
67         }
68
69         if (el->num_values) {
70                 elnew->values = talloc_array(ret->elements, struct ldb_val, el->num_values);
71                 if (!elnew->values) {
72                         return -1;
73                 }
74         } else {
75                 elnew->values = NULL;
76         }
77
78         for (i=0;i<el->num_values;i++) {
79                 elnew->values[i] = ldb_val_dup(elnew->values, &el->values[i]);
80                 if (elnew->values[i].length != el->values[i].length) {
81                         return -1;
82                 }
83         }
84
85         elnew->num_values = el->num_values;
86
87         ret->num_elements++;
88
89         return 0;
90 }
91
92 /*
93   add the special distinguishedName element
94 */
95 static int msg_add_distinguished_name(struct ldb_module *module, struct ldb_message *msg)
96 {
97         struct ldb_message_element el;
98         struct ldb_val val;
99         int ret;
100
101         el.flags = 0;
102         el.name = "distinguishedName";
103         el.num_values = 1;
104         el.values = &val;
105         val.data = (uint8_t *)ldb_dn_linearize(msg, msg->dn);
106         val.length = strlen((char *)val.data);
107         
108         ret = msg_add_element(module->ldb, msg, &el, 1);
109         return ret;
110 }
111
112 /*
113   add all elements from one message into another
114  */
115 static int msg_add_all_elements(struct ldb_module *module, struct ldb_message *ret,
116                                 const struct ldb_message *msg)
117 {
118         struct ldb_context *ldb = module->ldb;
119         unsigned int i;
120         int check_duplicates = (ret->num_elements != 0);
121
122         if (msg_add_distinguished_name(module, ret) != 0) {
123                 return -1;
124         }
125
126         for (i=0;i<msg->num_elements;i++) {
127                 const struct ldb_attrib_handler *h;
128                 h = ldb_attrib_handler(ldb, msg->elements[i].name);
129                 if (h->flags & LDB_ATTR_FLAG_HIDDEN) {
130                         continue;
131                 }
132                 if (msg_add_element(ldb, ret, &msg->elements[i],
133                                     check_duplicates) != 0) {
134                         return -1;
135                 }
136         }
137
138         return 0;
139 }
140
141
142 /*
143   pull the specified list of attributes from a message
144  */
145 static struct ldb_message *ltdb_pull_attrs(struct ldb_module *module, 
146                                            const struct ldb_message *msg, 
147                                            const char * const *attrs)
148 {
149         struct ldb_context *ldb = module->ldb;
150         struct ldb_message *ret;
151         int i;
152
153         ret = talloc(ldb, struct ldb_message);
154         if (!ret) {
155                 return NULL;
156         }
157
158         ret->dn = ldb_dn_copy(ret, msg->dn);
159         if (!ret->dn) {
160                 talloc_free(ret);
161                 return NULL;
162         }
163
164         ret->num_elements = 0;
165         ret->elements = NULL;
166
167         if (!attrs) {
168                 if (msg_add_all_elements(module, ret, msg) != 0) {
169                         talloc_free(ret);
170                         return NULL;
171                 }
172                 return ret;
173         }
174
175         for (i=0;attrs[i];i++) {
176                 struct ldb_message_element *el;
177
178                 if (strcmp(attrs[i], "*") == 0) {
179                         if (msg_add_all_elements(module, ret, msg) != 0) {
180                                 talloc_free(ret);
181                                 return NULL;
182                         }
183                         continue;
184                 }
185
186                 if (ldb_attr_cmp(attrs[i], "distinguishedName") == 0) {
187                         if (msg_add_distinguished_name(module, ret) != 0) {
188                                 return NULL;
189                         }
190                         continue;
191                 }
192
193                 el = ldb_msg_find_element(msg, attrs[i]);
194                 if (!el) {
195                         continue;
196                 }
197                 if (msg_add_element(ldb, ret, el, 1) != 0) {
198                         talloc_free(ret);
199                         return NULL;                            
200                 }
201         }
202
203         return ret;
204 }
205
206
207 /*
208   search the database for a single simple dn, returning all attributes
209   in a single message
210
211   return 1 on success, 0 on record-not-found and -1 on error
212 */
213 int ltdb_search_dn1(struct ldb_module *module, const struct ldb_dn *dn, struct ldb_message *msg)
214 {
215         struct ltdb_private *ltdb = module->private_data;
216         int ret;
217         TDB_DATA tdb_key, tdb_data, tdb_data2;
218
219         memset(msg, 0, sizeof(*msg));
220
221         /* form the key */
222         tdb_key = ltdb_key(module, dn);
223         if (!tdb_key.dptr) {
224                 return -1;
225         }
226
227         tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
228         talloc_free(tdb_key.dptr);
229         if (!tdb_data.dptr) {
230                 return 0;
231         }
232
233         tdb_data2.dptr = talloc_memdup(msg, tdb_data.dptr, tdb_data.dsize);
234         free(tdb_data.dptr);
235         if (!tdb_data2.dptr) {
236                 return -1;
237         }
238         tdb_data2.dsize = tdb_data.dsize;
239
240         msg->num_elements = 0;
241         msg->elements = NULL;
242
243         ret = ltdb_unpack_data(module, &tdb_data2, msg);
244         if (ret == -1) {
245                 talloc_free(tdb_data2.dptr);
246                 return -1;              
247         }
248
249         if (!msg->dn) {
250                 msg->dn = ldb_dn_copy(tdb_data2.dptr, dn);
251         }
252         if (!msg->dn) {
253                 talloc_free(tdb_data2.dptr);
254                 return -1;
255         }
256
257         return 1;
258 }
259
260 /* the lock key for search locking. Note that this is not a DN, its
261    just an arbitrary key to give to tdb. Also note that as we and
262    using transactions for all write operations and transactions take
263    care of their own locks, we don't need to do any locking anywhere
264    other than in ldb_search() */
265 #define LDBLOCK "INT_LDBLOCK"
266
267 /*
268   lock the database for read - use by ltdb_search
269 */
270 static int ltdb_lock_read(struct ldb_module *module)
271 {
272         struct ltdb_private *ltdb = module->private_data;
273         TDB_DATA key;
274
275         key.dptr = discard_const(LDBLOCK);
276         key.dsize = strlen(LDBLOCK);
277
278         return tdb_chainlock_read(ltdb->tdb, key);
279 }
280
281 /*
282   unlock the database after a ltdb_lock_read()
283 */
284 static int ltdb_unlock_read(struct ldb_module *module)
285 {
286         struct ltdb_private *ltdb = module->private_data;
287         TDB_DATA key;
288
289         key.dptr = discard_const(LDBLOCK);
290         key.dsize = strlen(LDBLOCK);
291
292         return tdb_chainunlock_read(ltdb->tdb, key);
293 }
294
295 /*
296   add a set of attributes from a record to a set of results
297   return 0 on success, -1 on failure
298 */
299 int ltdb_add_attr_results(struct ldb_module *module, struct ldb_message *msg,
300                           const char * const attrs[], 
301                           unsigned int *count, 
302                           struct ldb_message ***res)
303 {
304         struct ldb_context *ldb = module->ldb;
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, msg, attrs);
310         if (!msg2) {
311                 return -1;
312         }
313
314         /* add to the results list */
315         res2 = talloc_realloc(ldb, *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, 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