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 233914630 : 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 233914630 : int ret = 0;
48 :
49 233914630 : if (base == NULL || dn == NULL) {
50 0 : return 1;
51 : }
52 :
53 233914630 : 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 233571890 : case LDB_SCOPE_SUBTREE:
69 : default:
70 233571890 : if (ldb_dn_compare_base(base, dn) == 0) {
71 139450041 : ret = 1;
72 : }
73 230572257 : break;
74 : }
75 :
76 230914153 : return ret;
77 : }
78 :
79 :
80 : /*
81 : match if node is present
82 : */
83 54666838 : 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 1939747 : const struct ldb_schema_attribute *a;
89 1939747 : struct ldb_message_element *el;
90 :
91 54666838 : if (ldb_attr_dn(tree->u.present.attr) == 0) {
92 5669453 : *matched = true;
93 5669453 : return LDB_SUCCESS;
94 : }
95 :
96 48997385 : el = ldb_msg_find_element(msg, tree->u.present.attr);
97 48997385 : if (el == NULL) {
98 6306994 : *matched = false;
99 6306994 : return LDB_SUCCESS;
100 : }
101 :
102 42690391 : a = ldb_schema_attribute_by_name(ldb, el->name);
103 42690391 : if (!a) {
104 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
105 : }
106 :
107 42690391 : if (a->syntax->operator_fn) {
108 : unsigned int i;
109 452706 : for (i = 0; i < el->num_values; i++) {
110 452706 : int ret = a->syntax->operator_fn(ldb, LDB_OP_PRESENT, a, &el->values[i], NULL, matched);
111 452706 : if (ret != LDB_SUCCESS) return ret;
112 452706 : if (*matched) return LDB_SUCCESS;
113 : }
114 0 : *matched = false;
115 0 : return LDB_SUCCESS;
116 : }
117 :
118 42237685 : *matched = true;
119 42237685 : return LDB_SUCCESS;
120 : }
121 :
122 5819942 : 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 5819942 : if (comp_op == LDB_OP_APPROX) {
134 0 : return LDB_ERR_INAPPROPRIATE_MATCHING;
135 : }
136 :
137 5819942 : el = ldb_msg_find_element(msg, tree->u.comparison.attr);
138 5819942 : if (el == NULL) {
139 123777 : *matched = false;
140 123777 : return LDB_SUCCESS;
141 : }
142 :
143 5696165 : a = ldb_schema_attribute_by_name(ldb, el->name);
144 5696165 : if (!a) {
145 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
146 : }
147 :
148 8767830 : for (i = 0; i < el->num_values; i++) {
149 5696178 : 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 5694334 : int ret = a->syntax->comparison_fn(ldb, ldb, &el->values[i], &tree->u.comparison.value);
156 :
157 5694334 : if (ret == 0) {
158 2017 : *matched = true;
159 2017 : return LDB_SUCCESS;
160 : }
161 5692317 : if (ret > 0 && comp_op == LDB_OP_GREATER) {
162 2616614 : *matched = true;
163 2616614 : return LDB_SUCCESS;
164 : }
165 3075703 : if (ret < 0 && comp_op == LDB_OP_LESS) {
166 4764 : *matched = true;
167 4764 : return LDB_SUCCESS;
168 : }
169 : }
170 : }
171 :
172 3071652 : *matched = false;
173 3071652 : return LDB_SUCCESS;
174 : }
175 :
176 : /*
177 : match a simple leaf node
178 : */
179 283902028 : 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 6180080 : unsigned int i;
186 6180080 : struct ldb_message_element *el;
187 6180080 : const struct ldb_schema_attribute *a;
188 6180080 : struct ldb_dn *valuedn;
189 6180080 : int ret;
190 :
191 283902028 : if (ldb_attr_dn(tree->u.equality.attr) == 0) {
192 184520 : valuedn = ldb_dn_from_ldb_val(ldb, ldb, &tree->u.equality.value);
193 184520 : if (valuedn == NULL) {
194 0 : return LDB_ERR_INVALID_DN_SYNTAX;
195 : }
196 :
197 184520 : ret = ldb_dn_compare(msg->dn, valuedn);
198 :
199 184520 : talloc_free(valuedn);
200 :
201 184520 : *matched = (ret == 0);
202 184520 : return LDB_SUCCESS;
203 : }
204 :
205 : /* TODO: handle the "*" case derived from an extended search
206 : operation without the attribute type defined */
207 283717508 : el = ldb_msg_find_element(msg, tree->u.equality.attr);
208 283717508 : if (el == NULL) {
209 131402107 : *matched = false;
210 131402107 : return LDB_SUCCESS;
211 : }
212 :
213 152315401 : a = ldb_schema_attribute_by_name(ldb, el->name);
214 152315401 : if (a == NULL) {
215 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
216 : }
217 :
218 286159638 : for (i=0;i<el->num_values;i++) {
219 263510453 : if (a->syntax->operator_fn) {
220 28683791 : ret = a->syntax->operator_fn(ldb, LDB_OP_EQUALITY, a,
221 28155381 : &tree->u.equality.value, &el->values[i], matched);
222 28155381 : if (ret != LDB_SUCCESS) return ret;
223 28155381 : if (*matched) return LDB_SUCCESS;
224 : } else {
225 235355072 : if (a->syntax->comparison_fn(ldb, ldb, &tree->u.equality.value,
226 235355072 : &el->values[i]) == 0) {
227 102740150 : *matched = true;
228 102740150 : return LDB_SUCCESS;
229 : }
230 : }
231 : }
232 :
233 22649185 : *matched = false;
234 22649185 : return LDB_SUCCESS;
235 : }
236 :
237 3151633 : 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 3151633 : uint8_t *save_p = NULL;
246 3151633 : unsigned int c = 0;
247 :
248 3151633 : if (tree->operation != LDB_OP_SUBSTRING) {
249 1 : *matched = false;
250 1 : return LDB_ERR_INAPPROPRIATE_MATCHING;
251 : }
252 :
253 3151632 : a = ldb_schema_attribute_by_name(ldb, tree->u.substring.attr);
254 3151632 : if (!a) {
255 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
256 : }
257 :
258 3151632 : 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 3151629 : if (a->syntax->canonicalise_fn != ldb_handler_copy) {
265 2398417 : 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 2398417 : save_p = val.data;
275 : } else {
276 753212 : val = value;
277 : }
278 :
279 3151629 : cnk.data = NULL;
280 :
281 3151629 : if ( ! tree->u.substring.start_with_wildcard ) {
282 2367174 : uint8_t *cnk_to_free = NULL;
283 :
284 2367174 : chunk = tree->u.substring.chunks[c];
285 : /* No need to just copy this value for a binary match */
286 2367174 : if (a->syntax->canonicalise_fn != ldb_handler_copy) {
287 2365969 : if (a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) {
288 0 : goto mismatch;
289 : }
290 :
291 2365969 : 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 2367174 : if (cnk.length > val.length) {
298 58435 : TALLOC_FREE(cnk_to_free);
299 58435 : goto mismatch;
300 : }
301 : /*
302 : * Empty strings are returned as length 0. Ensure
303 : * we can cope with this.
304 : */
305 2308739 : if (cnk.length == 0) {
306 0 : TALLOC_FREE(cnk_to_free);
307 0 : goto mismatch;
308 : }
309 :
310 2308739 : if (memcmp((char *)val.data, (char *)cnk.data, cnk.length) != 0) {
311 1852478 : TALLOC_FREE(cnk_to_free);
312 1852478 : 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 1241484 : while (tree->u.substring.chunks[c]) {
323 143 : uint8_t *p;
324 784511 : uint8_t *cnk_to_free = NULL;
325 :
326 784511 : chunk = tree->u.substring.chunks[c];
327 : /* No need to just copy this value for a binary match */
328 784511 : if (a->syntax->canonicalise_fn != ldb_handler_copy) {
329 32501 : if (a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) {
330 0 : goto mismatch;
331 : }
332 :
333 32501 : cnk_to_free = cnk.data;
334 : } else {
335 752010 : cnk = *chunk;
336 : }
337 : /*
338 : * Empty strings are returned as length 0. Ensure
339 : * we can cope with this.
340 : */
341 784511 : if (cnk.length == 0) {
342 0 : TALLOC_FREE(cnk_to_free);
343 0 : goto mismatch;
344 : }
345 784511 : if (cnk.length > val.length) {
346 22718 : TALLOC_FREE(cnk_to_free);
347 22718 : goto mismatch;
348 : }
349 :
350 761793 : if ( (tree->u.substring.chunks[c + 1]) == NULL &&
351 762414 : (! 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 9205 : p = val.data + val.length - cnk.length;
358 9205 : cmp = memcmp(p,
359 9205 : cnk.data,
360 : cnk.length);
361 9205 : TALLOC_FREE(cnk_to_free);
362 :
363 9205 : if (cmp != 0) {
364 8490 : goto mismatch;
365 : }
366 : } else {
367 : /*
368 : * Values might be binary blobs. Don't use string
369 : * search, but memory search instead.
370 : */
371 752588 : p = memmem((const void *)val.data, val.length,
372 752588 : (const void *)cnk.data, cnk.length);
373 752588 : if (p == NULL) {
374 752535 : TALLOC_FREE(cnk_to_free);
375 752535 : 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 2694656 : mismatch:
391 2694656 : *matched = false;
392 2694656 : talloc_free(save_p);
393 2694656 : return LDB_SUCCESS;
394 : }
395 :
396 : /*
397 : match a simple leaf node
398 : */
399 3745461 : 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 3745461 : el = ldb_msg_find_element(msg, tree->u.substring.attr);
408 3745461 : if (el == NULL) {
409 593941 : *matched = false;
410 593941 : return LDB_SUCCESS;
411 : }
412 :
413 5846173 : for (i = 0; i < el->num_values; i++) {
414 271 : int ret;
415 3151600 : ret = ldb_wildcard_compare(ldb, tree, el->values[i], matched);
416 3151600 : if (ret != LDB_SUCCESS) return ret;
417 3151600 : if (*matched) return LDB_SUCCESS;
418 : }
419 :
420 2694573 : *matched = false;
421 2694573 : return LDB_SUCCESS;
422 : }
423 :
424 :
425 : /*
426 : bitwise and/or comparator depending on oid
427 : */
428 4532517 : static int ldb_comparator_bitmask(const char *oid, const struct ldb_val *v1, const struct ldb_val *v2,
429 : bool *matched)
430 : {
431 136850 : uint64_t i1, i2;
432 136850 : char ibuf[100];
433 4532517 : char *endptr = NULL;
434 :
435 4532517 : if (v1->length >= sizeof(ibuf)-1) {
436 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
437 : }
438 4532517 : memcpy(ibuf, (char *)v1->data, v1->length);
439 4532517 : ibuf[v1->length] = 0;
440 4532517 : i1 = strtoull(ibuf, &endptr, 0);
441 4532517 : if (endptr != NULL) {
442 4532517 : if (endptr == ibuf || *endptr != 0) {
443 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
444 : }
445 : }
446 :
447 4532517 : if (v2->length >= sizeof(ibuf)-1) {
448 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
449 : }
450 4532517 : endptr = NULL;
451 4532517 : memcpy(ibuf, (char *)v2->data, v2->length);
452 4532517 : ibuf[v2->length] = 0;
453 4532517 : i2 = strtoull(ibuf, &endptr, 0);
454 4532517 : if (endptr != NULL) {
455 4532517 : if (endptr == ibuf || *endptr != 0) {
456 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
457 : }
458 : }
459 4532517 : if (strcmp(LDB_OID_COMPARATOR_AND, oid) == 0) {
460 4530799 : *matched = ((i1 & i2) == i2);
461 1718 : } else if (strcmp(LDB_OID_COMPARATOR_OR, oid) == 0) {
462 1718 : *matched = ((i1 & i2) != 0);
463 : } else {
464 0 : return LDB_ERR_INAPPROPRIATE_MATCHING;
465 : }
466 4395667 : return LDB_SUCCESS;
467 : }
468 :
469 4537631 : 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 136897 : unsigned int i;
477 136897 : struct ldb_message_element *el;
478 :
479 : /* find the message element */
480 4537631 : el = ldb_msg_find_element(msg, attribute_to_match);
481 4537631 : if (el == NULL) {
482 5121 : *matched = false;
483 5121 : return LDB_SUCCESS;
484 : }
485 :
486 6591556 : for (i=0;i<el->num_values;i++) {
487 136850 : int ret;
488 4532517 : struct ldb_val *v = &el->values[i];
489 :
490 4532517 : ret = ldb_comparator_bitmask(oid, v, value_to_match, matched);
491 4532517 : if (ret != LDB_SUCCESS) {
492 0 : return ret;
493 : }
494 4532517 : if (*matched) {
495 2397232 : return LDB_SUCCESS;
496 : }
497 : }
498 :
499 2059039 : *matched = false;
500 2059039 : return LDB_SUCCESS;
501 : }
502 :
503 : /*
504 : always return false
505 : */
506 3341 : 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 3341 : *matched = false;
514 3341 : return LDB_SUCCESS;
515 : }
516 :
517 :
518 17200323 : static const struct ldb_extended_match_rule *ldb_find_extended_match_rule(struct ldb_context *ldb,
519 : const char *oid)
520 : {
521 631348 : struct ldb_extended_match_entry *extended_match_rule;
522 :
523 17200323 : for (extended_match_rule = ldb->extended_match_rules;
524 61120810 : extended_match_rule;
525 43920487 : extended_match_rule = extended_match_rule->next) {
526 56658097 : if (strcmp(extended_match_rule->rule->oid, oid) == 0) {
527 12737610 : return extended_match_rule->rule;
528 : }
529 : }
530 :
531 4376304 : return NULL;
532 : }
533 :
534 :
535 : /*
536 : extended match, handles things like bitops
537 : */
538 12737613 : 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 544939 : const struct ldb_extended_match_rule *rule;
544 :
545 12737613 : 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 12737613 : 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 12737613 : 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 12737613 : rule = ldb_find_extended_match_rule(ldb, tree->u.extended.rule_id);
562 12737613 : 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 12737610 : return rule->callback(ldb, rule->oid, msg,
570 12192671 : tree->u.extended.attr,
571 : &tree->u.extended.value, matched);
572 : }
573 :
574 759754054 : static bool ldb_must_suppress_match(const struct ldb_message *msg,
575 : const struct ldb_parse_tree *tree)
576 : {
577 759754054 : const char *attr = NULL;
578 759754054 : struct ldb_message_element *el = NULL;
579 :
580 759754054 : attr = ldb_parse_tree_get_attr(tree);
581 759754054 : if (attr == NULL) {
582 402026182 : return false;
583 : }
584 :
585 : /* find the message element */
586 348139697 : el = ldb_msg_find_element(msg, attr);
587 348139697 : if (el == NULL) {
588 141082363 : return false;
589 : }
590 :
591 203858914 : 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 772491667 : 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 18255786 : unsigned int i;
609 18255786 : int ret;
610 :
611 772491667 : *matched = false;
612 :
613 772491667 : 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 772491667 : if (tree->operation != LDB_OP_EXTENDED) {
624 759754054 : if (ldb_must_suppress_match(msg, tree)) {
625 5428 : return LDB_SUCCESS;
626 : }
627 : }
628 :
629 772486239 : switch (tree->operation) {
630 137597673 : case LDB_OP_AND:
631 391116575 : for (i=0;i<tree->u.list.num_elements;i++) {
632 273776193 : ret = ldb_match_message(ldb, msg, tree->u.list.elements[i], scope, matched);
633 273776193 : if (ret != LDB_SUCCESS) return ret;
634 273776178 : if (!*matched) return LDB_SUCCESS;
635 : }
636 117340382 : *matched = true;
637 117340382 : return LDB_SUCCESS;
638 :
639 135247728 : case LDB_OP_OR:
640 180292338 : for (i=0;i<tree->u.list.num_elements;i++) {
641 174231096 : ret = ldb_match_message(ldb, msg, tree->u.list.elements[i], scope, matched);
642 174231096 : if (ret != LDB_SUCCESS) return ret;
643 174231096 : if (*matched) return LDB_SUCCESS;
644 : }
645 6061242 : *matched = false;
646 6061242 : return LDB_SUCCESS;
647 :
648 132135094 : case LDB_OP_NOT:
649 132135094 : ret = ldb_match_message(ldb, msg, tree->u.isnot.child, scope, matched);
650 132135094 : if (ret != LDB_SUCCESS) return ret;
651 132135094 : *matched = ! *matched;
652 132135094 : return LDB_SUCCESS;
653 :
654 283902028 : case LDB_OP_EQUALITY:
655 283902028 : return ldb_match_equality(ldb, msg, tree, scope, matched);
656 :
657 3745461 : case LDB_OP_SUBSTRING:
658 3745461 : return ldb_match_substring(ldb, msg, tree, scope, matched);
659 :
660 5750141 : case LDB_OP_GREATER:
661 5750141 : return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_GREATER, matched);
662 :
663 69801 : case LDB_OP_LESS:
664 69801 : return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_LESS, matched);
665 :
666 54666838 : case LDB_OP_PRESENT:
667 54666838 : 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 12737613 : case LDB_OP_EXTENDED:
673 12737613 : 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 901805 : int ldb_match_msg_objectclass(const struct ldb_message *msg,
724 : const char *objectclass)
725 : {
726 29460 : unsigned int i;
727 901805 : struct ldb_message_element *el = ldb_msg_find_element(msg, "objectClass");
728 901805 : if (!el) {
729 0 : return 0;
730 : }
731 3607205 : for (i=0; i < el->num_values; i++) {
732 3607192 : if (ldb_attr_cmp((const char *)el->values[i].data, objectclass) == 0) {
733 872332 : return 1;
734 : }
735 : }
736 13 : return 0;
737 : }
738 :
739 746826 : _PRIVATE_ int ldb_register_extended_match_rules(struct ldb_context *ldb)
740 : {
741 15452 : struct ldb_extended_match_rule *bitmask_and;
742 15452 : struct ldb_extended_match_rule *bitmask_or;
743 15452 : struct ldb_extended_match_rule *always_false;
744 15452 : int ret;
745 :
746 : /* Register bitmask-and match */
747 746826 : bitmask_and = talloc_zero(ldb, struct ldb_extended_match_rule);
748 746826 : if (bitmask_and == NULL) {
749 0 : return LDB_ERR_OPERATIONS_ERROR;
750 : }
751 :
752 746826 : bitmask_and->oid = LDB_OID_COMPARATOR_AND;
753 746826 : bitmask_and->callback = ldb_match_bitmask;
754 :
755 746826 : ret = ldb_register_extended_match_rule(ldb, bitmask_and);
756 746826 : if (ret != LDB_SUCCESS) {
757 0 : return ret;
758 : }
759 :
760 : /* Register bitmask-or match */
761 746826 : bitmask_or = talloc_zero(ldb, struct ldb_extended_match_rule);
762 746826 : if (bitmask_or == NULL) {
763 0 : return LDB_ERR_OPERATIONS_ERROR;
764 : }
765 :
766 746826 : bitmask_or->oid = LDB_OID_COMPARATOR_OR;
767 746826 : bitmask_or->callback = ldb_match_bitmask;
768 :
769 746826 : ret = ldb_register_extended_match_rule(ldb, bitmask_or);
770 746826 : if (ret != LDB_SUCCESS) {
771 0 : return ret;
772 : }
773 :
774 : /* Register always-false match */
775 746826 : always_false = talloc_zero(ldb, struct ldb_extended_match_rule);
776 746826 : if (always_false == NULL) {
777 0 : return LDB_ERR_OPERATIONS_ERROR;
778 : }
779 :
780 746826 : always_false->oid = SAMBA_LDAP_MATCH_ALWAYS_FALSE;
781 746826 : always_false->callback = ldb_comparator_false;
782 :
783 746826 : ret = ldb_register_extended_match_rule(ldb, always_false);
784 746826 : if (ret != LDB_SUCCESS) {
785 0 : return ret;
786 : }
787 :
788 731374 : return LDB_SUCCESS;
789 : }
790 :
791 : /*
792 : register a new ldb extended matching rule
793 : */
794 4462710 : int ldb_register_extended_match_rule(struct ldb_context *ldb,
795 : const struct ldb_extended_match_rule *rule)
796 : {
797 86409 : const struct ldb_extended_match_rule *lookup_rule;
798 86409 : struct ldb_extended_match_entry *entry;
799 :
800 4462710 : lookup_rule = ldb_find_extended_match_rule(ldb, rule->oid);
801 4462710 : if (lookup_rule) {
802 0 : return LDB_ERR_ENTRY_ALREADY_EXISTS;
803 : }
804 :
805 4462710 : entry = talloc_zero(ldb, struct ldb_extended_match_entry);
806 4462710 : if (!entry) {
807 0 : return LDB_ERR_OPERATIONS_ERROR;
808 : }
809 4462710 : entry->rule = rule;
810 4462710 : DLIST_ADD_END(ldb->extended_match_rules, entry);
811 :
812 4376301 : return LDB_SUCCESS;
813 : }
814 :
815 402909 : int ldb_register_redact_callback(struct ldb_context *ldb,
816 : ldb_redact_fn redact_fn,
817 : struct ldb_module *module)
818 : {
819 402909 : if (ldb->redact.callback != NULL) {
820 0 : return LDB_ERR_ENTRY_ALREADY_EXISTS;
821 : }
822 :
823 402909 : ldb->redact.callback = redact_fn;
824 402909 : ldb->redact.module = module;
825 402909 : return LDB_SUCCESS;
826 : }
|