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