LCOV - code coverage report
Current view: top level - lib/ldb/common - ldb_parse.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 419 513 81.7 %
Date: 2021-09-23 10:06:22 Functions: 19 19 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    26695966 : 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    26695966 :         size_t slen = str?strlen(str):0;
      77             : 
      78    26695966 :         ret.data = (uint8_t *)talloc_size(mem_ctx, slen+1);
      79    26695966 :         ret.length = 0;
      80    26695966 :         if (ret.data == NULL) return ret;
      81             : 
      82   610175372 :         for (i=j=0;i<slen;i++) {
      83   583949985 :                 if (str[i] == '\\') {
      84             :                         uint8_t c;
      85             :                         bool ok;
      86             : 
      87   114036858 :                         ok = hex_byte(&str[i+1], &c);
      88   114036858 :                         if (!ok) {
      89           2 :                                 talloc_free(ret.data);
      90           2 :                                 memset(&ret, 0, sizeof(ret));
      91           2 :                                 return ret;
      92             :                         }
      93   114036856 :                         ((uint8_t *)ret.data)[j++] = c;
      94   114036856 :                         i += 2;
      95             :                 } else {
      96   469913127 :                         ((uint8_t *)ret.data)[j++] = str[i];
      97             :                 }
      98             :         }
      99    26695964 :         ret.length = j;
     100    26695964 :         ((uint8_t *)ret.data)[j] = 0;
     101             : 
     102    26695964 :         return ret;
     103             : }
     104             : 
     105   330781300 : static bool need_encode(unsigned char cval)
     106             : {
     107   338744524 :         if (cval < 0x20 || cval > 0x7E || strchr(" *()\\&|!\"", cval)) {
     108   223701124 :                 return true;
     109             :         }
     110   107080176 :         return false;
     111             : }
     112             : 
     113             : /*
     114             :    encode a blob as a RFC2254 binary string, escaping any
     115             :    non-printable or '\' characters
     116             : */
     117     9374207 : char *ldb_binary_encode(TALLOC_CTX *mem_ctx, struct ldb_val val)
     118             : {
     119             :         size_t i;
     120             :         char *ret;
     121     9374207 :         size_t len = val.length;
     122     9374207 :         unsigned char *buf = val.data;
     123             : 
     124   178746469 :         for (i=0;i<val.length;i++) {
     125   169372262 :                 if (need_encode(buf[i])) {
     126   114038222 :                         len += 2;
     127             :                 }
     128             :         }
     129     9374207 :         ret = talloc_array(mem_ctx, char, len+1);
     130     9374207 :         if (ret == NULL) return NULL;
     131             : 
     132     9153642 :         len = 0;
     133   178525904 :         for (i=0;i<val.length;i++) {
     134   171166214 :                 if (need_encode(buf[i])) {
     135   116225882 :                         snprintf(ret+len, 4, "\\%02X", buf[i]);
     136   114038222 :                         len += 3;
     137             :                 } else {
     138    55334040 :                         ret[len++] = buf[i];
     139             :                 }
     140             :         }
     141             : 
     142     9374207 :         ret[len] = 0;
     143             : 
     144     9374207 :         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      759310 : char *ldb_binary_encode_string(TALLOC_CTX *mem_ctx, const char *string)
     153             : {
     154             :         struct ldb_val val;
     155      759310 :         if (string == NULL) {
     156           0 :                 return NULL;
     157             :         }
     158      759310 :         val.data = discard_const_p(uint8_t, string);
     159      759310 :         val.length = strlen(string);
     160      759310 :         return ldb_binary_encode(mem_ctx, val);
     161             : }
     162             : 
     163             : /* find the first matching wildcard */
     164    24987959 : static char *ldb_parse_find_wildcard(char *value)
     165             : {
     166   159750616 :         while (*value) {
     167   139024811 :                 value = strpbrk(value, "\\*");
     168   139024811 :                 if (value == NULL) return NULL;
     169             : 
     170   114079527 :                 if (value[0] == '\\') {
     171   114036855 :                         if (value[1] == '\0') return NULL;
     172   114036855 :                         value += 2;
     173   114036855 :                         continue;
     174             :                 }
     175             : 
     176       42672 :                 if (value[0] == '*') return value;
     177             :         }
     178             : 
     179           2 :         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       21182 : static struct ldb_val **ldb_wildcard_decode(TALLOC_CTX *mem_ctx, const char *string)
     186             : {
     187       21182 :         struct ldb_val **ret = NULL;
     188       21182 :         unsigned int val = 0;
     189             :         char *wc, *str;
     190             : 
     191       21182 :         wc = talloc_strdup(mem_ctx, string);
     192       21182 :         if (wc == NULL) return NULL;
     193             : 
     194       79928 :         while (wc && *wc) {
     195       38068 :                 str = wc;
     196       38068 :                 wc = ldb_parse_find_wildcard(str);
     197       38068 :                 if (wc && *wc) {
     198       21490 :                         if (wc == str) {
     199       16819 :                                 wc++;
     200       16819 :                                 continue;
     201             :                         }
     202        4671 :                         *wc = 0;
     203        4671 :                         wc++;
     204             :                 }
     205             : 
     206       21249 :                 ret = talloc_realloc(mem_ctx, ret, struct ldb_val *, val + 2);
     207       21249 :                 if (ret == NULL) return NULL;
     208             : 
     209       21249 :                 ret[val] = talloc(mem_ctx, struct ldb_val);
     210       21249 :                 if (ret[val] == NULL) return NULL;
     211             : 
     212       21249 :                 *(ret[val]) = ldb_binary_decode(mem_ctx, str);
     213       21249 :                 if ((ret[val])->data == NULL) return NULL;
     214             : 
     215       21249 :                 val++;
     216             :         }
     217             : 
     218       21182 :         if (ret != NULL) {
     219       21182 :                 ret[val] = NULL;
     220             :         }
     221             : 
     222       21171 :         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     1739076 : 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     1739076 :         ret->operation = LDB_OP_EXTENDED;
     251     1739076 :         ret->u.extended.value = ldb_binary_decode(ret, value);
     252     1739076 :         if (ret->u.extended.value.data == NULL) goto failed;
     253             : 
     254     1739076 :         p1 = strchr(attr, ':');
     255     1739076 :         if (p1 == NULL) goto failed;
     256     1739076 :         p2 = strchr(p1+1, ':');
     257             : 
     258     1739076 :         *p1 = 0;
     259     1739076 :         if (p2) *p2 = 0;
     260             : 
     261     1739076 :         ret->u.extended.attr = attr;
     262     1739076 :         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     1739076 :                 ret->u.extended.dnAttributes = 0;
     272     1739076 :                 ret->u.extended.rule_id = talloc_strdup(ret, p1+1);
     273     1739076 :                 if (ret->u.extended.rule_id == NULL) goto failed;
     274             :         }
     275             : 
     276     1691709 :         return ret;
     277             : 
     278           0 : failed:
     279           0 :         talloc_free(ret);
     280           0 :         return NULL;
     281             : }
     282             : 
     283   108206423 : static enum ldb_parse_op ldb_parse_filtertype(TALLOC_CTX *mem_ctx, char **type, char **value, const char **s)
     284             : {
     285   108206423 :         enum ldb_parse_op filter = 0;
     286             :         char *name, *val, *k;
     287   108206423 :         const char *p = *s;
     288             :         const char *t, *t1;
     289             : 
     290             :         /* retrieve attributetype name */
     291   108206423 :         t = p;
     292             : 
     293   108206423 :         if (*p == '@') { /* for internal attributes the first char can be @ */
     294      545350 :                 p++;
     295             :         }
     296             : 
     297  1587424849 :         while ((isascii(*p) && isalnum((unsigned char)*p)) || (*p == '-') || (*p == '.')) { 
     298             :                 /* attribute names can only be alphanums */
     299  1391516917 :                 p++;
     300             :         }
     301             : 
     302   108206423 :         if (*p == ':') { /* but extended searches have : and . chars too */
     303     1739078 :                 p = strstr(p, ":=");
     304     1739078 :                 if (p == NULL) { /* malformed attribute name */
     305           2 :                         return 0;
     306             :                 }
     307             :         }
     308             : 
     309   108206421 :         t1 = p;
     310             : 
     311   108206421 :         while (isspace((unsigned char)*p)) p++;
     312             : 
     313   108206421 :         if (!strchr("=<>~:", *p)) {
     314           3 :                 return 0;
     315             :         }
     316             : 
     317             :         /* save name */
     318   108206418 :         name = (char *)talloc_memdup(mem_ctx, t, t1 - t + 1);
     319   108206418 :         if (name == NULL) return 0;
     320   108206418 :         name[t1 - t] = '\0';
     321             : 
     322             :         /* retrieve filtertype */
     323             : 
     324   108206418 :         if (*p == '=') {
     325   102505725 :                 filter = LDB_OP_EQUALITY;
     326     1746010 :         } else if (*p != '\0' && *(p + 1) == '=') {
     327     1746006 :                 switch (*p) {
     328        1274 :                 case '<':
     329        1274 :                         filter = LDB_OP_LESS;
     330        1274 :                         p++;
     331        1245 :                         break;
     332        5656 :                 case '>':
     333        5656 :                         filter = LDB_OP_GREATER;
     334        5656 :                         p++;
     335        5639 :                         break;
     336           0 :                 case '~':
     337           0 :                         filter = LDB_OP_APPROX;
     338           0 :                         p++;
     339           0 :                         break;
     340     1739076 :                 case ':':
     341     1739076 :                         filter = LDB_OP_EXTENDED;
     342     1739076 :                         p++;
     343     1691709 :                         break;
     344             :                 }
     345             :         }
     346   104204320 :         if (!filter) {
     347           4 :                 talloc_free(name);
     348           4 :                 return 0;
     349             :         }
     350   108206414 :         p++;
     351             : 
     352   108206414 :         while (isspace((unsigned char)*p)) p++;
     353             : 
     354             :         /* retrieve value */
     355   104204318 :         t = p;
     356             : 
     357   253288670 :         while (*p && ((*p != ')') || ((*p == ')') && (*(p - 1) == '\\')))) p++;
     358             : 
     359   108206414 :         val = (char *)talloc_memdup(mem_ctx, t, p - t + 1);
     360   108206414 :         if (val == NULL) {
     361           0 :                 talloc_free(name);
     362           0 :                 return 0;
     363             :         }
     364   108206414 :         val[p - t] = '\0';
     365             : 
     366   108206414 :         k = &(val[p - t]);
     367             : 
     368             :         /* remove trailing spaces from value */
     369   108206414 :         while ((k > val) && (isspace((unsigned char)*(k - 1)))) k--;
     370   108206414 :         *k = '\0';
     371             : 
     372   108206414 :         *type = name;
     373   108206414 :         *value = val;
     374   108206414 :         *s = p;
     375   108206414 :         return filter;
     376             : }
     377             : 
     378             : /*
     379             :   <simple> ::= <attributetype> <filtertype> <attributevalue>
     380             : */
     381   108206423 : 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   108206423 :         ret = talloc_zero(mem_ctx, struct ldb_parse_tree);
     388   108206423 :         if (!ret) {
     389           0 :                 errno = ENOMEM;
     390           0 :                 return NULL;
     391             :         }
     392             : 
     393   108206423 :         filtertype = ldb_parse_filtertype(ret, &attr, &value, s);
     394   108206423 :         if (!filtertype) {
     395           9 :                 talloc_free(ret);
     396           9 :                 return NULL;
     397             :         }
     398             : 
     399   108206414 :         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   106460408 :                 case LDB_OP_EQUALITY:
     407             : 
     408   106460408 :                         if (strcmp(value, "*") == 0) {
     409    81510517 :                                 ret->operation = LDB_OP_PRESENT;
     410    81510517 :                                 ret->u.present.attr = attr;
     411    81510517 :                                 break;
     412             :                         }
     413             : 
     414    24949891 :                         if (ldb_parse_find_wildcard(value) != NULL) {
     415       21182 :                                 ret->operation = LDB_OP_SUBSTRING;
     416       21182 :                                 ret->u.substring.attr = attr;
     417       21182 :                                 ret->u.substring.start_with_wildcard = 0;
     418       21182 :                                 ret->u.substring.end_with_wildcard = 0;
     419       21182 :                                 ret->u.substring.chunks = ldb_wildcard_decode(ret, value);
     420       21182 :                                 if (ret->u.substring.chunks == NULL){
     421           0 :                                         talloc_free(ret);
     422           0 :                                         return NULL;
     423             :                                 }
     424       21182 :                                 if (value[0] == '*')
     425       16819 :                                         ret->u.substring.start_with_wildcard = 1;
     426       21182 :                                 if (value[strlen(value) - 1] == '*')
     427        4604 :                                         ret->u.substring.end_with_wildcard = 1;
     428       21182 :                                 talloc_free(value);
     429             : 
     430       21182 :                                 break;
     431             :                         }
     432             : 
     433    24928709 :                         ret->operation = LDB_OP_EQUALITY;
     434    24928709 :                         ret->u.equality.attr = attr;
     435    24928709 :                         ret->u.equality.value = ldb_binary_decode(ret, value);
     436    24928709 :                         if (ret->u.equality.value.data == NULL) {
     437           2 :                                 talloc_free(ret);
     438           2 :                                 return NULL;
     439             :                         }
     440    24928707 :                         talloc_free(value);
     441    24928707 :                         break;
     442             : 
     443        5656 :                 case LDB_OP_GREATER:
     444        5656 :                         ret->operation = LDB_OP_GREATER;
     445        5656 :                         ret->u.comparison.attr = attr;
     446        5656 :                         ret->u.comparison.value = ldb_binary_decode(ret, value);
     447        5656 :                         if (ret->u.comparison.value.data == NULL) {
     448           0 :                                 talloc_free(ret);
     449           0 :                                 return NULL;
     450             :                         }
     451        5656 :                         talloc_free(value);
     452        5656 :                         break;
     453             : 
     454        1274 :                 case LDB_OP_LESS:
     455        1274 :                         ret->operation = LDB_OP_LESS;
     456        1274 :                         ret->u.comparison.attr = attr;
     457        1274 :                         ret->u.comparison.value = ldb_binary_decode(ret, value);
     458        1274 :                         if (ret->u.comparison.value.data == NULL) {
     459           0 :                                 talloc_free(ret);
     460           0 :                                 return NULL;
     461             :                         }
     462        1274 :                         talloc_free(value);
     463        1274 :                         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     1739076 :                 case LDB_OP_EXTENDED:
     477             : 
     478     1739076 :                         ret = ldb_parse_extended(ret, attr, value);
     479     1739076 :                         break;
     480             : 
     481           0 :                 default:
     482           0 :                         talloc_free(ret);
     483           0 :                         return NULL;
     484             :         }
     485             : 
     486   104204317 :         return ret;
     487             : }
     488             : 
     489             : 
     490             : /*
     491             :   parse a filterlist
     492             :   <and> ::= '&' <filterlist>
     493             :   <or> ::= '|' <filterlist>
     494             :   <filterlist> ::= <filter> | <filter> <filterlist>
     495             : */
     496    41871383 : 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    41871383 :         const char *p = *s;
     505             : 
     506    41871383 :         switch (*p) {
     507     2983632 :                 case '&':
     508     2983632 :                         op = LDB_OP_AND;
     509     2983632 :                         break;
     510    38813262 :                 case '|':
     511    38813262 :                         op = LDB_OP_OR;
     512    38813262 :                         break;
     513           0 :                 default:
     514           0 :                         return NULL;
     515             :         }
     516    41871383 :         p++;
     517             : 
     518    41871383 :         while (isspace((unsigned char)*p)) p++;
     519             : 
     520    41871383 :         ret = talloc(mem_ctx, struct ldb_parse_tree);
     521    41871383 :         if (!ret) {
     522           0 :                 errno = ENOMEM;
     523           0 :                 return NULL;
     524             :         }
     525             : 
     526    41871383 :         ret->operation = op;
     527    41871383 :         ret->u.list.num_elements = 1;
     528    41871383 :         ret->u.list.elements = talloc(ret, struct ldb_parse_tree *);
     529    41871383 :         if (!ret->u.list.elements) {
     530           0 :                 errno = ENOMEM;
     531           0 :                 talloc_free(ret);
     532           0 :                 return NULL;
     533             :         }
     534             : 
     535    82034402 :         ret->u.list.elements[0] =
     536    75585383 :                 ldb_parse_filter(ret->u.list.elements, &p, depth, max_depth);
     537    41871383 :         if (!ret->u.list.elements[0]) {
     538         118 :                 talloc_free(ret);
     539         118 :                 return NULL;
     540             :         }
     541             : 
     542    40162901 :         while (isspace((unsigned char)*p)) p++;
     543             : 
     544   119247840 :         while (*p) {
     545             :                 struct ldb_parse_tree **e;
     546    85533958 :                 if (*p == ')') {
     547    40162900 :                         break;
     548             :                 }
     549             : 
     550    43662695 :                 next = ldb_parse_filter(
     551    43662695 :                         ret->u.list.elements, &p, depth, max_depth);
     552    43662695 :                 if (next == NULL) {
     553             :                         /* an invalid filter element */
     554           2 :                         talloc_free(ret);
     555           2 :                         return NULL;
     556             :                 }
     557    43662693 :                 e = talloc_realloc(ret, ret->u.list.elements, 
     558             :                                      struct ldb_parse_tree *, 
     559             :                                      ret->u.list.num_elements + 1);
     560    43662693 :                 if (!e) {
     561           0 :                         errno = ENOMEM;
     562           0 :                         talloc_free(ret);
     563           0 :                         return NULL;
     564             :                 }
     565    43662693 :                 ret->u.list.elements = e;
     566    43662693 :                 ret->u.list.elements[ret->u.list.num_elements] = next;
     567    43662693 :                 ret->u.list.num_elements++;
     568    43662693 :                 while (isspace((unsigned char)*p)) p++;
     569             :         }
     570             : 
     571    41871263 :         *s = p;
     572             : 
     573    41871263 :         return ret;
     574             : }
     575             : 
     576             : 
     577             : /*
     578             :   <not> ::= '!' <filter>
     579             : */
     580      857546 : 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      857546 :         const char *p = *s;
     588             : 
     589      857546 :         if (*p != '!') {
     590           0 :                 return NULL;
     591             :         }
     592      857546 :         p++;
     593             : 
     594      857546 :         ret = talloc(mem_ctx, struct ldb_parse_tree);
     595      857546 :         if (!ret) {
     596           0 :                 errno = ENOMEM;
     597           0 :                 return NULL;
     598             :         }
     599             : 
     600      857546 :         ret->operation = LDB_OP_NOT;
     601      857546 :         ret->u.isnot.child = ldb_parse_filter(ret, &p, depth, max_depth);
     602      857546 :         if (!ret->u.isnot.child) {
     603          11 :                 talloc_free(ret);
     604          11 :                 return NULL;
     605             :         }
     606             : 
     607      857535 :         *s = p;
     608             : 
     609      857535 :         return ret;
     610             : }
     611             : 
     612             : /*
     613             :   parse a filtercomp
     614             :   <filtercomp> ::= <and> | <or> | <not> | <simple>
     615             : */
     616   140766772 : 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   140766772 :         const char *p = *s;
     624             : 
     625   140766772 :         while (isspace((unsigned char)*p)) p++;
     626             : 
     627   140766772 :         switch (*p) {
     628     3058121 :         case '&':
     629     3058121 :                 ret = ldb_parse_filterlist(mem_ctx, &p, depth, max_depth);
     630     3058121 :                 break;
     631             : 
     632    38813262 :         case '|':
     633    38813262 :                 ret = ldb_parse_filterlist(mem_ctx, &p, depth, max_depth);
     634    38813262 :                 break;
     635             : 
     636      857546 :         case '!':
     637      857546 :                 ret = ldb_parse_not(mem_ctx, &p, depth, max_depth);
     638      857546 :                 break;
     639             : 
     640           0 :         case '(':
     641             :         case ')':
     642           0 :                 return NULL;
     643             : 
     644    98037843 :         default:
     645    98037843 :                 ret = ldb_parse_simple(mem_ctx, &p);
     646             : 
     647             :         }
     648             : 
     649   140766772 :         *s = p;
     650   140766772 :         return ret;
     651             : }
     652             : 
     653             : /*
     654             :   <filter> ::= '(' <filtercomp> ')'
     655             : */
     656   140766773 : 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   140766773 :         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   140766773 :         if (depth > max_depth) {
     671           1 :                 return NULL;
     672             :         }
     673   140766772 :         depth++;
     674             : 
     675   140766772 :         if (*p != '(') {
     676           0 :                 return NULL;
     677             :         }
     678   140766772 :         p++;
     679             : 
     680   140766772 :         ret = ldb_parse_filtercomp(mem_ctx, &p, depth, max_depth);
     681             : 
     682   140766772 :         if (*p != ')') {
     683         132 :                 return NULL;
     684             :         }
     685   140766637 :         p++;
     686             : 
     687   260108722 :         while (isspace((unsigned char)*p)) {
     688           0 :                 p++;
     689             :         }
     690             : 
     691   140766637 :         *s = p;
     692             : 
     693   140766637 :         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    64543729 : struct ldb_parse_tree *ldb_parse_tree(TALLOC_CTX *mem_ctx, const char *s)
     703             : {
     704    64543729 :         unsigned depth = 0;
     705             : 
     706    64543729 :         while (s && isspace((unsigned char)*s)) s++;
     707             : 
     708    64543729 :         if (s == NULL || *s == 0) {
     709    38089982 :                 s = "(|(objectClass=*)(distinguishedName=*))";
     710             :         }
     711             : 
     712    64543729 :         if (*s == '(') {
     713    54375149 :                 return ldb_parse_filter(
     714             :                         mem_ctx, &s, depth, LDB_MAX_PARSE_TREE_DEPTH);
     715             :         }
     716             : 
     717    10168580 :         return ldb_parse_simple(mem_ctx, &s);
     718             : }
     719             : 
     720             : 
     721             : /*
     722             :   construct a ldap parse filter given a parse tree
     723             : */
     724      211116 : 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      211116 :         if (tree == NULL) {
     730           0 :                 return NULL;
     731             :         }
     732             : 
     733      211116 :         switch (tree->operation) {
     734       63014 :         case LDB_OP_AND:
     735             :         case LDB_OP_OR:
     736       63014 :                 ret = talloc_asprintf(mem_ctx, "(%c", tree->operation==LDB_OP_AND?'&':'|');
     737       63014 :                 if (ret == NULL) return NULL;
     738      205088 :                 for (i=0;i<tree->u.list.num_elements;i++) {
     739      142074 :                         s = ldb_filter_from_tree(mem_ctx, tree->u.list.elements[i]);
     740      142074 :                         if (s == NULL) {
     741           0 :                                 talloc_free(ret);
     742           0 :                                 return NULL;
     743             :                         }
     744      142074 :                         s2 = talloc_asprintf_append(ret, "%s", s);
     745      142074 :                         talloc_free(s);
     746      142074 :                         if (s2 == NULL) {
     747           0 :                                 talloc_free(ret);
     748           0 :                                 return NULL;
     749             :                         }
     750      142074 :                         ret = s2;
     751             :                 }
     752       63014 :                 s = talloc_asprintf_append(ret, ")");
     753       63014 :                 if (s == NULL) {
     754           0 :                         talloc_free(ret);
     755           0 :                         return NULL;
     756             :                 }
     757       63014 :                 return s;
     758       10757 :         case LDB_OP_NOT:
     759       10757 :                 s = ldb_filter_from_tree(mem_ctx, tree->u.isnot.child);
     760       10757 :                 if (s == NULL) return NULL;
     761             : 
     762       10757 :                 ret = talloc_asprintf(mem_ctx, "(!%s)", s);
     763       10757 :                 talloc_free(s);
     764       10757 :                 return ret;
     765       50353 :         case LDB_OP_EQUALITY:
     766       50353 :                 s = ldb_binary_encode(mem_ctx, tree->u.equality.value);
     767       50353 :                 if (s == NULL) return NULL;
     768       50353 :                 ret = talloc_asprintf(mem_ctx, "(%s=%s)", 
     769       22167 :                                       tree->u.equality.attr, s);
     770       50353 :                 talloc_free(s);
     771       50353 :                 return ret;
     772         108 :         case LDB_OP_SUBSTRING:
     773         108 :                 ret = talloc_asprintf(mem_ctx, "(%s=%s", tree->u.substring.attr,
     774         108 :                                       tree->u.substring.start_with_wildcard?"*":"");
     775         108 :                 if (ret == NULL) return NULL;
     776         216 :                 for (i = 0; tree->u.substring.chunks && tree->u.substring.chunks[i]; i++) {
     777         108 :                         s2 = ldb_binary_encode(mem_ctx, *(tree->u.substring.chunks[i]));
     778         108 :                         if (s2 == NULL) {
     779           0 :                                 talloc_free(ret);
     780           0 :                                 return NULL;
     781             :                         }
     782         191 :                         if (tree->u.substring.chunks[i+1] ||
     783         108 :                             tree->u.substring.end_with_wildcard) {
     784         108 :                                 s = talloc_asprintf_append(ret, "%s*", s2);
     785             :                         } else {
     786           0 :                                 s = talloc_asprintf_append(ret, "%s", s2);
     787             :                         }
     788         108 :                         if (s == NULL) {
     789           0 :                                 talloc_free(ret);
     790           0 :                                 return NULL;
     791             :                         }
     792         108 :                         ret = s;
     793             :                 }
     794         108 :                 s = talloc_asprintf_append(ret, ")");
     795         108 :                 if (s == NULL) {
     796           0 :                         talloc_free(ret);
     797           0 :                         return NULL;
     798             :                 }
     799         108 :                 ret = s;
     800         108 :                 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       81457 :         case LDB_OP_PRESENT:
     816       81457 :                 ret = talloc_asprintf(mem_ctx, "(%s=*)", tree->u.present.attr);
     817       81457 :                 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        5414 :         case LDB_OP_EXTENDED:
     826        5414 :                 s = ldb_binary_encode(mem_ctx, tree->u.extended.value);
     827        5414 :                 if (s == NULL) return NULL;
     828       21656 :                 ret = talloc_asprintf(mem_ctx, "(%s%s%s%s:=%s)", 
     829        5414 :                                       tree->u.extended.attr?tree->u.extended.attr:"", 
     830        5414 :                                       tree->u.extended.dnAttributes?":dn":"",
     831        5414 :                                       tree->u.extended.rule_id?":":"", 
     832        5414 :                                       tree->u.extended.rule_id?tree->u.extended.rule_id:"", 
     833             :                                       s);
     834        5414 :                 talloc_free(s);
     835        5414 :                 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   496383306 : 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   496383306 :         ret = callback(tree, private_context);
     853   496383306 :         if (ret != LDB_SUCCESS) {
     854           0 :                 return ret;
     855             :         }
     856             : 
     857   496383306 :         switch (tree->operation) {
     858   133080205 :         case LDB_OP_AND:
     859             :         case LDB_OP_OR:
     860   419246906 :                 for (i=0;i<tree->u.list.num_elements;i++) {
     861   286166701 :                         ret = ldb_parse_tree_walk(tree->u.list.elements[i], callback, private_context);
     862   286166701 :                         if (ret != LDB_SUCCESS) {
     863           0 :                                 return ret;
     864             :                         }
     865             :                 }
     866   133080205 :                 break;
     867     3517239 :         case LDB_OP_NOT:
     868     3517239 :                 ret = ldb_parse_tree_walk(tree->u.isnot.child, callback, private_context);
     869     3517239 :                 if (ret != LDB_SUCCESS) {
     870           0 :                         return ret;
     871             :                 }
     872     3460623 :                 break;
     873   337190689 :         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   337190689 :                 break;
     881             :         }
     882   473731517 :         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   427995996 : static int parse_tree_attr_replace(struct ldb_parse_tree *tree, void *private_context)
     894             : {
     895   427995996 :         struct parse_tree_attr_replace_ctx *ctx = private_context;
     896   427995996 :         switch (tree->operation) {
     897    65332840 :         case LDB_OP_EQUALITY:
     898             :         case LDB_OP_GREATER:
     899             :         case LDB_OP_LESS:
     900             :         case LDB_OP_APPROX:
     901    65332840 :                 if (ldb_attr_cmp(tree->u.equality.attr, ctx->attr) == 0) {
     902           0 :                         tree->u.equality.attr = ctx->replace;
     903             :                 }
     904    64406338 :                 break;
     905      445383 :         case LDB_OP_SUBSTRING:
     906      445383 :                 if (ldb_attr_cmp(tree->u.substring.attr, ctx->attr) == 0) {
     907           0 :                         tree->u.substring.attr = ctx->replace;
     908             :                 }
     909      445383 :                 break;
     910   237860482 :         case LDB_OP_PRESENT:
     911   237860482 :                 if (ldb_attr_cmp(tree->u.present.attr, ctx->attr) == 0) {
     912           0 :                         tree->u.present.attr = ctx->replace;
     913             :                 }
     914   224482162 :                 break;
     915     3925634 :         case LDB_OP_EXTENDED:
     916     7410726 :                 if (tree->u.extended.attr &&
     917     3925634 :                     ldb_attr_cmp(tree->u.extended.attr, ctx->attr) == 0) {
     918           0 :                         tree->u.extended.attr = ctx->replace;
     919             :                 }
     920     3823108 :                 break;
     921   114810685 :         default:
     922   114810685 :                 break;
     923             :         }
     924   427995996 :         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   184513196 : 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   184513196 :         ctx.attr    = attr;
     938   184513196 :         ctx.replace = replace;
     939             : 
     940   184513196 :         ldb_parse_tree_walk(tree, parse_tree_attr_replace, &ctx);
     941   184513196 : }
     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    14541279 : 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    14541279 :         nt = talloc(mem_ctx, struct ldb_parse_tree);
     954    14541279 :         if (!nt) {
     955           0 :                 return NULL;
     956             :         }
     957             : 
     958    14541279 :         *nt = *ot;
     959             : 
     960    14541279 :         switch (ot->operation) {
     961     4033607 :         case LDB_OP_AND:
     962             :         case LDB_OP_OR:
     963     4033607 :                 nt->u.list.elements = talloc_array(nt, struct ldb_parse_tree *,
     964             :                                                    ot->u.list.num_elements);
     965     4033607 :                 if (!nt->u.list.elements) {
     966           0 :                         talloc_free(nt);
     967           0 :                         return NULL;
     968             :                 }
     969             : 
     970    11996113 :                 for (i=0;i<ot->u.list.num_elements;i++) {
     971    16354220 :                         nt->u.list.elements[i] =
     972    14829534 :                                 ldb_parse_tree_copy_shallow(nt->u.list.elements,
     973     8177110 :                                                 ot->u.list.elements[i]);
     974     8177110 :                         if (!nt->u.list.elements[i]) {
     975           0 :                                 talloc_free(nt);
     976           0 :                                 return NULL;
     977             :                         }
     978             :                 }
     979     3819003 :                 break;
     980       47029 :         case LDB_OP_NOT:
     981       57712 :                 nt->u.isnot.child = ldb_parse_tree_copy_shallow(nt,
     982       47029 :                                                         ot->u.isnot.child);
     983       47029 :                 if (!nt->u.isnot.child) {
     984           0 :                         talloc_free(nt);
     985           0 :                         return NULL;
     986             :                 }
     987       46855 :                 break;
     988     9909842 :         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     9909842 :                 break;
     996             :         }
     997             : 
     998    13775700 :         return nt;
     999             : }

Generated by: LCOV version 1.13