]> git.samba.org - kamenim/samba.git/blob - source4/lib/ldb/ldb_tdb/ldb_match.c
r7527: - added a ldb_search_bytree() interface, which takes a ldb_parse_tree
[kamenim/samba.git] / source4 / lib / ldb / ldb_tdb / ldb_match.c
1 /* 
2    ldb database library
3
4    Copyright (C) Andrew Tridgell  2004
5
6      ** NOTE! The following LGPL license applies to the ldb
7      ** library. This does NOT imply that all of Samba is released
8      ** under the LGPL
9    
10    This library is free software; you can redistribute it and/or
11    modify it under the terms of the GNU Lesser General Public
12    License as published by the Free Software Foundation; either
13    version 2 of the License, or (at your option) any later version.
14
15    This library is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    Lesser General Public License for more details.
19
20    You should have received a copy of the GNU Lesser General Public
21    License along with this library; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 */
24
25 /*
26  *  Name: ldb
27  *
28  *  Component: ldb expression matching
29  *
30  *  Description: ldb expression matching for tdb backend
31  *
32  *  Author: Andrew Tridgell
33  */
34
35 #include "includes.h"
36 #include "ldb/include/ldb.h"
37 #include "ldb/include/ldb_private.h"
38 #include "ldb/ldb_tdb/ldb_tdb.h"
39 #include <fnmatch.h>
40
41 /*
42   see if two ldb_val structures contain the same data as integers
43   return 1 for a match, 0 for a mis-match
44 */
45 static int ltdb_val_equal_integer(const struct ldb_val *v1, const struct ldb_val *v2)
46 {
47         int i1, i2;
48
49         i1 = strtol(v1->data, NULL, 0);
50         i2 = strtol(v2->data, NULL, 0);
51
52         return i1 == i2;
53 }
54
55 /*
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
58 */
59 static int ltdb_val_equal_case_insensitive(const struct ldb_val *v1, 
60                                           const struct ldb_val *v2)
61 {
62         if (v1->length != v2->length) {
63                 return 0;
64         }
65         if (strncasecmp(v1->data, v2->data, v1->length) == 0) {
66                 return 1;
67         }
68         return 0;
69 }
70
71 /*
72   see if two ldb_val structures contain the same data with wildcards 
73   and case insensitive
74   return 1 for a match, 0 for a mis-match
75 */
76 static int ltdb_val_equal_wildcard_ci(struct ldb_module *module,
77                                      const struct ldb_val *v1, 
78                                      const struct ldb_val *v2)
79 {
80         struct ldb_context *ldb = module->ldb;
81         char *s1, *s2;
82         int ret;
83
84         if (!v1->data || !v2->data) {
85                 return v1->data == v2->data;
86         }
87
88         s1 = ldb_casefold(ldb, v1->data);
89         if (!s1) {
90                 return -1;
91         }
92
93         s2 = ldb_casefold(ldb, v2->data);
94         if (!s2) {
95                 talloc_free(s1);
96                 return -1;
97         }
98
99         ret = fnmatch(s2, s1, 0);
100
101         talloc_free(s1);
102         talloc_free(s2);
103
104         if (ret == 0) {
105                 return 1;
106         }
107
108         return 0;
109 }
110
111 /*
112   see if two ldb_val structures contain the same data with wildcards
113   return 1 for a match, 0 for a mis-match
114 */
115 static int ltdb_val_equal_wildcard(struct ldb_module *module,
116                                   const struct ldb_val *v1, 
117                                   const struct ldb_val *v2,
118                                   int flags)
119 {
120         if (flags & LTDB_FLAG_CASE_INSENSITIVE) {
121                 return ltdb_val_equal_wildcard_ci(module, v1, v2);
122         }
123         if (!v1->data || !v2->data) {
124                 return v1->data == v2->data;
125         }
126         if (fnmatch(v2->data, v1->data, 0) == 0) {
127                 return 1;
128         }
129         return 0;
130 }
131
132
133 /*
134   see if two objectclasses are considered equal. This handles
135   the subclass attributes
136
137   v1 contains the in-database value, v2 contains the value
138   that the user gave
139
140   return 1 for a match, 0 for a mis-match
141 */
142 static int ltdb_val_equal_objectclass(struct ldb_module *module, 
143                                      const struct ldb_val *v1, const struct ldb_val *v2)
144 {
145         struct ltdb_private *ltdb = module->private_data;
146         unsigned int i;
147
148         if (ltdb_val_equal_case_insensitive(v1, v2) == 1) {
149                 return 1;
150         }
151
152         for (i=0;i<ltdb->cache->subclasses->num_elements;i++) {
153                 struct ldb_message_element *el = &ltdb->cache->subclasses->elements[i];
154                 if (ldb_attr_cmp(el->name, v2->data) == 0) {
155                         unsigned int j;
156                         for (j=0;j<el->num_values;j++) {
157                                 if (ltdb_val_equal_objectclass(module, v1, &el->values[j])) {
158                                         return 1;
159                                 }
160                         }
161                 }
162         }
163
164         return 0;
165 }
166                                      
167
168 /*
169   see if two ldb_val structures contain the same data
170   
171   v1 contains the in-database value, v2 contains the value
172   that the user gave
173   
174   return 1 for a match, 0 for a mis-match
175 */
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)
179 {
180         int flags = ltdb_attribute_flags(module, attr_name);
181
182         if (flags & LTDB_FLAG_OBJECTCLASS) {
183                 return ltdb_val_equal_objectclass(module, v1, v2);
184         }
185
186         if (flags & LTDB_FLAG_INTEGER) {
187                 return ltdb_val_equal_integer(v1, v2);
188         }
189
190         if (flags & LTDB_FLAG_WILDCARD) {
191                 return ltdb_val_equal_wildcard(module, v1, v2, flags);
192         }
193
194         if (flags & LTDB_FLAG_CASE_INSENSITIVE) {
195                 return ltdb_val_equal_case_insensitive(v1, v2);
196         }
197
198         if (v1->length != v2->length) return 0;
199
200         if (v1->length == 0) return 1;
201
202         if (memcmp(v1->data, v2->data, v1->length) == 0) {
203                 return 1;
204         }
205
206         return 0;
207 }
208
209 /*
210   check if the scope matches in a search result
211 */
212 static int scope_match(const char *dn, const char *base, enum ldb_scope scope)
213 {
214         size_t dn_len, base_len;
215
216         if (base == NULL) {
217                 return 1;
218         }
219
220         base_len = strlen(base);
221         dn_len = strlen(dn);
222
223         if (scope != LDB_SCOPE_ONELEVEL && ldb_dn_cmp(dn, base) == 0) {
224                 return 1;
225         }
226
227         if (base_len+1 >= dn_len) {
228                 return 0;
229         }
230
231         switch (scope) {
232         case LDB_SCOPE_BASE:
233                 break;
234
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]) {
239                         return 1;
240                 }
241                 break;
242                 
243         case LDB_SCOPE_SUBTREE:
244         default:
245                 if (ldb_dn_cmp(dn + (dn_len - base_len), base) == 0 &&
246                     dn[dn_len - base_len - 1] == ',') {
247                         return 1;
248                 }
249                 break;
250         }
251
252         return 0;
253 }
254
255
256 /*
257   match a leaf node
258 */
259 static int match_leaf(struct ldb_module *module, 
260                       struct ldb_message *msg,
261                       struct ldb_parse_tree *tree,
262                       const char *base,
263                       enum ldb_scope scope)
264 {
265         unsigned int i, j;
266
267         if (!scope_match(msg->dn, base, scope)) {
268                 return 0;
269         }
270
271         if (ldb_attr_cmp(tree->u.simple.attr, "dn") == 0) {
272                 if (strcmp(tree->u.simple.value.data, "*") == 0) {
273                         return 1;
274                 }
275                 return ldb_dn_cmp(msg->dn, tree->u.simple.value.data) == 0;
276         }
277
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) {
281                                 return 1;
282                         }
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)) {
287                                         return 1;
288                                 }
289                         }
290                 }
291         }
292
293         return 0;
294 }
295
296 /*
297   return 0 if the given parse tree matches the given message. Assumes
298   the message is in sorted order
299
300   return 1 if it matches, and 0 if it doesn't match
301
302   this is a recursive function, and does short-circuit evaluation
303  */
304 int ltdb_message_match(struct ldb_module *module, 
305                       struct ldb_message *msg,
306                       struct ldb_parse_tree *tree,
307                       const char *base,
308                       enum ldb_scope scope)
309 {
310         unsigned int i;
311         int v;
312
313         switch (tree->operation) {
314         case LDB_OP_SIMPLE:
315                 break;
316
317         case LDB_OP_NOT:
318                 return ! ltdb_message_match(module, msg, tree->u.not.child, base, scope);
319
320         case LDB_OP_AND:
321                 for (i=0;i<tree->u.list.num_elements;i++) {
322                         v = ltdb_message_match(module, msg, tree->u.list.elements[i],
323                                               base, scope);
324                         if (!v) return 0;
325                 }
326                 return 1;
327
328         case LDB_OP_OR:
329                 for (i=0;i<tree->u.list.num_elements;i++) {
330                         v = ltdb_message_match(module, msg, tree->u.list.elements[i],
331                                               base, scope);
332                         if (v) return 1;
333                 }
334                 return 0;
335         }
336
337         return match_leaf(module, msg, tree, base, scope);
338 }