LCOV - code coverage report
Current view: top level - lib/ldb/common - ldb_match.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 350 402 87.1 %
Date: 2024-04-21 15:09:00 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   233057536 : 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   233057536 :         int ret = 0;
      48             : 
      49   233057536 :         if (base == NULL || dn == NULL) {
      50           0 :                 return 1;
      51             :         }
      52             : 
      53   233057536 :         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      342708 :         case LDB_SCOPE_ONELEVEL:
      61      342708 :                 if (ldb_dn_get_comp_num(dn) == (ldb_dn_get_comp_num(base) + 1)) {
      62       70446 :                         if (ldb_dn_compare_base(base, dn) == 0) {
      63       33253 :                                 ret = 1;
      64             :                         }
      65             :                 }
      66      341896 :                 break;
      67             :                 
      68   232714796 :         case LDB_SCOPE_SUBTREE:
      69             :         default:
      70   232714796 :                 if (ldb_dn_compare_base(base, dn) == 0) {
      71   138797706 :                         ret = 1;
      72             :                 }
      73   229736762 :                 break;
      74             :         }
      75             : 
      76   230078658 :         return ret;
      77             : }
      78             : 
      79             : 
      80             : /*
      81             :   match if node is present
      82             : */
      83    54551404 : 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     1968744 :         const struct ldb_schema_attribute *a;
      89     1968744 :         struct ldb_message_element *el;
      90             : 
      91    54551404 :         if (ldb_attr_dn(tree->u.present.attr) == 0) {
      92     5703630 :                 *matched = true;
      93     5703630 :                 return LDB_SUCCESS;
      94             :         }
      95             : 
      96    48847774 :         el = ldb_msg_find_element(msg, tree->u.present.attr);
      97    48847774 :         if (el == NULL) {
      98     6341687 :                 *matched = false;
      99     6341687 :                 return LDB_SUCCESS;
     100             :         }
     101             : 
     102    42506087 :         a = ldb_schema_attribute_by_name(ldb, el->name);
     103    42506087 :         if (!a) {
     104           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     105             :         }
     106             : 
     107    42506087 :         if (a->syntax->operator_fn) {
     108             :                 unsigned int i;
     109      455287 :                 for (i = 0; i < el->num_values; i++) {
     110      455287 :                         int ret = a->syntax->operator_fn(ldb, LDB_OP_PRESENT, a, &el->values[i], NULL, matched);
     111      455287 :                         if (ret != LDB_SUCCESS) return ret;
     112      455287 :                         if (*matched) return LDB_SUCCESS;
     113             :                 }
     114           0 :                 *matched = false;
     115           0 :                 return LDB_SUCCESS;
     116             :         }
     117             : 
     118    42050800 :         *matched = true;
     119    42050800 :         return LDB_SUCCESS;
     120             : }
     121             : 
     122     5948193 : 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        2596 :         unsigned int i;
     129        2596 :         struct ldb_message_element *el;
     130        2596 :         const struct ldb_schema_attribute *a;
     131             : 
     132             :         /* FIXME: APPROX comparison not handled yet */
     133     5948193 :         if (comp_op == LDB_OP_APPROX) {
     134           0 :                 return LDB_ERR_INAPPROPRIATE_MATCHING;
     135             :         }
     136             : 
     137     5948193 :         el = ldb_msg_find_element(msg, tree->u.comparison.attr);
     138     5948193 :         if (el == NULL) {
     139      123677 :                 *matched = false;
     140      123677 :                 return LDB_SUCCESS;
     141             :         }
     142             : 
     143     5824516 :         a = ldb_schema_attribute_by_name(ldb, el->name);
     144     5824516 :         if (!a) {
     145           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     146             :         }
     147             : 
     148     9035129 :         for (i = 0; i < el->num_values; i++) {
     149     5824529 :                 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     5822685 :                         int ret = a->syntax->comparison_fn(ldb, ldb, &el->values[i], &tree->u.comparison.value);
     156             : 
     157     5822685 :                         if (ret == 0) {
     158        1948 :                                 *matched = true;
     159        1948 :                                 return LDB_SUCCESS;
     160             :                         }
     161     5820737 :                         if (ret > 0 && comp_op == LDB_OP_GREATER) {
     162     2608474 :                                 *matched = true;
     163     2608474 :                                 return LDB_SUCCESS;
     164             :                         }
     165     3212263 :                         if (ret < 0 && comp_op == LDB_OP_LESS) {
     166        2376 :                                 *matched = true;
     167        2376 :                                 return LDB_SUCCESS;
     168             :                         }
     169             :                 }
     170             :         }
     171             : 
     172     3210600 :         *matched = false;
     173     3210600 :         return LDB_SUCCESS;
     174             : }
     175             : 
     176             : /*
     177             :   match a simple leaf node
     178             : */
     179   282433350 : 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     6109649 :         unsigned int i;
     186     6109649 :         struct ldb_message_element *el;
     187     6109649 :         const struct ldb_schema_attribute *a;
     188     6109649 :         struct ldb_dn *valuedn;
     189     6109649 :         int ret;
     190             : 
     191   282433350 :         if (ldb_attr_dn(tree->u.equality.attr) == 0) {
     192      185473 :                 valuedn = ldb_dn_from_ldb_val(ldb, ldb, &tree->u.equality.value);
     193      185473 :                 if (valuedn == NULL) {
     194           0 :                         return LDB_ERR_INVALID_DN_SYNTAX;
     195             :                 }
     196             : 
     197      185473 :                 ret = ldb_dn_compare(msg->dn, valuedn);
     198             : 
     199      185473 :                 talloc_free(valuedn);
     200             : 
     201      185473 :                 *matched = (ret == 0);
     202      185473 :                 return LDB_SUCCESS;
     203             :         }
     204             : 
     205             :         /* TODO: handle the "*" case derived from an extended search
     206             :            operation without the attribute type defined */
     207   282247877 :         el = ldb_msg_find_element(msg, tree->u.equality.attr);
     208   282247877 :         if (el == NULL) {
     209   130773210 :                 *matched = false;
     210   130773210 :                 return LDB_SUCCESS;
     211             :         }
     212             : 
     213   151474667 :         a = ldb_schema_attribute_by_name(ldb, el->name);
     214   151474667 :         if (a == NULL) {
     215           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     216             :         }
     217             : 
     218   284595293 :         for (i=0;i<el->num_values;i++) {
     219   262020344 :                 if (a->syntax->operator_fn) {
     220    28398291 :                         ret = a->syntax->operator_fn(ldb, LDB_OP_EQUALITY, a,
     221    27874704 :                                                      &tree->u.equality.value, &el->values[i], matched);
     222    27874704 :                         if (ret != LDB_SUCCESS) return ret;
     223    27874704 :                         if (*matched) return LDB_SUCCESS;
     224             :                 } else {
     225   234145640 :                         if (a->syntax->comparison_fn(ldb, ldb, &tree->u.equality.value,
     226   234145640 :                                                      &el->values[i]) == 0) {
     227   102254695 :                                 *matched = true;
     228   102254695 :                                 return LDB_SUCCESS;
     229             :                         }
     230             :                 }
     231             :         }
     232             : 
     233    22574949 :         *matched = false;
     234    22574949 :         return LDB_SUCCESS;
     235             : }
     236             : 
     237     3115620 : 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         304 :         const struct ldb_schema_attribute *a;
     242         304 :         struct ldb_val val;
     243         304 :         struct ldb_val cnk;
     244         304 :         struct ldb_val *chunk;
     245     3115620 :         uint8_t *save_p = NULL;
     246     3115620 :         unsigned int c = 0;
     247             : 
     248     3115620 :         if (tree->operation != LDB_OP_SUBSTRING) {
     249           1 :                 *matched = false;
     250           1 :                 return LDB_ERR_INAPPROPRIATE_MATCHING;
     251             :         }
     252             : 
     253     3115619 :         a = ldb_schema_attribute_by_name(ldb, tree->u.substring.attr);
     254     3115619 :         if (!a) {
     255           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     256             :         }
     257             : 
     258     3115619 :         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     3115616 :         if (a->syntax->canonicalise_fn != ldb_handler_copy) {
     265     2398404 :                 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     2398404 :                 save_p = val.data;
     275             :         } else {
     276      717212 :                 val = value;
     277             :         }
     278             : 
     279     3115616 :         cnk.data = NULL;
     280             : 
     281     3115616 :         if ( ! tree->u.substring.start_with_wildcard ) {
     282     2367175 :                 uint8_t *cnk_to_free = NULL;
     283             : 
     284     2367175 :                 chunk = tree->u.substring.chunks[c];
     285             :                 /* No need to just copy this value for a binary match */
     286     2367175 :                 if (a->syntax->canonicalise_fn != ldb_handler_copy) {
     287     2365970 :                         if (a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) {
     288           0 :                                 goto mismatch;
     289             :                         }
     290             : 
     291     2365970 :                         cnk_to_free = cnk.data;
     292             :                 } else {
     293        1205 :                         cnk = *chunk;
     294             :                 }
     295             : 
     296             :                 /* This deals with wildcard prefix searches on binary attributes (eg objectGUID) */
     297     2367175 :                 if (cnk.length > val.length) {
     298       58512 :                         TALLOC_FREE(cnk_to_free);
     299       58512 :                         goto mismatch;
     300             :                 }
     301             :                 /*
     302             :                  * Empty strings are returned as length 0. Ensure
     303             :                  * we can cope with this.
     304             :                  */
     305     2308663 :                 if (cnk.length == 0) {
     306           0 :                         TALLOC_FREE(cnk_to_free);
     307           0 :                         goto mismatch;
     308             :                 }
     309             : 
     310     2308663 :                 if (memcmp((char *)val.data, (char *)cnk.data, cnk.length) != 0) {
     311     1852402 :                         TALLOC_FREE(cnk_to_free);
     312     1852402 :                         goto mismatch;
     313             :                 }
     314             : 
     315      456261 :                 val.length -= cnk.length;
     316      456261 :                 val.data += cnk.length;
     317      456261 :                 c++;
     318      456261 :                 TALLOC_FREE(cnk_to_free);
     319      456261 :                 cnk.data = NULL;
     320             :         }
     321             : 
     322     1205470 :         while (tree->u.substring.chunks[c]) {
     323         143 :                 uint8_t *p;
     324      748497 :                 uint8_t *cnk_to_free = NULL;
     325             : 
     326      748497 :                 chunk = tree->u.substring.chunks[c];
     327             :                 /* No need to just copy this value for a binary match */
     328      748497 :                 if (a->syntax->canonicalise_fn != ldb_handler_copy) {
     329       32487 :                         if (a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) {
     330           0 :                                 goto mismatch;
     331             :                         }
     332             : 
     333       32487 :                         cnk_to_free = cnk.data;
     334             :                 } else {
     335      716010 :                         cnk = *chunk;
     336             :                 }
     337             :                 /*
     338             :                  * Empty strings are returned as length 0. Ensure
     339             :                  * we can cope with this.
     340             :                  */
     341      748497 :                 if (cnk.length == 0) {
     342           0 :                         TALLOC_FREE(cnk_to_free);
     343           0 :                         goto mismatch;
     344             :                 }
     345      748497 :                 if (cnk.length > val.length) {
     346       22710 :                         TALLOC_FREE(cnk_to_free);
     347       22710 :                         goto mismatch;
     348             :                 }
     349             : 
     350      725787 :                 if ( (tree->u.substring.chunks[c + 1]) == NULL &&
     351      726408 :                      (! 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          45 :                         int cmp;
     357        9199 :                         p = val.data + val.length - cnk.length;
     358        9199 :                         cmp = memcmp(p,
     359        9199 :                                      cnk.data,
     360             :                                      cnk.length);
     361        9199 :                         TALLOC_FREE(cnk_to_free);
     362             : 
     363        9199 :                         if (cmp != 0) {
     364        8484 :                                 goto mismatch;
     365             :                         }
     366             :                 } else {
     367             :                         /*
     368             :                          * Values might be binary blobs. Don't use string
     369             :                          * search, but memory search instead.
     370             :                          */
     371      716588 :                         p = memmem((const void *)val.data, val.length,
     372      716588 :                                    (const void *)cnk.data, cnk.length);
     373      716588 :                         if (p == NULL) {
     374      716535 :                                 TALLOC_FREE(cnk_to_free);
     375      716535 :                                 goto mismatch;
     376             :                         }
     377             :                         /* move val to the end of the match */
     378          53 :                         p += cnk.length;
     379          53 :                         val.length -= (p - val.data);
     380          53 :                         val.data = p;
     381          53 :                         TALLOC_FREE(cnk_to_free);
     382             :                 }
     383         694 :                 c++;
     384             :         }
     385             : 
     386      456973 :         talloc_free(save_p);
     387      456973 :         *matched = true;
     388      456973 :         return LDB_SUCCESS;
     389             : 
     390     2658643 : mismatch:
     391     2658643 :         *matched = false;
     392     2658643 :         talloc_free(save_p);
     393     2658643 :         return LDB_SUCCESS;
     394             : }
     395             : 
     396             : /*
     397             :   match a simple leaf node
     398             : */
     399     3709404 : 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         249 :         unsigned int i;
     405         249 :         struct ldb_message_element *el;
     406             : 
     407     3709404 :         el = ldb_msg_find_element(msg, tree->u.substring.attr);
     408     3709404 :         if (el == NULL) {
     409      593897 :                 *matched = false;
     410      593897 :                 return LDB_SUCCESS;
     411             :         }
     412             : 
     413     5774147 :         for (i = 0; i < el->num_values; i++) {
     414         271 :                 int ret;
     415     3115587 :                 ret = ldb_wildcard_compare(ldb, tree, el->values[i], matched);
     416     3115587 :                 if (ret != LDB_SUCCESS) return ret;
     417     3115587 :                 if (*matched) return LDB_SUCCESS;
     418             :         }
     419             : 
     420     2658560 :         *matched = false;
     421     2658560 :         return LDB_SUCCESS;
     422             : }
     423             : 
     424             : 
     425             : /*
     426             :   bitwise and/or comparator depending on oid
     427             : */
     428     4564640 : 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     4564640 :         char *endptr = NULL;
     434             : 
     435     4564640 :         if (v1->length >= sizeof(ibuf)-1) {
     436           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     437             :         }
     438     4564640 :         memcpy(ibuf, (char *)v1->data, v1->length);
     439     4564640 :         ibuf[v1->length] = 0;
     440     4564640 :         i1 = strtoull(ibuf, &endptr, 0);
     441     4564640 :         if (endptr != NULL) {
     442     4564640 :                 if (endptr == ibuf || *endptr != 0) {
     443           0 :                         return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     444             :                 }
     445             :         }
     446             : 
     447     4564640 :         if (v2->length >= sizeof(ibuf)-1) {
     448           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     449             :         }
     450     4564640 :         endptr = NULL;
     451     4564640 :         memcpy(ibuf, (char *)v2->data, v2->length);
     452     4564640 :         ibuf[v2->length] = 0;
     453     4564640 :         i2 = strtoull(ibuf, &endptr, 0);
     454     4564640 :         if (endptr != NULL) {
     455     4564640 :                 if (endptr == ibuf || *endptr != 0) {
     456           0 :                         return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     457             :                 }
     458             :         }
     459     4564640 :         if (strcmp(LDB_OID_COMPARATOR_AND, oid) == 0) {
     460     4562924 :                 *matched = ((i1 & i2) == i2);
     461        1716 :         } else if (strcmp(LDB_OID_COMPARATOR_OR, oid) == 0) {
     462        1716 :                 *matched = ((i1 & i2) != 0);
     463             :         } else {
     464           0 :                 return LDB_ERR_INAPPROPRIATE_MATCHING;
     465             :         }
     466     4429207 :         return LDB_SUCCESS;
     467             : }
     468             : 
     469     4569754 : 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     4569754 :         el = ldb_msg_find_element(msg, attribute_to_match);
     481     4569754 :         if (el == NULL) {
     482        5121 :                 *matched = false;
     483        5121 :                 return LDB_SUCCESS;
     484             :         }
     485             : 
     486     6639899 :         for (i=0;i<el->num_values;i++) {
     487      135433 :                 int ret;
     488     4564640 :                 struct ldb_val *v = &el->values[i];
     489             : 
     490     4564640 :                 ret = ldb_comparator_bitmask(oid, v, value_to_match, matched);
     491     4564640 :                 if (ret != LDB_SUCCESS) {
     492           0 :                         return ret;
     493             :                 }
     494     4564640 :                 if (*matched) {
     495     2413922 :                         return LDB_SUCCESS;
     496             :                 }
     497             :         }
     498             : 
     499     2075259 :         *matched = false;
     500     2075259 :         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    17293318 : static const struct ldb_extended_match_rule *ldb_find_extended_match_rule(struct ldb_context *ldb,
     519             :                                                                           const char *oid)
     520             : {
     521      628834 :         struct ldb_extended_match_entry *extended_match_rule;
     522             : 
     523    17293318 :         for (extended_match_rule = ldb->extended_match_rules;
     524    61367250 :              extended_match_rule;
     525    44073932 :              extended_match_rule = extended_match_rule->next) {
     526    56844447 :                 if (strcmp(extended_match_rule->rule->oid, oid) == 0) {
     527    12770515 :                         return extended_match_rule->rule;
     528             :                 }
     529             :         }
     530             : 
     531     4437486 :         return NULL;
     532             : }
     533             : 
     534             : 
     535             : /*
     536             :   extended match, handles things like bitops
     537             : */
     538    12770518 : 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      543517 :         const struct ldb_extended_match_rule *rule;
     544             : 
     545    12770518 :         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    12770518 :         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    12770518 :         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    12770518 :         rule = ldb_find_extended_match_rule(ldb, tree->u.extended.rule_id);
     562    12770518 :         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    12770515 :         return rule->callback(ldb, rule->oid, msg,
     570    12226998 :                               tree->u.extended.attr,
     571             :                               &tree->u.extended.value, matched);
     572             : }
     573             : 
     574   756423398 : static bool ldb_must_suppress_match(const struct ldb_message *msg,
     575             :                                     const struct ldb_parse_tree *tree)
     576             : {
     577   756423398 :         const char *attr = NULL;
     578   756423398 :         struct ldb_message_element *el = NULL;
     579             : 
     580   756423398 :         attr = ldb_parse_tree_get_attr(tree);
     581   756423398 :         if (attr == NULL) {
     582   400294697 :                 return false;
     583             :         }
     584             : 
     585             :         /* find the message element */
     586   346647779 :         el = ldb_msg_find_element(msg, attr);
     587   346647779 :         if (el == NULL) {
     588   140530669 :                 return false;
     589             :         }
     590             : 
     591   202926214 :         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   769193916 : 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    18105677 :         unsigned int i;
     609    18105677 :         int ret;
     610             : 
     611   769193916 :         *matched = false;
     612             : 
     613   769193916 :         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   769193916 :         if (tree->operation != LDB_OP_EXTENDED) {
     624   756423398 :                 if (ldb_must_suppress_match(msg, tree)) {
     625        5428 :                         return LDB_SUCCESS;
     626             :                 }
     627             :         }
     628             : 
     629   769188488 :         switch (tree->operation) {
     630   137030538 :         case LDB_OP_AND:
     631   389218685 :                 for (i=0;i<tree->u.list.num_elements;i++) {
     632   272540880 :                         ret = ldb_match_message(ldb, msg, tree->u.list.elements[i], scope, matched);
     633   272540880 :                         if (ret != LDB_SUCCESS) return ret;
     634   272540865 :                         if (!*matched) return LDB_SUCCESS;
     635             :                 }
     636   116677805 :                 *matched = true;
     637   116677805 :                 return LDB_SUCCESS;
     638             : 
     639   134650764 :         case LDB_OP_OR:
     640   179582681 :                 for (i=0;i<tree->u.list.num_elements;i++) {
     641   173519999 :                         ret = ldb_match_message(ldb, msg, tree->u.list.elements[i], scope, matched);
     642   173519999 :                         if (ret != LDB_SUCCESS) return ret;
     643   173519999 :                         if (*matched) return LDB_SUCCESS;
     644             :                 }
     645     6062682 :                 *matched = false;
     646     6062682 :                 return LDB_SUCCESS;
     647             : 
     648   131526247 :         case LDB_OP_NOT:
     649   131526247 :                 ret = ldb_match_message(ldb, msg, tree->u.isnot.child, scope, matched);
     650   131526247 :                 if (ret != LDB_SUCCESS) return ret;
     651   131526247 :                 *matched = ! *matched;
     652   131526247 :                 return LDB_SUCCESS;
     653             : 
     654   282433350 :         case LDB_OP_EQUALITY:
     655   282433350 :                 return ldb_match_equality(ldb, msg, tree, scope, matched);
     656             : 
     657     3709404 :         case LDB_OP_SUBSTRING:
     658     3709404 :                 return ldb_match_substring(ldb, msg, tree, scope, matched);
     659             : 
     660     5881288 :         case LDB_OP_GREATER:
     661     5881288 :                 return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_GREATER, matched);
     662             : 
     663       66905 :         case LDB_OP_LESS:
     664       66905 :                 return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_LESS, matched);
     665             : 
     666    54551404 :         case LDB_OP_PRESENT:
     667    54551404 :                 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    12770518 :         case LDB_OP_EXTENDED:
     673    12770518 :                 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      907523 : int ldb_match_msg_objectclass(const struct ldb_message *msg,
     724             :                               const char *objectclass)
     725             : {
     726       29180 :         unsigned int i;
     727      907523 :         struct ldb_message_element *el = ldb_msg_find_element(msg, "objectClass");
     728      907523 :         if (!el) {
     729           0 :                 return 0;
     730             :         }
     731     3630077 :         for (i=0; i < el->num_values; i++) {
     732     3630064 :                 if (ldb_attr_cmp((const char *)el->values[i].data, objectclass) == 0) {
     733      878330 :                         return 1;
     734             :                 }
     735             :         }
     736          13 :         return 0;
     737             : }
     738             : 
     739      756824 : _PRIVATE_ int ldb_register_extended_match_rules(struct ldb_context *ldb)
     740             : {
     741       15268 :         struct ldb_extended_match_rule *bitmask_and;
     742       15268 :         struct ldb_extended_match_rule *bitmask_or;
     743       15268 :         struct ldb_extended_match_rule *always_false;
     744       15268 :         int ret;
     745             : 
     746             :         /* Register bitmask-and match */
     747      756824 :         bitmask_and = talloc_zero(ldb, struct ldb_extended_match_rule);
     748      756824 :         if (bitmask_and == NULL) {
     749           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     750             :         }
     751             : 
     752      756824 :         bitmask_and->oid = LDB_OID_COMPARATOR_AND;
     753      756824 :         bitmask_and->callback = ldb_match_bitmask;
     754             : 
     755      756824 :         ret = ldb_register_extended_match_rule(ldb, bitmask_and);
     756      756824 :         if (ret != LDB_SUCCESS) {
     757           0 :                 return ret;
     758             :         }
     759             : 
     760             :         /* Register bitmask-or match */
     761      756824 :         bitmask_or = talloc_zero(ldb, struct ldb_extended_match_rule);
     762      756824 :         if (bitmask_or == NULL) {
     763           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     764             :         }
     765             : 
     766      756824 :         bitmask_or->oid = LDB_OID_COMPARATOR_OR;
     767      756824 :         bitmask_or->callback = ldb_match_bitmask;
     768             : 
     769      756824 :         ret = ldb_register_extended_match_rule(ldb, bitmask_or);
     770      756824 :         if (ret != LDB_SUCCESS) {
     771           0 :                 return ret;
     772             :         }
     773             : 
     774             :         /* Register always-false match */
     775      756824 :         always_false = talloc_zero(ldb, struct ldb_extended_match_rule);
     776      756824 :         if (always_false == NULL) {
     777           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     778             :         }
     779             : 
     780      756824 :         always_false->oid = SAMBA_LDAP_MATCH_ALWAYS_FALSE;
     781      756824 :         always_false->callback = ldb_comparator_false;
     782             : 
     783      756824 :         ret = ldb_register_extended_match_rule(ldb, always_false);
     784      756824 :         if (ret != LDB_SUCCESS) {
     785           0 :                 return ret;
     786             :         }
     787             : 
     788      741556 :         return LDB_SUCCESS;
     789             : }
     790             : 
     791             : /*
     792             :   register a new ldb extended matching rule
     793             : */
     794     4522800 : int ldb_register_extended_match_rule(struct ldb_context *ldb,
     795             :                                      const struct ldb_extended_match_rule *rule)
     796             : {
     797       85317 :         const struct ldb_extended_match_rule *lookup_rule;
     798       85317 :         struct ldb_extended_match_entry *entry;
     799             : 
     800     4522800 :         lookup_rule = ldb_find_extended_match_rule(ldb, rule->oid);
     801     4522800 :         if (lookup_rule) {
     802           0 :                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
     803             :         }
     804             : 
     805     4522800 :         entry = talloc_zero(ldb, struct ldb_extended_match_entry);
     806     4522800 :         if (!entry) {
     807           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     808             :         }
     809     4522800 :         entry->rule = rule;
     810     4522800 :         DLIST_ADD_END(ldb->extended_match_rules, entry);
     811             : 
     812     4437483 :         return LDB_SUCCESS;
     813             : }
     814             : 
     815      405599 : int ldb_register_redact_callback(struct ldb_context *ldb,
     816             :                                  ldb_redact_fn redact_fn,
     817             :                                  struct ldb_module *module)
     818             : {
     819      405599 :         if (ldb->redact.callback != NULL) {
     820           0 :                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
     821             :         }
     822             : 
     823      405599 :         ldb->redact.callback = redact_fn;
     824      405599 :         ldb->redact.module = module;
     825      405599 :         return LDB_SUCCESS;
     826             : }

Generated by: LCOV version 1.14