4 Copyright (C) Andrew Tridgell 2004
6 ** NOTE! The following LGPL license applies to the ldb
7 ** library. This does NOT imply that all of Samba is released
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 * Component: ldb expression matching
30 * Description: ldb expression matching for tdb backend
32 * Author: Andrew Tridgell
36 #include "ldb/include/ldb.h"
37 #include "ldb/include/ldb_private.h"
38 #include "ldb/ldb_tdb/ldb_tdb.h"
39 #include "ldb/include/ldb_parse.h"
43 see if two ldb_val structures contain the same data as integers
44 return 1 for a match, 0 for a mis-match
46 static int ltdb_val_equal_integer(const struct ldb_val *v1, const struct ldb_val *v2)
50 i1 = strtol(v1->data, NULL, 0);
51 i2 = strtol(v2->data, NULL, 0);
57 see if two ldb_val structures contain the same data as case insensitive strings
58 return 1 for a match, 0 for a mis-match
60 static int ltdb_val_equal_case_insensitive(const struct ldb_val *v1,
61 const struct ldb_val *v2)
63 if (v1->length != v2->length) {
66 if (strncasecmp(v1->data, v2->data, v1->length) == 0) {
73 see if two ldb_val structures contain the same data with wildcards
75 return 1 for a match, 0 for a mis-match
77 static int ltdb_val_equal_wildcard_ci(struct ldb_module *module,
78 const struct ldb_val *v1,
79 const struct ldb_val *v2)
81 struct ldb_context *ldb = module->ldb;
85 if (!v1->data || !v2->data) {
86 return v1->data == v2->data;
89 s1 = ldb_casefold(ldb, v1->data);
94 s2 = ldb_casefold(ldb, v2->data);
100 ret = fnmatch(s2, s1, 0);
113 see if two ldb_val structures contain the same data with wildcards
114 return 1 for a match, 0 for a mis-match
116 static int ltdb_val_equal_wildcard(struct ldb_module *module,
117 const struct ldb_val *v1,
118 const struct ldb_val *v2,
121 if (flags & LTDB_FLAG_CASE_INSENSITIVE) {
122 return ltdb_val_equal_wildcard_ci(module, v1, v2);
124 if (!v1->data || !v2->data) {
125 return v1->data == v2->data;
127 if (fnmatch(v2->data, v1->data, 0) == 0) {
135 see if two objectclasses are considered equal. This handles
136 the subclass attributes
138 v1 contains the in-database value, v2 contains the value
141 return 1 for a match, 0 for a mis-match
143 static int ltdb_val_equal_objectclass(struct ldb_module *module,
144 const struct ldb_val *v1, const struct ldb_val *v2)
146 struct ltdb_private *ltdb = module->private_data;
149 if (ltdb_val_equal_case_insensitive(v1, v2) == 1) {
153 for (i=0;i<ltdb->cache->subclasses->num_elements;i++) {
154 struct ldb_message_element *el = <db->cache->subclasses->elements[i];
155 if (ldb_attr_cmp(el->name, v2->data) == 0) {
157 for (j=0;j<el->num_values;j++) {
158 if (ltdb_val_equal_objectclass(module, v1, &el->values[j])) {
170 see if two ldb_val structures contain the same data
172 v1 contains the in-database value, v2 contains the value
175 return 1 for a match, 0 for a mis-match
177 int ltdb_val_equal(struct ldb_module *module,
178 const char *attr_name,
179 const struct ldb_val *v1, const struct ldb_val *v2)
181 int flags = ltdb_attribute_flags(module, attr_name);
183 if (flags & LTDB_FLAG_OBJECTCLASS) {
184 return ltdb_val_equal_objectclass(module, v1, v2);
187 if (flags & LTDB_FLAG_INTEGER) {
188 return ltdb_val_equal_integer(v1, v2);
191 if (flags & LTDB_FLAG_WILDCARD) {
192 return ltdb_val_equal_wildcard(module, v1, v2, flags);
195 if (flags & LTDB_FLAG_CASE_INSENSITIVE) {
196 return ltdb_val_equal_case_insensitive(v1, v2);
199 if (v1->length != v2->length) return 0;
201 if (v1->length == 0) return 1;
203 if (memcmp(v1->data, v2->data, v1->length) == 0) {
211 check if the scope matches in a search result
213 static int scope_match(const char *dn, const char *base, enum ldb_scope scope)
215 size_t dn_len, base_len;
221 base_len = strlen(base);
224 if (scope != LDB_SCOPE_ONELEVEL && ldb_dn_cmp(dn, base) == 0) {
228 if (base_len+1 >= dn_len) {
236 case LDB_SCOPE_ONELEVEL:
237 if (ldb_dn_cmp(dn + (dn_len - base_len), base) == 0 &&
238 dn[dn_len - base_len - 1] == ',' &&
239 strchr(dn, ',') == &dn[dn_len - base_len - 1]) {
244 case LDB_SCOPE_SUBTREE:
246 if (ldb_dn_cmp(dn + (dn_len - base_len), base) == 0 &&
247 dn[dn_len - base_len - 1] == ',') {
260 static int match_leaf(struct ldb_module *module,
261 struct ldb_message *msg,
262 struct ldb_parse_tree *tree,
264 enum ldb_scope scope)
268 if (!scope_match(msg->dn, base, scope)) {
272 if (ldb_attr_cmp(tree->u.simple.attr, "dn") == 0) {
273 if (strcmp(tree->u.simple.value.data, "*") == 0) {
276 return ldb_dn_cmp(msg->dn, tree->u.simple.value.data) == 0;
279 for (i=0;i<msg->num_elements;i++) {
280 if (ldb_attr_cmp(msg->elements[i].name, tree->u.simple.attr) == 0) {
281 if (strcmp(tree->u.simple.value.data, "*") == 0) {
284 for (j=0;j<msg->elements[i].num_values;j++) {
285 if (ltdb_val_equal(module, msg->elements[i].name,
286 &msg->elements[i].values[j],
287 &tree->u.simple.value)) {
298 return 0 if the given parse tree matches the given message. Assumes
299 the message is in sorted order
301 return 1 if it matches, and 0 if it doesn't match
303 this is a recursive function, and does short-circuit evaluation
305 int ltdb_message_match(struct ldb_module *module,
306 struct ldb_message *msg,
307 struct ldb_parse_tree *tree,
309 enum ldb_scope scope)
314 switch (tree->operation) {
319 return ! ltdb_message_match(module, msg, tree->u.not.child, base, scope);
322 for (i=0;i<tree->u.list.num_elements;i++) {
323 v = ltdb_message_match(module, msg, tree->u.list.elements[i],
330 for (i=0;i<tree->u.list.num_elements;i++) {
331 v = ltdb_message_match(module, msg, tree->u.list.elements[i],
338 return match_leaf(module, msg, tree, base, scope);