Line data Source code
1 : /*
2 : ldb database library
3 :
4 : Copyright (C) Andrew Tridgell 2004-2005
5 : Copyright (C) Simo Sorce 2005
6 :
7 : ** NOTE! The following LGPL license applies to the ldb
8 : ** library. This does NOT imply that all of Samba is released
9 : ** under the LGPL
10 :
11 : This library is free software; you can redistribute it and/or
12 : modify it under the terms of the GNU Lesser General Public
13 : License as published by the Free Software Foundation; either
14 : version 3 of the License, or (at your option) any later version.
15 :
16 : This library is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 : Lesser General Public License for more details.
20 :
21 : You should have received a copy of the GNU Lesser General Public
22 : License along with this library; if not, see <http://www.gnu.org/licenses/>.
23 : */
24 :
25 : /*
26 : * Name: ldb
27 : *
28 : * Component: ldb expression matching
29 : *
30 : * Description: ldb expression matching
31 : *
32 : * Author: Andrew Tridgell
33 : */
34 :
35 : #include "ldb_private.h"
36 : #include "dlinklist.h"
37 : #include "ldb_handlers.h"
38 :
39 : /*
40 : check if the scope matches in a search result
41 : */
42 233057536 : int ldb_match_scope(struct ldb_context *ldb,
43 : struct ldb_dn *base,
44 : struct ldb_dn *dn,
45 : enum ldb_scope scope)
46 : {
47 233057536 : int ret = 0;
48 :
49 233057536 : if (base == NULL || dn == NULL) {
50 0 : return 1;
51 : }
52 :
53 233057536 : switch (scope) {
54 32 : case LDB_SCOPE_BASE:
55 32 : if (ldb_dn_compare(base, dn) == 0) {
56 32 : ret = 1;
57 : }
58 0 : break;
59 :
60 342708 : case LDB_SCOPE_ONELEVEL:
61 342708 : if (ldb_dn_get_comp_num(dn) == (ldb_dn_get_comp_num(base) + 1)) {
62 70446 : if (ldb_dn_compare_base(base, dn) == 0) {
63 33253 : ret = 1;
64 : }
65 : }
66 341896 : break;
67 :
68 232714796 : case LDB_SCOPE_SUBTREE:
69 : default:
70 232714796 : if (ldb_dn_compare_base(base, dn) == 0) {
71 138797706 : ret = 1;
72 : }
73 229736762 : break;
74 : }
75 :
76 230078658 : return ret;
77 : }
78 :
79 :
80 : /*
81 : match if node is present
82 : */
83 54551404 : static int ldb_match_present(struct ldb_context *ldb,
84 : const struct ldb_message *msg,
85 : const struct ldb_parse_tree *tree,
86 : enum ldb_scope scope, bool *matched)
87 : {
88 1968744 : const struct ldb_schema_attribute *a;
89 1968744 : struct ldb_message_element *el;
90 :
91 54551404 : if (ldb_attr_dn(tree->u.present.attr) == 0) {
92 5703630 : *matched = true;
93 5703630 : return LDB_SUCCESS;
94 : }
95 :
96 48847774 : el = ldb_msg_find_element(msg, tree->u.present.attr);
97 48847774 : if (el == NULL) {
98 6341687 : *matched = false;
99 6341687 : return LDB_SUCCESS;
100 : }
101 :
102 42506087 : a = ldb_schema_attribute_by_name(ldb, el->name);
103 42506087 : if (!a) {
104 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
105 : }
106 :
107 42506087 : if (a->syntax->operator_fn) {
108 : unsigned int i;
109 455287 : for (i = 0; i < el->num_values; i++) {
110 455287 : int ret = a->syntax->operator_fn(ldb, LDB_OP_PRESENT, a, &el->values[i], NULL, matched);
111 455287 : if (ret != LDB_SUCCESS) return ret;
112 455287 : if (*matched) return LDB_SUCCESS;
113 : }
114 0 : *matched = false;
115 0 : return LDB_SUCCESS;
116 : }
117 :
118 42050800 : *matched = true;
119 42050800 : return LDB_SUCCESS;
120 : }
121 :
122 5948193 : static int ldb_match_comparison(struct ldb_context *ldb,
123 : const struct ldb_message *msg,
124 : const struct ldb_parse_tree *tree,
125 : enum ldb_scope scope,
126 : enum ldb_parse_op comp_op, bool *matched)
127 : {
128 2596 : unsigned int i;
129 2596 : struct ldb_message_element *el;
130 2596 : const struct ldb_schema_attribute *a;
131 :
132 : /* FIXME: APPROX comparison not handled yet */
133 5948193 : if (comp_op == LDB_OP_APPROX) {
134 0 : return LDB_ERR_INAPPROPRIATE_MATCHING;
135 : }
136 :
137 5948193 : el = ldb_msg_find_element(msg, tree->u.comparison.attr);
138 5948193 : if (el == NULL) {
139 123677 : *matched = false;
140 123677 : return LDB_SUCCESS;
141 : }
142 :
143 5824516 : a = ldb_schema_attribute_by_name(ldb, el->name);
144 5824516 : if (!a) {
145 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
146 : }
147 :
148 9035129 : for (i = 0; i < el->num_values; i++) {
149 5824529 : if (a->syntax->operator_fn) {
150 842 : int ret;
151 1844 : ret = a->syntax->operator_fn(ldb, comp_op, a, &el->values[i], &tree->u.comparison.value, matched);
152 1844 : if (ret != LDB_SUCCESS) return ret;
153 1844 : if (*matched) return LDB_SUCCESS;
154 : } else {
155 5822685 : int ret = a->syntax->comparison_fn(ldb, ldb, &el->values[i], &tree->u.comparison.value);
156 :
157 5822685 : if (ret == 0) {
158 1948 : *matched = true;
159 1948 : return LDB_SUCCESS;
160 : }
161 5820737 : if (ret > 0 && comp_op == LDB_OP_GREATER) {
162 2608474 : *matched = true;
163 2608474 : return LDB_SUCCESS;
164 : }
165 3212263 : if (ret < 0 && comp_op == LDB_OP_LESS) {
166 2376 : *matched = true;
167 2376 : return LDB_SUCCESS;
168 : }
169 : }
170 : }
171 :
172 3210600 : *matched = false;
173 3210600 : return LDB_SUCCESS;
174 : }
175 :
176 : /*
177 : match a simple leaf node
178 : */
179 282433350 : static int ldb_match_equality(struct ldb_context *ldb,
180 : const struct ldb_message *msg,
181 : const struct ldb_parse_tree *tree,
182 : enum ldb_scope scope,
183 : bool *matched)
184 : {
185 6109649 : unsigned int i;
186 6109649 : struct ldb_message_element *el;
187 6109649 : const struct ldb_schema_attribute *a;
188 6109649 : struct ldb_dn *valuedn;
189 6109649 : int ret;
190 :
191 282433350 : if (ldb_attr_dn(tree->u.equality.attr) == 0) {
192 185473 : valuedn = ldb_dn_from_ldb_val(ldb, ldb, &tree->u.equality.value);
193 185473 : if (valuedn == NULL) {
194 0 : return LDB_ERR_INVALID_DN_SYNTAX;
195 : }
196 :
197 185473 : ret = ldb_dn_compare(msg->dn, valuedn);
198 :
199 185473 : talloc_free(valuedn);
200 :
201 185473 : *matched = (ret == 0);
202 185473 : return LDB_SUCCESS;
203 : }
204 :
205 : /* TODO: handle the "*" case derived from an extended search
206 : operation without the attribute type defined */
207 282247877 : el = ldb_msg_find_element(msg, tree->u.equality.attr);
208 282247877 : if (el == NULL) {
209 130773210 : *matched = false;
210 130773210 : return LDB_SUCCESS;
211 : }
212 :
213 151474667 : a = ldb_schema_attribute_by_name(ldb, el->name);
214 151474667 : if (a == NULL) {
215 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
216 : }
217 :
218 284595293 : for (i=0;i<el->num_values;i++) {
219 262020344 : if (a->syntax->operator_fn) {
220 28398291 : ret = a->syntax->operator_fn(ldb, LDB_OP_EQUALITY, a,
221 27874704 : &tree->u.equality.value, &el->values[i], matched);
222 27874704 : if (ret != LDB_SUCCESS) return ret;
223 27874704 : if (*matched) return LDB_SUCCESS;
224 : } else {
225 234145640 : if (a->syntax->comparison_fn(ldb, ldb, &tree->u.equality.value,
226 234145640 : &el->values[i]) == 0) {
227 102254695 : *matched = true;
228 102254695 : return LDB_SUCCESS;
229 : }
230 : }
231 : }
232 :
233 22574949 : *matched = false;
234 22574949 : return LDB_SUCCESS;
235 : }
236 :
237 3115620 : static int ldb_wildcard_compare(struct ldb_context *ldb,
238 : const struct ldb_parse_tree *tree,
239 : const struct ldb_val value, bool *matched)
240 : {
241 304 : const struct ldb_schema_attribute *a;
242 304 : struct ldb_val val;
243 304 : struct ldb_val cnk;
244 304 : struct ldb_val *chunk;
245 3115620 : uint8_t *save_p = NULL;
246 3115620 : unsigned int c = 0;
247 :
248 3115620 : if (tree->operation != LDB_OP_SUBSTRING) {
249 1 : *matched = false;
250 1 : return LDB_ERR_INAPPROPRIATE_MATCHING;
251 : }
252 :
253 3115619 : a = ldb_schema_attribute_by_name(ldb, tree->u.substring.attr);
254 3115619 : if (!a) {
255 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
256 : }
257 :
258 3115619 : if (tree->u.substring.chunks == NULL) {
259 3 : *matched = false;
260 3 : return LDB_SUCCESS;
261 : }
262 :
263 : /* No need to just copy this value for a binary match */
264 3115616 : if (a->syntax->canonicalise_fn != ldb_handler_copy) {
265 2398404 : if (a->syntax->canonicalise_fn(ldb, ldb, &value, &val) != 0) {
266 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
267 : }
268 :
269 : /*
270 : * Only set save_p if we allocate (call
271 : * a->syntax->canonicalise_fn()), as we
272 : * talloc_free(save_p) below to clean up
273 : */
274 2398404 : save_p = val.data;
275 : } else {
276 717212 : val = value;
277 : }
278 :
279 3115616 : cnk.data = NULL;
280 :
281 3115616 : if ( ! tree->u.substring.start_with_wildcard ) {
282 2367175 : uint8_t *cnk_to_free = NULL;
283 :
284 2367175 : chunk = tree->u.substring.chunks[c];
285 : /* No need to just copy this value for a binary match */
286 2367175 : if (a->syntax->canonicalise_fn != ldb_handler_copy) {
287 2365970 : if (a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) {
288 0 : goto mismatch;
289 : }
290 :
291 2365970 : cnk_to_free = cnk.data;
292 : } else {
293 1205 : cnk = *chunk;
294 : }
295 :
296 : /* This deals with wildcard prefix searches on binary attributes (eg objectGUID) */
297 2367175 : if (cnk.length > val.length) {
298 58512 : TALLOC_FREE(cnk_to_free);
299 58512 : goto mismatch;
300 : }
301 : /*
302 : * Empty strings are returned as length 0. Ensure
303 : * we can cope with this.
304 : */
305 2308663 : if (cnk.length == 0) {
306 0 : TALLOC_FREE(cnk_to_free);
307 0 : goto mismatch;
308 : }
309 :
310 2308663 : if (memcmp((char *)val.data, (char *)cnk.data, cnk.length) != 0) {
311 1852402 : TALLOC_FREE(cnk_to_free);
312 1852402 : goto mismatch;
313 : }
314 :
315 456261 : val.length -= cnk.length;
316 456261 : val.data += cnk.length;
317 456261 : c++;
318 456261 : TALLOC_FREE(cnk_to_free);
319 456261 : cnk.data = NULL;
320 : }
321 :
322 1205470 : while (tree->u.substring.chunks[c]) {
323 143 : uint8_t *p;
324 748497 : uint8_t *cnk_to_free = NULL;
325 :
326 748497 : chunk = tree->u.substring.chunks[c];
327 : /* No need to just copy this value for a binary match */
328 748497 : if (a->syntax->canonicalise_fn != ldb_handler_copy) {
329 32487 : if (a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) {
330 0 : goto mismatch;
331 : }
332 :
333 32487 : cnk_to_free = cnk.data;
334 : } else {
335 716010 : cnk = *chunk;
336 : }
337 : /*
338 : * Empty strings are returned as length 0. Ensure
339 : * we can cope with this.
340 : */
341 748497 : if (cnk.length == 0) {
342 0 : TALLOC_FREE(cnk_to_free);
343 0 : goto mismatch;
344 : }
345 748497 : if (cnk.length > val.length) {
346 22710 : TALLOC_FREE(cnk_to_free);
347 22710 : goto mismatch;
348 : }
349 :
350 725787 : if ( (tree->u.substring.chunks[c + 1]) == NULL &&
351 726408 : (! tree->u.substring.end_with_wildcard) ) {
352 : /*
353 : * The last bit, after all the asterisks, must match
354 : * exactly the last bit of the string.
355 : */
356 45 : int cmp;
357 9199 : p = val.data + val.length - cnk.length;
358 9199 : cmp = memcmp(p,
359 9199 : cnk.data,
360 : cnk.length);
361 9199 : TALLOC_FREE(cnk_to_free);
362 :
363 9199 : if (cmp != 0) {
364 8484 : goto mismatch;
365 : }
366 : } else {
367 : /*
368 : * Values might be binary blobs. Don't use string
369 : * search, but memory search instead.
370 : */
371 716588 : p = memmem((const void *)val.data, val.length,
372 716588 : (const void *)cnk.data, cnk.length);
373 716588 : if (p == NULL) {
374 716535 : TALLOC_FREE(cnk_to_free);
375 716535 : goto mismatch;
376 : }
377 : /* move val to the end of the match */
378 53 : p += cnk.length;
379 53 : val.length -= (p - val.data);
380 53 : val.data = p;
381 53 : TALLOC_FREE(cnk_to_free);
382 : }
383 694 : c++;
384 : }
385 :
386 456973 : talloc_free(save_p);
387 456973 : *matched = true;
388 456973 : return LDB_SUCCESS;
389 :
390 2658643 : mismatch:
391 2658643 : *matched = false;
392 2658643 : talloc_free(save_p);
393 2658643 : return LDB_SUCCESS;
394 : }
395 :
396 : /*
397 : match a simple leaf node
398 : */
399 3709404 : static int ldb_match_substring(struct ldb_context *ldb,
400 : const struct ldb_message *msg,
401 : const struct ldb_parse_tree *tree,
402 : enum ldb_scope scope, bool *matched)
403 : {
404 249 : unsigned int i;
405 249 : struct ldb_message_element *el;
406 :
407 3709404 : el = ldb_msg_find_element(msg, tree->u.substring.attr);
408 3709404 : if (el == NULL) {
409 593897 : *matched = false;
410 593897 : return LDB_SUCCESS;
411 : }
412 :
413 5774147 : for (i = 0; i < el->num_values; i++) {
414 271 : int ret;
415 3115587 : ret = ldb_wildcard_compare(ldb, tree, el->values[i], matched);
416 3115587 : if (ret != LDB_SUCCESS) return ret;
417 3115587 : if (*matched) return LDB_SUCCESS;
418 : }
419 :
420 2658560 : *matched = false;
421 2658560 : return LDB_SUCCESS;
422 : }
423 :
424 :
425 : /*
426 : bitwise and/or comparator depending on oid
427 : */
428 4564640 : static int ldb_comparator_bitmask(const char *oid, const struct ldb_val *v1, const struct ldb_val *v2,
429 : bool *matched)
430 : {
431 135433 : uint64_t i1, i2;
432 135433 : char ibuf[100];
433 4564640 : char *endptr = NULL;
434 :
435 4564640 : if (v1->length >= sizeof(ibuf)-1) {
436 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
437 : }
438 4564640 : memcpy(ibuf, (char *)v1->data, v1->length);
439 4564640 : ibuf[v1->length] = 0;
440 4564640 : i1 = strtoull(ibuf, &endptr, 0);
441 4564640 : if (endptr != NULL) {
442 4564640 : if (endptr == ibuf || *endptr != 0) {
443 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
444 : }
445 : }
446 :
447 4564640 : if (v2->length >= sizeof(ibuf)-1) {
448 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
449 : }
450 4564640 : endptr = NULL;
451 4564640 : memcpy(ibuf, (char *)v2->data, v2->length);
452 4564640 : ibuf[v2->length] = 0;
453 4564640 : i2 = strtoull(ibuf, &endptr, 0);
454 4564640 : if (endptr != NULL) {
455 4564640 : if (endptr == ibuf || *endptr != 0) {
456 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
457 : }
458 : }
459 4564640 : if (strcmp(LDB_OID_COMPARATOR_AND, oid) == 0) {
460 4562924 : *matched = ((i1 & i2) == i2);
461 1716 : } else if (strcmp(LDB_OID_COMPARATOR_OR, oid) == 0) {
462 1716 : *matched = ((i1 & i2) != 0);
463 : } else {
464 0 : return LDB_ERR_INAPPROPRIATE_MATCHING;
465 : }
466 4429207 : return LDB_SUCCESS;
467 : }
468 :
469 4569754 : static int ldb_match_bitmask(struct ldb_context *ldb,
470 : const char *oid,
471 : const struct ldb_message *msg,
472 : const char *attribute_to_match,
473 : const struct ldb_val *value_to_match,
474 : bool *matched)
475 : {
476 135480 : unsigned int i;
477 135480 : struct ldb_message_element *el;
478 :
479 : /* find the message element */
480 4569754 : el = ldb_msg_find_element(msg, attribute_to_match);
481 4569754 : if (el == NULL) {
482 5121 : *matched = false;
483 5121 : return LDB_SUCCESS;
484 : }
485 :
486 6639899 : for (i=0;i<el->num_values;i++) {
487 135433 : int ret;
488 4564640 : struct ldb_val *v = &el->values[i];
489 :
490 4564640 : ret = ldb_comparator_bitmask(oid, v, value_to_match, matched);
491 4564640 : if (ret != LDB_SUCCESS) {
492 0 : return ret;
493 : }
494 4564640 : if (*matched) {
495 2413922 : return LDB_SUCCESS;
496 : }
497 : }
498 :
499 2075259 : *matched = false;
500 2075259 : return LDB_SUCCESS;
501 : }
502 :
503 : /*
504 : always return false
505 : */
506 3373 : static int ldb_comparator_false(struct ldb_context *ldb,
507 : const char *oid,
508 : const struct ldb_message *msg,
509 : const char *attribute_to_match,
510 : const struct ldb_val *value_to_match,
511 : bool *matched)
512 : {
513 3373 : *matched = false;
514 3373 : return LDB_SUCCESS;
515 : }
516 :
517 :
518 17293318 : static const struct ldb_extended_match_rule *ldb_find_extended_match_rule(struct ldb_context *ldb,
519 : const char *oid)
520 : {
521 628834 : struct ldb_extended_match_entry *extended_match_rule;
522 :
523 17293318 : for (extended_match_rule = ldb->extended_match_rules;
524 61367250 : extended_match_rule;
525 44073932 : extended_match_rule = extended_match_rule->next) {
526 56844447 : if (strcmp(extended_match_rule->rule->oid, oid) == 0) {
527 12770515 : return extended_match_rule->rule;
528 : }
529 : }
530 :
531 4437486 : return NULL;
532 : }
533 :
534 :
535 : /*
536 : extended match, handles things like bitops
537 : */
538 12770518 : static int ldb_match_extended(struct ldb_context *ldb,
539 : const struct ldb_message *msg,
540 : const struct ldb_parse_tree *tree,
541 : enum ldb_scope scope, bool *matched)
542 : {
543 543517 : const struct ldb_extended_match_rule *rule;
544 :
545 12770518 : if (tree->u.extended.dnAttributes) {
546 : /* FIXME: We really need to find out what this ":dn" part in
547 : * an extended match means and how to handle it. For now print
548 : * only a warning to have s3 winbind and other tools working
549 : * against us. - Matthias */
550 912 : ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb: dnAttributes extended match not supported yet");
551 : }
552 12770518 : if (tree->u.extended.rule_id == NULL) {
553 0 : ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: no-rule extended matches not supported yet");
554 0 : return LDB_ERR_INAPPROPRIATE_MATCHING;
555 : }
556 12770518 : if (tree->u.extended.attr == NULL) {
557 0 : ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: no-attribute extended matches not supported yet");
558 0 : return LDB_ERR_INAPPROPRIATE_MATCHING;
559 : }
560 :
561 12770518 : rule = ldb_find_extended_match_rule(ldb, tree->u.extended.rule_id);
562 12770518 : if (rule == NULL) {
563 3 : *matched = false;
564 3 : ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: unknown extended rule_id %s",
565 3 : tree->u.extended.rule_id);
566 3 : return LDB_SUCCESS;
567 : }
568 :
569 12770515 : return rule->callback(ldb, rule->oid, msg,
570 12226998 : tree->u.extended.attr,
571 : &tree->u.extended.value, matched);
572 : }
573 :
574 756423398 : static bool ldb_must_suppress_match(const struct ldb_message *msg,
575 : const struct ldb_parse_tree *tree)
576 : {
577 756423398 : const char *attr = NULL;
578 756423398 : struct ldb_message_element *el = NULL;
579 :
580 756423398 : attr = ldb_parse_tree_get_attr(tree);
581 756423398 : if (attr == NULL) {
582 400294697 : return false;
583 : }
584 :
585 : /* find the message element */
586 346647779 : el = ldb_msg_find_element(msg, attr);
587 346647779 : if (el == NULL) {
588 140530669 : return false;
589 : }
590 :
591 202926214 : return ldb_msg_element_is_inaccessible(el);
592 : }
593 :
594 : /*
595 : Check if a particular message will match the given filter
596 :
597 : set *matched to true if it matches, false otherwise
598 :
599 : returns LDB_SUCCESS or an error
600 :
601 : this is a recursive function, and does short-circuit evaluation
602 : */
603 769193916 : int ldb_match_message(struct ldb_context *ldb,
604 : const struct ldb_message *msg,
605 : const struct ldb_parse_tree *tree,
606 : enum ldb_scope scope, bool *matched)
607 : {
608 18105677 : unsigned int i;
609 18105677 : int ret;
610 :
611 769193916 : *matched = false;
612 :
613 769193916 : if (scope != LDB_SCOPE_BASE && ldb_dn_is_special(msg->dn)) {
614 : /* don't match special records except on base searches */
615 0 : return LDB_SUCCESS;
616 : }
617 :
618 : /*
619 : * Suppress matches on confidential attributes (handled
620 : * manually in extended matches as these can do custom things
621 : * like read other parts of the DB or other attributes).
622 : */
623 769193916 : if (tree->operation != LDB_OP_EXTENDED) {
624 756423398 : if (ldb_must_suppress_match(msg, tree)) {
625 5428 : return LDB_SUCCESS;
626 : }
627 : }
628 :
629 769188488 : switch (tree->operation) {
630 137030538 : case LDB_OP_AND:
631 389218685 : for (i=0;i<tree->u.list.num_elements;i++) {
632 272540880 : ret = ldb_match_message(ldb, msg, tree->u.list.elements[i], scope, matched);
633 272540880 : if (ret != LDB_SUCCESS) return ret;
634 272540865 : if (!*matched) return LDB_SUCCESS;
635 : }
636 116677805 : *matched = true;
637 116677805 : return LDB_SUCCESS;
638 :
639 134650764 : case LDB_OP_OR:
640 179582681 : for (i=0;i<tree->u.list.num_elements;i++) {
641 173519999 : ret = ldb_match_message(ldb, msg, tree->u.list.elements[i], scope, matched);
642 173519999 : if (ret != LDB_SUCCESS) return ret;
643 173519999 : if (*matched) return LDB_SUCCESS;
644 : }
645 6062682 : *matched = false;
646 6062682 : return LDB_SUCCESS;
647 :
648 131526247 : case LDB_OP_NOT:
649 131526247 : ret = ldb_match_message(ldb, msg, tree->u.isnot.child, scope, matched);
650 131526247 : if (ret != LDB_SUCCESS) return ret;
651 131526247 : *matched = ! *matched;
652 131526247 : return LDB_SUCCESS;
653 :
654 282433350 : case LDB_OP_EQUALITY:
655 282433350 : return ldb_match_equality(ldb, msg, tree, scope, matched);
656 :
657 3709404 : case LDB_OP_SUBSTRING:
658 3709404 : return ldb_match_substring(ldb, msg, tree, scope, matched);
659 :
660 5881288 : case LDB_OP_GREATER:
661 5881288 : return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_GREATER, matched);
662 :
663 66905 : case LDB_OP_LESS:
664 66905 : return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_LESS, matched);
665 :
666 54551404 : case LDB_OP_PRESENT:
667 54551404 : return ldb_match_present(ldb, msg, tree, scope, matched);
668 :
669 0 : case LDB_OP_APPROX:
670 0 : return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_APPROX, matched);
671 :
672 12770518 : case LDB_OP_EXTENDED:
673 12770518 : return ldb_match_extended(ldb, msg, tree, scope, matched);
674 : }
675 :
676 0 : return LDB_ERR_INAPPROPRIATE_MATCHING;
677 : }
678 :
679 : /*
680 : return 0 if the given parse tree matches the given message. Assumes
681 : the message is in sorted order
682 :
683 : return 1 if it matches, and 0 if it doesn't match
684 : */
685 :
686 0 : int ldb_match_msg(struct ldb_context *ldb,
687 : const struct ldb_message *msg,
688 : const struct ldb_parse_tree *tree,
689 : struct ldb_dn *base,
690 : enum ldb_scope scope)
691 : {
692 0 : bool matched;
693 0 : int ret;
694 :
695 0 : if ( ! ldb_match_scope(ldb, base, msg->dn, scope) ) {
696 0 : return 0;
697 : }
698 :
699 0 : ret = ldb_match_message(ldb, msg, tree, scope, &matched);
700 0 : if (ret != LDB_SUCCESS) {
701 : /* to match the old API, we need to consider this a
702 : failure to match */
703 0 : return 0;
704 : }
705 0 : return matched?1:0;
706 : }
707 :
708 254 : int ldb_match_msg_error(struct ldb_context *ldb,
709 : const struct ldb_message *msg,
710 : const struct ldb_parse_tree *tree,
711 : struct ldb_dn *base,
712 : enum ldb_scope scope,
713 : bool *matched)
714 : {
715 254 : if ( ! ldb_match_scope(ldb, base, msg->dn, scope) ) {
716 0 : *matched = false;
717 0 : return LDB_SUCCESS;
718 : }
719 :
720 254 : return ldb_match_message(ldb, msg, tree, scope, matched);
721 : }
722 :
723 907523 : int ldb_match_msg_objectclass(const struct ldb_message *msg,
724 : const char *objectclass)
725 : {
726 29180 : unsigned int i;
727 907523 : struct ldb_message_element *el = ldb_msg_find_element(msg, "objectClass");
728 907523 : if (!el) {
729 0 : return 0;
730 : }
731 3630077 : for (i=0; i < el->num_values; i++) {
732 3630064 : if (ldb_attr_cmp((const char *)el->values[i].data, objectclass) == 0) {
733 878330 : return 1;
734 : }
735 : }
736 13 : return 0;
737 : }
738 :
739 756824 : _PRIVATE_ int ldb_register_extended_match_rules(struct ldb_context *ldb)
740 : {
741 15268 : struct ldb_extended_match_rule *bitmask_and;
742 15268 : struct ldb_extended_match_rule *bitmask_or;
743 15268 : struct ldb_extended_match_rule *always_false;
744 15268 : int ret;
745 :
746 : /* Register bitmask-and match */
747 756824 : bitmask_and = talloc_zero(ldb, struct ldb_extended_match_rule);
748 756824 : if (bitmask_and == NULL) {
749 0 : return LDB_ERR_OPERATIONS_ERROR;
750 : }
751 :
752 756824 : bitmask_and->oid = LDB_OID_COMPARATOR_AND;
753 756824 : bitmask_and->callback = ldb_match_bitmask;
754 :
755 756824 : ret = ldb_register_extended_match_rule(ldb, bitmask_and);
756 756824 : if (ret != LDB_SUCCESS) {
757 0 : return ret;
758 : }
759 :
760 : /* Register bitmask-or match */
761 756824 : bitmask_or = talloc_zero(ldb, struct ldb_extended_match_rule);
762 756824 : if (bitmask_or == NULL) {
763 0 : return LDB_ERR_OPERATIONS_ERROR;
764 : }
765 :
766 756824 : bitmask_or->oid = LDB_OID_COMPARATOR_OR;
767 756824 : bitmask_or->callback = ldb_match_bitmask;
768 :
769 756824 : ret = ldb_register_extended_match_rule(ldb, bitmask_or);
770 756824 : if (ret != LDB_SUCCESS) {
771 0 : return ret;
772 : }
773 :
774 : /* Register always-false match */
775 756824 : always_false = talloc_zero(ldb, struct ldb_extended_match_rule);
776 756824 : if (always_false == NULL) {
777 0 : return LDB_ERR_OPERATIONS_ERROR;
778 : }
779 :
780 756824 : always_false->oid = SAMBA_LDAP_MATCH_ALWAYS_FALSE;
781 756824 : always_false->callback = ldb_comparator_false;
782 :
783 756824 : ret = ldb_register_extended_match_rule(ldb, always_false);
784 756824 : if (ret != LDB_SUCCESS) {
785 0 : return ret;
786 : }
787 :
788 741556 : return LDB_SUCCESS;
789 : }
790 :
791 : /*
792 : register a new ldb extended matching rule
793 : */
794 4522800 : int ldb_register_extended_match_rule(struct ldb_context *ldb,
795 : const struct ldb_extended_match_rule *rule)
796 : {
797 85317 : const struct ldb_extended_match_rule *lookup_rule;
798 85317 : struct ldb_extended_match_entry *entry;
799 :
800 4522800 : lookup_rule = ldb_find_extended_match_rule(ldb, rule->oid);
801 4522800 : if (lookup_rule) {
802 0 : return LDB_ERR_ENTRY_ALREADY_EXISTS;
803 : }
804 :
805 4522800 : entry = talloc_zero(ldb, struct ldb_extended_match_entry);
806 4522800 : if (!entry) {
807 0 : return LDB_ERR_OPERATIONS_ERROR;
808 : }
809 4522800 : entry->rule = rule;
810 4522800 : DLIST_ADD_END(ldb->extended_match_rules, entry);
811 :
812 4437483 : return LDB_SUCCESS;
813 : }
814 :
815 405599 : int ldb_register_redact_callback(struct ldb_context *ldb,
816 : ldb_redact_fn redact_fn,
817 : struct ldb_module *module)
818 : {
819 405599 : if (ldb->redact.callback != NULL) {
820 0 : return LDB_ERR_ENTRY_ALREADY_EXISTS;
821 : }
822 :
823 405599 : ldb->redact.callback = redact_fn;
824 405599 : ldb->redact.module = module;
825 405599 : return LDB_SUCCESS;
826 : }
|