]> git.sur5r.net Git - openldap/blob - servers/slapd/sets.c
updated certificateExactMatch support,
[openldap] / servers / slapd / sets.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 2000-2003 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6
7 #include "portable.h"
8
9 #include <stdio.h>
10 #include <ac/string.h>
11
12 #include "slap.h"
13 #include "sets.h"
14
15 static BerVarray set_join (SetCookie *cp, BerVarray lset, int op, BerVarray rset);
16 static BerVarray set_chase (SLAP_SET_GATHER gatherer,
17         SetCookie *cookie, BerVarray set, struct berval *attr, int closure);
18 static int set_samedn (char *dn1, char *dn2);
19
20 long
21 slap_set_size (BerVarray set)
22 {
23         long    i;
24
25         i = 0;
26         if (set != NULL) {
27                 while (set[i].bv_val)
28                         i++;
29         }
30         return i;
31 }
32
33 void
34 slap_set_dispose (SetCookie *cp, BerVarray set)
35 {
36         ber_bvarray_free_x(set, cp->op->o_tmpmemctx);
37 }
38
39 static BerVarray
40 set_join (SetCookie *cp, BerVarray lset, int op, BerVarray rset)
41 {
42         BerVarray set;
43         long i, j, last;
44
45         set = NULL;
46         if (op == '|') {
47                 if (lset == NULL || lset->bv_val == NULL) {
48                         if (rset == NULL) {
49                                 if (lset == NULL)
50                                         return(cp->op->o_tmpcalloc(1, sizeof(struct berval),
51                                                 cp->op->o_tmpmemctx));
52                                 return(lset);
53                         }
54                         slap_set_dispose(cp, lset);
55                         return(rset);
56                 }
57                 if (rset == NULL || rset->bv_val == NULL) {
58                         slap_set_dispose(cp, rset);
59                         return(lset);
60                 }
61
62                 i = slap_set_size(lset) + slap_set_size(rset) + 1;
63                 set = cp->op->o_tmpcalloc(i, sizeof(struct berval), cp->op->o_tmpmemctx);
64                 if (set != NULL) {
65                         /* set_chase() depends on this routine to
66                          * keep the first elements of the result
67                          * set the same (and in the same order)
68                          * as the left-set.
69                          */
70                         for (i = 0; lset[i].bv_val; i++)
71                                 set[i] = lset[i];
72                         cp->op->o_tmpfree(lset, cp->op->o_tmpmemctx);
73                         for (i = 0; rset[i].bv_val; i++) {
74                                 for (j = 0; set[j].bv_val; j++) {
75                                         if (set_samedn(rset[i].bv_val, set[j].bv_val)) {
76                                                 cp->op->o_tmpfree(rset[i].bv_val, cp->op->o_tmpmemctx);
77                                                 rset[i].bv_val = NULL;
78                                                 break;          
79                                         }       
80                                 }
81                                 if (rset[i].bv_val)
82                                         set[j] = rset[i];
83                         }
84                         cp->op->o_tmpfree(rset, cp->op->o_tmpmemctx);
85                 }
86                 return(set);
87         }
88
89         if (op == '&') {
90                 if (lset == NULL || lset->bv_val == NULL || rset == NULL || rset->bv_val == NULL) {
91                         set = cp->op->o_tmpcalloc(1, sizeof(struct berval), cp->op->o_tmpmemctx);
92                 } else {
93                         set = lset;
94                         lset = NULL;
95                         last = slap_set_size(set) - 1;
96                         for (i = 0; set[i].bv_val; i++) {
97                                 for (j = 0; rset[j].bv_val; j++) {
98                                         if (set_samedn(set[i].bv_val, rset[j].bv_val))
99                                                 break;
100                                 }
101                                 if (rset[j].bv_val == NULL) {
102                                         cp->op->o_tmpfree(set[i].bv_val, cp->op->o_tmpmemctx);
103                                         set[i] = set[last];
104                                         set[last].bv_val = NULL;
105                                         last--;
106                                         i--;
107                                 }
108                         }
109                 }
110         }
111
112         slap_set_dispose(cp, lset);
113         slap_set_dispose(cp, rset);
114         return(set);
115 }
116
117 static BerVarray
118 set_chase (SLAP_SET_GATHER gatherer,
119         SetCookie *cp, BerVarray set, struct berval *attr, int closure)
120 {
121         BerVarray vals, nset;
122         char attrstr[32];
123         struct berval bv;
124         int i;
125
126         bv.bv_len = attr->bv_len;
127         bv.bv_val = attrstr;
128
129         if (set == NULL)
130                 return(cp->op->o_tmpcalloc(1, sizeof(struct berval), cp->op->o_tmpmemctx));
131
132         if (set->bv_val == NULL)
133                 return(set);
134
135         if (attr->bv_len > (sizeof(attrstr) - 1)) {
136                 slap_set_dispose(cp, set);
137                 return(NULL);
138         }
139         AC_MEMCPY(attrstr, attr->bv_val, attr->bv_len);
140         attrstr[attr->bv_len] = 0;
141
142         nset = cp->op->o_tmpcalloc(1, sizeof(struct berval), cp->op->o_tmpmemctx);
143         if (nset == NULL) {
144                 slap_set_dispose(cp, set);
145                 return(NULL);
146         }
147         for (i = 0; set[i].bv_val; i++) {
148                 vals = (gatherer)(cp, &set[i], &bv);
149                 if (vals != NULL)
150                         nset = set_join(cp, nset, '|', vals);
151         }
152         slap_set_dispose(cp, set);
153
154         if (closure) {
155                 for (i = 0; nset[i].bv_val; i++) {
156                         vals = (gatherer)(cp, &nset[i], &bv);
157                         if (vals != NULL) {
158                                 nset = set_join(cp, nset, '|', vals);
159                                 if (nset == NULL)
160                                         break;
161                         }
162                 }
163         }
164         return(nset);
165 }
166
167 static int
168 set_samedn (char *dn1, char *dn2)
169 {
170         char c1, c2;
171
172         while (*dn1 == ' ') dn1++;
173         while (*dn2 == ' ') dn2++;
174         while (*dn1 || *dn2) {
175                 if (*dn1 != '=' && *dn1 != ','
176                         && *dn2 != '=' && *dn2 != ',')
177                 {
178                         c1 = *dn1++;
179                         c2 = *dn2++;
180                         if (c1 >= 'a' && c1 <= 'z')
181                                 c1 -= 'a' - 'A';
182                         if (c2 >= 'a' && c2 <= 'z')
183                                 c2 -= 'a' - 'A';
184                         if (c1 != c2)
185                                 return(0);
186                 } else {
187                         while (*dn1 == ' ') dn1++;
188                         while (*dn2 == ' ') dn2++;
189                         if (*dn1++ != *dn2++)
190                                 return(0);
191                         while (*dn1 == ' ') dn1++;
192                         while (*dn2 == ' ') dn2++;
193                 }
194         }
195         return(1);
196 }
197
198 int
199 slap_set_filter (SLAP_SET_GATHER gatherer,
200         SetCookie *cp, struct berval *fbv,
201         struct berval *user, struct berval *this, BerVarray *results)
202 {
203 #define IS_SET(x)       ( (long)(x) >= 256 )
204 #define IS_OP(x)        ( (long)(x) < 256 )
205 #define SF_ERROR(x)     do { rc = -1; goto _error; } while (0)
206 #define SF_TOP()        ( (BerVarray)( (stp < 0) ? 0 : stack[stp] ) )
207 #define SF_POP()        ( (BerVarray)( (stp < 0) ? 0 : stack[stp--] ) )
208 #define SF_PUSH(x)      do { \
209                 if (stp >= 63) SF_ERROR(overflow); \
210                 stack[++stp] = (BerVarray)(long)(x); \
211         } while (0)
212
213         BerVarray set, lset;
214         BerVarray stack[64];
215         int len, op, rc, stp;
216         char c, *filter = fbv->bv_val;
217
218         if (results)
219                 *results = NULL;
220
221         stp = -1;
222         while ((c = *filter++)) {
223                 set = NULL;
224                 switch (c) {
225                 case ' ':
226                 case '\t':
227                 case '\x0A':
228                 case '\x0D':
229                         break;
230
231                 case '(':
232                         if (IS_SET(SF_TOP()))
233                                 SF_ERROR(syntax);
234                         SF_PUSH(c);
235                         break;
236
237                 case ')':
238                         set = SF_POP();
239                         if (IS_OP(set))
240                                 SF_ERROR(syntax);
241                         if (SF_TOP() == (void *)'(') {
242                                 SF_POP();
243                                 SF_PUSH(set);
244                                 set = NULL;
245                         } else if (IS_OP(SF_TOP())) {
246                                 op = (long)SF_POP();
247                                 lset = SF_POP();
248                                 SF_POP();
249                                 set = set_join(cp, lset, op, set);
250                                 if (set == NULL)
251                                         SF_ERROR(memory);
252                                 SF_PUSH(set);
253                                 set = NULL;
254                         } else {
255                                 SF_ERROR(syntax);
256                         }
257                         break;
258
259                 case '&':
260                 case '|':
261                         set = SF_POP();
262                         if (IS_OP(set))
263                                 SF_ERROR(syntax);
264                         if (SF_TOP() == 0 || SF_TOP() == (void *)'(') {
265                                 SF_PUSH(set);
266                                 set = NULL;
267                         } else if (IS_OP(SF_TOP())) {
268                                 op = (long)SF_POP();
269                                 lset = SF_POP();
270                                 set = set_join(cp, lset, op, set);
271                                 if (set == NULL)
272                                         SF_ERROR(memory);
273                                 SF_PUSH(set);
274                                 set = NULL;
275                         } else {
276                                 SF_ERROR(syntax);
277                         }
278                         SF_PUSH(c);
279                         break;
280
281                 case '[':
282                         if ((SF_TOP() == (void *)'/') || IS_SET(SF_TOP()))
283                                 SF_ERROR(syntax);
284                         for (   len = 0;
285                                         (c = *filter++) && (c != ']');
286                                         len++)
287                         { }
288                         if (c == 0)
289                                 SF_ERROR(syntax);
290                         
291                         set = cp->op->o_tmpcalloc(2, sizeof(struct berval), cp->op->o_tmpmemctx);
292                         if (set == NULL)
293                                 SF_ERROR(memory);
294                         set->bv_val = cp->op->o_tmpcalloc(len + 1, sizeof(char), cp->op->o_tmpmemctx);
295                         if (set->bv_val == NULL)
296                                 SF_ERROR(memory);
297                         AC_MEMCPY(set->bv_val, &filter[-len - 1], len);
298                         set->bv_len = len;
299                         SF_PUSH(set);
300                         set = NULL;
301                         break;
302
303                 case '-':
304                         c = *filter++;
305                         if (c != '>')
306                                 SF_ERROR(syntax);
307                         /* fall through to next case */
308
309                 case '/':
310                         if (IS_OP(SF_TOP()))
311                                 SF_ERROR(syntax);
312                         SF_PUSH('/');
313                         break;
314
315                 default:
316                         if ((c != '_')
317                                 && (c < 'A' || c > 'Z')
318                                 && (c < 'a' || c > 'z'))
319                         {
320                                 SF_ERROR(syntax);
321                         }
322                         filter--;
323                         for (   len = 1;
324                                         (c = filter[len])
325                                                 && ((c >= '0' && c <= '9')
326                                                         || (c >= 'A' && c <= 'Z')
327                                                         || (c >= 'a' && c <= 'z'));
328                                         len++)
329                         { }
330                         if (len == 4
331                                 && memcmp("this", filter, len) == 0)
332                         {
333                                 if ((SF_TOP() == (void *)'/') || IS_SET(SF_TOP()))
334                                         SF_ERROR(syntax);
335                                 set = cp->op->o_tmpcalloc(2, sizeof(struct berval), cp->op->o_tmpmemctx);
336                                 if (set == NULL)
337                                         SF_ERROR(memory);
338                                 ber_dupbv_x( set, this, cp->op->o_tmpmemctx );
339                                 if (set->bv_val == NULL)
340                                         SF_ERROR(memory);
341                         } else if (len == 4
342                                 && memcmp("user", filter, len) == 0) 
343                         {
344                                 if ((SF_TOP() == (void *)'/') || IS_SET(SF_TOP()))
345                                         SF_ERROR(syntax);
346                                 set = cp->op->o_tmpcalloc(2, sizeof(struct berval), cp->op->o_tmpmemctx);
347                                 if (set == NULL)
348                                         SF_ERROR(memory);
349                                 ber_dupbv_x( set, user, cp->op->o_tmpmemctx );
350                                 if (set->bv_val == NULL)
351                                         SF_ERROR(memory);
352                         } else if (SF_TOP() != (void *)'/') {
353                                 SF_ERROR(syntax);
354                         } else {
355                                 struct berval fb2;
356                                 SF_POP();
357                                 fb2.bv_val = filter;
358                                 fb2.bv_len = len;
359                                 set = set_chase(gatherer,
360                                         cp, SF_POP(), &fb2, c == '*');
361                                 if (set == NULL)
362                                         SF_ERROR(memory);
363                                 if (c == '*')
364                                         len++;
365                         }
366                         filter += len;
367                         SF_PUSH(set);
368                         set = NULL;
369                         break;
370                 }
371         }
372
373         set = SF_POP();
374         if (IS_OP(set))
375                 SF_ERROR(syntax);
376         if (SF_TOP() == 0) {
377
378         } else if (IS_OP(SF_TOP())) {
379                 op = (long)SF_POP();
380                 lset = SF_POP();
381                 set = set_join(cp, lset, op, set);
382                 if (set == NULL)
383                         SF_ERROR(memory);
384         } else {
385                 SF_ERROR(syntax);
386         }
387
388         rc = slap_set_size(set) > 0 ? 1 : 0;
389         if (results) {
390                 *results = set;
391                 set = NULL;
392         }
393
394 _error:
395         if (IS_SET(set))
396                 slap_set_dispose(cp, set);
397         while ((set = SF_POP())) {
398                 if (IS_SET(set))
399                         slap_set_dispose(cp, set);
400         }
401         return(rc);
402 }