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"
42 see if two ldb_val structures contain the same data as integers
43 return 1 for a match, 0 for a mis-match
45 static int ltdb_val_equal_integer(const struct ldb_val *v1, const struct ldb_val *v2)
49 i1 = strtol(v1->data, NULL, 0);
50 i2 = strtol(v2->data, NULL, 0);
56 see if two ldb_val structures contain the same data as case insensitive strings
57 return 1 for a match, 0 for a mis-match
59 static int ltdb_val_equal_case_insensitive(const struct ldb_val *v1,
60 const struct ldb_val *v2)
62 if (v1->length != v2->length) {
65 if (strncasecmp(v1->data, v2->data, v1->length) == 0) {
72 see if two ldb_val structures contain the same data with wildcards
74 return 1 for a match, 0 for a mis-match
76 static int ltdb_val_equal_wildcard_ci(struct ldb_module *module,
77 const struct ldb_val *v1,
78 const struct ldb_val *v2)
80 struct ldb_context *ldb = module->ldb;
84 if (!v1->data || !v2->data) {
85 return v1->data == v2->data;
88 s1 = ldb_casefold(ldb, v1->data);
93 s2 = ldb_casefold(ldb, v2->data);
99 ret = fnmatch(s2, s1, 0);
112 see if two ldb_val structures contain the same data with wildcards
113 return 1 for a match, 0 for a mis-match
115 static int ltdb_val_equal_wildcard(struct ldb_module *module,
116 const struct ldb_val *v1,
117 const struct ldb_val *v2,
120 if (flags & LTDB_FLAG_CASE_INSENSITIVE) {
121 return ltdb_val_equal_wildcard_ci(module, v1, v2);
123 if (!v1->data || !v2->data) {
124 return v1->data == v2->data;
126 if (fnmatch(v2->data, v1->data, 0) == 0) {
134 see if two objectclasses are considered equal. This handles
135 the subclass attributes
137 v1 contains the in-database value, v2 contains the value
140 return 1 for a match, 0 for a mis-match
142 static int ltdb_val_equal_objectclass(struct ldb_module *module,
143 const struct ldb_val *v1, const struct ldb_val *v2)
145 struct ltdb_private *ltdb = module->private_data;
148 if (ltdb_val_equal_case_insensitive(v1, v2) == 1) {
152 for (i=0;i<ltdb->cache->subclasses->num_elements;i++) {
153 struct ldb_message_element *el = <db->cache->subclasses->elements[i];
154 if (ldb_attr_cmp(el->name, v2->data) == 0) {
156 for (j=0;j<el->num_values;j++) {
157 if (ltdb_val_equal_objectclass(module, v1, &el->values[j])) {
169 see if two ldb_val structures contain the same data
171 v1 contains the in-database value, v2 contains the value
174 return 1 for a match, 0 for a mis-match
176 int ltdb_val_equal(struct ldb_module *module,
177 const char *attr_name,
178 const struct ldb_val *v1, const struct ldb_val *v2)
180 int flags = ltdb_attribute_flags(module, attr_name);
182 if (flags & LTDB_FLAG_OBJECTCLASS) {
183 return ltdb_val_equal_objectclass(module, v1, v2);
186 if (flags & LTDB_FLAG_INTEGER) {
187 return ltdb_val_equal_integer(v1, v2);
190 if (flags & LTDB_FLAG_WILDCARD) {
191 return ltdb_val_equal_wildcard(module, v1, v2, flags);
194 if (flags & LTDB_FLAG_CASE_INSENSITIVE) {
195 return ltdb_val_equal_case_insensitive(v1, v2);
198 if (v1->length != v2->length) return 0;
200 if (v1->length == 0) return 1;
202 if (memcmp(v1->data, v2->data, v1->length) == 0) {
210 check if the scope matches in a search result
212 static int scope_match(const char *dn, const char *base, enum ldb_scope scope)
214 size_t dn_len, base_len;
220 base_len = strlen(base);
223 if (scope != LDB_SCOPE_ONELEVEL && ldb_dn_cmp(dn, base) == 0) {
227 if (base_len+1 >= dn_len) {
235 case LDB_SCOPE_ONELEVEL:
236 if (ldb_dn_cmp(dn + (dn_len - base_len), base) == 0 &&
237 dn[dn_len - base_len - 1] == ',' &&
238 strchr(dn, ',') == &dn[dn_len - base_len - 1]) {
243 case LDB_SCOPE_SUBTREE:
245 if (ldb_dn_cmp(dn + (dn_len - base_len), base) == 0 &&
246 dn[dn_len - base_len - 1] == ',') {
259 static int match_leaf(struct ldb_module *module,
260 struct ldb_message *msg,
261 struct ldb_parse_tree *tree,
263 enum ldb_scope scope)
267 if (!scope_match(msg->dn, base, scope)) {
271 if (ldb_attr_cmp(tree->u.simple.attr, "dn") == 0) {
272 if (strcmp(tree->u.simple.value.data, "*") == 0) {
275 return ldb_dn_cmp(msg->dn, tree->u.simple.value.data) == 0;
278 for (i=0;i<msg->num_elements;i++) {
279 if (ldb_attr_cmp(msg->elements[i].name, tree->u.simple.attr) == 0) {
280 if (strcmp(tree->u.simple.value.data, "*") == 0) {
283 for (j=0;j<msg->elements[i].num_values;j++) {
284 if (ltdb_val_equal(module, msg->elements[i].name,
285 &msg->elements[i].values[j],
286 &tree->u.simple.value)) {
297 return 0 if the given parse tree matches the given message. Assumes
298 the message is in sorted order
300 return 1 if it matches, and 0 if it doesn't match
302 this is a recursive function, and does short-circuit evaluation
304 int ltdb_message_match(struct ldb_module *module,
305 struct ldb_message *msg,
306 struct ldb_parse_tree *tree,
308 enum ldb_scope scope)
313 switch (tree->operation) {
318 return ! ltdb_message_match(module, msg, tree->u.not.child, base, scope);
321 for (i=0;i<tree->u.list.num_elements;i++) {
322 v = ltdb_message_match(module, msg, tree->u.list.elements[i],
329 for (i=0;i<tree->u.list.num_elements;i++) {
330 v = ltdb_message_match(module, msg, tree->u.list.elements[i],
337 return match_leaf(module, msg, tree, base, scope);