LCOV - code coverage report
Current view: top level - lib/ldb/common - ldb_match.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 350 402 87.1 %
Date: 2024-02-28 12:06:22 Functions: 18 19 94.7 %

          Line data    Source code
       1             : /* 
       2             :    ldb database library
       3             : 
       4             :    Copyright (C) Andrew Tridgell  2004-2005
       5             :    Copyright (C) Simo Sorce            2005
       6             : 
       7             :      ** NOTE! The following LGPL license applies to the ldb
       8             :      ** library. This does NOT imply that all of Samba is released
       9             :      ** under the LGPL
      10             :    
      11             :    This library is free software; you can redistribute it and/or
      12             :    modify it under the terms of the GNU Lesser General Public
      13             :    License as published by the Free Software Foundation; either
      14             :    version 3 of the License, or (at your option) any later version.
      15             : 
      16             :    This library is distributed in the hope that it will be useful,
      17             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      19             :    Lesser General Public License for more details.
      20             : 
      21             :    You should have received a copy of the GNU Lesser General Public
      22             :    License along with this library; if not, see <http://www.gnu.org/licenses/>.
      23             : */
      24             : 
      25             : /*
      26             :  *  Name: ldb
      27             :  *
      28             :  *  Component: ldb expression matching
      29             :  *
      30             :  *  Description: ldb expression matching 
      31             :  *
      32             :  *  Author: Andrew Tridgell
      33             :  */
      34             : 
      35             : #include "ldb_private.h"
      36             : #include "dlinklist.h"
      37             : #include "ldb_handlers.h"
      38             : 
      39             : /*
      40             :   check if the scope matches in a search result
      41             : */
      42   230798509 : int ldb_match_scope(struct ldb_context *ldb,
      43             :                     struct ldb_dn *base,
      44             :                     struct ldb_dn *dn,
      45             :                     enum ldb_scope scope)
      46             : {
      47   230798509 :         int ret = 0;
      48             : 
      49   230798509 :         if (base == NULL || dn == NULL) {
      50           0 :                 return 1;
      51             :         }
      52             : 
      53   230798509 :         switch (scope) {
      54          32 :         case LDB_SCOPE_BASE:
      55          32 :                 if (ldb_dn_compare(base, dn) == 0) {
      56          32 :                         ret = 1;
      57             :                 }
      58           0 :                 break;
      59             : 
      60      343428 :         case LDB_SCOPE_ONELEVEL:
      61      343428 :                 if (ldb_dn_get_comp_num(dn) == (ldb_dn_get_comp_num(base) + 1)) {
      62       71055 :                         if (ldb_dn_compare_base(base, dn) == 0) {
      63       33553 :                                 ret = 1;
      64             :                         }
      65             :                 }
      66      342815 :                 break;
      67             :                 
      68   230455049 :         case LDB_SCOPE_SUBTREE:
      69             :         default:
      70   230455049 :                 if (ldb_dn_compare_base(base, dn) == 0) {
      71   137143393 :                         ret = 1;
      72             :                 }
      73   227475421 :                 break;
      74             :         }
      75             : 
      76   227818236 :         return ret;
      77             : }
      78             : 
      79             : 
      80             : /*
      81             :   match if node is present
      82             : */
      83    54167518 : static int ldb_match_present(struct ldb_context *ldb, 
      84             :                              const struct ldb_message *msg,
      85             :                              const struct ldb_parse_tree *tree,
      86             :                              enum ldb_scope scope, bool *matched)
      87             : {
      88     1966660 :         const struct ldb_schema_attribute *a;
      89     1966660 :         struct ldb_message_element *el;
      90             : 
      91    54167518 :         if (ldb_attr_dn(tree->u.present.attr) == 0) {
      92     5655094 :                 *matched = true;
      93     5655094 :                 return LDB_SUCCESS;
      94             :         }
      95             : 
      96    48512424 :         el = ldb_msg_find_element(msg, tree->u.present.attr);
      97    48512424 :         if (el == NULL) {
      98     6304448 :                 *matched = false;
      99     6304448 :                 return LDB_SUCCESS;
     100             :         }
     101             : 
     102    42207976 :         a = ldb_schema_attribute_by_name(ldb, el->name);
     103    42207976 :         if (!a) {
     104           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     105             :         }
     106             : 
     107    42207976 :         if (a->syntax->operator_fn) {
     108             :                 unsigned int i;
     109      450279 :                 for (i = 0; i < el->num_values; i++) {
     110      450279 :                         int ret = a->syntax->operator_fn(ldb, LDB_OP_PRESENT, a, &el->values[i], NULL, matched);
     111      450279 :                         if (ret != LDB_SUCCESS) return ret;
     112      450279 :                         if (*matched) return LDB_SUCCESS;
     113             :                 }
     114           0 :                 *matched = false;
     115           0 :                 return LDB_SUCCESS;
     116             :         }
     117             : 
     118    41757697 :         *matched = true;
     119    41757697 :         return LDB_SUCCESS;
     120             : }
     121             : 
     122     5550554 : static int ldb_match_comparison(struct ldb_context *ldb, 
     123             :                                 const struct ldb_message *msg,
     124             :                                 const struct ldb_parse_tree *tree,
     125             :                                 enum ldb_scope scope,
     126             :                                 enum ldb_parse_op comp_op, bool *matched)
     127             : {
     128         912 :         unsigned int i;
     129         912 :         struct ldb_message_element *el;
     130         912 :         const struct ldb_schema_attribute *a;
     131             : 
     132             :         /* FIXME: APPROX comparison not handled yet */
     133     5550554 :         if (comp_op == LDB_OP_APPROX) {
     134           0 :                 return LDB_ERR_INAPPROPRIATE_MATCHING;
     135             :         }
     136             : 
     137     5550554 :         el = ldb_msg_find_element(msg, tree->u.comparison.attr);
     138     5550554 :         if (el == NULL) {
     139      123627 :                 *matched = false;
     140      123627 :                 return LDB_SUCCESS;
     141             :         }
     142             : 
     143     5426927 :         a = ldb_schema_attribute_by_name(ldb, el->name);
     144     5426927 :         if (!a) {
     145           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     146             :         }
     147             : 
     148     8291678 :         for (i = 0; i < el->num_values; i++) {
     149     5426953 :                 if (a->syntax->operator_fn) {
     150         842 :                         int ret;
     151        1844 :                         ret = a->syntax->operator_fn(ldb, comp_op, a, &el->values[i], &tree->u.comparison.value, matched);
     152        1844 :                         if (ret != LDB_SUCCESS) return ret;
     153        1844 :                         if (*matched) return LDB_SUCCESS;
     154             :                 } else {
     155     5425109 :                         int ret = a->syntax->comparison_fn(ldb, ldb, &el->values[i], &tree->u.comparison.value);
     156             : 
     157     5425109 :                         if (ret == 0) {
     158        1965 :                                 *matched = true;
     159        1965 :                                 return LDB_SUCCESS;
     160             :                         }
     161     5423144 :                         if (ret > 0 && comp_op == LDB_OP_GREATER) {
     162     2558366 :                                 *matched = true;
     163     2558366 :                                 return LDB_SUCCESS;
     164             :                         }
     165     2864778 :                         if (ret < 0 && comp_op == LDB_OP_LESS) {
     166         753 :                                 *matched = true;
     167         753 :                                 return LDB_SUCCESS;
     168             :                         }
     169             :                 }
     170             :         }
     171             : 
     172     2864725 :         *matched = false;
     173     2864725 :         return LDB_SUCCESS;
     174             : }
     175             : 
     176             : /*
     177             :   match a simple leaf node
     178             : */
     179   279562703 : static int ldb_match_equality(struct ldb_context *ldb, 
     180             :                               const struct ldb_message *msg,
     181             :                               const struct ldb_parse_tree *tree,
     182             :                               enum ldb_scope scope,
     183             :                               bool *matched)
     184             : {
     185     6112939 :         unsigned int i;
     186     6112939 :         struct ldb_message_element *el;
     187     6112939 :         const struct ldb_schema_attribute *a;
     188     6112939 :         struct ldb_dn *valuedn;
     189     6112939 :         int ret;
     190             : 
     191   279562703 :         if (ldb_attr_dn(tree->u.equality.attr) == 0) {
     192      182972 :                 valuedn = ldb_dn_from_ldb_val(ldb, ldb, &tree->u.equality.value);
     193      182972 :                 if (valuedn == NULL) {
     194           0 :                         return LDB_ERR_INVALID_DN_SYNTAX;
     195             :                 }
     196             : 
     197      182972 :                 ret = ldb_dn_compare(msg->dn, valuedn);
     198             : 
     199      182972 :                 talloc_free(valuedn);
     200             : 
     201      182972 :                 *matched = (ret == 0);
     202      182972 :                 return LDB_SUCCESS;
     203             :         }
     204             : 
     205             :         /* TODO: handle the "*" case derived from an extended search
     206             :            operation without the attribute type defined */
     207   279379731 :         el = ldb_msg_find_element(msg, tree->u.equality.attr);
     208   279379731 :         if (el == NULL) {
     209   129439040 :                 *matched = false;
     210   129439040 :                 return LDB_SUCCESS;
     211             :         }
     212             : 
     213   149940691 :         a = ldb_schema_attribute_by_name(ldb, el->name);
     214   149940691 :         if (a == NULL) {
     215           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     216             :         }
     217             : 
     218   281575548 :         for (i=0;i<el->num_values;i++) {
     219   259189659 :                 if (a->syntax->operator_fn) {
     220    28275586 :                         ret = a->syntax->operator_fn(ldb, LDB_OP_EQUALITY, a,
     221    27747035 :                                                      &tree->u.equality.value, &el->values[i], matched);
     222    27747035 :                         if (ret != LDB_SUCCESS) return ret;
     223    27747035 :                         if (*matched) return LDB_SUCCESS;
     224             :                 } else {
     225   231442624 :                         if (a->syntax->comparison_fn(ldb, ldb, &tree->u.equality.value,
     226   231442624 :                                                      &el->values[i]) == 0) {
     227   101032062 :                                 *matched = true;
     228   101032062 :                                 return LDB_SUCCESS;
     229             :                         }
     230             :                 }
     231             :         }
     232             : 
     233    22385889 :         *matched = false;
     234    22385889 :         return LDB_SUCCESS;
     235             : }
     236             : 
     237     3222864 : static int ldb_wildcard_compare(struct ldb_context *ldb,
     238             :                                 const struct ldb_parse_tree *tree,
     239             :                                 const struct ldb_val value, bool *matched)
     240             : {
     241         197 :         const struct ldb_schema_attribute *a;
     242         197 :         struct ldb_val val;
     243         197 :         struct ldb_val cnk;
     244         197 :         struct ldb_val *chunk;
     245     3222864 :         uint8_t *save_p = NULL;
     246     3222864 :         unsigned int c = 0;
     247             : 
     248     3222864 :         if (tree->operation != LDB_OP_SUBSTRING) {
     249           1 :                 *matched = false;
     250           1 :                 return LDB_ERR_INAPPROPRIATE_MATCHING;
     251             :         }
     252             : 
     253     3222863 :         a = ldb_schema_attribute_by_name(ldb, tree->u.substring.attr);
     254     3222863 :         if (!a) {
     255           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     256             :         }
     257             : 
     258     3222863 :         if (tree->u.substring.chunks == NULL) {
     259           3 :                 *matched = false;
     260           3 :                 return LDB_SUCCESS;
     261             :         }
     262             : 
     263             :         /* No need to just copy this value for a binary match */
     264     3222860 :         if (a->syntax->canonicalise_fn != ldb_handler_copy) {
     265     2397430 :                 if (a->syntax->canonicalise_fn(ldb, ldb, &value, &val) != 0) {
     266           0 :                         return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     267             :                 }
     268             : 
     269             :                 /*
     270             :                  * Only set save_p if we allocate (call
     271             :                  * a->syntax->canonicalise_fn()), as we
     272             :                  * talloc_free(save_p) below to clean up
     273             :                  */
     274     2397430 :                 save_p = val.data;
     275             :         } else {
     276      825430 :                 val = value;
     277             :         }
     278             : 
     279     3222860 :         cnk.data = NULL;
     280             : 
     281     3222860 :         if ( ! tree->u.substring.start_with_wildcard ) {
     282     2367105 :                 uint8_t *cnk_to_free = NULL;
     283             : 
     284     2367105 :                 chunk = tree->u.substring.chunks[c];
     285             :                 /* No need to just copy this value for a binary match */
     286     2367105 :                 if (a->syntax->canonicalise_fn != ldb_handler_copy) {
     287     2365682 :                         if (a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) {
     288           0 :                                 goto mismatch;
     289             :                         }
     290             : 
     291     2365682 :                         cnk_to_free = cnk.data;
     292             :                 } else {
     293        1423 :                         cnk = *chunk;
     294             :                 }
     295             : 
     296             :                 /* This deals with wildcard prefix searches on binary attributes (eg objectGUID) */
     297     2367105 :                 if (cnk.length > val.length) {
     298       58515 :                         TALLOC_FREE(cnk_to_free);
     299       58515 :                         goto mismatch;
     300             :                 }
     301             :                 /*
     302             :                  * Empty strings are returned as length 0. Ensure
     303             :                  * we can cope with this.
     304             :                  */
     305     2308590 :                 if (cnk.length == 0) {
     306           0 :                         TALLOC_FREE(cnk_to_free);
     307           0 :                         goto mismatch;
     308             :                 }
     309             : 
     310     2308590 :                 if (memcmp((char *)val.data, (char *)cnk.data, cnk.length) != 0) {
     311     1852267 :                         TALLOC_FREE(cnk_to_free);
     312     1852267 :                         goto mismatch;
     313             :                 }
     314             : 
     315      456323 :                 val.length -= cnk.length;
     316      456323 :                 val.data += cnk.length;
     317      456323 :                 c++;
     318      456323 :                 TALLOC_FREE(cnk_to_free);
     319      456323 :                 cnk.data = NULL;
     320             :         }
     321             : 
     322     1312839 :         while (tree->u.substring.chunks[c]) {
     323          76 :                 uint8_t *p;
     324      855822 :                 uint8_t *cnk_to_free = NULL;
     325             : 
     326      855822 :                 chunk = tree->u.substring.chunks[c];
     327             :                 /* No need to just copy this value for a binary match */
     328      855822 :                 if (a->syntax->canonicalise_fn != ldb_handler_copy) {
     329       31811 :                         if (a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) {
     330           0 :                                 goto mismatch;
     331             :                         }
     332             : 
     333       31811 :                         cnk_to_free = cnk.data;
     334             :                 } else {
     335      824011 :                         cnk = *chunk;
     336             :                 }
     337             :                 /*
     338             :                  * Empty strings are returned as length 0. Ensure
     339             :                  * we can cope with this.
     340             :                  */
     341      855822 :                 if (cnk.length == 0) {
     342           0 :                         TALLOC_FREE(cnk_to_free);
     343           0 :                         goto mismatch;
     344             :                 }
     345      855822 :                 if (cnk.length > val.length) {
     346       22098 :                         TALLOC_FREE(cnk_to_free);
     347       22098 :                         goto mismatch;
     348             :                 }
     349             : 
     350      833724 :                 if ( (tree->u.substring.chunks[c + 1]) == NULL &&
     351      834309 :                      (! tree->u.substring.end_with_wildcard) ) {
     352             :                         /*
     353             :                          * The last bit, after all the asterisks, must match
     354             :                          * exactly the last bit of the string.
     355             :                          */
     356          23 :                         int cmp;
     357        9096 :                         p = val.data + val.length - cnk.length;
     358        9096 :                         cmp = memcmp(p,
     359        9096 :                                      cnk.data,
     360             :                                      cnk.length);
     361        9096 :                         TALLOC_FREE(cnk_to_free);
     362             : 
     363        9096 :                         if (cmp != 0) {
     364        8397 :                                 goto mismatch;
     365             :                         }
     366             :                 } else {
     367             :                         /*
     368             :                          * Values might be binary blobs. Don't use string
     369             :                          * search, but memory search instead.
     370             :                          */
     371      824628 :                         p = memmem((const void *)val.data, val.length,
     372      824628 :                                    (const void *)cnk.data, cnk.length);
     373      824628 :                         if (p == NULL) {
     374      824566 :                                 TALLOC_FREE(cnk_to_free);
     375      824566 :                                 goto mismatch;
     376             :                         }
     377             :                         /* move val to the end of the match */
     378          62 :                         p += cnk.length;
     379          62 :                         val.length -= (p - val.data);
     380          62 :                         val.data = p;
     381          62 :                         TALLOC_FREE(cnk_to_free);
     382             :                 }
     383         748 :                 c++;
     384             :         }
     385             : 
     386      457017 :         talloc_free(save_p);
     387      457017 :         *matched = true;
     388      457017 :         return LDB_SUCCESS;
     389             : 
     390     2765843 : mismatch:
     391     2765843 :         *matched = false;
     392     2765843 :         talloc_free(save_p);
     393     2765843 :         return LDB_SUCCESS;
     394             : }
     395             : 
     396             : /*
     397             :   match a simple leaf node
     398             : */
     399     3814627 : static int ldb_match_substring(struct ldb_context *ldb, 
     400             :                                const struct ldb_message *msg,
     401             :                                const struct ldb_parse_tree *tree,
     402             :                                enum ldb_scope scope, bool *matched)
     403             : {
     404         175 :         unsigned int i;
     405         175 :         struct ldb_message_element *el;
     406             : 
     407     3814627 :         el = ldb_msg_find_element(msg, tree->u.substring.attr);
     408     3814627 :         if (el == NULL) {
     409      591954 :                 *matched = false;
     410      591954 :                 return LDB_SUCCESS;
     411             :         }
     412             : 
     413     5988513 :         for (i = 0; i < el->num_values; i++) {
     414         197 :                 int ret;
     415     3222831 :                 ret = ldb_wildcard_compare(ldb, tree, el->values[i], matched);
     416     3222831 :                 if (ret != LDB_SUCCESS) return ret;
     417     3222831 :                 if (*matched) return LDB_SUCCESS;
     418             :         }
     419             : 
     420     2765682 :         *matched = false;
     421     2765682 :         return LDB_SUCCESS;
     422             : }
     423             : 
     424             : 
     425             : /*
     426             :   bitwise and/or comparator depending on oid
     427             : */
     428     4497054 : static int ldb_comparator_bitmask(const char *oid, const struct ldb_val *v1, const struct ldb_val *v2,
     429             :                                   bool *matched)
     430             : {
     431      135433 :         uint64_t i1, i2;
     432      135433 :         char ibuf[100];
     433     4497054 :         char *endptr = NULL;
     434             : 
     435     4497054 :         if (v1->length >= sizeof(ibuf)-1) {
     436           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     437             :         }
     438     4497054 :         memcpy(ibuf, (char *)v1->data, v1->length);
     439     4497054 :         ibuf[v1->length] = 0;
     440     4497054 :         i1 = strtoull(ibuf, &endptr, 0);
     441     4497054 :         if (endptr != NULL) {
     442     4497054 :                 if (endptr == ibuf || *endptr != 0) {
     443           0 :                         return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     444             :                 }
     445             :         }
     446             : 
     447     4497054 :         if (v2->length >= sizeof(ibuf)-1) {
     448           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     449             :         }
     450     4497054 :         endptr = NULL;
     451     4497054 :         memcpy(ibuf, (char *)v2->data, v2->length);
     452     4497054 :         ibuf[v2->length] = 0;
     453     4497054 :         i2 = strtoull(ibuf, &endptr, 0);
     454     4497054 :         if (endptr != NULL) {
     455     4497054 :                 if (endptr == ibuf || *endptr != 0) {
     456           0 :                         return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     457             :                 }
     458             :         }
     459     4497054 :         if (strcmp(LDB_OID_COMPARATOR_AND, oid) == 0) {
     460     4495371 :                 *matched = ((i1 & i2) == i2);
     461        1683 :         } else if (strcmp(LDB_OID_COMPARATOR_OR, oid) == 0) {
     462        1683 :                 *matched = ((i1 & i2) != 0);
     463             :         } else {
     464           0 :                 return LDB_ERR_INAPPROPRIATE_MATCHING;
     465             :         }
     466     4361621 :         return LDB_SUCCESS;
     467             : }
     468             : 
     469     4502215 : static int ldb_match_bitmask(struct ldb_context *ldb,
     470             :                              const char *oid,
     471             :                              const struct ldb_message *msg,
     472             :                              const char *attribute_to_match,
     473             :                              const struct ldb_val *value_to_match,
     474             :                              bool *matched)
     475             : {
     476      135480 :         unsigned int i;
     477      135480 :         struct ldb_message_element *el;
     478             : 
     479             :         /* find the message element */
     480     4502215 :         el = ldb_msg_find_element(msg, attribute_to_match);
     481     4502215 :         if (el == NULL) {
     482        5175 :                 *matched = false;
     483        5175 :                 return LDB_SUCCESS;
     484             :         }
     485             : 
     486     6540160 :         for (i=0;i<el->num_values;i++) {
     487      135433 :                 int ret;
     488     4497054 :                 struct ldb_val *v = &el->values[i];
     489             : 
     490     4497054 :                 ret = ldb_comparator_bitmask(oid, v, value_to_match, matched);
     491     4497054 :                 if (ret != LDB_SUCCESS) {
     492           0 :                         return ret;
     493             :                 }
     494     4497054 :                 if (*matched) {
     495     2378482 :                         return LDB_SUCCESS;
     496             :                 }
     497             :         }
     498             : 
     499     2043106 :         *matched = false;
     500     2043106 :         return LDB_SUCCESS;
     501             : }
     502             : 
     503             : /*
     504             :   always return false
     505             : */
     506        3373 : static int ldb_comparator_false(struct ldb_context *ldb,
     507             :                                 const char *oid,
     508             :                                 const struct ldb_message *msg,
     509             :                                 const char *attribute_to_match,
     510             :                                 const struct ldb_val *value_to_match,
     511             :                                 bool *matched)
     512             : {
     513        3373 :         *matched = false;
     514        3373 :         return LDB_SUCCESS;
     515             : }
     516             : 
     517             : 
     518    17021935 : static const struct ldb_extended_match_rule *ldb_find_extended_match_rule(struct ldb_context *ldb,
     519             :                                                                           const char *oid)
     520             : {
     521      622553 :         struct ldb_extended_match_entry *extended_match_rule;
     522             : 
     523    17021935 :         for (extended_match_rule = ldb->extended_match_rules;
     524    60356462 :              extended_match_rule;
     525    43334527 :              extended_match_rule = extended_match_rule->next) {
     526    55884548 :                 if (strcmp(extended_match_rule->rule->oid, oid) == 0) {
     527    12550021 :                         return extended_match_rule->rule;
     528             :                 }
     529             :         }
     530             : 
     531     4392735 :         return NULL;
     532             : }
     533             : 
     534             : 
     535             : /*
     536             :   extended match, handles things like bitops
     537             : */
     538    12550024 : static int ldb_match_extended(struct ldb_context *ldb, 
     539             :                               const struct ldb_message *msg,
     540             :                               const struct ldb_parse_tree *tree,
     541             :                               enum ldb_scope scope, bool *matched)
     542             : {
     543      543374 :         const struct ldb_extended_match_rule *rule;
     544             : 
     545    12550024 :         if (tree->u.extended.dnAttributes) {
     546             :                 /* FIXME: We really need to find out what this ":dn" part in
     547             :                  * an extended match means and how to handle it. For now print
     548             :                  * only a warning to have s3 winbind and other tools working
     549             :                  * against us. - Matthias */
     550         912 :                 ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb: dnAttributes extended match not supported yet");
     551             :         }
     552    12550024 :         if (tree->u.extended.rule_id == NULL) {
     553           0 :                 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: no-rule extended matches not supported yet");
     554           0 :                 return LDB_ERR_INAPPROPRIATE_MATCHING;
     555             :         }
     556    12550024 :         if (tree->u.extended.attr == NULL) {
     557           0 :                 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: no-attribute extended matches not supported yet");
     558           0 :                 return LDB_ERR_INAPPROPRIATE_MATCHING;
     559             :         }
     560             : 
     561    12550024 :         rule = ldb_find_extended_match_rule(ldb, tree->u.extended.rule_id);
     562    12550024 :         if (rule == NULL) {
     563           3 :                 *matched = false;
     564           3 :                 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: unknown extended rule_id %s",
     565           3 :                           tree->u.extended.rule_id);
     566           3 :                 return LDB_SUCCESS;
     567             :         }
     568             : 
     569    12550021 :         return rule->callback(ldb, rule->oid, msg,
     570    12006647 :                               tree->u.extended.attr,
     571             :                               &tree->u.extended.value, matched);
     572             : }
     573             : 
     574   748571538 : static bool ldb_must_suppress_match(const struct ldb_message *msg,
     575             :                                     const struct ldb_parse_tree *tree)
     576             : {
     577   748571538 :         const char *attr = NULL;
     578   748571538 :         struct ldb_message_element *el = NULL;
     579             : 
     580   748571538 :         attr = ldb_parse_tree_get_attr(tree);
     581   748571538 :         if (attr == NULL) {
     582   395989678 :                 return false;
     583             :         }
     584             : 
     585             :         /* find the message element */
     586   343100819 :         el = ldb_msg_find_element(msg, attr);
     587   343100819 :         if (el == NULL) {
     588   139113344 :                 return false;
     589             :         }
     590             : 
     591   200803693 :         return ldb_msg_element_is_inaccessible(el);
     592             : }
     593             : 
     594             : /*
     595             :   Check if a particular message will match the given filter
     596             : 
     597             :   set *matched to true if it matches, false otherwise
     598             : 
     599             :   returns LDB_SUCCESS or an error
     600             : 
     601             :   this is a recursive function, and does short-circuit evaluation
     602             :  */
     603   761121562 : int ldb_match_message(struct ldb_context *ldb,
     604             :                       const struct ldb_message *msg,
     605             :                       const struct ldb_parse_tree *tree,
     606             :                       enum ldb_scope scope, bool *matched)
     607             : {
     608    18105101 :         unsigned int i;
     609    18105101 :         int ret;
     610             : 
     611   761121562 :         *matched = false;
     612             : 
     613   761121562 :         if (scope != LDB_SCOPE_BASE && ldb_dn_is_special(msg->dn)) {
     614             :                 /* don't match special records except on base searches */
     615           0 :                 return LDB_SUCCESS;
     616             :         }
     617             : 
     618             :         /*
     619             :          * Suppress matches on confidential attributes (handled
     620             :          * manually in extended matches as these can do custom things
     621             :          * like read other parts of the DB or other attributes).
     622             :          */
     623   761121562 :         if (tree->operation != LDB_OP_EXTENDED) {
     624   748571538 :                 if (ldb_must_suppress_match(msg, tree)) {
     625        5417 :                         return LDB_SUCCESS;
     626             :                 }
     627             :         }
     628             : 
     629   761116145 :         switch (tree->operation) {
     630   135508057 :         case LDB_OP_AND:
     631   384987584 :                 for (i=0;i<tree->u.list.num_elements;i++) {
     632   269599119 :                         ret = ldb_match_message(ldb, msg, tree->u.list.elements[i], scope, matched);
     633   269599119 :                         if (ret != LDB_SUCCESS) return ret;
     634   269599104 :                         if (!*matched) return LDB_SUCCESS;
     635             :                 }
     636   115388465 :                 *matched = true;
     637   115388465 :                 return LDB_SUCCESS;
     638             : 
     639   133307576 :         case LDB_OP_OR:
     640   177990177 :                 for (i=0;i<tree->u.list.num_elements;i++) {
     641   171929047 :                         ret = ldb_match_message(ldb, msg, tree->u.list.elements[i], scope, matched);
     642   171929047 :                         if (ret != LDB_SUCCESS) return ret;
     643   171929047 :                         if (*matched) return LDB_SUCCESS;
     644             :                 }
     645     6061130 :                 *matched = false;
     646     6061130 :                 return LDB_SUCCESS;
     647             : 
     648   130086209 :         case LDB_OP_NOT:
     649   130086209 :                 ret = ldb_match_message(ldb, msg, tree->u.isnot.child, scope, matched);
     650   130086209 :                 if (ret != LDB_SUCCESS) return ret;
     651   130086209 :                 *matched = ! *matched;
     652   130086209 :                 return LDB_SUCCESS;
     653             : 
     654   279562703 :         case LDB_OP_EQUALITY:
     655   279562703 :                 return ldb_match_equality(ldb, msg, tree, scope, matched);
     656             : 
     657     3814627 :         case LDB_OP_SUBSTRING:
     658     3814627 :                 return ldb_match_substring(ldb, msg, tree, scope, matched);
     659             : 
     660     5485658 :         case LDB_OP_GREATER:
     661     5485658 :                 return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_GREATER, matched);
     662             : 
     663       64896 :         case LDB_OP_LESS:
     664       64896 :                 return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_LESS, matched);
     665             : 
     666    54167518 :         case LDB_OP_PRESENT:
     667    54167518 :                 return ldb_match_present(ldb, msg, tree, scope, matched);
     668             : 
     669           0 :         case LDB_OP_APPROX:
     670           0 :                 return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_APPROX, matched);
     671             : 
     672    12550024 :         case LDB_OP_EXTENDED:
     673    12550024 :                 return ldb_match_extended(ldb, msg, tree, scope, matched);
     674             :         }
     675             : 
     676           0 :         return LDB_ERR_INAPPROPRIATE_MATCHING;
     677             : }
     678             : 
     679             : /*
     680             :   return 0 if the given parse tree matches the given message. Assumes
     681             :   the message is in sorted order
     682             : 
     683             :   return 1 if it matches, and 0 if it doesn't match
     684             : */
     685             : 
     686           0 : int ldb_match_msg(struct ldb_context *ldb,
     687             :                   const struct ldb_message *msg,
     688             :                   const struct ldb_parse_tree *tree,
     689             :                   struct ldb_dn *base,
     690             :                   enum ldb_scope scope)
     691             : {
     692           0 :         bool matched;
     693           0 :         int ret;
     694             : 
     695           0 :         if ( ! ldb_match_scope(ldb, base, msg->dn, scope) ) {
     696           0 :                 return 0;
     697             :         }
     698             : 
     699           0 :         ret = ldb_match_message(ldb, msg, tree, scope, &matched);
     700           0 :         if (ret != LDB_SUCCESS) {
     701             :                 /* to match the old API, we need to consider this a
     702             :                    failure to match */
     703           0 :                 return 0;
     704             :         }
     705           0 :         return matched?1:0;
     706             : }
     707             : 
     708         254 : int ldb_match_msg_error(struct ldb_context *ldb,
     709             :                         const struct ldb_message *msg,
     710             :                         const struct ldb_parse_tree *tree,
     711             :                         struct ldb_dn *base,
     712             :                         enum ldb_scope scope,
     713             :                         bool *matched)
     714             : {
     715         254 :         if ( ! ldb_match_scope(ldb, base, msg->dn, scope) ) {
     716           0 :                 *matched = false;
     717           0 :                 return LDB_SUCCESS;
     718             :         }
     719             : 
     720         254 :         return ldb_match_message(ldb, msg, tree, scope, matched);
     721             : }
     722             : 
     723      890085 : int ldb_match_msg_objectclass(const struct ldb_message *msg,
     724             :                               const char *objectclass)
     725             : {
     726       29180 :         unsigned int i;
     727      890085 :         struct ldb_message_element *el = ldb_msg_find_element(msg, "objectClass");
     728      890085 :         if (!el) {
     729           0 :                 return 0;
     730             :         }
     731     3560325 :         for (i=0; i < el->num_values; i++) {
     732     3560312 :                 if (ldb_attr_cmp((const char *)el->values[i].data, objectclass) == 0) {
     733      860892 :                         return 1;
     734             :                 }
     735             :         }
     736          13 :         return 0;
     737             : }
     738             : 
     739      748381 : _PRIVATE_ int ldb_register_extended_match_rules(struct ldb_context *ldb)
     740             : {
     741       13279 :         struct ldb_extended_match_rule *bitmask_and;
     742       13279 :         struct ldb_extended_match_rule *bitmask_or;
     743       13279 :         struct ldb_extended_match_rule *always_false;
     744       13279 :         int ret;
     745             : 
     746             :         /* Register bitmask-and match */
     747      748381 :         bitmask_and = talloc_zero(ldb, struct ldb_extended_match_rule);
     748      748381 :         if (bitmask_and == NULL) {
     749           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     750             :         }
     751             : 
     752      748381 :         bitmask_and->oid = LDB_OID_COMPARATOR_AND;
     753      748381 :         bitmask_and->callback = ldb_match_bitmask;
     754             : 
     755      748381 :         ret = ldb_register_extended_match_rule(ldb, bitmask_and);
     756      748381 :         if (ret != LDB_SUCCESS) {
     757           0 :                 return ret;
     758             :         }
     759             : 
     760             :         /* Register bitmask-or match */
     761      748381 :         bitmask_or = talloc_zero(ldb, struct ldb_extended_match_rule);
     762      748381 :         if (bitmask_or == NULL) {
     763           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     764             :         }
     765             : 
     766      748381 :         bitmask_or->oid = LDB_OID_COMPARATOR_OR;
     767      748381 :         bitmask_or->callback = ldb_match_bitmask;
     768             : 
     769      748381 :         ret = ldb_register_extended_match_rule(ldb, bitmask_or);
     770      748381 :         if (ret != LDB_SUCCESS) {
     771           0 :                 return ret;
     772             :         }
     773             : 
     774             :         /* Register always-false match */
     775      748381 :         always_false = talloc_zero(ldb, struct ldb_extended_match_rule);
     776      748381 :         if (always_false == NULL) {
     777           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     778             :         }
     779             : 
     780      748381 :         always_false->oid = SAMBA_LDAP_MATCH_ALWAYS_FALSE;
     781      748381 :         always_false->callback = ldb_comparator_false;
     782             : 
     783      748381 :         ret = ldb_register_extended_match_rule(ldb, always_false);
     784      748381 :         if (ret != LDB_SUCCESS) {
     785           0 :                 return ret;
     786             :         }
     787             : 
     788      735102 :         return LDB_SUCCESS;
     789             : }
     790             : 
     791             : /*
     792             :   register a new ldb extended matching rule
     793             : */
     794     4471911 : int ldb_register_extended_match_rule(struct ldb_context *ldb,
     795             :                                      const struct ldb_extended_match_rule *rule)
     796             : {
     797       79179 :         const struct ldb_extended_match_rule *lookup_rule;
     798       79179 :         struct ldb_extended_match_entry *entry;
     799             : 
     800     4471911 :         lookup_rule = ldb_find_extended_match_rule(ldb, rule->oid);
     801     4471911 :         if (lookup_rule) {
     802           0 :                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
     803             :         }
     804             : 
     805     4471911 :         entry = talloc_zero(ldb, struct ldb_extended_match_entry);
     806     4471911 :         if (!entry) {
     807           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     808             :         }
     809     4471911 :         entry->rule = rule;
     810     4471911 :         DLIST_ADD_END(ldb->extended_match_rules, entry);
     811             : 
     812     4392732 :         return LDB_SUCCESS;
     813             : }
     814             : 
     815      400694 : int ldb_register_redact_callback(struct ldb_context *ldb,
     816             :                                  ldb_redact_fn redact_fn,
     817             :                                  struct ldb_module *module)
     818             : {
     819      400694 :         if (ldb->redact.callback != NULL) {
     820           0 :                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
     821             :         }
     822             : 
     823      400694 :         ldb->redact.callback = redact_fn;
     824      400694 :         ldb->redact.module = module;
     825      400694 :         return LDB_SUCCESS;
     826             : }

Generated by: LCOV version 1.14