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 :
38 : /*
39 : check if the scope matches in a search result
40 : */
41 174615827 : static int ldb_match_scope(struct ldb_context *ldb,
42 : struct ldb_dn *base,
43 : struct ldb_dn *dn,
44 : enum ldb_scope scope)
45 : {
46 174615827 : int ret = 0;
47 :
48 174615827 : if (base == NULL || dn == NULL) {
49 0 : return 1;
50 : }
51 :
52 174615827 : switch (scope) {
53 31 : case LDB_SCOPE_BASE:
54 31 : if (ldb_dn_compare(base, dn) == 0) {
55 31 : ret = 1;
56 : }
57 0 : break;
58 :
59 18532 : case LDB_SCOPE_ONELEVEL:
60 18532 : if (ldb_dn_get_comp_num(dn) == (ldb_dn_get_comp_num(base) + 1)) {
61 8250 : if (ldb_dn_compare_base(base, dn) == 0) {
62 4570 : ret = 1;
63 : }
64 : }
65 17921 : break;
66 :
67 174597264 : case LDB_SCOPE_SUBTREE:
68 : default:
69 174597264 : if (ldb_dn_compare_base(base, dn) == 0) {
70 105724590 : ret = 1;
71 : }
72 172591175 : break;
73 : }
74 :
75 172609096 : return ret;
76 : }
77 :
78 :
79 : /*
80 : match if node is present
81 : */
82 47822950 : static int ldb_match_present(struct ldb_context *ldb,
83 : const struct ldb_message *msg,
84 : const struct ldb_parse_tree *tree,
85 : enum ldb_scope scope, bool *matched)
86 : {
87 : const struct ldb_schema_attribute *a;
88 : struct ldb_message_element *el;
89 :
90 47822950 : if (ldb_attr_dn(tree->u.present.attr) == 0) {
91 8699366 : *matched = true;
92 8247408 : return LDB_SUCCESS;
93 : }
94 :
95 39123584 : el = ldb_msg_find_element(msg, tree->u.present.attr);
96 39123584 : if (el == NULL) {
97 9287056 : *matched = false;
98 8826851 : return LDB_SUCCESS;
99 : }
100 :
101 29836528 : a = ldb_schema_attribute_by_name(ldb, el->name);
102 29836528 : if (!a) {
103 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
104 : }
105 :
106 29836528 : if (a->syntax->operator_fn) {
107 : unsigned int i;
108 351164 : for (i = 0; i < el->num_values; i++) {
109 361316 : int ret = a->syntax->operator_fn(ldb, LDB_OP_PRESENT, a, &el->values[i], NULL, matched);
110 361316 : if (ret != LDB_SUCCESS) return ret;
111 361316 : if (*matched) return LDB_SUCCESS;
112 : }
113 0 : *matched = false;
114 0 : return LDB_SUCCESS;
115 : }
116 :
117 29475212 : *matched = true;
118 28333287 : return LDB_SUCCESS;
119 : }
120 :
121 5595299 : static int ldb_match_comparison(struct ldb_context *ldb,
122 : const struct ldb_message *msg,
123 : const struct ldb_parse_tree *tree,
124 : enum ldb_scope scope,
125 : enum ldb_parse_op comp_op, bool *matched)
126 : {
127 : unsigned int i;
128 : struct ldb_message_element *el;
129 : const struct ldb_schema_attribute *a;
130 :
131 : /* FIXME: APPROX comparison not handled yet */
132 5595299 : if (comp_op == LDB_OP_APPROX) {
133 0 : return LDB_ERR_INAPPROPRIATE_MATCHING;
134 : }
135 :
136 5595299 : el = ldb_msg_find_element(msg, tree->u.comparison.attr);
137 5595299 : if (el == NULL) {
138 99465 : *matched = false;
139 99447 : return LDB_SUCCESS;
140 : }
141 :
142 5495834 : a = ldb_schema_attribute_by_name(ldb, el->name);
143 5495834 : if (!a) {
144 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
145 : }
146 :
147 8912904 : for (i = 0; i < el->num_values; i++) {
148 5495860 : if (a->syntax->operator_fn) {
149 : int ret;
150 1844 : ret = a->syntax->operator_fn(ldb, comp_op, a, &el->values[i], &tree->u.comparison.value, matched);
151 1844 : if (ret != LDB_SUCCESS) return ret;
152 1844 : if (*matched) return LDB_SUCCESS;
153 : } else {
154 5494016 : int ret = a->syntax->comparison_fn(ldb, ldb, &el->values[i], &tree->u.comparison.value);
155 :
156 5494016 : if (ret == 0) {
157 1868 : *matched = true;
158 1868 : return LDB_SUCCESS;
159 : }
160 5492148 : if (ret > 0 && comp_op == LDB_OP_GREATER) {
161 2074070 : *matched = true;
162 2074069 : return LDB_SUCCESS;
163 : }
164 3418078 : if (ret < 0 && comp_op == LDB_OP_LESS) {
165 837 : *matched = true;
166 814 : return LDB_SUCCESS;
167 : }
168 : }
169 : }
170 :
171 3417941 : *matched = false;
172 3417568 : return LDB_SUCCESS;
173 : }
174 :
175 : /*
176 : match a simple leaf node
177 : */
178 211770945 : static int ldb_match_equality(struct ldb_context *ldb,
179 : const struct ldb_message *msg,
180 : const struct ldb_parse_tree *tree,
181 : enum ldb_scope scope,
182 : bool *matched)
183 : {
184 : unsigned int i;
185 : struct ldb_message_element *el;
186 : const struct ldb_schema_attribute *a;
187 : struct ldb_dn *valuedn;
188 : int ret;
189 :
190 211770945 : if (ldb_attr_dn(tree->u.equality.attr) == 0) {
191 158847 : valuedn = ldb_dn_from_ldb_val(ldb, ldb, &tree->u.equality.value);
192 158847 : if (valuedn == NULL) {
193 0 : return LDB_ERR_INVALID_DN_SYNTAX;
194 : }
195 :
196 158847 : ret = ldb_dn_compare(msg->dn, valuedn);
197 :
198 158847 : talloc_free(valuedn);
199 :
200 158847 : *matched = (ret == 0);
201 155934 : return LDB_SUCCESS;
202 : }
203 :
204 : /* TODO: handle the "*" case derived from an extended search
205 : operation without the attibute type defined */
206 211612098 : el = ldb_msg_find_element(msg, tree->u.equality.attr);
207 211612098 : if (el == NULL) {
208 100120518 : *matched = false;
209 98140496 : return LDB_SUCCESS;
210 : }
211 :
212 111491580 : a = ldb_schema_attribute_by_name(ldb, el->name);
213 111491580 : if (a == NULL) {
214 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
215 : }
216 :
217 212607712 : for (i=0;i<el->num_values;i++) {
218 198472988 : if (a->syntax->operator_fn) {
219 33519035 : ret = a->syntax->operator_fn(ldb, LDB_OP_EQUALITY, a,
220 18336885 : &tree->u.equality.value, &el->values[i], matched);
221 18336885 : if (ret != LDB_SUCCESS) return ret;
222 18336885 : if (*matched) return LDB_SUCCESS;
223 : } else {
224 307054143 : if (a->syntax->comparison_fn(ldb, ldb, &tree->u.equality.value,
225 180136103 : &el->values[i]) == 0) {
226 78064751 : *matched = true;
227 76432815 : return LDB_SUCCESS;
228 : }
229 : }
230 : }
231 :
232 16230013 : *matched = false;
233 15974900 : return LDB_SUCCESS;
234 : }
235 :
236 2431155 : static int ldb_wildcard_compare(struct ldb_context *ldb,
237 : const struct ldb_parse_tree *tree,
238 : const struct ldb_val value, bool *matched)
239 : {
240 : const struct ldb_schema_attribute *a;
241 : struct ldb_val val;
242 : struct ldb_val cnk;
243 : struct ldb_val *chunk;
244 2431155 : uint8_t *save_p = NULL;
245 2431155 : unsigned int c = 0;
246 :
247 2431155 : if (tree->operation != LDB_OP_SUBSTRING) {
248 1 : *matched = false;
249 1 : return LDB_ERR_INAPPROPRIATE_MATCHING;
250 : }
251 :
252 2431154 : a = ldb_schema_attribute_by_name(ldb, tree->u.substring.attr);
253 2431154 : if (!a) {
254 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
255 : }
256 :
257 2431154 : if (tree->u.substring.chunks == NULL) {
258 3 : *matched = false;
259 3 : return LDB_SUCCESS;
260 : }
261 :
262 2431151 : if (a->syntax->canonicalise_fn(ldb, ldb, &value, &val) != 0) {
263 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
264 : }
265 :
266 2431151 : save_p = val.data;
267 2431151 : cnk.data = NULL;
268 :
269 2431151 : if ( ! tree->u.substring.start_with_wildcard ) {
270 :
271 2403184 : chunk = tree->u.substring.chunks[c];
272 2403184 : if (a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) goto mismatch;
273 :
274 : /* This deals with wildcard prefix searches on binary attributes (eg objectGUID) */
275 2403184 : if (cnk.length > val.length) {
276 56535 : goto mismatch;
277 : }
278 : /*
279 : * Empty strings are returned as length 0. Ensure
280 : * we can cope with this.
281 : */
282 2346634 : if (cnk.length == 0) {
283 0 : goto mismatch;
284 : }
285 :
286 2346634 : if (memcmp((char *)val.data, (char *)cnk.data, cnk.length) != 0) goto mismatch;
287 441080 : val.length -= cnk.length;
288 441080 : val.data += cnk.length;
289 441080 : c++;
290 441080 : talloc_free(cnk.data);
291 441080 : cnk.data = NULL;
292 : }
293 :
294 932685 : while (tree->u.substring.chunks[c]) {
295 : uint8_t *p;
296 :
297 28034 : chunk = tree->u.substring.chunks[c];
298 28034 : if(a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) {
299 0 : goto mismatch;
300 : }
301 : /*
302 : * Empty strings are returned as length 0. Ensure
303 : * we can cope with this.
304 : */
305 28034 : if (cnk.length == 0) {
306 0 : goto mismatch;
307 : }
308 28034 : if (cnk.length > val.length) {
309 18556 : goto mismatch;
310 : }
311 :
312 16736 : if ( (tree->u.substring.chunks[c + 1]) == NULL &&
313 10092 : (! tree->u.substring.end_with_wildcard) ) {
314 : /*
315 : * The last bit, after all the asterisks, must match
316 : * exactly the last bit of the string.
317 : */
318 : int cmp;
319 8861 : p = val.data + val.length - cnk.length;
320 15697 : cmp = memcmp(p,
321 8861 : cnk.data,
322 : cnk.length);
323 8861 : if (cmp != 0) {
324 8101 : goto mismatch;
325 : }
326 : } else {
327 : /*
328 : * Values might be binary blobs. Don't use string
329 : * search, but memory search instead.
330 : */
331 1086 : p = memmem((const void *)val.data, val.length,
332 604 : (const void *)cnk.data, cnk.length);
333 604 : if (p == NULL) {
334 511 : goto mismatch;
335 : }
336 : /* move val to the end of the match */
337 62 : p += cnk.length;
338 62 : val.length -= (p - val.data);
339 62 : val.data = p;
340 : }
341 803 : c++;
342 803 : TALLOC_FREE(cnk.data);
343 : }
344 :
345 441816 : talloc_free(save_p);
346 441816 : *matched = true;
347 441816 : return LDB_SUCCESS;
348 :
349 1989335 : mismatch:
350 1989335 : *matched = false;
351 1989335 : talloc_free(save_p);
352 1989335 : talloc_free(cnk.data);
353 1989335 : return LDB_SUCCESS;
354 : }
355 :
356 : /*
357 : match a simple leaf node
358 : */
359 3088549 : static int ldb_match_substring(struct ldb_context *ldb,
360 : const struct ldb_message *msg,
361 : const struct ldb_parse_tree *tree,
362 : enum ldb_scope scope, bool *matched)
363 : {
364 : unsigned int i;
365 : struct ldb_message_element *el;
366 :
367 3088549 : el = ldb_msg_find_element(msg, tree->u.substring.attr);
368 3088549 : if (el == NULL) {
369 657585 : *matched = false;
370 657529 : return LDB_SUCCESS;
371 : }
372 :
373 4420177 : for (i = 0; i < el->num_values; i++) {
374 : int ret;
375 2431122 : ret = ldb_wildcard_compare(ldb, tree, el->values[i], matched);
376 2431122 : if (ret != LDB_SUCCESS) return ret;
377 2431122 : if (*matched) return LDB_SUCCESS;
378 : }
379 :
380 1989174 : *matched = false;
381 1989064 : return LDB_SUCCESS;
382 : }
383 :
384 :
385 : /*
386 : bitwise and/or comparator depending on oid
387 : */
388 1885709 : static int ldb_comparator_bitmask(const char *oid, const struct ldb_val *v1, const struct ldb_val *v2,
389 : bool *matched)
390 : {
391 : uint64_t i1, i2;
392 : char ibuf[100];
393 1885709 : char *endptr = NULL;
394 :
395 1885709 : if (v1->length >= sizeof(ibuf)-1) {
396 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
397 : }
398 1934328 : memcpy(ibuf, (char *)v1->data, v1->length);
399 1885709 : ibuf[v1->length] = 0;
400 1885709 : i1 = strtoull(ibuf, &endptr, 0);
401 1885709 : if (endptr != NULL) {
402 1885709 : if (endptr == ibuf || *endptr != 0) {
403 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
404 : }
405 : }
406 :
407 1885709 : if (v2->length >= sizeof(ibuf)-1) {
408 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
409 : }
410 1885709 : endptr = NULL;
411 1934328 : memcpy(ibuf, (char *)v2->data, v2->length);
412 1885709 : ibuf[v2->length] = 0;
413 1885709 : i2 = strtoull(ibuf, &endptr, 0);
414 1885709 : if (endptr != NULL) {
415 1885709 : if (endptr == ibuf || *endptr != 0) {
416 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
417 : }
418 : }
419 1885709 : if (strcmp(LDB_OID_COMPARATOR_AND, oid) == 0) {
420 1884279 : *matched = ((i1 & i2) == i2);
421 1430 : } else if (strcmp(LDB_OID_COMPARATOR_OR, oid) == 0) {
422 1430 : *matched = ((i1 & i2) != 0);
423 : } else {
424 0 : return LDB_ERR_INAPPROPRIATE_MATCHING;
425 : }
426 1837090 : return LDB_SUCCESS;
427 : }
428 :
429 1890618 : static int ldb_match_bitmask(struct ldb_context *ldb,
430 : const char *oid,
431 : const struct ldb_message *msg,
432 : const char *attribute_to_match,
433 : const struct ldb_val *value_to_match,
434 : bool *matched)
435 : {
436 : unsigned int i;
437 : struct ldb_message_element *el;
438 :
439 : /* find the message element */
440 1890618 : el = ldb_msg_find_element(msg, attribute_to_match);
441 1890618 : if (el == NULL) {
442 4923 : *matched = false;
443 4923 : return LDB_SUCCESS;
444 : }
445 :
446 2562151 : for (i=0;i<el->num_values;i++) {
447 : int ret;
448 1885709 : struct ldb_val *v = &el->values[i];
449 :
450 1885709 : ret = ldb_comparator_bitmask(oid, v, value_to_match, matched);
451 1885709 : if (ret != LDB_SUCCESS) {
452 0 : return ret;
453 : }
454 1885709 : if (*matched) {
455 1131695 : return LDB_SUCCESS;
456 : }
457 : }
458 :
459 725054 : *matched = false;
460 725054 : return LDB_SUCCESS;
461 : }
462 :
463 : /*
464 : always return false
465 : */
466 82932 : static int ldb_comparator_false(struct ldb_context *ldb,
467 : const char *oid,
468 : const struct ldb_message *msg,
469 : const char *attribute_to_match,
470 : const struct ldb_val *value_to_match,
471 : bool *matched)
472 : {
473 82932 : *matched = false;
474 82932 : return LDB_SUCCESS;
475 : }
476 :
477 :
478 12727069 : static const struct ldb_extended_match_rule *ldb_find_extended_match_rule(struct ldb_context *ldb,
479 : const char *oid)
480 : {
481 : struct ldb_extended_match_entry *extended_match_rule;
482 :
483 53667667 : for (extended_match_rule = ldb->extended_match_rules;
484 12806227 : extended_match_rule;
485 40037202 : extended_match_rule = extended_match_rule->next) {
486 49864375 : if (strcmp(extended_match_rule->rule->oid, oid) == 0) {
487 9396061 : return extended_match_rule->rule;
488 : }
489 : }
490 :
491 3331008 : return NULL;
492 : }
493 :
494 :
495 : /*
496 : extended match, handles things like bitops
497 : */
498 9827176 : static int ldb_match_extended(struct ldb_context *ldb,
499 : const struct ldb_message *msg,
500 : const struct ldb_parse_tree *tree,
501 : enum ldb_scope scope, bool *matched)
502 : {
503 : const struct ldb_extended_match_rule *rule;
504 :
505 9827176 : if (tree->u.extended.dnAttributes) {
506 : /* FIXME: We really need to find out what this ":dn" part in
507 : * an extended match means and how to handle it. For now print
508 : * only a warning to have s3 winbind and other tools working
509 : * against us. - Matthias */
510 880 : ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb: dnAttributes extended match not supported yet");
511 : }
512 9827176 : if (tree->u.extended.rule_id == NULL) {
513 0 : ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: no-rule extended matches not supported yet");
514 0 : return LDB_ERR_INAPPROPRIATE_MATCHING;
515 : }
516 9827176 : if (tree->u.extended.attr == NULL) {
517 0 : ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: no-attribute extended matches not supported yet");
518 0 : return LDB_ERR_INAPPROPRIATE_MATCHING;
519 : }
520 :
521 10258288 : rule = ldb_find_extended_match_rule(ldb, tree->u.extended.rule_id);
522 9827176 : if (rule == NULL) {
523 3 : *matched = false;
524 3 : ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: unknown extended rule_id %s",
525 0 : tree->u.extended.rule_id);
526 3 : return LDB_SUCCESS;
527 : }
528 :
529 9827173 : return rule->callback(ldb, rule->oid, msg,
530 2159501 : tree->u.extended.attr,
531 : &tree->u.extended.value, matched);
532 : }
533 :
534 : /*
535 : Check if a particular message will match the given filter
536 :
537 : set *matched to true if it matches, false otherwise
538 :
539 : returns LDB_SUCCESS or an error
540 :
541 : this is a recursive function, and does short-circuit evaluation
542 : */
543 588287850 : int ldb_match_message(struct ldb_context *ldb,
544 : const struct ldb_message *msg,
545 : const struct ldb_parse_tree *tree,
546 : enum ldb_scope scope, bool *matched)
547 : {
548 : unsigned int i;
549 : int ret;
550 :
551 588287850 : *matched = false;
552 :
553 588287850 : if (scope != LDB_SCOPE_BASE && ldb_dn_is_special(msg->dn)) {
554 : /* don't match special records except on base searches */
555 0 : return LDB_SUCCESS;
556 : }
557 :
558 588287850 : switch (tree->operation) {
559 99703502 : case LDB_OP_AND:
560 288988370 : for (i=0;i<tree->u.list.num_elements;i++) {
561 201449233 : ret = ldb_match_message(ldb, msg, tree->u.list.elements[i], scope, matched);
562 201449233 : if (ret != LDB_SUCCESS) return ret;
563 201449218 : if (!*matched) return LDB_SUCCESS;
564 : }
565 89590010 : *matched = true;
566 89590010 : return LDB_SUCCESS;
567 :
568 108249939 : case LDB_OP_OR:
569 147332359 : for (i=0;i<tree->u.list.num_elements;i++) {
570 144732744 : ret = ldb_match_message(ldb, msg, tree->u.list.elements[i], scope, matched);
571 144732744 : if (ret != LDB_SUCCESS) return ret;
572 144732744 : if (*matched) return LDB_SUCCESS;
573 : }
574 5368078 : *matched = false;
575 5368078 : return LDB_SUCCESS;
576 :
577 97410154 : case LDB_OP_NOT:
578 97410154 : ret = ldb_match_message(ldb, msg, tree->u.isnot.child, scope, matched);
579 97410154 : if (ret != LDB_SUCCESS) return ret;
580 97410154 : *matched = ! *matched;
581 97410154 : return LDB_SUCCESS;
582 :
583 211770945 : case LDB_OP_EQUALITY:
584 211770945 : return ldb_match_equality(ldb, msg, tree, scope, matched);
585 :
586 3088549 : case LDB_OP_SUBSTRING:
587 3088549 : return ldb_match_substring(ldb, msg, tree, scope, matched);
588 :
589 5542730 : case LDB_OP_GREATER:
590 5542730 : return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_GREATER, matched);
591 :
592 52569 : case LDB_OP_LESS:
593 52569 : return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_LESS, matched);
594 :
595 47822950 : case LDB_OP_PRESENT:
596 47822950 : return ldb_match_present(ldb, msg, tree, scope, matched);
597 :
598 0 : case LDB_OP_APPROX:
599 0 : return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_APPROX, matched);
600 :
601 9827176 : case LDB_OP_EXTENDED:
602 9827176 : return ldb_match_extended(ldb, msg, tree, scope, matched);
603 : }
604 :
605 0 : return LDB_ERR_INAPPROPRIATE_MATCHING;
606 : }
607 :
608 : /*
609 : return 0 if the given parse tree matches the given message. Assumes
610 : the message is in sorted order
611 :
612 : return 1 if it matches, and 0 if it doesn't match
613 : */
614 :
615 0 : int ldb_match_msg(struct ldb_context *ldb,
616 : const struct ldb_message *msg,
617 : const struct ldb_parse_tree *tree,
618 : struct ldb_dn *base,
619 : enum ldb_scope scope)
620 : {
621 : bool matched;
622 : int ret;
623 :
624 0 : if ( ! ldb_match_scope(ldb, base, msg->dn, scope) ) {
625 0 : return 0;
626 : }
627 :
628 0 : ret = ldb_match_message(ldb, msg, tree, scope, &matched);
629 0 : if (ret != LDB_SUCCESS) {
630 : /* to match the old API, we need to consider this a
631 : failure to match */
632 0 : return 0;
633 : }
634 0 : return matched?1:0;
635 : }
636 :
637 174615827 : int ldb_match_msg_error(struct ldb_context *ldb,
638 : const struct ldb_message *msg,
639 : const struct ldb_parse_tree *tree,
640 : struct ldb_dn *base,
641 : enum ldb_scope scope,
642 : bool *matched)
643 : {
644 174615827 : if ( ! ldb_match_scope(ldb, base, msg->dn, scope) ) {
645 68886636 : *matched = false;
646 68886636 : return LDB_SUCCESS;
647 : }
648 :
649 105729191 : return ldb_match_message(ldb, msg, tree, scope, matched);
650 : }
651 :
652 632057 : int ldb_match_msg_objectclass(const struct ldb_message *msg,
653 : const char *objectclass)
654 : {
655 : unsigned int i;
656 632057 : struct ldb_message_element *el = ldb_msg_find_element(msg, "objectClass");
657 632057 : if (!el) {
658 0 : return 0;
659 : }
660 2511898 : for (i=0; i < el->num_values; i++) {
661 2528200 : if (ldb_attr_cmp((const char *)el->values[i].data, objectclass) == 0) {
662 615729 : return 1;
663 : }
664 : }
665 13 : return 0;
666 : }
667 :
668 567547 : _PRIVATE_ int ldb_register_extended_match_rules(struct ldb_context *ldb)
669 : {
670 : struct ldb_extended_match_rule *bitmask_and;
671 : struct ldb_extended_match_rule *bitmask_or;
672 : struct ldb_extended_match_rule *always_false;
673 : int ret;
674 :
675 : /* Register bitmask-and match */
676 567547 : bitmask_and = talloc_zero(ldb, struct ldb_extended_match_rule);
677 567547 : if (bitmask_and == NULL) {
678 0 : return LDB_ERR_OPERATIONS_ERROR;
679 : }
680 :
681 567547 : bitmask_and->oid = LDB_OID_COMPARATOR_AND;
682 567547 : bitmask_and->callback = ldb_match_bitmask;
683 :
684 567547 : ret = ldb_register_extended_match_rule(ldb, bitmask_and);
685 567547 : if (ret != LDB_SUCCESS) {
686 0 : return ret;
687 : }
688 :
689 : /* Register bitmask-or match */
690 567547 : bitmask_or = talloc_zero(ldb, struct ldb_extended_match_rule);
691 567547 : if (bitmask_or == NULL) {
692 0 : return LDB_ERR_OPERATIONS_ERROR;
693 : }
694 :
695 567547 : bitmask_or->oid = LDB_OID_COMPARATOR_OR;
696 567547 : bitmask_or->callback = ldb_match_bitmask;
697 :
698 567547 : ret = ldb_register_extended_match_rule(ldb, bitmask_or);
699 567547 : if (ret != LDB_SUCCESS) {
700 0 : return ret;
701 : }
702 :
703 : /* Register always-false match */
704 567547 : always_false = talloc_zero(ldb, struct ldb_extended_match_rule);
705 567547 : if (always_false == NULL) {
706 0 : return LDB_ERR_OPERATIONS_ERROR;
707 : }
708 :
709 567547 : always_false->oid = SAMBA_LDAP_MATCH_ALWAYS_FALSE;
710 567547 : always_false->callback = ldb_comparator_false;
711 :
712 567547 : ret = ldb_register_extended_match_rule(ldb, always_false);
713 567547 : if (ret != LDB_SUCCESS) {
714 0 : return ret;
715 : }
716 :
717 567547 : return LDB_SUCCESS;
718 : }
719 :
720 : /*
721 : register a new ldb extended matching rule
722 : */
723 3391170 : int ldb_register_extended_match_rule(struct ldb_context *ldb,
724 : const struct ldb_extended_match_rule *rule)
725 : {
726 : const struct ldb_extended_match_rule *lookup_rule;
727 : struct ldb_extended_match_entry *entry;
728 :
729 3451335 : lookup_rule = ldb_find_extended_match_rule(ldb, rule->oid);
730 3391170 : if (lookup_rule) {
731 0 : return LDB_ERR_ENTRY_ALREADY_EXISTS;
732 : }
733 :
734 3391170 : entry = talloc_zero(ldb, struct ldb_extended_match_entry);
735 3391170 : if (!entry) {
736 0 : return LDB_ERR_OPERATIONS_ERROR;
737 : }
738 3391170 : entry->rule = rule;
739 3391170 : DLIST_ADD_END(ldb->extended_match_rules, entry);
740 :
741 3331005 : return LDB_SUCCESS;
742 : }
743 :
|