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