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-test 1498b464 Lines: 433 528 82.0 %
Date: 2024-06-13 04:01:37 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    25579326 : 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    25579326 :         size_t slen = str?strlen(str):0;
      77             : 
      78    25579326 :         ret.data = (uint8_t *)talloc_size(mem_ctx, slen+1);
      79    25579326 :         ret.length = 0;
      80    25579326 :         if (ret.data == NULL) return ret;
      81             : 
      82   595076556 :         for (i=j=0;i<slen;i++) {
      83   569497231 :                 if (str[i] == '\\') {
      84             :                         uint8_t c;
      85             :                         bool ok;
      86             : 
      87   126752858 :                         ok = hex_byte(&str[i+1], &c);
      88   126752858 :                         if (!ok) {
      89           1 :                                 talloc_free(ret.data);
      90           1 :                                 memset(&ret, 0, sizeof(ret));
      91           1 :                                 return ret;
      92             :                         }
      93   126752857 :                         ((uint8_t *)ret.data)[j++] = c;
      94   126752857 :                         i += 2;
      95             :                 } else {
      96   442744373 :                         ((uint8_t *)ret.data)[j++] = str[i];
      97             :                 }
      98             :         }
      99    25579325 :         ret.length = j;
     100    25579325 :         ((uint8_t *)ret.data)[j] = 0;
     101             : 
     102    25579325 :         return ret;
     103             : }
     104             : 
     105   386456944 : static bool need_encode(unsigned char cval)
     106             : {
     107   386456944 :         if (cval < 0x20 || cval > 0x7E || strchr(" *()\\&|!\"", cval)) {
     108   253508966 :                 return true;
     109             :         }
     110   132947978 :         return false;
     111             : }
     112             : 
     113             : /*
     114             :    encode a blob as a RFC2254 binary string, escaping any
     115             :    non-printable or '\' characters
     116             : */
     117    10893565 : char *ldb_binary_encode(TALLOC_CTX *mem_ctx, struct ldb_val val)
     118             : {
     119             :         size_t i;
     120             :         char *ret;
     121    10893565 :         size_t len = val.length;
     122    10893565 :         unsigned char *buf = val.data;
     123             : 
     124   204122037 :         for (i=0;i<val.length;i++) {
     125   193228472 :                 if (need_encode(buf[i])) {
     126   126754483 :                         len += 2;
     127             :                 }
     128             :         }
     129    10893565 :         ret = talloc_array(mem_ctx, char, len+1);
     130    10893565 :         if (ret == NULL) return NULL;
     131             : 
     132    10893565 :         len = 0;
     133   204122037 :         for (i=0;i<val.length;i++) {
     134   193228472 :                 if (need_encode(buf[i])) {
     135   126754483 :                         snprintf(ret+len, 4, "\\%02X", buf[i]);
     136   126754483 :                         len += 3;
     137             :                 } else {
     138    66473989 :                         ret[len++] = buf[i];
     139             :                 }
     140             :         }
     141             : 
     142    10893565 :         ret[len] = 0;
     143             : 
     144    10893565 :         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     1012484 : char *ldb_binary_encode_string(TALLOC_CTX *mem_ctx, const char *string)
     153             : {
     154             :         struct ldb_val val;
     155     1012484 :         if (string == NULL) {
     156           0 :                 return NULL;
     157             :         }
     158     1012484 :         val.data = discard_const_p(uint8_t, string);
     159     1012484 :         val.length = strlen(string);
     160     1012484 :         return ldb_binary_encode(mem_ctx, val);
     161             : }
     162             : 
     163             : /* find the first matching wildcard */
     164    23964878 : static char *ldb_parse_find_wildcard(char *value)
     165             : {
     166   171990638 :         while (*value) {
     167   150717731 :                 value = strpbrk(value, "\\*");
     168   150717731 :                 if (value == NULL) return NULL;
     169             : 
     170   126832504 :                 if (value[0] == '\\') {
     171   126752856 :                         if (value[1] == '\0') return NULL;
     172   126752856 :                         value += 2;
     173   126752856 :                         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     1672667 : 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     1672667 :         ret->operation = LDB_OP_EXTENDED;
     251     1672667 :         ret->u.extended.value = ldb_binary_decode(ret, value);
     252     1672667 :         if (ret->u.extended.value.data == NULL) goto failed;
     253             : 
     254     1672667 :         p1 = strchr(attr, ':');
     255     1672667 :         if (p1 == NULL) goto failed;
     256     1672667 :         p2 = strchr(p1+1, ':');
     257             : 
     258     1672667 :         *p1 = 0;
     259     1672667 :         if (p2) *p2 = 0;
     260             : 
     261     1672667 :         ret->u.extended.attr = attr;
     262     1672667 :         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     1672667 :                 ret->u.extended.dnAttributes = 0;
     272     1672667 :                 ret->u.extended.rule_id = talloc_strdup(ret, p1+1);
     273     1672667 :                 if (ret->u.extended.rule_id == NULL) goto failed;
     274             :         }
     275             : 
     276     1672667 :         return ret;
     277             : 
     278           0 : failed:
     279           0 :         talloc_free(ret);
     280           0 :         return NULL;
     281             : }
     282             : 
     283    93310266 : static enum ldb_parse_op ldb_parse_filtertype(TALLOC_CTX *mem_ctx, char **type, char **value, const char **s)
     284             : {
     285    93310266 :         enum ldb_parse_op filter = 0;
     286             :         char *name, *val, *k;
     287    93310266 :         const char *p = *s;
     288             :         const char *t, *t1;
     289             : 
     290             :         /* retrieve attributetype name */
     291    93310266 :         t = p;
     292             : 
     293    93310266 :         if (*p == '@') { /* for internal attributes the first char can be @ */
     294      529355 :                 p++;
     295             :         }
     296             : 
     297  1365311223 :         while ((isascii(*p) && isalnum((unsigned char)*p)) || (*p == '-') || (*p == '.')) { 
     298             :                 /* attribute names can only be alphanums */
     299  1189383754 :                 p++;
     300             :         }
     301             : 
     302    93310266 :         if (*p == ':') { /* but extended searches have : and . chars too */
     303     1672669 :                 p = strstr(p, ":=");
     304     1672669 :                 if (p == NULL) { /* malformed attribute name */
     305           2 :                         return 0;
     306             :                 }
     307             :         }
     308             : 
     309    93310264 :         t1 = p;
     310             : 
     311    93310264 :         while (isspace((unsigned char)*p)) p++;
     312             : 
     313    93310264 :         if (!strchr("=<>~:", *p)) {
     314           3 :                 return 0;
     315             :         }
     316             : 
     317             :         /* save name */
     318    93310261 :         name = (char *)talloc_memdup(mem_ctx, t, t1 - t + 1);
     319    93310261 :         if (name == NULL) return 0;
     320    93310261 :         name[t1 - t] = '\0';
     321             : 
     322             :         /* retrieve filtertype */
     323             : 
     324    93310261 :         if (*p == '=') {
     325    91630629 :                 filter = LDB_OP_EQUALITY;
     326     1679632 :         } else if (*p != '\0' && *(p + 1) == '=') {
     327     1679630 :                 switch (*p) {
     328        1171 :                 case '<':
     329        1171 :                         filter = LDB_OP_LESS;
     330        1171 :                         p++;
     331        1171 :                         break;
     332        5792 :                 case '>':
     333        5792 :                         filter = LDB_OP_GREATER;
     334        5792 :                         p++;
     335        5792 :                         break;
     336           0 :                 case '~':
     337           0 :                         filter = LDB_OP_APPROX;
     338           0 :                         p++;
     339           0 :                         break;
     340     1672667 :                 case ':':
     341     1672667 :                         filter = LDB_OP_EXTENDED;
     342     1672667 :                         p++;
     343     1672667 :                         break;
     344             :                 }
     345             :         }
     346    93310261 :         if (!filter) {
     347           2 :                 talloc_free(name);
     348           2 :                 return 0;
     349             :         }
     350    93310259 :         p++;
     351             : 
     352    93310259 :         while (isspace((unsigned char)*p)) p++;
     353             : 
     354             :         /* retrieve value */
     355    93310259 :         t = p;
     356             : 
     357   194381708 :         while (*p && ((*p != ')') || ((*p == ')') && (*(p - 1) == '\\')))) p++;
     358             : 
     359    93310259 :         val = (char *)talloc_memdup(mem_ctx, t, p - t + 1);
     360    93310259 :         if (val == NULL) {
     361           0 :                 talloc_free(name);
     362           0 :                 return 0;
     363             :         }
     364    93310259 :         val[p - t] = '\0';
     365             : 
     366    93310259 :         k = &(val[p - t]);
     367             : 
     368             :         /* remove trailing spaces from value */
     369    93310259 :         while ((k > val) && (isspace((unsigned char)*(k - 1)))) k--;
     370    93310259 :         *k = '\0';
     371             : 
     372    93310259 :         *type = name;
     373    93310259 :         *value = val;
     374    93310259 :         *s = p;
     375    93310259 :         return filter;
     376             : }
     377             : 
     378             : /*
     379             :   <simple> ::= <attributetype> <filtertype> <attributevalue>
     380             : */
     381    93310266 : 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    93310266 :         ret = talloc_zero(mem_ctx, struct ldb_parse_tree);
     388    93310266 :         if (!ret) {
     389           0 :                 errno = ENOMEM;
     390           0 :                 return NULL;
     391             :         }
     392             : 
     393    93310266 :         filtertype = ldb_parse_filtertype(ret, &attr, &value, s);
     394    93310266 :         if (!filtertype) {
     395           7 :                 talloc_free(ret);
     396           7 :                 return NULL;
     397             :         }
     398             : 
     399    93310259 :         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    91630629 :                 case LDB_OP_EQUALITY:
     407             : 
     408    91630629 :                         if (strcmp(value, "*") == 0) {
     409    67730991 :                                 ret->operation = LDB_OP_PRESENT;
     410    67730991 :                                 ret->u.present.attr = attr;
     411    67730991 :                                 break;
     412             :                         }
     413             : 
     414    23899638 :                         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    23864922 :                         ret->operation = LDB_OP_EQUALITY;
     434    23864922 :                         ret->u.equality.attr = attr;
     435    23864922 :                         ret->u.equality.value = ldb_binary_decode(ret, value);
     436    23864922 :                         if (ret->u.equality.value.data == NULL) {
     437           1 :                                 talloc_free(ret);
     438           1 :                                 return NULL;
     439             :                         }
     440    23864921 :                         talloc_free(value);
     441    23864921 :                         break;
     442             : 
     443        5792 :                 case LDB_OP_GREATER:
     444        5792 :                         ret->operation = LDB_OP_GREATER;
     445        5792 :                         ret->u.comparison.attr = attr;
     446        5792 :                         ret->u.comparison.value = ldb_binary_decode(ret, value);
     447        5792 :                         if (ret->u.comparison.value.data == NULL) {
     448           0 :                                 talloc_free(ret);
     449           0 :                                 return NULL;
     450             :                         }
     451        5792 :                         talloc_free(value);
     452        5792 :                         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     1672667 :                 case LDB_OP_EXTENDED:
     477             : 
     478     1672667 :                         ret = ldb_parse_extended(ret, attr, value);
     479     1672667 :                         break;
     480             : 
     481           0 :                 default:
     482           0 :                         talloc_free(ret);
     483           0 :                         return NULL;
     484             :         }
     485             : 
     486    93310258 :         return ret;
     487             : }
     488             : 
     489             : 
     490             : /*
     491             :   parse a filterlist
     492             :   <and> ::= '&' <filterlist>
     493             :   <or> ::= '|' <filterlist>
     494             :   <filterlist> ::= <filter> | <filter> <filterlist>
     495             : */
     496    34318287 : 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    34318287 :         const char *p = *s;
     505             : 
     506    34318287 :         switch (*p) {
     507     2301140 :                 case '&':
     508     2301140 :                         op = LDB_OP_AND;
     509     2301140 :                         break;
     510    32017147 :                 case '|':
     511    32017147 :                         op = LDB_OP_OR;
     512    32017147 :                         break;
     513           0 :                 default:
     514           0 :                         return NULL;
     515             :         }
     516    34318287 :         p++;
     517             : 
     518    34318287 :         while (isspace((unsigned char)*p)) p++;
     519             : 
     520    34318287 :         ret = talloc(mem_ctx, struct ldb_parse_tree);
     521    34318287 :         if (!ret) {
     522           0 :                 errno = ENOMEM;
     523           0 :                 return NULL;
     524             :         }
     525             : 
     526    34318287 :         ret->operation = op;
     527    34318287 :         ret->u.list.num_elements = 1;
     528    34318287 :         ret->u.list.elements = talloc(ret, struct ldb_parse_tree *);
     529    34318287 :         if (!ret->u.list.elements) {
     530           0 :                 errno = ENOMEM;
     531           0 :                 talloc_free(ret);
     532           0 :                 return NULL;
     533             :         }
     534             : 
     535    68636574 :         ret->u.list.elements[0] =
     536    64787286 :                 ldb_parse_filter(ret->u.list.elements, &p, depth, max_depth);
     537    34318287 :         if (!ret->u.list.elements[0]) {
     538         118 :                 talloc_free(ret);
     539         118 :                 return NULL;
     540             :         }
     541             : 
     542    34318169 :         while (isspace((unsigned char)*p)) p++;
     543             : 
     544   100272293 :         while (*p) {
     545             :                 struct ldb_parse_tree **e;
     546    69803412 :                 if (*p == ')') {
     547    34318168 :                         break;
     548             :                 }
     549             : 
     550    35485244 :                 next = ldb_parse_filter(
     551    35485244 :                         ret->u.list.elements, &p, depth, max_depth);
     552    35485244 :                 if (next == NULL) {
     553             :                         /* an invalid filter element */
     554           1 :                         talloc_free(ret);
     555           1 :                         return NULL;
     556             :                 }
     557    35485243 :                 e = talloc_realloc(ret, ret->u.list.elements, 
     558             :                                      struct ldb_parse_tree *, 
     559             :                                      ret->u.list.num_elements + 1);
     560    35485243 :                 if (!e) {
     561           0 :                         errno = ENOMEM;
     562           0 :                         talloc_free(ret);
     563           0 :                         return NULL;
     564             :                 }
     565    35485243 :                 ret->u.list.elements = e;
     566    35485243 :                 ret->u.list.elements[ret->u.list.num_elements] = next;
     567    35485243 :                 ret->u.list.num_elements++;
     568    35485243 :                 while (isspace((unsigned char)*p)) p++;
     569             :         }
     570             : 
     571    34318168 :         *s = p;
     572             : 
     573    34318168 :         return ret;
     574             : }
     575             : 
     576             : 
     577             : /*
     578             :   <not> ::= '!' <filter>
     579             : */
     580      708419 : 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      708419 :         const char *p = *s;
     588             : 
     589      708419 :         if (*p != '!') {
     590           0 :                 return NULL;
     591             :         }
     592      708419 :         p++;
     593             : 
     594      708419 :         ret = talloc(mem_ctx, struct ldb_parse_tree);
     595      708419 :         if (!ret) {
     596           0 :                 errno = ENOMEM;
     597           0 :                 return NULL;
     598             :         }
     599             : 
     600      708419 :         ret->operation = LDB_OP_NOT;
     601      708419 :         ret->u.isnot.child = ldb_parse_filter(ret, &p, depth, max_depth);
     602      708419 :         if (!ret->u.isnot.child) {
     603          11 :                 talloc_free(ret);
     604          11 :                 return NULL;
     605             :         }
     606             : 
     607      708408 :         *s = p;
     608             : 
     609      708408 :         return ret;
     610             : }
     611             : 
     612             : /*
     613             :   parse a filtercomp
     614             :   <filtercomp> ::= <and> | <or> | <not> | <simple>
     615             : */
     616   118735174 : 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   118735174 :         const char *p = *s;
     624             : 
     625   118735174 :         while (isspace((unsigned char)*p)) p++;
     626             : 
     627   118735174 :         switch (*p) {
     628     2301140 :         case '&':
     629     2301140 :                 ret = ldb_parse_filterlist(mem_ctx, &p, depth, max_depth);
     630     2301140 :                 break;
     631             : 
     632    32017147 :         case '|':
     633    32017147 :                 ret = ldb_parse_filterlist(mem_ctx, &p, depth, max_depth);
     634    32017147 :                 break;
     635             : 
     636      708419 :         case '!':
     637      708419 :                 ret = ldb_parse_not(mem_ctx, &p, depth, max_depth);
     638      708419 :                 break;
     639             : 
     640           0 :         case '(':
     641             :         case ')':
     642           0 :                 return NULL;
     643             : 
     644    83708468 :         default:
     645    83708468 :                 ret = ldb_parse_simple(mem_ctx, &p);
     646             : 
     647             :         }
     648             : 
     649   118735174 :         *s = p;
     650   118735174 :         return ret;
     651             : }
     652             : 
     653             : /*
     654             :   <filter> ::= '(' <filtercomp> ')'
     655             : */
     656   118735175 : 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   118735175 :         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   118735175 :         if (depth > max_depth) {
     671           1 :                 return NULL;
     672             :         }
     673   118735174 :         depth++;
     674             : 
     675   118735174 :         if (*p != '(') {
     676           0 :                 return NULL;
     677             :         }
     678   118735174 :         p++;
     679             : 
     680   118735174 :         ret = ldb_parse_filtercomp(mem_ctx, &p, depth, max_depth);
     681             : 
     682   118735174 :         if (*p != ')') {
     683         132 :                 return NULL;
     684             :         }
     685   118735042 :         p++;
     686             : 
     687   224511988 :         while (isspace((unsigned char)*p)) {
     688           0 :                 p++;
     689             :         }
     690             : 
     691   118735042 :         *s = p;
     692             : 
     693   118735042 :         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    57825023 : struct ldb_parse_tree *ldb_parse_tree(TALLOC_CTX *mem_ctx, const char *s)
     703             : {
     704    57825023 :         unsigned depth = 0;
     705             : 
     706    57825023 :         while (s && isspace((unsigned char)*s)) s++;
     707             : 
     708    57825023 :         if (s == NULL || *s == 0) {
     709    31673517 :                 s = "(|(objectClass=*)(distinguishedName=*))";
     710             :         }
     711             : 
     712    57825023 :         if (*s == '(') {
     713    48223225 :                 return ldb_parse_filter(
     714             :                         mem_ctx, &s, depth, LDB_MAX_PARSE_TREE_DEPTH);
     715             :         }
     716             : 
     717     9601798 :         return ldb_parse_simple(mem_ctx, &s);
     718             : }
     719             : 
     720             : 
     721             : /*
     722             :   construct a ldap parse filter given a parse tree
     723             : */
     724      233031 : 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      233031 :         if (tree == NULL) {
     730           0 :                 return NULL;
     731             :         }
     732             : 
     733      233031 :         switch (tree->operation) {
     734       67146 :         case LDB_OP_AND:
     735             :         case LDB_OP_OR:
     736       67146 :                 ret = talloc_asprintf(mem_ctx, "(%c", tree->operation==LDB_OP_AND?'&':'|');
     737       67146 :                 if (ret == NULL) return NULL;
     738      227430 :                 for (i=0;i<tree->u.list.num_elements;i++) {
     739      160284 :                         s = ldb_filter_from_tree(mem_ctx, tree->u.list.elements[i]);
     740      160284 :                         if (s == NULL) {
     741           0 :                                 talloc_free(ret);
     742           0 :                                 return NULL;
     743             :                         }
     744      160284 :                         s2 = talloc_asprintf_append(ret, "%s", s);
     745      160284 :                         talloc_free(s);
     746      160284 :                         if (s2 == NULL) {
     747           0 :                                 talloc_free(ret);
     748           0 :                                 return NULL;
     749             :                         }
     750      160284 :                         ret = s2;
     751             :                 }
     752       67146 :                 s = talloc_asprintf_append(ret, ")");
     753       67146 :                 if (s == NULL) {
     754           0 :                         talloc_free(ret);
     755           0 :                         return NULL;
     756             :                 }
     757       67146 :                 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       89470 :         case LDB_OP_PRESENT:
     816       89470 :                 ret = talloc_asprintf(mem_ctx, "(%s=*)", tree->u.present.attr);
     817       89470 :                 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   273123530 : 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   273123530 :         ret = callback(tree, private_context);
     853   273123530 :         if (ret != LDB_SUCCESS) {
     854           0 :                 return ret;
     855             :         }
     856             : 
     857   273123530 :         switch (tree->operation) {
     858    79349847 :         case LDB_OP_AND:
     859             :         case LDB_OP_OR:
     860   242783622 :                 for (i=0;i<tree->u.list.num_elements;i++) {
     861   163433775 :                         ret = ldb_parse_tree_walk(tree->u.list.elements[i], callback, private_context);
     862   163433775 :                         if (ret != LDB_SUCCESS) {
     863           0 :                                 return ret;
     864             :                         }
     865             :                 }
     866    79349847 :                 break;
     867     2874739 :         case LDB_OP_NOT:
     868     2874739 :                 ret = ldb_parse_tree_walk(tree->u.isnot.child, callback, private_context);
     869     2874739 :                 if (ret != LDB_SUCCESS) {
     870           0 :                         return ret;
     871             :                 }
     872     2874739 :                 break;
     873   190898944 :         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   190898944 :                 break;
     881             :         }
     882   273123530 :         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   161882952 : static int parse_tree_attr_replace(struct ldb_parse_tree *tree, void *private_context)
     894             : {
     895   161882952 :         struct parse_tree_attr_replace_ctx *ctx = private_context;
     896   161882952 :         switch (tree->operation) {
     897    29078980 :         case LDB_OP_EQUALITY:
     898             :         case LDB_OP_GREATER:
     899             :         case LDB_OP_LESS:
     900             :         case LDB_OP_APPROX:
     901    29078980 :                 if (ldb_attr_cmp(tree->u.equality.attr, ctx->attr) == 0) {
     902           0 :                         tree->u.equality.attr = ctx->replace;
     903             :                 }
     904    29078980 :                 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    83924634 :         case LDB_OP_PRESENT:
     911    83924634 :                 if (ldb_attr_cmp(tree->u.present.attr, ctx->attr) == 0) {
     912           0 :                         tree->u.present.attr = ctx->replace;
     913             :                 }
     914    83924634 :                 break;
     915     3357122 :         case LDB_OP_EXTENDED:
     916     6556422 :                 if (tree->u.extended.attr &&
     917     3357122 :                     ldb_attr_cmp(tree->u.extended.attr, ctx->attr) == 0) {
     918           0 :                         tree->u.extended.attr = ctx->replace;
     919             :                 }
     920     3357122 :                 break;
     921    45452438 :         default:
     922    45452438 :                 break;
     923             :         }
     924   161882952 :         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    70050062 : 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    70050062 :         ctx.attr    = attr;
     938    70050062 :         ctx.replace = replace;
     939             : 
     940    70050062 :         ldb_parse_tree_walk(tree, parse_tree_attr_replace, &ctx);
     941    70050062 : }
     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      145193 : 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      145193 :         nt = talloc(mem_ctx, struct ldb_parse_tree);
     954      145193 :         if (!nt) {
     955           0 :                 return NULL;
     956             :         }
     957             : 
     958      145193 :         *nt = *ot;
     959             : 
     960      145193 :         switch (ot->operation) {
     961       37048 :         case LDB_OP_AND:
     962             :         case LDB_OP_OR:
     963       37048 :                 nt->u.list.elements = talloc_array(nt, struct ldb_parse_tree *,
     964             :                                                    ot->u.list.num_elements);
     965       37048 :                 if (!nt->u.list.elements) {
     966           0 :                         talloc_free(nt);
     967           0 :                         return NULL;
     968             :                 }
     969             : 
     970      138221 :                 for (i=0;i<ot->u.list.num_elements;i++) {
     971      202346 :                         nt->u.list.elements[i] =
     972      200209 :                                 ldb_parse_tree_copy_shallow(nt->u.list.elements,
     973      101173 :                                                 ot->u.list.elements[i]);
     974      101173 :                         if (!nt->u.list.elements[i]) {
     975           0 :                                 talloc_free(nt);
     976           0 :                                 return NULL;
     977             :                         }
     978             :                 }
     979       37048 :                 break;
     980         853 :         case LDB_OP_NOT:
     981         935 :                 nt->u.isnot.child = ldb_parse_tree_copy_shallow(nt,
     982         853 :                                                         ot->u.isnot.child);
     983         853 :                 if (!nt->u.isnot.child) {
     984           0 :                         talloc_free(nt);
     985           0 :                         return NULL;
     986             :                 }
     987         853 :                 break;
     988      107292 :         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      107292 :                 break;
     996             :         }
     997             : 
     998      145193 :         return nt;
     999             : }
    1000             : 
    1001             : /* Get the attribute (if any) associated with the top node of a parse tree. */
    1002   525060336 : const char *ldb_parse_tree_get_attr(const struct ldb_parse_tree *tree)
    1003             : {
    1004   525060336 :         switch (tree->operation) {
    1005   283214719 :         case LDB_OP_AND:
    1006             :         case LDB_OP_OR:
    1007             :         case LDB_OP_NOT:
    1008   283214719 :                 return NULL;
    1009   194173835 :         case LDB_OP_EQUALITY:
    1010   194173835 :                 return tree->u.equality.attr;
    1011     3667437 :         case LDB_OP_SUBSTRING:
    1012     3667437 :                 return tree->u.substring.attr;
    1013     4529827 :         case LDB_OP_GREATER:
    1014             :         case LDB_OP_LESS:
    1015             :         case LDB_OP_APPROX:
    1016     4529827 :                 return tree->u.comparison.attr;
    1017    39453380 :         case LDB_OP_PRESENT:
    1018    39453380 :                 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