LCOV - code coverage report
Current view: top level - lib/ldb/common - ldb_parse.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-lts cc996e7c Lines: 433 528 82.0 %
Date: 2025-10-17 03:45:34 Functions: 20 20 100.0 %

          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    25934586 : struct ldb_val ldb_binary_decode(TALLOC_CTX *mem_ctx, const char *str)
      73             : {
      74             :         size_t i, j;
      75             :         struct ldb_val ret;
      76    25934586 :         size_t slen = str?strlen(str):0;
      77             : 
      78    25934586 :         ret.data = (uint8_t *)talloc_size(mem_ctx, slen+1);
      79    25934586 :         ret.length = 0;
      80    25934586 :         if (ret.data == NULL) return ret;
      81             : 
      82   608397449 :         for (i=j=0;i<slen;i++) {
      83   582462864 :                 if (str[i] == '\\') {
      84             :                         uint8_t c;
      85             :                         bool ok;
      86             : 
      87   123174776 :                         ok = hex_byte(&str[i+1], &c);
      88   123174776 :                         if (!ok) {
      89           1 :                                 talloc_free(ret.data);
      90           1 :                                 memset(&ret, 0, sizeof(ret));
      91           1 :                                 return ret;
      92             :                         }
      93   123174775 :                         ((uint8_t *)ret.data)[j++] = c;
      94   123174775 :                         i += 2;
      95             :                 } else {
      96   459288088 :                         ((uint8_t *)ret.data)[j++] = str[i];
      97             :                 }
      98             :         }
      99    25934585 :         ret.length = j;
     100    25934585 :         ((uint8_t *)ret.data)[j] = 0;
     101             : 
     102    25934585 :         return ret;
     103             : }
     104             : 
     105   386862430 : static bool need_encode(unsigned char cval)
     106             : {
     107   386862430 :         if (cval < 0x20 || cval > 0x7E || strchr(" *()\\&|!\"", cval)) {
     108   246352778 :                 return true;
     109             :         }
     110   140509652 :         return false;
     111             : }
     112             : 
     113             : /*
     114             :    encode a blob as a RFC2254 binary string, escaping any
     115             :    non-printable or '\' characters
     116             : */
     117    10906785 : char *ldb_binary_encode(TALLOC_CTX *mem_ctx, struct ldb_val val)
     118             : {
     119             :         size_t i;
     120             :         char *ret;
     121    10906785 :         size_t len = val.length;
     122    10906785 :         unsigned char *buf = val.data;
     123             : 
     124   204338000 :         for (i=0;i<val.length;i++) {
     125   193431215 :                 if (need_encode(buf[i])) {
     126   123176389 :                         len += 2;
     127             :                 }
     128             :         }
     129    10906785 :         ret = talloc_array(mem_ctx, char, len+1);
     130    10906785 :         if (ret == NULL) return NULL;
     131             : 
     132    10906785 :         len = 0;
     133   204338000 :         for (i=0;i<val.length;i++) {
     134   193431215 :                 if (need_encode(buf[i])) {
     135   123176389 :                         snprintf(ret+len, 4, "\\%02X", buf[i]);
     136   123176389 :                         len += 3;
     137             :                 } else {
     138    70254826 :                         ret[len++] = buf[i];
     139             :                 }
     140             :         }
     141             : 
     142    10906785 :         ret[len] = 0;
     143             : 
     144    10906785 :         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     1012712 : char *ldb_binary_encode_string(TALLOC_CTX *mem_ctx, const char *string)
     153             : {
     154             :         struct ldb_val val;
     155     1012712 :         if (string == NULL) {
     156           0 :                 return NULL;
     157             :         }
     158     1012712 :         val.data = discard_const_p(uint8_t, string);
     159     1012712 :         val.length = strlen(string);
     160     1012712 :         return ldb_binary_encode(mem_ctx, val);
     161             : }
     162             : 
     163             : /* find the first matching wildcard */
     164    24319499 : static char *ldb_parse_find_wildcard(char *value)
     165             : {
     166   169150661 :         while (*value) {
     167   147494270 :                 value = strpbrk(value, "\\*");
     168   147494270 :                 if (value == NULL) return NULL;
     169             : 
     170   123254422 :                 if (value[0] == '\\') {
     171   123174774 :                         if (value[1] == '\0') return NULL;
     172   123174774 :                         value += 2;
     173   123174774 :                         continue;
     174             :                 }
     175             : 
     176       79648 :                 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       34716 : static struct ldb_val **ldb_wildcard_decode(TALLOC_CTX *mem_ctx, const char *string)
     186             : {
     187       34716 :         struct ldb_val **ret = NULL;
     188       34716 :         unsigned int val = 0;
     189             :         char *wc, *str;
     190             : 
     191       34716 :         wc = talloc_strdup(mem_ctx, string);
     192       34716 :         if (wc == NULL) return NULL;
     193             : 
     194      132583 :         while (wc && *wc) {
     195       65240 :                 str = wc;
     196       65240 :                 wc = ldb_parse_find_wildcard(str);
     197       65240 :                 if (wc && *wc) {
     198       44932 :                         if (wc == str) {
     199       30468 :                                 wc++;
     200       30468 :                                 continue;
     201             :                         }
     202       14464 :                         *wc = 0;
     203       14464 :                         wc++;
     204             :                 }
     205             : 
     206       34772 :                 ret = talloc_realloc(mem_ctx, ret, struct ldb_val *, val + 2);
     207       34772 :                 if (ret == NULL) return NULL;
     208             : 
     209       34772 :                 ret[val] = talloc(mem_ctx, struct ldb_val);
     210       34772 :                 if (ret[val] == NULL) return NULL;
     211             : 
     212       34772 :                 *(ret[val]) = ldb_binary_decode(mem_ctx, str);
     213       34772 :                 if ((ret[val])->data == NULL) return NULL;
     214             : 
     215       34772 :                 val++;
     216             :         }
     217             : 
     218       34716 :         if (ret != NULL) {
     219       34716 :                 ret[val] = NULL;
     220             :         }
     221             : 
     222       34716 :         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     1673208 : static struct ldb_parse_tree *ldb_parse_extended(struct ldb_parse_tree *ret, 
     246             :                                                  char *attr, char *value)
     247             : {
     248             :         char *p1, *p2;
     249             : 
     250     1673208 :         ret->operation = LDB_OP_EXTENDED;
     251     1673208 :         ret->u.extended.value = ldb_binary_decode(ret, value);
     252     1673208 :         if (ret->u.extended.value.data == NULL) goto failed;
     253             : 
     254     1673208 :         p1 = strchr(attr, ':');
     255     1673208 :         if (p1 == NULL) goto failed;
     256     1673208 :         p2 = strchr(p1+1, ':');
     257             : 
     258     1673208 :         *p1 = 0;
     259     1673208 :         if (p2) *p2 = 0;
     260             : 
     261     1673208 :         ret->u.extended.attr = attr;
     262     1673208 :         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     1673208 :                 ret->u.extended.dnAttributes = 0;
     272     1673208 :                 ret->u.extended.rule_id = talloc_strdup(ret, p1+1);
     273     1673208 :                 if (ret->u.extended.rule_id == NULL) goto failed;
     274             :         }
     275             : 
     276     1673208 :         return ret;
     277             : 
     278           0 : failed:
     279           0 :         talloc_free(ret);
     280           0 :         return NULL;
     281             : }
     282             : 
     283    93949905 : static enum ldb_parse_op ldb_parse_filtertype(TALLOC_CTX *mem_ctx, char **type, char **value, const char **s)
     284             : {
     285    93949905 :         enum ldb_parse_op filter = 0;
     286             :         char *name, *val, *k;
     287    93949905 :         const char *p = *s;
     288             :         const char *t, *t1;
     289             : 
     290             :         /* retrieve attributetype name */
     291    93949905 :         t = p;
     292             : 
     293    93949905 :         if (*p == '@') { /* for internal attributes the first char can be @ */
     294      529406 :                 p++;
     295             :         }
     296             : 
     297  1374083077 :         while ((isascii(*p) && isalnum((unsigned char)*p)) || (*p == '-') || (*p == '.')) { 
     298             :                 /* attribute names can only be alphanums */
     299  1196850787 :                 p++;
     300             :         }
     301             : 
     302    93949905 :         if (*p == ':') { /* but extended searches have : and . chars too */
     303     1673210 :                 p = strstr(p, ":=");
     304     1673210 :                 if (p == NULL) { /* malformed attribute name */
     305           2 :                         return 0;
     306             :                 }
     307             :         }
     308             : 
     309    93949903 :         t1 = p;
     310             : 
     311    93949903 :         while (isspace((unsigned char)*p)) p++;
     312             : 
     313    93949903 :         if (!strchr("=<>~:", *p)) {
     314           3 :                 return 0;
     315             :         }
     316             : 
     317             :         /* save name */
     318    93949900 :         name = (char *)talloc_memdup(mem_ctx, t, t1 - t + 1);
     319    93949900 :         if (name == NULL) return 0;
     320    93949900 :         name[t1 - t] = '\0';
     321             : 
     322             :         /* retrieve filtertype */
     323             : 
     324    93949900 :         if (*p == '=') {
     325    92269629 :                 filter = LDB_OP_EQUALITY;
     326     1680271 :         } else if (*p != '\0' && *(p + 1) == '=') {
     327     1680269 :                 switch (*p) {
     328        1171 :                 case '<':
     329        1171 :                         filter = LDB_OP_LESS;
     330        1171 :                         p++;
     331        1171 :                         break;
     332        5890 :                 case '>':
     333        5890 :                         filter = LDB_OP_GREATER;
     334        5890 :                         p++;
     335        5890 :                         break;
     336           0 :                 case '~':
     337           0 :                         filter = LDB_OP_APPROX;
     338           0 :                         p++;
     339           0 :                         break;
     340     1673208 :                 case ':':
     341     1673208 :                         filter = LDB_OP_EXTENDED;
     342     1673208 :                         p++;
     343     1673208 :                         break;
     344             :                 }
     345             :         }
     346    93949900 :         if (!filter) {
     347           2 :                 talloc_free(name);
     348           2 :                 return 0;
     349             :         }
     350    93949898 :         p++;
     351             : 
     352    93949898 :         while (isspace((unsigned char)*p)) p++;
     353             : 
     354             :         /* retrieve value */
     355    93949898 :         t = p;
     356             : 
     357   194469054 :         while (*p && ((*p != ')') || ((*p == ')') && (*(p - 1) == '\\')))) p++;
     358             : 
     359    93949898 :         val = (char *)talloc_memdup(mem_ctx, t, p - t + 1);
     360    93949898 :         if (val == NULL) {
     361           0 :                 talloc_free(name);
     362           0 :                 return 0;
     363             :         }
     364    93949898 :         val[p - t] = '\0';
     365             : 
     366    93949898 :         k = &(val[p - t]);
     367             : 
     368             :         /* remove trailing spaces from value */
     369    93949898 :         while ((k > val) && (isspace((unsigned char)*(k - 1)))) k--;
     370    93949898 :         *k = '\0';
     371             : 
     372    93949898 :         *type = name;
     373    93949898 :         *value = val;
     374    93949898 :         *s = p;
     375    93949898 :         return filter;
     376             : }
     377             : 
     378             : /*
     379             :   <simple> ::= <attributetype> <filtertype> <attributevalue>
     380             : */
     381    93949905 : static struct ldb_parse_tree *ldb_parse_simple(TALLOC_CTX *mem_ctx, const char **s)
     382             : {
     383             :         char *attr, *value;
     384             :         struct ldb_parse_tree *ret;
     385             :         enum ldb_parse_op filtertype;
     386             : 
     387    93949905 :         ret = talloc_zero(mem_ctx, struct ldb_parse_tree);
     388    93949905 :         if (!ret) {
     389           0 :                 errno = ENOMEM;
     390           0 :                 return NULL;
     391             :         }
     392             : 
     393    93949905 :         filtertype = ldb_parse_filtertype(ret, &attr, &value, s);
     394    93949905 :         if (!filtertype) {
     395           7 :                 talloc_free(ret);
     396           7 :                 return NULL;
     397             :         }
     398             : 
     399    93949898 :         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    92269629 :                 case LDB_OP_EQUALITY:
     407             : 
     408    92269629 :                         if (strcmp(value, "*") == 0) {
     409    68015370 :                                 ret->operation = LDB_OP_PRESENT;
     410    68015370 :                                 ret->u.present.attr = attr;
     411    68015370 :                                 break;
     412             :                         }
     413             : 
     414    24254259 :                         if (ldb_parse_find_wildcard(value) != NULL) {
     415       34716 :                                 ret->operation = LDB_OP_SUBSTRING;
     416       34716 :                                 ret->u.substring.attr = attr;
     417       34716 :                                 ret->u.substring.start_with_wildcard = 0;
     418       34716 :                                 ret->u.substring.end_with_wildcard = 0;
     419       34716 :                                 ret->u.substring.chunks = ldb_wildcard_decode(ret, value);
     420       34716 :                                 if (ret->u.substring.chunks == NULL){
     421           0 :                                         talloc_free(ret);
     422           0 :                                         return NULL;
     423             :                                 }
     424       34716 :                                 if (value[0] == '*')
     425       30468 :                                         ret->u.substring.start_with_wildcard = 1;
     426       34716 :                                 if (value[strlen(value) - 1] == '*')
     427       14408 :                                         ret->u.substring.end_with_wildcard = 1;
     428       34716 :                                 talloc_free(value);
     429             : 
     430       34716 :                                 break;
     431             :                         }
     432             : 
     433    24219543 :                         ret->operation = LDB_OP_EQUALITY;
     434    24219543 :                         ret->u.equality.attr = attr;
     435    24219543 :                         ret->u.equality.value = ldb_binary_decode(ret, value);
     436    24219543 :                         if (ret->u.equality.value.data == NULL) {
     437           1 :                                 talloc_free(ret);
     438           1 :                                 return NULL;
     439             :                         }
     440    24219542 :                         talloc_free(value);
     441    24219542 :                         break;
     442             : 
     443        5890 :                 case LDB_OP_GREATER:
     444        5890 :                         ret->operation = LDB_OP_GREATER;
     445        5890 :                         ret->u.comparison.attr = attr;
     446        5890 :                         ret->u.comparison.value = ldb_binary_decode(ret, value);
     447        5890 :                         if (ret->u.comparison.value.data == NULL) {
     448           0 :                                 talloc_free(ret);
     449           0 :                                 return NULL;
     450             :                         }
     451        5890 :                         talloc_free(value);
     452        5890 :                         break;
     453             : 
     454        1171 :                 case LDB_OP_LESS:
     455        1171 :                         ret->operation = LDB_OP_LESS;
     456        1171 :                         ret->u.comparison.attr = attr;
     457        1171 :                         ret->u.comparison.value = ldb_binary_decode(ret, value);
     458        1171 :                         if (ret->u.comparison.value.data == NULL) {
     459           0 :                                 talloc_free(ret);
     460           0 :                                 return NULL;
     461             :                         }
     462        1171 :                         talloc_free(value);
     463        1171 :                         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     1673208 :                 case LDB_OP_EXTENDED:
     477             : 
     478     1673208 :                         ret = ldb_parse_extended(ret, attr, value);
     479     1673208 :                         break;
     480             : 
     481           0 :                 default:
     482           0 :                         talloc_free(ret);
     483           0 :                         return NULL;
     484             :         }
     485             : 
     486    93949897 :         return ret;
     487             : }
     488             : 
     489             : 
     490             : /*
     491             :   parse a filterlist
     492             :   <and> ::= '&' <filterlist>
     493             :   <or> ::= '|' <filterlist>
     494             :   <filterlist> ::= <filter> | <filter> <filterlist>
     495             : */
     496    34444361 : 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             :         struct ldb_parse_tree *ret, *next;
     503             :         enum ldb_parse_op op;
     504    34444361 :         const char *p = *s;
     505             : 
     506    34444361 :         switch (*p) {
     507     2294689 :                 case '&':
     508     2294689 :                         op = LDB_OP_AND;
     509     2294689 :                         break;
     510    32149672 :                 case '|':
     511    32149672 :                         op = LDB_OP_OR;
     512    32149672 :                         break;
     513           0 :                 default:
     514           0 :                         return NULL;
     515             :         }
     516    34444361 :         p++;
     517             : 
     518    34444361 :         while (isspace((unsigned char)*p)) p++;
     519             : 
     520    34444361 :         ret = talloc(mem_ctx, struct ldb_parse_tree);
     521    34444361 :         if (!ret) {
     522           0 :                 errno = ENOMEM;
     523           0 :                 return NULL;
     524             :         }
     525             : 
     526    34444361 :         ret->operation = op;
     527    34444361 :         ret->u.list.num_elements = 1;
     528    34444361 :         ret->u.list.elements = talloc(ret, struct ldb_parse_tree *);
     529    34444361 :         if (!ret->u.list.elements) {
     530           0 :                 errno = ENOMEM;
     531           0 :                 talloc_free(ret);
     532           0 :                 return NULL;
     533             :         }
     534             : 
     535    68888722 :         ret->u.list.elements[0] =
     536    65050842 :                 ldb_parse_filter(ret->u.list.elements, &p, depth, max_depth);
     537    34444361 :         if (!ret->u.list.elements[0]) {
     538         118 :                 talloc_free(ret);
     539         118 :                 return NULL;
     540             :         }
     541             : 
     542    34444243 :         while (isspace((unsigned char)*p)) p++;
     543             : 
     544   100651235 :         while (*p) {
     545             :                 struct ldb_parse_tree **e;
     546    70044872 :                 if (*p == ')') {
     547    34444242 :                         break;
     548             :                 }
     549             : 
     550    35600630 :                 next = ldb_parse_filter(
     551    35600630 :                         ret->u.list.elements, &p, depth, max_depth);
     552    35600630 :                 if (next == NULL) {
     553             :                         /* an invalid filter element */
     554           1 :                         talloc_free(ret);
     555           1 :                         return NULL;
     556             :                 }
     557    35600629 :                 e = talloc_realloc(ret, ret->u.list.elements, 
     558             :                                      struct ldb_parse_tree *, 
     559             :                                      ret->u.list.num_elements + 1);
     560    35600629 :                 if (!e) {
     561           0 :                         errno = ENOMEM;
     562           0 :                         talloc_free(ret);
     563           0 :                         return NULL;
     564             :                 }
     565    35600629 :                 ret->u.list.elements = e;
     566    35600629 :                 ret->u.list.elements[ret->u.list.num_elements] = next;
     567    35600629 :                 ret->u.list.num_elements++;
     568    35600629 :                 while (isspace((unsigned char)*p)) p++;
     569             :         }
     570             : 
     571    34444242 :         *s = p;
     572             : 
     573    34444242 :         return ret;
     574             : }
     575             : 
     576             : 
     577             : /*
     578             :   <not> ::= '!' <filter>
     579             : */
     580      710546 : 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             :         struct ldb_parse_tree *ret;
     587      710546 :         const char *p = *s;
     588             : 
     589      710546 :         if (*p != '!') {
     590           0 :                 return NULL;
     591             :         }
     592      710546 :         p++;
     593             : 
     594      710546 :         ret = talloc(mem_ctx, struct ldb_parse_tree);
     595      710546 :         if (!ret) {
     596           0 :                 errno = ENOMEM;
     597           0 :                 return NULL;
     598             :         }
     599             : 
     600      710546 :         ret->operation = LDB_OP_NOT;
     601      710546 :         ret->u.isnot.child = ldb_parse_filter(ret, &p, depth, max_depth);
     602      710546 :         if (!ret->u.isnot.child) {
     603          11 :                 talloc_free(ret);
     604          11 :                 return NULL;
     605             :         }
     606             : 
     607      710535 :         *s = p;
     608             : 
     609      710535 :         return ret;
     610             : }
     611             : 
     612             : /*
     613             :   parse a filtercomp
     614             :   <filtercomp> ::= <and> | <or> | <not> | <simple>
     615             : */
     616   119158339 : 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             :         struct ldb_parse_tree *ret;
     623   119158339 :         const char *p = *s;
     624             : 
     625   119158339 :         while (isspace((unsigned char)*p)) p++;
     626             : 
     627   119158339 :         switch (*p) {
     628     2294689 :         case '&':
     629     2294689 :                 ret = ldb_parse_filterlist(mem_ctx, &p, depth, max_depth);
     630     2294689 :                 break;
     631             : 
     632    32149672 :         case '|':
     633    32149672 :                 ret = ldb_parse_filterlist(mem_ctx, &p, depth, max_depth);
     634    32149672 :                 break;
     635             : 
     636      710546 :         case '!':
     637      710546 :                 ret = ldb_parse_not(mem_ctx, &p, depth, max_depth);
     638      710546 :                 break;
     639             : 
     640           0 :         case '(':
     641             :         case ')':
     642           0 :                 return NULL;
     643             : 
     644    84003432 :         default:
     645    84003432 :                 ret = ldb_parse_simple(mem_ctx, &p);
     646             : 
     647             :         }
     648             : 
     649   119158339 :         *s = p;
     650   119158339 :         return ret;
     651             : }
     652             : 
     653             : /*
     654             :   <filter> ::= '(' <filtercomp> ')'
     655             : */
     656   119158340 : 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             :         struct ldb_parse_tree *ret;
     663   119158340 :         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   119158340 :         if (depth > max_depth) {
     671           1 :                 return NULL;
     672             :         }
     673   119158339 :         depth++;
     674             : 
     675   119158339 :         if (*p != '(') {
     676           0 :                 return NULL;
     677             :         }
     678   119158339 :         p++;
     679             : 
     680   119158339 :         ret = ldb_parse_filtercomp(mem_ctx, &p, depth, max_depth);
     681             : 
     682   119158339 :         if (*p != ')') {
     683         132 :                 return NULL;
     684             :         }
     685   119158207 :         p++;
     686             : 
     687   225397180 :         while (isspace((unsigned char)*p)) {
     688           0 :                 p++;
     689             :         }
     690             : 
     691   119158207 :         *s = p;
     692             : 
     693   119158207 :         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    58349276 : struct ldb_parse_tree *ldb_parse_tree(TALLOC_CTX *mem_ctx, const char *s)
     703             : {
     704    58349276 :         unsigned depth = 0;
     705             : 
     706    58349276 :         while (s && isspace((unsigned char)*s)) s++;
     707             : 
     708    58349276 :         if (s == NULL || *s == 0) {
     709    31811909 :                 s = "(|(objectClass=*)(distinguishedName=*))";
     710             :         }
     711             : 
     712    58349276 :         if (*s == '(') {
     713    48402803 :                 return ldb_parse_filter(
     714             :                         mem_ctx, &s, depth, LDB_MAX_PARSE_TREE_DEPTH);
     715             :         }
     716             : 
     717     9946473 :         return ldb_parse_simple(mem_ctx, &s);
     718             : }
     719             : 
     720             : 
     721             : /*
     722             :   construct a ldap parse filter given a parse tree
     723             : */
     724      233028 : char *ldb_filter_from_tree(TALLOC_CTX *mem_ctx, const struct ldb_parse_tree *tree)
     725             : {
     726             :         char *s, *s2, *ret;
     727             :         unsigned int i;
     728             : 
     729      233028 :         if (tree == NULL) {
     730           0 :                 return NULL;
     731             :         }
     732             : 
     733      233028 :         switch (tree->operation) {
     734       67145 :         case LDB_OP_AND:
     735             :         case LDB_OP_OR:
     736       67145 :                 ret = talloc_asprintf(mem_ctx, "(%c", tree->operation==LDB_OP_AND?'&':'|');
     737       67145 :                 if (ret == NULL) return NULL;
     738      227427 :                 for (i=0;i<tree->u.list.num_elements;i++) {
     739      160282 :                         s = ldb_filter_from_tree(mem_ctx, tree->u.list.elements[i]);
     740      160282 :                         if (s == NULL) {
     741           0 :                                 talloc_free(ret);
     742           0 :                                 return NULL;
     743             :                         }
     744      160282 :                         s2 = talloc_asprintf_append(ret, "%s", s);
     745      160282 :                         talloc_free(s);
     746      160282 :                         if (s2 == NULL) {
     747           0 :                                 talloc_free(ret);
     748           0 :                                 return NULL;
     749             :                         }
     750      160282 :                         ret = s2;
     751             :                 }
     752       67145 :                 s = talloc_asprintf_append(ret, ")");
     753       67145 :                 if (s == NULL) {
     754           0 :                         talloc_free(ret);
     755           0 :                         return NULL;
     756             :                 }
     757       67145 :                 return s;
     758       10707 :         case LDB_OP_NOT:
     759       10707 :                 s = ldb_filter_from_tree(mem_ctx, tree->u.isnot.child);
     760       10707 :                 if (s == NULL) return NULL;
     761             : 
     762       10707 :                 ret = talloc_asprintf(mem_ctx, "(!%s)", s);
     763       10707 :                 talloc_free(s);
     764       10707 :                 return ret;
     765       50268 :         case LDB_OP_EQUALITY:
     766       50268 :                 s = ldb_binary_encode(mem_ctx, tree->u.equality.value);
     767       50268 :                 if (s == NULL) return NULL;
     768       50268 :                 ret = talloc_asprintf(mem_ctx, "(%s=%s)", 
     769       22109 :                                       tree->u.equality.attr, s);
     770       50268 :                 talloc_free(s);
     771       50268 :                 return ret;
     772       10057 :         case LDB_OP_SUBSTRING:
     773       10057 :                 ret = talloc_asprintf(mem_ctx, "(%s=%s", tree->u.substring.attr,
     774       10057 :                                       tree->u.substring.start_with_wildcard?"*":"");
     775       10057 :                 if (ret == NULL) return NULL;
     776       20114 :                 for (i = 0; tree->u.substring.chunks && tree->u.substring.chunks[i]; i++) {
     777       10057 :                         s2 = ldb_binary_encode(mem_ctx, *(tree->u.substring.chunks[i]));
     778       10057 :                         if (s2 == NULL) {
     779           0 :                                 talloc_free(ret);
     780           0 :                                 return NULL;
     781             :                         }
     782       18114 :                         if (tree->u.substring.chunks[i+1] ||
     783       10057 :                             tree->u.substring.end_with_wildcard) {
     784       10057 :                                 s = talloc_asprintf_append(ret, "%s*", s2);
     785             :                         } else {
     786           0 :                                 s = talloc_asprintf_append(ret, "%s", s2);
     787             :                         }
     788       10057 :                         if (s == NULL) {
     789           0 :                                 talloc_free(ret);
     790           0 :                                 return NULL;
     791             :                         }
     792       10057 :                         ret = s;
     793             :                 }
     794       10057 :                 s = talloc_asprintf_append(ret, ")");
     795       10057 :                 if (s == NULL) {
     796           0 :                         talloc_free(ret);
     797           0 :                         return NULL;
     798             :                 }
     799       10057 :                 ret = s;
     800       10057 :                 return ret;
     801           7 :         case LDB_OP_GREATER:
     802           7 :                 s = ldb_binary_encode(mem_ctx, tree->u.equality.value);
     803           7 :                 if (s == NULL) return NULL;
     804           7 :                 ret = talloc_asprintf(mem_ctx, "(%s>=%s)", 
     805           0 :                                       tree->u.equality.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.equality.value);
     810           6 :                 if (s == NULL) return NULL;
     811           6 :                 ret = talloc_asprintf(mem_ctx, "(%s<=%s)", 
     812           0 :                                       tree->u.equality.attr, s);
     813           6 :                 talloc_free(s);
     814           6 :                 return ret;
     815       89468 :         case LDB_OP_PRESENT:
     816       89468 :                 ret = talloc_asprintf(mem_ctx, "(%s=*)", tree->u.present.attr);
     817       89468 :                 return ret;
     818           0 :         case LDB_OP_APPROX:
     819           0 :                 s = ldb_binary_encode(mem_ctx, tree->u.equality.value);
     820           0 :                 if (s == NULL) return NULL;
     821           0 :                 ret = talloc_asprintf(mem_ctx, "(%s~=%s)", 
     822           0 :                                       tree->u.equality.attr, s);
     823           0 :                 talloc_free(s);
     824           0 :                 return ret;
     825        5370 :         case LDB_OP_EXTENDED:
     826        5370 :                 s = ldb_binary_encode(mem_ctx, tree->u.extended.value);
     827        5370 :                 if (s == NULL) return NULL;
     828       21480 :                 ret = talloc_asprintf(mem_ctx, "(%s%s%s%s:=%s)", 
     829        5370 :                                       tree->u.extended.attr?tree->u.extended.attr:"", 
     830        5370 :                                       tree->u.extended.dnAttributes?":dn":"",
     831        5370 :                                       tree->u.extended.rule_id?":":"", 
     832        5370 :                                       tree->u.extended.rule_id?tree->u.extended.rule_id:"", 
     833             :                                       s);
     834        5370 :                 talloc_free(s);
     835        5370 :                 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   274323252 : 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             :         unsigned int i;
     850             :         int ret;
     851             : 
     852   274323252 :         ret = callback(tree, private_context);
     853   274323252 :         if (ret != LDB_SUCCESS) {
     854           0 :                 return ret;
     855             :         }
     856             : 
     857   274323252 :         switch (tree->operation) {
     858    79719855 :         case LDB_OP_AND:
     859             :         case LDB_OP_OR:
     860   243850867 :                 for (i=0;i<tree->u.list.num_elements;i++) {
     861   164131012 :                         ret = ldb_parse_tree_walk(tree->u.list.elements[i], callback, private_context);
     862   164131012 :                         if (ret != LDB_SUCCESS) {
     863           0 :                                 return ret;
     864             :                         }
     865             :                 }
     866    79719855 :                 break;
     867     2883243 :         case LDB_OP_NOT:
     868     2883243 :                 ret = ldb_parse_tree_walk(tree->u.isnot.child, callback, private_context);
     869     2883243 :                 if (ret != LDB_SUCCESS) {
     870           0 :                         return ret;
     871             :                 }
     872     2883243 :                 break;
     873   191720154 :         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   191720154 :                 break;
     881             :         }
     882   274323252 :         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   162583416 : static int parse_tree_attr_replace(struct ldb_parse_tree *tree, void *private_context)
     894             : {
     895   162583416 :         struct parse_tree_attr_replace_ctx *ctx = private_context;
     896   162583416 :         switch (tree->operation) {
     897    29129072 :         case LDB_OP_EQUALITY:
     898             :         case LDB_OP_GREATER:
     899             :         case LDB_OP_LESS:
     900             :         case LDB_OP_APPROX:
     901    29129072 :                 if (ldb_attr_cmp(tree->u.equality.attr, ctx->attr) == 0) {
     902           0 :                         tree->u.equality.attr = ctx->replace;
     903             :                 }
     904    29129072 :                 break;
     905       69778 :         case LDB_OP_SUBSTRING:
     906       69778 :                 if (ldb_attr_cmp(tree->u.substring.attr, ctx->attr) == 0) {
     907           0 :                         tree->u.substring.attr = ctx->replace;
     908             :                 }
     909       69778 :                 break;
     910    84367580 :         case LDB_OP_PRESENT:
     911    84367580 :                 if (ldb_attr_cmp(tree->u.present.attr, ctx->attr) == 0) {
     912           0 :                         tree->u.present.attr = ctx->replace;
     913             :                 }
     914    84367580 :                 break;
     915     3358204 :         case LDB_OP_EXTENDED:
     916     6558602 :                 if (tree->u.extended.attr &&
     917     3358204 :                     ldb_attr_cmp(tree->u.extended.attr, ctx->attr) == 0) {
     918           0 :                         tree->u.extended.attr = ctx->replace;
     919             :                 }
     920     3358204 :                 break;
     921    45658782 :         default:
     922    45658782 :                 break;
     923             :         }
     924   162583416 :         return LDB_SUCCESS;
     925             : }
     926             : 
     927             : /*
     928             :   replace any occurrences of an attribute name in the parse tree with a
     929             :   new name
     930             : */
     931    70363484 : void ldb_parse_tree_attr_replace(struct ldb_parse_tree *tree,
     932             :                                  const char *attr,
     933             :                                  const char *replace)
     934             : {
     935             :         struct parse_tree_attr_replace_ctx ctx;
     936             : 
     937    70363484 :         ctx.attr    = attr;
     938    70363484 :         ctx.replace = replace;
     939             : 
     940    70363484 :         ldb_parse_tree_walk(tree, parse_tree_attr_replace, &ctx);
     941    70363484 : }
     942             : 
     943             : /*
     944             :   shallow copy a tree - copying only the elements array so that the caller
     945             :   can safely add new elements without changing the message
     946             : */
     947      145179 : struct ldb_parse_tree *ldb_parse_tree_copy_shallow(TALLOC_CTX *mem_ctx,
     948             :                                                    const struct ldb_parse_tree *ot)
     949             : {
     950             :         unsigned int i;
     951             :         struct ldb_parse_tree *nt;
     952             : 
     953      145179 :         nt = talloc(mem_ctx, struct ldb_parse_tree);
     954      145179 :         if (!nt) {
     955           0 :                 return NULL;
     956             :         }
     957             : 
     958      145179 :         *nt = *ot;
     959             : 
     960      145179 :         switch (ot->operation) {
     961       37046 :         case LDB_OP_AND:
     962             :         case LDB_OP_OR:
     963       37046 :                 nt->u.list.elements = talloc_array(nt, struct ldb_parse_tree *,
     964             :                                                    ot->u.list.num_elements);
     965       37046 :                 if (!nt->u.list.elements) {
     966           0 :                         talloc_free(nt);
     967           0 :                         return NULL;
     968             :                 }
     969             : 
     970      138212 :                 for (i=0;i<ot->u.list.num_elements;i++) {
     971      202332 :                         nt->u.list.elements[i] =
     972      200213 :                                 ldb_parse_tree_copy_shallow(nt->u.list.elements,
     973      101166 :                                                 ot->u.list.elements[i]);
     974      101166 :                         if (!nt->u.list.elements[i]) {
     975           0 :                                 talloc_free(nt);
     976           0 :                                 return NULL;
     977             :                         }
     978             :                 }
     979       37046 :                 break;
     980         849 :         case LDB_OP_NOT:
     981         929 :                 nt->u.isnot.child = ldb_parse_tree_copy_shallow(nt,
     982         849 :                                                         ot->u.isnot.child);
     983         849 :                 if (!nt->u.isnot.child) {
     984           0 :                         talloc_free(nt);
     985           0 :                         return NULL;
     986             :                 }
     987         849 :                 break;
     988      107284 :         case LDB_OP_EQUALITY:
     989             :         case LDB_OP_GREATER:
     990             :         case LDB_OP_LESS:
     991             :         case LDB_OP_APPROX:
     992             :         case LDB_OP_SUBSTRING:
     993             :         case LDB_OP_PRESENT:
     994             :         case LDB_OP_EXTENDED:
     995      107284 :                 break;
     996             :         }
     997             : 
     998      145179 :         return nt;
     999             : }
    1000             : 
    1001             : /* Get the attribute (if any) associated with the top node of a parse tree. */
    1002   530091492 : const char *ldb_parse_tree_get_attr(const struct ldb_parse_tree *tree)
    1003             : {
    1004   530091492 :         switch (tree->operation) {
    1005   285852776 :         case LDB_OP_AND:
    1006             :         case LDB_OP_OR:
    1007             :         case LDB_OP_NOT:
    1008   285852776 :                 return NULL;
    1009   196403270 :         case LDB_OP_EQUALITY:
    1010   196403270 :                 return tree->u.equality.attr;
    1011     3583417 :         case LDB_OP_SUBSTRING:
    1012     3583417 :                 return tree->u.substring.attr;
    1013     4626350 :         case LDB_OP_GREATER:
    1014             :         case LDB_OP_LESS:
    1015             :         case LDB_OP_APPROX:
    1016     4626350 :                 return tree->u.comparison.attr;
    1017    39604541 :         case LDB_OP_PRESENT:
    1018    39604541 :                 return tree->u.present.attr;
    1019       21138 :         case LDB_OP_EXTENDED:
    1020       21138 :                 return tree->u.extended.attr;
    1021             :         }
    1022             : 
    1023           0 :         return NULL;
    1024             : }

Generated by: LCOV version 1.13