s4:ldb Remove LTDB_PACKING_FORMAT_NODN
[ira/wip.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 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 search functions
28  *
29  *  Description: functions to search ldb+tdb databases
30  *
31  *  Author: Andrew Tridgell
32  */
33
34 #include "ldb_tdb.h"
35
36 /*
37   add one element to a message
38 */
39 static int msg_add_element(struct ldb_message *ret, 
40                            const struct ldb_message_element *el,
41                            int check_duplicates)
42 {
43         unsigned int i;
44         struct ldb_message_element *e2, *elnew;
45
46         if (check_duplicates && ldb_msg_find_element(ret, el->name)) {
47                 /* its already there */
48                 return 0;
49         }
50
51         e2 = talloc_realloc(ret, ret->elements, struct ldb_message_element, ret->num_elements+1);
52         if (!e2) {
53                 return -1;
54         }
55         ret->elements = e2;
56         
57         elnew = &e2[ret->num_elements];
58
59         elnew->name = talloc_strdup(ret->elements, el->name);
60         if (!elnew->name) {
61                 return -1;
62         }
63
64         if (el->num_values) {
65                 elnew->values = talloc_array(ret->elements, struct ldb_val, el->num_values);
66                 if (!elnew->values) {
67                         return -1;
68                 }
69         } else {
70                 elnew->values = NULL;
71         }
72
73         for (i=0;i<el->num_values;i++) {
74                 elnew->values[i] = ldb_val_dup(elnew->values, &el->values[i]);
75                 if (elnew->values[i].length != el->values[i].length) {
76                         return -1;
77                 }
78         }
79
80         elnew->num_values = el->num_values;
81
82         ret->num_elements++;
83
84         return 0;
85 }
86
87 /*
88   add the special distinguishedName element
89 */
90 static int msg_add_distinguished_name(struct ldb_message *msg)
91 {
92         struct ldb_message_element el;
93         struct ldb_val val;
94         int ret;
95
96         el.flags = 0;
97         el.name = "distinguishedName";
98         el.num_values = 1;
99         el.values = &val;
100         val.data = (uint8_t *)ldb_dn_alloc_linearized(msg, msg->dn);
101         val.length = strlen((char *)val.data);
102         
103         ret = msg_add_element(msg, &el, 1);
104         return ret;
105 }
106
107 /*
108   add all elements from one message into another
109  */
110 static int msg_add_all_elements(struct ldb_module *module, struct ldb_message *ret,
111                                 const struct ldb_message *msg)
112 {
113         struct ldb_context *ldb;
114         unsigned int i;
115         int check_duplicates = (ret->num_elements != 0);
116
117         ldb = ldb_module_get_ctx(module);
118
119         if (msg_add_distinguished_name(ret) != 0) {
120                 return -1;
121         }
122
123         for (i=0;i<msg->num_elements;i++) {
124                 const struct ldb_schema_attribute *a;
125                 a = ldb_schema_attribute_by_name(ldb, msg->elements[i].name);
126                 if (a->flags & LDB_ATTR_FLAG_HIDDEN) {
127                         continue;
128                 }
129                 if (msg_add_element(ret, &msg->elements[i],
130                                     check_duplicates) != 0) {
131                         return -1;
132                 }
133         }
134
135         return 0;
136 }
137
138
139 /*
140   pull the specified list of attributes from a message
141  */
142 static struct ldb_message *ltdb_pull_attrs(struct ldb_module *module, 
143                                            TALLOC_CTX *mem_ctx, 
144                                            const struct ldb_message *msg, 
145                                            const char * const *attrs)
146 {
147         struct ldb_message *ret;
148         int i;
149
150         ret = talloc(mem_ctx, struct ldb_message);
151         if (!ret) {
152                 return NULL;
153         }
154
155         ret->dn = ldb_dn_copy(ret, msg->dn);
156         if (!ret->dn) {
157                 talloc_free(ret);
158                 return NULL;
159         }
160
161         ret->num_elements = 0;
162         ret->elements = NULL;
163
164         if (!attrs) {
165                 if (msg_add_all_elements(module, ret, msg) != 0) {
166                         talloc_free(ret);
167                         return NULL;
168                 }
169                 return ret;
170         }
171
172         for (i=0;attrs[i];i++) {
173                 struct ldb_message_element *el;
174
175                 if (strcmp(attrs[i], "*") == 0) {
176                         if (msg_add_all_elements(module, ret, msg) != 0) {
177                                 talloc_free(ret);
178                                 return NULL;
179                         }
180                         continue;
181                 }
182
183                 if (ldb_attr_cmp(attrs[i], "distinguishedName") == 0) {
184                         if (msg_add_distinguished_name(ret) != 0) {
185                                 return NULL;
186                         }
187                         continue;
188                 }
189
190                 el = ldb_msg_find_element(msg, attrs[i]);
191                 if (!el) {
192                         continue;
193                 }
194                 if (msg_add_element(ret, el, 1) != 0) {
195                         talloc_free(ret);
196                         return NULL;                            
197                 }
198         }
199
200         return ret;
201 }
202
203 /*
204   search the database for a single simple dn.
205   return LDB_ERR_NO_SUCH_OBJECT on record-not-found
206   and LDB_SUCCESS on success
207 */
208 static int ltdb_search_base(struct ldb_module *module, struct ldb_dn *dn)
209 {
210         void *data = ldb_module_get_private(module);
211         struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
212         TDB_DATA tdb_key, tdb_data;
213
214         if (ldb_dn_is_null(dn)) {
215                 return LDB_ERR_NO_SUCH_OBJECT;
216         }
217
218         /* form the key */
219         tdb_key = ltdb_key(module, dn);
220         if (!tdb_key.dptr) {
221                 return LDB_ERR_OPERATIONS_ERROR;
222         }
223
224         tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
225         talloc_free(tdb_key.dptr);
226         if (!tdb_data.dptr) {
227                 return LDB_ERR_NO_SUCH_OBJECT;
228         }
229         
230         free(tdb_data.dptr);
231         return LDB_SUCCESS;
232 }
233
234 /*
235   search the database for a single simple dn, returning all attributes
236   in a single message
237
238   return LDB_ERR_NO_SUCH_OBJECT on record-not-found
239   and LDB_SUCCESS on success
240 */
241 int ltdb_search_dn1(struct ldb_module *module, struct ldb_dn *dn, struct ldb_message *msg)
242 {
243         void *data = ldb_module_get_private(module);
244         struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
245         int ret;
246         TDB_DATA tdb_key, tdb_data;
247
248         memset(msg, 0, sizeof(*msg));
249
250         /* form the key */
251         tdb_key = ltdb_key(module, dn);
252         if (!tdb_key.dptr) {
253                 return LDB_ERR_OPERATIONS_ERROR;
254         }
255
256         tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
257         talloc_free(tdb_key.dptr);
258         if (!tdb_data.dptr) {
259                 return LDB_ERR_NO_SUCH_OBJECT;
260         }
261         
262         msg->num_elements = 0;
263         msg->elements = NULL;
264
265         ret = ltdb_unpack_data(module, &tdb_data, msg);
266         free(tdb_data.dptr);
267         if (ret == -1) {
268                 struct ldb_context *ldb = ldb_module_get_ctx(module);
269                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid data for index %s\n",
270                           ldb_dn_get_linearized(msg->dn));
271                 return LDB_ERR_OPERATIONS_ERROR;                
272         }
273
274         if (!msg->dn) {
275                 msg->dn = ldb_dn_copy(msg, dn);
276         }
277         if (!msg->dn) {
278                 return LDB_ERR_OPERATIONS_ERROR;
279         }
280
281         return LDB_SUCCESS;
282 }
283
284 /*
285   add a set of attributes from a record to a set of results
286   return 0 on success, -1 on failure
287 */
288 int ltdb_add_attr_results(struct ldb_module *module, 
289                           TALLOC_CTX *mem_ctx, 
290                           struct ldb_message *msg,
291                           const char * const attrs[], 
292                           unsigned int *count, 
293                           struct ldb_message ***res)
294 {
295         struct ldb_message *msg2;
296         struct ldb_message **res2;
297
298         /* pull the attributes that the user wants */
299         msg2 = ltdb_pull_attrs(module, mem_ctx, msg, attrs);
300         if (!msg2) {
301                 return -1;
302         }
303
304         /* add to the results list */
305         res2 = talloc_realloc(mem_ctx, *res, struct ldb_message *, (*count)+2);
306         if (!res2) {
307                 talloc_free(msg2);
308                 return -1;
309         }
310
311         (*res) = res2;
312
313         (*res)[*count] = talloc_move(*res, &msg2);
314         (*res)[(*count)+1] = NULL;
315         (*count)++;
316
317         return 0;
318 }
319
320
321
322 /*
323   filter the specified list of attributes from a message
324   removing not requested attrs.
325  */
326 int ltdb_filter_attrs(struct ldb_message *msg, const char * const *attrs)
327 {
328         int i, keep_all = 0;
329
330         if (attrs) {
331                 /* check for special attrs */
332                 for (i = 0; attrs[i]; i++) {
333                         if (strcmp(attrs[i], "*") == 0) {
334                                 keep_all = 1;
335                                 break;
336                         }
337
338                         if (ldb_attr_cmp(attrs[i], "distinguishedName") == 0) {
339                                 if (msg_add_distinguished_name(msg) != 0) {
340                                         return -1;
341                                 }
342                         }
343                 }
344         } else {
345                 keep_all = 1;
346         }
347         
348         if (keep_all) {
349                 if (msg_add_distinguished_name(msg) != 0) {
350                         return -1;
351                 }
352                 return 0;
353         }
354
355         for (i = 0; i < msg->num_elements; i++) {
356                 int j, found;
357                 
358                 for (j = 0, found = 0; attrs[j]; j++) {
359                         if (ldb_attr_cmp(msg->elements[i].name, attrs[j]) == 0) {
360                                 found = 1;
361                                 break;
362                         }
363                 }
364
365                 if (!found) {
366                         ldb_msg_remove_attr(msg, msg->elements[i].name);
367                         i--;
368                 }
369         }
370
371         return 0;
372 }
373
374 /*
375   search function for a non-indexed search
376  */
377 static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
378 {
379         struct ldb_context *ldb;
380         struct ltdb_context *ac;
381         struct ldb_message *msg;
382         int ret;
383
384         ac = talloc_get_type(state, struct ltdb_context);
385         ldb = ldb_module_get_ctx(ac->module);
386
387         if (key.dsize < 4 || 
388             strncmp((char *)key.dptr, "DN=", 3) != 0) {
389                 return 0;
390         }
391
392         msg = ldb_msg_new(ac);
393         if (!msg) {
394                 return -1;
395         }
396
397         /* unpack the record */
398         ret = ltdb_unpack_data(ac->module, &data, msg);
399         if (ret == -1) {
400                 talloc_free(msg);
401                 return -1;
402         }
403
404         /* see if it matches the given expression */
405         if (!ldb_match_msg(ldb, msg,
406                            ac->tree, ac->base, ac->scope)) {
407                 talloc_free(msg);
408                 return 0;
409         }
410
411         /* filter the attributes that the user wants */
412         ret = ltdb_filter_attrs(msg, ac->attrs);
413
414         if (ret == -1) {
415                 talloc_free(msg);
416                 return -1;
417         }
418
419         ret = ldb_module_send_entry(ac->req, msg, NULL);
420         if (ret != LDB_SUCCESS) {
421                 ac->request_terminated = true;
422                 /* the callback failed, abort the operation */
423                 return -1;
424         }
425
426         return 0;
427 }
428
429
430 /*
431   search the database with a LDAP-like expression.
432   this is the "full search" non-indexed variant
433 */
434 static int ltdb_search_full(struct ltdb_context *ctx)
435 {
436         void *data = ldb_module_get_private(ctx->module);
437         struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
438         int ret;
439
440         if (ltdb->in_transaction != 0) {
441                 ret = tdb_traverse(ltdb->tdb, search_func, ctx);
442         } else {
443                 ret = tdb_traverse_read(ltdb->tdb, search_func, ctx);
444         }
445
446         if (ret == -1) {
447                 return LDB_ERR_OPERATIONS_ERROR;
448         }
449
450         return LDB_SUCCESS;
451 }
452
453 /*
454   search the database with a LDAP-like expression.
455   choses a search method
456 */
457 int ltdb_search(struct ltdb_context *ctx)
458 {
459         struct ldb_context *ldb;
460         struct ldb_module *module = ctx->module;
461         struct ldb_request *req = ctx->req;
462         void *data = ldb_module_get_private(module);
463         struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
464         int ret;
465
466         ldb = ldb_module_get_ctx(module);
467
468         ldb_request_set_state(req, LDB_ASYNC_PENDING);
469
470         if (ltdb_lock_read(module) != 0) {
471                 return LDB_ERR_OPERATIONS_ERROR;
472         }
473
474         if (ltdb_cache_load(module) != 0) {
475                 ltdb_unlock_read(module);
476                 return LDB_ERR_OPERATIONS_ERROR;
477         }
478
479         if (req->op.search.tree == NULL) {
480                 ltdb_unlock_read(module);
481                 return LDB_ERR_OPERATIONS_ERROR;
482         }
483
484         if ((req->op.search.base == NULL) || (ldb_dn_is_null(req->op.search.base) == true)) {
485
486                 /* Check what we should do with a NULL dn */
487                 switch (req->op.search.scope) {
488                 case LDB_SCOPE_BASE:
489                         ldb_asprintf_errstring(ldb, 
490                                                "NULL Base DN invalid for a base search");
491                         ret = LDB_ERR_INVALID_DN_SYNTAX;
492                         break;
493                 case LDB_SCOPE_ONELEVEL:
494                         ldb_asprintf_errstring(ldb, 
495                                                "NULL Base DN invalid for a one-level search");
496                         ret = LDB_ERR_INVALID_DN_SYNTAX;        
497                         break;
498                 case LDB_SCOPE_SUBTREE:
499                 default:
500                         /* We accept subtree searches from a NULL base DN, ie over the whole DB */
501                         ret = LDB_SUCCESS;
502                 }
503         } else if (ldb_dn_is_valid(req->op.search.base) == false) {
504
505                 /* We don't want invalid base DNs here */
506                 ldb_asprintf_errstring(ldb, 
507                                        "Invalid Base DN: %s", 
508                                        ldb_dn_get_linearized(req->op.search.base));
509                 ret = LDB_ERR_INVALID_DN_SYNTAX;
510
511         } else if (ltdb->check_base) {
512                 /* This database has been marked as 'checkBaseOnSearch', so do a spot check of the base dn */
513                 ret = ltdb_search_base(module, req->op.search.base);
514                 
515                 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
516                         ldb_asprintf_errstring(ldb, 
517                                                "No such Base DN: %s", 
518                                                ldb_dn_get_linearized(req->op.search.base));
519                 }
520                         
521         } else {
522                 /* If we are not checking the base DN life is easy */
523                 ret = LDB_SUCCESS;
524         }
525
526         ctx->tree = req->op.search.tree;
527         ctx->scope = req->op.search.scope;
528         ctx->base = req->op.search.base;
529         ctx->attrs = req->op.search.attrs;
530
531         if (ret == LDB_SUCCESS) {
532                 uint32_t match_count = 0;
533
534                 ret = ltdb_search_indexed(ctx, &match_count);
535                 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
536                         /* Not in the index, therefore OK! */
537                         ret = LDB_SUCCESS;
538                         
539                 }
540                 /* Check if we got just a normal error.
541                  * In that case proceed to a full search unless we got a
542                  * callback error */
543                 if ( ! ctx->request_terminated && ret != LDB_SUCCESS) {
544                         /* Not indexed, so we need to do a full scan */
545 #if 0
546                         /* useful for debugging when slow performance
547                          * is caused by unindexed searches */
548                         char *expression = ldb_filter_from_tree(ctx, ctx->tree);
549                         printf("FULL SEARCH: %s\n", expression);
550                         talloc_free(expression);
551 #endif
552                         if (match_count != 0) {
553                                 /* the indexing code gave an error
554                                  * after having returned at least one
555                                  * entry. This means the indexes are
556                                  * corrupt or a database record is
557                                  * corrupt. We cannot continue with a
558                                  * full search or we may return
559                                  * duplicate entries
560                                  */
561                                 return LDB_ERR_OPERATIONS_ERROR;
562                         }
563                         ret = ltdb_search_full(ctx);
564                         if (ret != LDB_SUCCESS) {
565                                 ldb_set_errstring(ldb, "Indexed and full searches both failed!\n");
566                         }
567                 }
568         }
569
570         ltdb_unlock_read(module);
571
572         return ret;
573 }
574