Line data Source code
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 expression parsing
28 : *
29 : * Description: parse LDAP-like search expressions
30 : *
31 : * Author: Andrew Tridgell
32 : */
33 :
34 : /*
35 : TODO:
36 : - add RFC2254 binary string handling
37 : - possibly add ~=, <= and >= handling
38 : - expand the test suite
39 : - add better parse error handling
40 :
41 : */
42 :
43 : #include "ldb_private.h"
44 : #include "system/locale.h"
45 :
46 : /*
47 : * Maximum depth of the filter parse tree, the value chosen is small enough to
48 : * avoid triggering ASAN stack overflow checks. But large enough to be useful.
49 : *
50 : * On Windows clients the maximum number of levels of recursion allowed is 100.
51 : * In the LDAP server, Windows restricts clients to 512 nested
52 : * (eg) OR statements.
53 : */
54 : #define LDB_MAX_PARSE_TREE_DEPTH 128
55 :
56 : /*
57 : a filter is defined by:
58 : <filter> ::= '(' <filtercomp> ')'
59 : <filtercomp> ::= <and> | <or> | <not> | <simple>
60 : <and> ::= '&' <filterlist>
61 : <or> ::= '|' <filterlist>
62 : <not> ::= '!' <filter>
63 : <filterlist> ::= <filter> | <filter> <filterlist>
64 : <simple> ::= <attributetype> <filtertype> <attributevalue>
65 : <filtertype> ::= '=' | '~=' | '<=' | '>='
66 : */
67 :
68 : /*
69 : decode a RFC2254 binary string representation of a buffer.
70 : Used in LDAP filters.
71 : */
72 42679701 : struct ldb_val ldb_binary_decode(TALLOC_CTX *mem_ctx, const char *str)
73 : {
74 1044312 : size_t i, j;
75 1044312 : struct ldb_val ret;
76 42679701 : size_t slen = str?strlen(str):0;
77 :
78 42679701 : ret.data = (uint8_t *)talloc_size(mem_ctx, slen+1);
79 42679701 : ret.length = 0;
80 42679701 : if (ret.data == NULL) return ret;
81 :
82 910661626 : for (i=j=0;i<slen;i++) {
83 867981926 : if (str[i] == '\\') {
84 5456026 : uint8_t c;
85 5456026 : bool ok;
86 :
87 195355455 : ok = hex_byte(&str[i+1], &c);
88 195355455 : if (!ok) {
89 1 : talloc_free(ret.data);
90 1 : memset(&ret, 0, sizeof(ret));
91 1 : return ret;
92 : }
93 195355454 : ((uint8_t *)ret.data)[j++] = c;
94 195355454 : i += 2;
95 : } else {
96 672626471 : ((uint8_t *)ret.data)[j++] = str[i];
97 : }
98 : }
99 42679700 : ret.length = j;
100 42679700 : ((uint8_t *)ret.data)[j] = 0;
101 :
102 42679700 : return ret;
103 : }
104 :
105 602376304 : static bool need_encode(unsigned char cval)
106 : {
107 591879896 : if (cval < 0x20 || cval > 0x7E || strchr(" *()\\&|!\"", cval)) {
108 390711284 : return true;
109 : }
110 203773174 : return false;
111 : }
112 :
113 : /*
114 : encode a blob as a RFC2254 binary string, escaping any
115 : non-printable or '\' characters
116 : */
117 16826009 : char *ldb_binary_encode(TALLOC_CTX *mem_ctx, struct ldb_val val)
118 : {
119 523800 : size_t i;
120 523800 : char *ret;
121 16826009 : size_t len = val.length;
122 16826009 : unsigned char *buf = val.data;
123 :
124 318014161 : for (i=0;i<val.length;i++) {
125 310590097 : if (need_encode(buf[i])) {
126 195355642 : len += 2;
127 : }
128 : }
129 16826009 : ret = talloc_array(mem_ctx, char, len+1);
130 16826009 : if (ret == NULL) return NULL;
131 :
132 16302209 : len = 0;
133 318014161 : for (i=0;i<val.length;i++) {
134 301188152 : if (need_encode(buf[i])) {
135 195355642 : snprintf(ret+len, 4, "\\%02X", buf[i]);
136 195355642 : len += 3;
137 : } else {
138 105832510 : ret[len++] = buf[i];
139 : }
140 : }
141 :
142 16826009 : ret[len] = 0;
143 :
144 16826009 : return ret;
145 : }
146 :
147 : /*
148 : encode a string as a RFC2254 binary string, escaping any
149 : non-printable or '\' characters. This routine is suitable for use
150 : in escaping user data in ldap filters.
151 : */
152 1402090 : char *ldb_binary_encode_string(TALLOC_CTX *mem_ctx, const char *string)
153 : {
154 79801 : struct ldb_val val;
155 1402090 : if (string == NULL) {
156 0 : return NULL;
157 : }
158 1402090 : val.data = discard_const_p(uint8_t, string);
159 1402090 : val.length = strlen(string);
160 1402090 : return ldb_binary_encode(mem_ctx, val);
161 : }
162 :
163 : /* find the first matching wildcard */
164 38286979 : static char *ldb_parse_find_wildcard(char *value)
165 : {
166 233642431 : while (*value) {
167 233642427 : value = strpbrk(value, "\\*");
168 233642427 : if (value == NULL) return NULL;
169 :
170 195435896 : if (value[0] == '\\') {
171 195355452 : if (value[1] == '\0') return NULL;
172 195355452 : value += 2;
173 195355452 : continue;
174 : }
175 :
176 80444 : if (value[0] == '*') return value;
177 : }
178 :
179 3 : return NULL;
180 : }
181 :
182 : /* return a NULL terminated list of binary strings representing the value
183 : chunks separated by wildcards that makes the value portion of the filter
184 : */
185 35067 : static struct ldb_val **ldb_wildcard_decode(TALLOC_CTX *mem_ctx, const char *string)
186 : {
187 35067 : struct ldb_val **ret = NULL;
188 35067 : unsigned int val = 0;
189 80 : char *wc, *str;
190 :
191 35067 : wc = talloc_strdup(mem_ctx, string);
192 35067 : if (wc == NULL) return NULL;
193 :
194 100774 : while (wc && *wc) {
195 65707 : str = wc;
196 65707 : wc = ldb_parse_find_wildcard(str);
197 65707 : if (wc && *wc) {
198 45377 : if (wc == str) {
199 30584 : wc++;
200 30584 : continue;
201 : }
202 14793 : *wc = 0;
203 14793 : wc++;
204 : }
205 :
206 35123 : ret = talloc_realloc(mem_ctx, ret, struct ldb_val *, val + 2);
207 35123 : if (ret == NULL) return NULL;
208 :
209 35123 : ret[val] = talloc(mem_ctx, struct ldb_val);
210 35123 : if (ret[val] == NULL) return NULL;
211 :
212 35123 : *(ret[val]) = ldb_binary_decode(mem_ctx, str);
213 35123 : if ((ret[val])->data == NULL) return NULL;
214 :
215 35123 : val++;
216 : }
217 :
218 35067 : if (ret != NULL) {
219 35067 : ret[val] = NULL;
220 : }
221 :
222 34987 : return ret;
223 : }
224 :
225 : static struct ldb_parse_tree *ldb_parse_filter(
226 : TALLOC_CTX *mem_ctx,
227 : const char **s,
228 : unsigned depth,
229 : unsigned max_depth);
230 :
231 :
232 : /*
233 : parse an extended match
234 :
235 : possible forms:
236 : (attr:oid:=value)
237 : (attr:dn:oid:=value)
238 : (attr:dn:=value)
239 : (:dn:oid:=value)
240 :
241 : the ':dn' part sets the dnAttributes boolean if present
242 : the oid sets the rule_id string
243 :
244 : */
245 4447823 : static struct ldb_parse_tree *ldb_parse_extended(struct ldb_parse_tree *ret,
246 : char *attr, char *value)
247 : {
248 135458 : char *p1, *p2;
249 :
250 4447823 : ret->operation = LDB_OP_EXTENDED;
251 4447823 : ret->u.extended.value = ldb_binary_decode(ret, value);
252 4447823 : if (ret->u.extended.value.data == NULL) goto failed;
253 :
254 4447823 : p1 = strchr(attr, ':');
255 4447823 : if (p1 == NULL) goto failed;
256 4447823 : p2 = strchr(p1+1, ':');
257 :
258 4447823 : *p1 = 0;
259 4447823 : if (p2) *p2 = 0;
260 :
261 4447823 : ret->u.extended.attr = attr;
262 4447823 : if (strcmp(p1+1, "dn") == 0) {
263 0 : ret->u.extended.dnAttributes = 1;
264 0 : if (p2) {
265 0 : ret->u.extended.rule_id = talloc_strdup(ret, p2+1);
266 0 : if (ret->u.extended.rule_id == NULL) goto failed;
267 : } else {
268 0 : ret->u.extended.rule_id = NULL;
269 : }
270 : } else {
271 4447823 : ret->u.extended.dnAttributes = 0;
272 4447823 : ret->u.extended.rule_id = talloc_strdup(ret, p1+1);
273 4447823 : if (ret->u.extended.rule_id == NULL) goto failed;
274 : }
275 :
276 4312365 : return ret;
277 :
278 0 : failed:
279 0 : talloc_free(ret);
280 0 : return NULL;
281 : }
282 :
283 138021568 : static enum ldb_parse_op ldb_parse_filtertype(TALLOC_CTX *mem_ctx, char **type, char **value, const char **s)
284 : {
285 138021568 : enum ldb_parse_op filter = 0;
286 4805251 : char *name, *val, *k;
287 138021568 : const char *p = *s;
288 4805251 : const char *t, *t1;
289 :
290 : /* retrieve attributetype name */
291 138021568 : t = p;
292 :
293 138021568 : if (*p == '@') { /* for internal attributes the first char can be @ */
294 724686 : p++;
295 : }
296 :
297 1879703018 : while ((isascii(*p) && isalnum((unsigned char)*p)) || (*p == '-') || (*p == '.')) {
298 : /* attribute names can only be alphanums */
299 1741681450 : p++;
300 : }
301 :
302 138021568 : if (*p == ':') { /* but extended searches have : and . chars too */
303 4447825 : p = strstr(p, ":=");
304 4447825 : if (p == NULL) { /* malformed attribute name */
305 2 : return 0;
306 : }
307 : }
308 :
309 138021566 : t1 = p;
310 :
311 138021644 : while (isspace((unsigned char)*p)) p++;
312 :
313 138021566 : if (!strchr("=<>~:", *p)) {
314 4 : return 0;
315 : }
316 :
317 : /* save name */
318 138021562 : name = (char *)talloc_memdup(mem_ctx, t, t1 - t + 1);
319 138021562 : if (name == NULL) return 0;
320 138021562 : name[t1 - t] = '\0';
321 :
322 : /* retrieve filtertype */
323 :
324 138021562 : if (*p == '=') {
325 128893508 : filter = LDB_OP_EQUALITY;
326 4458373 : } else if (*p != '\0' && *(p + 1) == '=') {
327 4458371 : switch (*p) {
328 1454 : case '<':
329 1454 : filter = LDB_OP_LESS;
330 1454 : p++;
331 1454 : break;
332 9094 : case '>':
333 9094 : filter = LDB_OP_GREATER;
334 9094 : p++;
335 9094 : break;
336 0 : case '~':
337 0 : filter = LDB_OP_APPROX;
338 0 : p++;
339 0 : break;
340 4447823 : case ':':
341 4447823 : filter = LDB_OP_EXTENDED;
342 4447823 : p++;
343 4447823 : break;
344 : }
345 : }
346 133351879 : if (!filter) {
347 2 : talloc_free(name);
348 2 : return 0;
349 : }
350 138021560 : p++;
351 :
352 138023240 : while (isspace((unsigned char)*p)) p++;
353 :
354 : /* retrieve value */
355 168418389 : t = p;
356 :
357 1492101676 : while (*p && ((*p != ')') || ((*p == ')') && (*(p - 1) == '\\')))) p++;
358 :
359 138021560 : val = (char *)talloc_memdup(mem_ctx, t, p - t + 1);
360 138021560 : if (val == NULL) {
361 0 : talloc_free(name);
362 0 : return 0;
363 : }
364 138021560 : val[p - t] = '\0';
365 :
366 138021560 : k = &(val[p - t]);
367 :
368 : /* remove trailing spaces from value */
369 138021560 : while ((k > val) && (isspace((unsigned char)*(k - 1)))) k--;
370 138021560 : *k = '\0';
371 :
372 138021560 : *type = name;
373 138021560 : *value = val;
374 138021560 : *s = p;
375 138021560 : return filter;
376 : }
377 :
378 : /*
379 : <simple> ::= <attributetype> <filtertype> <attributevalue>
380 : */
381 138021568 : static struct ldb_parse_tree *ldb_parse_simple(TALLOC_CTX *mem_ctx, const char **s)
382 : {
383 4805251 : char *attr, *value;
384 4805251 : struct ldb_parse_tree *ret;
385 4805251 : enum ldb_parse_op filtertype;
386 :
387 138021568 : ret = talloc_zero(mem_ctx, struct ldb_parse_tree);
388 138021568 : if (!ret) {
389 0 : errno = ENOMEM;
390 0 : return NULL;
391 : }
392 :
393 138021568 : filtertype = ldb_parse_filtertype(ret, &attr, &value, s);
394 138021568 : if (!filtertype) {
395 8 : talloc_free(ret);
396 8 : return NULL;
397 : }
398 :
399 138021560 : switch (filtertype) {
400 :
401 0 : case LDB_OP_PRESENT:
402 0 : ret->operation = LDB_OP_PRESENT;
403 0 : ret->u.present.attr = attr;
404 0 : break;
405 :
406 133563189 : case LDB_OP_EQUALITY:
407 :
408 133563189 : if (strcmp(value, "*") == 0) {
409 95341917 : ret->operation = LDB_OP_PRESENT;
410 95341917 : ret->u.present.attr = attr;
411 95341917 : break;
412 : }
413 :
414 38221272 : if (ldb_parse_find_wildcard(value) != NULL) {
415 35067 : ret->operation = LDB_OP_SUBSTRING;
416 35067 : ret->u.substring.attr = attr;
417 35067 : ret->u.substring.start_with_wildcard = 0;
418 35067 : ret->u.substring.end_with_wildcard = 0;
419 35067 : ret->u.substring.chunks = ldb_wildcard_decode(ret, value);
420 35067 : if (ret->u.substring.chunks == NULL){
421 0 : talloc_free(ret);
422 0 : return NULL;
423 : }
424 35067 : if (value[0] == '*')
425 30584 : ret->u.substring.start_with_wildcard = 1;
426 35067 : if (value[strlen(value) - 1] == '*')
427 14737 : ret->u.substring.end_with_wildcard = 1;
428 35067 : talloc_free(value);
429 :
430 35067 : break;
431 : }
432 :
433 38186205 : ret->operation = LDB_OP_EQUALITY;
434 38186205 : ret->u.equality.attr = attr;
435 38186205 : ret->u.equality.value = ldb_binary_decode(ret, value);
436 38186205 : if (ret->u.equality.value.data == NULL) {
437 1 : talloc_free(ret);
438 1 : return NULL;
439 : }
440 38186204 : talloc_free(value);
441 38186204 : break;
442 :
443 9094 : case LDB_OP_GREATER:
444 9094 : ret->operation = LDB_OP_GREATER;
445 9094 : ret->u.comparison.attr = attr;
446 9094 : ret->u.comparison.value = ldb_binary_decode(ret, value);
447 9094 : if (ret->u.comparison.value.data == NULL) {
448 0 : talloc_free(ret);
449 0 : return NULL;
450 : }
451 9094 : talloc_free(value);
452 9094 : break;
453 :
454 1454 : case LDB_OP_LESS:
455 1454 : ret->operation = LDB_OP_LESS;
456 1454 : ret->u.comparison.attr = attr;
457 1454 : ret->u.comparison.value = ldb_binary_decode(ret, value);
458 1454 : if (ret->u.comparison.value.data == NULL) {
459 0 : talloc_free(ret);
460 0 : return NULL;
461 : }
462 1454 : talloc_free(value);
463 1454 : break;
464 :
465 0 : case LDB_OP_APPROX:
466 0 : ret->operation = LDB_OP_APPROX;
467 0 : ret->u.comparison.attr = attr;
468 0 : ret->u.comparison.value = ldb_binary_decode(ret, value);
469 0 : if (ret->u.comparison.value.data == NULL) {
470 0 : talloc_free(ret);
471 0 : return NULL;
472 : }
473 0 : talloc_free(value);
474 0 : break;
475 :
476 4447823 : case LDB_OP_EXTENDED:
477 :
478 4447823 : ret = ldb_parse_extended(ret, attr, value);
479 4447823 : break;
480 :
481 0 : default:
482 0 : talloc_free(ret);
483 0 : return NULL;
484 : }
485 :
486 133216311 : return ret;
487 : }
488 :
489 :
490 : /*
491 : parse a filterlist
492 : <and> ::= '&' <filterlist>
493 : <or> ::= '|' <filterlist>
494 : <filterlist> ::= <filter> | <filter> <filterlist>
495 : */
496 50470466 : static struct ldb_parse_tree *ldb_parse_filterlist(
497 : TALLOC_CTX *mem_ctx,
498 : const char **s,
499 : unsigned depth,
500 : unsigned max_depth)
501 : {
502 1885599 : struct ldb_parse_tree *ret, *next;
503 1885599 : enum ldb_parse_op op;
504 50470466 : const char *p = *s;
505 :
506 50470466 : switch (*p) {
507 5184895 : case '&':
508 5184895 : op = LDB_OP_AND;
509 5184895 : break;
510 45135544 : case '|':
511 45135544 : op = LDB_OP_OR;
512 45135544 : break;
513 0 : default:
514 0 : return NULL;
515 : }
516 50470466 : p++;
517 :
518 50470466 : while (isspace((unsigned char)*p)) p++;
519 :
520 50470466 : ret = talloc(mem_ctx, struct ldb_parse_tree);
521 50470466 : if (!ret) {
522 0 : errno = ENOMEM;
523 0 : return NULL;
524 : }
525 :
526 50470466 : ret->operation = op;
527 50470466 : ret->u.list.num_elements = 1;
528 50470466 : ret->u.list.elements = talloc(ret, struct ldb_parse_tree *);
529 50470466 : if (!ret->u.list.elements) {
530 0 : errno = ENOMEM;
531 0 : talloc_free(ret);
532 0 : return NULL;
533 : }
534 :
535 100940932 : ret->u.list.elements[0] =
536 50470466 : ldb_parse_filter(ret->u.list.elements, &p, depth, max_depth);
537 50470466 : if (!ret->u.list.elements[0]) {
538 118 : talloc_free(ret);
539 118 : return NULL;
540 : }
541 :
542 50470348 : while (isspace((unsigned char)*p)) p++;
543 :
544 103565331 : while (*p) {
545 3872427 : struct ldb_parse_tree **e;
546 103565331 : if (*p == ')') {
547 48584867 : break;
548 : }
549 :
550 55081931 : next = ldb_parse_filter(
551 53094984 : ret->u.list.elements, &p, depth, max_depth);
552 53094984 : if (next == NULL) {
553 : /* an invalid filter element */
554 1 : talloc_free(ret);
555 1 : return NULL;
556 : }
557 53094983 : e = talloc_realloc(ret, ret->u.list.elements,
558 : struct ldb_parse_tree *,
559 : ret->u.list.num_elements + 1);
560 53094983 : if (!e) {
561 0 : errno = ENOMEM;
562 0 : talloc_free(ret);
563 0 : return NULL;
564 : }
565 53094983 : ret->u.list.elements = e;
566 53094983 : ret->u.list.elements[ret->u.list.num_elements] = next;
567 53094983 : ret->u.list.num_elements++;
568 53094983 : while (isspace((unsigned char)*p)) p++;
569 : }
570 :
571 50470347 : *s = p;
572 :
573 50470347 : return ret;
574 : }
575 :
576 :
577 : /*
578 : <not> ::= '!' <filter>
579 : */
580 1375755 : static struct ldb_parse_tree *ldb_parse_not(
581 : TALLOC_CTX *mem_ctx,
582 : const char **s,
583 : unsigned depth,
584 : unsigned max_depth)
585 : {
586 53188 : struct ldb_parse_tree *ret;
587 1375755 : const char *p = *s;
588 :
589 1375755 : if (*p != '!') {
590 0 : return NULL;
591 : }
592 1375755 : p++;
593 :
594 1375755 : ret = talloc(mem_ctx, struct ldb_parse_tree);
595 1375755 : if (!ret) {
596 0 : errno = ENOMEM;
597 0 : return NULL;
598 : }
599 :
600 1375755 : ret->operation = LDB_OP_NOT;
601 1375755 : ret->u.isnot.child = ldb_parse_filter(ret, &p, depth, max_depth);
602 1375755 : if (!ret->u.isnot.child) {
603 11 : talloc_free(ret);
604 11 : return NULL;
605 : }
606 :
607 1375744 : *s = p;
608 :
609 1375744 : return ret;
610 : }
611 :
612 : /*
613 : parse a filtercomp
614 : <filtercomp> ::= <and> | <or> | <not> | <simple>
615 : */
616 176225426 : static struct ldb_parse_tree *ldb_parse_filtercomp(
617 : TALLOC_CTX *mem_ctx,
618 : const char **s,
619 : unsigned depth,
620 : unsigned max_depth)
621 : {
622 6631439 : struct ldb_parse_tree *ret;
623 176225426 : const char *p = *s;
624 :
625 176225426 : while (isspace((unsigned char)*p)) p++;
626 :
627 176225426 : switch (*p) {
628 5334922 : case '&':
629 5334922 : ret = ldb_parse_filterlist(mem_ctx, &p, depth, max_depth);
630 5334922 : break;
631 :
632 45135544 : case '|':
633 45135544 : ret = ldb_parse_filterlist(mem_ctx, &p, depth, max_depth);
634 45135544 : break;
635 :
636 1375755 : case '!':
637 1375755 : ret = ldb_parse_not(mem_ctx, &p, depth, max_depth);
638 1375755 : break;
639 :
640 0 : case '(':
641 : case ')':
642 0 : return NULL;
643 :
644 124379205 : default:
645 124379205 : ret = ldb_parse_simple(mem_ctx, &p);
646 :
647 : }
648 :
649 176225426 : *s = p;
650 176225426 : return ret;
651 : }
652 :
653 : /*
654 : <filter> ::= '(' <filtercomp> ')'
655 : */
656 176225427 : static struct ldb_parse_tree *ldb_parse_filter(
657 : TALLOC_CTX *mem_ctx,
658 : const char **s,
659 : unsigned depth,
660 : unsigned max_depth)
661 : {
662 6631440 : struct ldb_parse_tree *ret;
663 176225427 : const char *p = *s;
664 :
665 : /*
666 : * Check the depth of the parse tree, and reject the input if
667 : * max_depth exceeded. This avoids stack overflow
668 : * issues.
669 : */
670 176225427 : if (depth > max_depth) {
671 0 : return NULL;
672 : }
673 176225426 : depth++;
674 :
675 176225426 : if (*p != '(') {
676 0 : return NULL;
677 : }
678 176225426 : p++;
679 :
680 176225426 : ret = ldb_parse_filtercomp(mem_ctx, &p, depth, max_depth);
681 :
682 176225426 : if (*p != ')') {
683 0 : return NULL;
684 : }
685 176225294 : p++;
686 :
687 176225294 : while (isspace((unsigned char)*p)) {
688 0 : p++;
689 : }
690 :
691 176225294 : *s = p;
692 :
693 176225294 : return ret;
694 : }
695 :
696 :
697 : /*
698 : main parser entry point. Takes a search string and returns a parse tree
699 :
700 : expression ::= <simple> | <filter>
701 : */
702 84926585 : struct ldb_parse_tree *ldb_parse_tree(TALLOC_CTX *mem_ctx, const char *s)
703 : {
704 84926585 : unsigned depth = 0;
705 :
706 84926586 : while (s && isspace((unsigned char)*s)) s++;
707 :
708 84926585 : if (s == NULL || *s == 0) {
709 44418716 : s = "(|(objectClass=*)(distinguishedName=*))";
710 : }
711 :
712 84926585 : if (*s == '(') {
713 71284222 : return ldb_parse_filter(
714 : mem_ctx, &s, depth, LDB_MAX_PARSE_TREE_DEPTH);
715 : }
716 :
717 13642363 : return ldb_parse_simple(mem_ctx, &s);
718 : }
719 :
720 :
721 : /*
722 : construct a ldap parse filter given a parse tree
723 : */
724 250673 : char *ldb_filter_from_tree(TALLOC_CTX *mem_ctx, const struct ldb_parse_tree *tree)
725 : {
726 161 : char *s, *s2, *ret;
727 161 : unsigned int i;
728 :
729 250673 : if (tree == NULL) {
730 0 : return NULL;
731 : }
732 :
733 250673 : switch (tree->operation) {
734 72772 : case LDB_OP_AND:
735 : case LDB_OP_OR:
736 72874 : ret = talloc_asprintf(mem_ctx, "(%c", tree->operation==LDB_OP_AND?'&':'|');
737 72772 : if (ret == NULL) return NULL;
738 244428 : for (i=0;i<tree->u.list.num_elements;i++) {
739 171656 : s = ldb_filter_from_tree(mem_ctx, tree->u.list.elements[i]);
740 171656 : if (s == NULL) {
741 0 : talloc_free(ret);
742 0 : return NULL;
743 : }
744 171656 : s2 = talloc_asprintf_append(ret, "%s", s);
745 171656 : talloc_free(s);
746 171656 : if (s2 == NULL) {
747 0 : talloc_free(ret);
748 0 : return NULL;
749 : }
750 171656 : ret = s2;
751 : }
752 72772 : s = talloc_asprintf_append(ret, ")");
753 72772 : if (s == NULL) {
754 0 : talloc_free(ret);
755 0 : return NULL;
756 : }
757 72657 : return s;
758 10815 : case LDB_OP_NOT:
759 10815 : s = ldb_filter_from_tree(mem_ctx, tree->u.isnot.child);
760 10815 : if (s == NULL) return NULL;
761 :
762 10815 : ret = talloc_asprintf(mem_ctx, "(!%s)", s);
763 10815 : talloc_free(s);
764 10815 : return ret;
765 50618 : case LDB_OP_EQUALITY:
766 50618 : s = ldb_binary_encode(mem_ctx, tree->u.equality.value);
767 50618 : if (s == NULL) return NULL;
768 50622 : ret = talloc_asprintf(mem_ctx, "(%s=%s)",
769 50618 : tree->u.equality.attr, s);
770 50618 : talloc_free(s);
771 50618 : return ret;
772 10160 : case LDB_OP_SUBSTRING:
773 10160 : ret = talloc_asprintf(mem_ctx, "(%s=%s", tree->u.substring.attr,
774 10160 : tree->u.substring.start_with_wildcard?"*":"");
775 10160 : if (ret == NULL) return NULL;
776 20320 : for (i = 0; tree->u.substring.chunks && tree->u.substring.chunks[i]; i++) {
777 10160 : s2 = ldb_binary_encode(mem_ctx, *(tree->u.substring.chunks[i]));
778 10160 : if (s2 == NULL) {
779 0 : talloc_free(ret);
780 0 : return NULL;
781 : }
782 10160 : if (tree->u.substring.chunks[i+1] ||
783 10160 : tree->u.substring.end_with_wildcard) {
784 10160 : s = talloc_asprintf_append(ret, "%s*", s2);
785 : } else {
786 0 : s = talloc_asprintf_append(ret, "%s", s2);
787 : }
788 10160 : if (s == NULL) {
789 0 : talloc_free(ret);
790 0 : return NULL;
791 : }
792 10160 : ret = s;
793 : }
794 10160 : s = talloc_asprintf_append(ret, ")");
795 10160 : if (s == NULL) {
796 0 : talloc_free(ret);
797 0 : return NULL;
798 : }
799 10321 : ret = s;
800 10160 : return ret;
801 7 : case LDB_OP_GREATER:
802 7 : s = ldb_binary_encode(mem_ctx, tree->u.comparison.value);
803 7 : if (s == NULL) return NULL;
804 7 : ret = talloc_asprintf(mem_ctx, "(%s>=%s)",
805 7 : tree->u.comparison.attr, s);
806 7 : talloc_free(s);
807 7 : return ret;
808 6 : case LDB_OP_LESS:
809 6 : s = ldb_binary_encode(mem_ctx, tree->u.comparison.value);
810 6 : if (s == NULL) return NULL;
811 6 : ret = talloc_asprintf(mem_ctx, "(%s<=%s)",
812 6 : tree->u.comparison.attr, s);
813 6 : talloc_free(s);
814 6 : return ret;
815 100829 : case LDB_OP_PRESENT:
816 100829 : ret = talloc_asprintf(mem_ctx, "(%s=*)", tree->u.present.attr);
817 100829 : return ret;
818 0 : case LDB_OP_APPROX:
819 0 : s = ldb_binary_encode(mem_ctx, tree->u.comparison.value);
820 0 : if (s == NULL) return NULL;
821 0 : ret = talloc_asprintf(mem_ctx, "(%s~=%s)",
822 0 : tree->u.comparison.attr, s);
823 0 : talloc_free(s);
824 0 : return ret;
825 5466 : case LDB_OP_EXTENDED:
826 5466 : s = ldb_binary_encode(mem_ctx, tree->u.extended.value);
827 5466 : if (s == NULL) return NULL;
828 21864 : ret = talloc_asprintf(mem_ctx, "(%s%s%s%s:=%s)",
829 5466 : tree->u.extended.attr?tree->u.extended.attr:"",
830 5466 : tree->u.extended.dnAttributes?":dn":"",
831 5466 : tree->u.extended.rule_id?":":"",
832 5466 : tree->u.extended.rule_id?tree->u.extended.rule_id:"",
833 : s);
834 5466 : talloc_free(s);
835 5466 : return ret;
836 : }
837 :
838 0 : return NULL;
839 : }
840 :
841 :
842 : /*
843 : walk a parse tree, calling the provided callback on each node
844 : */
845 431678798 : int ldb_parse_tree_walk(struct ldb_parse_tree *tree,
846 : int (*callback)(struct ldb_parse_tree *tree, void *),
847 : void *private_context)
848 : {
849 18571682 : unsigned int i;
850 18571682 : int ret;
851 :
852 431678798 : ret = callback(tree, private_context);
853 431678798 : if (ret != LDB_SUCCESS) {
854 0 : return ret;
855 : }
856 :
857 431678798 : switch (tree->operation) {
858 119500750 : case LDB_OP_AND:
859 : case LDB_OP_OR:
860 385520844 : for (i=0;i<tree->u.list.num_elements;i++) {
861 260537332 : ret = ldb_parse_tree_walk(tree->u.list.elements[i], callback, private_context);
862 260537332 : if (ret != LDB_SUCCESS) {
863 0 : return ret;
864 : }
865 : }
866 119500750 : break;
867 5543771 : case LDB_OP_NOT:
868 5543771 : ret = ldb_parse_tree_walk(tree->u.isnot.child, callback, private_context);
869 5543771 : if (ret != LDB_SUCCESS) {
870 0 : return ret;
871 : }
872 5332557 : break;
873 288273809 : case LDB_OP_EQUALITY:
874 : case LDB_OP_GREATER:
875 : case LDB_OP_LESS:
876 : case LDB_OP_APPROX:
877 : case LDB_OP_SUBSTRING:
878 : case LDB_OP_PRESENT:
879 : case LDB_OP_EXTENDED:
880 288273809 : break;
881 : }
882 413107116 : return LDB_SUCCESS;
883 : }
884 :
885 : struct parse_tree_attr_replace_ctx {
886 : const char *attr;
887 : const char *replace;
888 : };
889 :
890 : /*
891 : callback for ldb_parse_tree_attr_replace()
892 : */
893 0 : static int parse_tree_attr_replace(struct ldb_parse_tree *tree, void *private_context)
894 : {
895 0 : struct parse_tree_attr_replace_ctx *ctx = private_context;
896 0 : switch (tree->operation) {
897 0 : case LDB_OP_EQUALITY:
898 0 : if (ldb_attr_cmp(tree->u.equality.attr, ctx->attr) == 0) {
899 0 : tree->u.equality.attr = ctx->replace;
900 : }
901 0 : break;
902 0 : case LDB_OP_GREATER:
903 : case LDB_OP_LESS:
904 : case LDB_OP_APPROX:
905 0 : if (ldb_attr_cmp(tree->u.comparison.attr, ctx->attr) == 0) {
906 0 : tree->u.comparison.attr = ctx->replace;
907 : }
908 0 : break;
909 0 : case LDB_OP_SUBSTRING:
910 0 : if (ldb_attr_cmp(tree->u.substring.attr, ctx->attr) == 0) {
911 0 : tree->u.substring.attr = ctx->replace;
912 : }
913 0 : break;
914 0 : case LDB_OP_PRESENT:
915 0 : if (ldb_attr_cmp(tree->u.present.attr, ctx->attr) == 0) {
916 0 : tree->u.present.attr = ctx->replace;
917 : }
918 0 : break;
919 0 : case LDB_OP_EXTENDED:
920 0 : if (tree->u.extended.attr &&
921 0 : ldb_attr_cmp(tree->u.extended.attr, ctx->attr) == 0) {
922 0 : tree->u.extended.attr = ctx->replace;
923 : }
924 0 : break;
925 0 : default:
926 0 : break;
927 : }
928 0 : return LDB_SUCCESS;
929 : }
930 :
931 : /*
932 : replace any occurrences of an attribute name in the parse tree with a
933 : new name
934 : */
935 0 : void ldb_parse_tree_attr_replace(struct ldb_parse_tree *tree,
936 : const char *attr,
937 : const char *replace)
938 : {
939 0 : struct parse_tree_attr_replace_ctx ctx;
940 :
941 0 : ctx.attr = attr;
942 0 : ctx.replace = replace;
943 :
944 0 : ldb_parse_tree_walk(tree, parse_tree_attr_replace, &ctx);
945 0 : }
946 :
947 : /*
948 : shallow copy a tree - copying only the elements array so that the caller
949 : can safely add new elements without changing the message
950 : */
951 446308 : struct ldb_parse_tree *ldb_parse_tree_copy_shallow(TALLOC_CTX *mem_ctx,
952 : const struct ldb_parse_tree *ot)
953 : {
954 3923 : unsigned int i;
955 3923 : struct ldb_parse_tree *nt;
956 :
957 446308 : nt = talloc(mem_ctx, struct ldb_parse_tree);
958 446308 : if (!nt) {
959 0 : return NULL;
960 : }
961 :
962 446308 : *nt = *ot;
963 :
964 446308 : switch (ot->operation) {
965 123248 : case LDB_OP_AND:
966 : case LDB_OP_OR:
967 123248 : nt->u.list.elements = talloc_array(nt, struct ldb_parse_tree *,
968 : ot->u.list.num_elements);
969 123248 : if (!nt->u.list.elements) {
970 0 : talloc_free(nt);
971 0 : return NULL;
972 : }
973 :
974 429807 : for (i=0;i<ot->u.list.num_elements;i++) {
975 613118 : nt->u.list.elements[i] =
976 306559 : ldb_parse_tree_copy_shallow(nt->u.list.elements,
977 306559 : ot->u.list.elements[i]);
978 306559 : if (!nt->u.list.elements[i]) {
979 0 : talloc_free(nt);
980 0 : return NULL;
981 : }
982 : }
983 122484 : break;
984 12431 : case LDB_OP_NOT:
985 24862 : nt->u.isnot.child = ldb_parse_tree_copy_shallow(nt,
986 12431 : ot->u.isnot.child);
987 12431 : if (!nt->u.isnot.child) {
988 0 : talloc_free(nt);
989 0 : return NULL;
990 : }
991 12431 : break;
992 307470 : case LDB_OP_EQUALITY:
993 : case LDB_OP_GREATER:
994 : case LDB_OP_LESS:
995 : case LDB_OP_APPROX:
996 : case LDB_OP_SUBSTRING:
997 : case LDB_OP_PRESENT:
998 : case LDB_OP_EXTENDED:
999 307470 : break;
1000 : }
1001 :
1002 442385 : return nt;
1003 : }
1004 :
1005 : /* Get the attribute (if any) associated with the top node of a parse tree. */
1006 756713846 : const char *ldb_parse_tree_get_attr(const struct ldb_parse_tree *tree)
1007 : {
1008 756713846 : switch (tree->operation) {
1009 400294697 : case LDB_OP_AND:
1010 : case LDB_OP_OR:
1011 : case LDB_OP_NOT:
1012 400294697 : return NULL;
1013 282671858 : case LDB_OP_EQUALITY:
1014 282671858 : return tree->u.equality.attr;
1015 3726324 : case LDB_OP_SUBSTRING:
1016 3726324 : return tree->u.substring.attr;
1017 5949441 : case LDB_OP_GREATER:
1018 : case LDB_OP_LESS:
1019 : case LDB_OP_APPROX:
1020 5949441 : return tree->u.comparison.attr;
1021 54567036 : case LDB_OP_PRESENT:
1022 54567036 : return tree->u.present.attr;
1023 23568 : case LDB_OP_EXTENDED:
1024 23568 : return tree->u.extended.attr;
1025 : }
1026 :
1027 0 : return NULL;
1028 : }
|