Coverage Report

Created: 2026-04-01 06:26

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