1 /* $NetBSD: sets.c,v 1.3 2021/08/14 16:14:58 christos Exp $ */
2
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 *
6 * Copyright 2000-2021 The OpenLDAP Foundation.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
11 * Public License.
12 *
13 * A copy of this license is available in the file LICENSE in the
14 * top-level directory of the distribution or, alternatively, at
15 * <http://www.OpenLDAP.org/license.html>.
16 */
17
18 #include <sys/cdefs.h>
19 __RCSID("$NetBSD: sets.c,v 1.3 2021/08/14 16:14:58 christos Exp $");
20
21 #include "portable.h"
22
23 #include <stdio.h>
24 #include <ac/string.h>
25
26 #include "slap.h"
27 #include "sets.h"
28
29 static BerVarray set_chase( SLAP_SET_GATHER gatherer,
30 SetCookie *cookie, BerVarray set, AttributeDescription *desc, int closure );
31
32 /* Count the array members */
33 static long
slap_set_size(BerVarray set)34 slap_set_size( BerVarray set )
35 {
36 long i = 0;
37
38 if ( set != NULL ) {
39 while ( !BER_BVISNULL( &set[ i ] ) ) {
40 i++;
41 }
42 }
43
44 return i;
45 }
46
47 /* Return 0 if there is at least one array member, non-zero otherwise */
48 static int
slap_set_isempty(BerVarray set)49 slap_set_isempty( BerVarray set )
50 {
51 if ( set == NULL ) {
52 return 1;
53 }
54
55 if ( !BER_BVISNULL( &set[ 0 ] ) ) {
56 return 0;
57 }
58
59 return 1;
60 }
61
62 /* Dispose of the contents of the array and the array itself according
63 * to the flags value. If SLAP_SET_REFVAL, don't dispose of values;
64 * if SLAP_SET_REFARR, don't dispose of the array itself. In case of
65 * binary operators, there are LEFT flags and RIGHT flags, referring to
66 * the first and the second operator arguments, respectively. In this
67 * case, flags must be transformed using macros SLAP_SET_LREF2REF() and
68 * SLAP_SET_RREF2REF() before calling this function.
69 */
70 static void
slap_set_dispose(SetCookie * cp,BerVarray set,unsigned flags)71 slap_set_dispose( SetCookie *cp, BerVarray set, unsigned flags )
72 {
73 if ( flags & SLAP_SET_REFVAL ) {
74 if ( ! ( flags & SLAP_SET_REFARR ) ) {
75 cp->set_op->o_tmpfree( set, cp->set_op->o_tmpmemctx );
76 }
77
78 } else {
79 ber_bvarray_free_x( set, cp->set_op->o_tmpmemctx );
80 }
81 }
82
83 /* Duplicate a set. If SLAP_SET_REFARR, is not set, the original array
84 * with the original values is returned, otherwise the array is duplicated;
85 * if SLAP_SET_REFVAL is set, also the values are duplicated.
86 */
87 static BerVarray
set_dup(SetCookie * cp,BerVarray set,unsigned flags)88 set_dup( SetCookie *cp, BerVarray set, unsigned flags )
89 {
90 BerVarray newset = NULL;
91
92 if ( set == NULL ) {
93 return NULL;
94 }
95
96 if ( flags & SLAP_SET_REFARR ) {
97 int i;
98
99 for ( i = 0; !BER_BVISNULL( &set[ i ] ); i++ )
100 ;
101 newset = cp->set_op->o_tmpcalloc( i + 1,
102 sizeof( struct berval ),
103 cp->set_op->o_tmpmemctx );
104 if ( newset == NULL ) {
105 return NULL;
106 }
107
108 if ( flags & SLAP_SET_REFVAL ) {
109 for ( i = 0; !BER_BVISNULL( &set[ i ] ); i++ ) {
110 ber_dupbv_x( &newset[ i ], &set[ i ],
111 cp->set_op->o_tmpmemctx );
112 }
113
114 } else {
115 AC_MEMCPY( newset, set, ( i + 1 ) * sizeof( struct berval ) );
116 }
117
118 } else {
119 newset = set;
120 }
121
122 return newset;
123 }
124
125 /* Join two sets according to operator op and flags op_flags.
126 * op can be:
127 * '|' (or): the union between the two sets is returned,
128 * eliminating duplicates
129 * '&' (and): the intersection between the two sets
130 * is returned
131 * '+' (add): the inner product of the two sets is returned,
132 * namely a set containing the concatenation of
133 * all combinations of the two sets members,
134 * except for duplicates.
135 * The two sets are disposed of according to the flags as described
136 * for slap_set_dispose().
137 */
138 BerVarray
slap_set_join(SetCookie * cp,BerVarray lset,unsigned op_flags,BerVarray rset)139 slap_set_join(
140 SetCookie *cp,
141 BerVarray lset,
142 unsigned op_flags,
143 BerVarray rset )
144 {
145 BerVarray set;
146 long i, j, last, rlast;
147 unsigned op = ( op_flags & SLAP_SET_OPMASK );
148
149 set = NULL;
150 switch ( op ) {
151 case '|': /* union */
152 if ( lset == NULL || BER_BVISNULL( &lset[ 0 ] ) ) {
153 if ( rset == NULL ) {
154 if ( lset == NULL ) {
155 set = cp->set_op->o_tmpcalloc( 1,
156 sizeof( struct berval ),
157 cp->set_op->o_tmpmemctx );
158 BER_BVZERO( &set[ 0 ] );
159 goto done2;
160 }
161 set = set_dup( cp, lset, SLAP_SET_LREF2REF( op_flags ) );
162 goto done2;
163 }
164 slap_set_dispose( cp, lset, SLAP_SET_LREF2REF( op_flags ) );
165 set = set_dup( cp, rset, SLAP_SET_RREF2REF( op_flags ) );
166 goto done2;
167 }
168 if ( rset == NULL || BER_BVISNULL( &rset[ 0 ] ) ) {
169 slap_set_dispose( cp, rset, SLAP_SET_RREF2REF( op_flags ) );
170 set = set_dup( cp, lset, SLAP_SET_LREF2REF( op_flags ) );
171 goto done2;
172 }
173
174 /* worst scenario: no duplicates */
175 rlast = slap_set_size( rset );
176 i = slap_set_size( lset ) + rlast + 1;
177 set = cp->set_op->o_tmpcalloc( i, sizeof( struct berval ), cp->set_op->o_tmpmemctx );
178 if ( set != NULL ) {
179 /* set_chase() depends on this routine to
180 * keep the first elements of the result
181 * set the same (and in the same order)
182 * as the left-set.
183 */
184 for ( i = 0; !BER_BVISNULL( &lset[ i ] ); i++ ) {
185 if ( op_flags & SLAP_SET_LREFVAL ) {
186 ber_dupbv_x( &set[ i ], &lset[ i ], cp->set_op->o_tmpmemctx );
187
188 } else {
189 set[ i ] = lset[ i ];
190 }
191 }
192
193 /* pointers to values have been used in set - don't free twice */
194 op_flags |= SLAP_SET_LREFVAL;
195
196 last = i;
197
198 for ( i = 0; !BER_BVISNULL( &rset[ i ] ); i++ ) {
199 int exists = 0;
200
201 for ( j = 0; !BER_BVISNULL( &set[ j ] ); j++ ) {
202 if ( bvmatch( &rset[ i ], &set[ j ] ) )
203 {
204 if ( !( op_flags & SLAP_SET_RREFVAL ) ) {
205 cp->set_op->o_tmpfree( rset[ i ].bv_val, cp->set_op->o_tmpmemctx );
206 rset[ i ] = rset[ --rlast ];
207 BER_BVZERO( &rset[ rlast ] );
208 i--;
209 }
210 exists = 1;
211 break;
212 }
213 }
214
215 if ( !exists ) {
216 if ( op_flags & SLAP_SET_RREFVAL ) {
217 ber_dupbv_x( &set[ last ], &rset[ i ], cp->set_op->o_tmpmemctx );
218
219 } else {
220 set[ last ] = rset[ i ];
221 }
222 last++;
223 }
224 }
225
226 /* pointers to values have been used in set - don't free twice */
227 op_flags |= SLAP_SET_RREFVAL;
228
229 BER_BVZERO( &set[ last ] );
230 }
231 break;
232
233 case '&': /* intersection */
234 if ( lset == NULL || BER_BVISNULL( &lset[ 0 ] )
235 || rset == NULL || BER_BVISNULL( &rset[ 0 ] ) )
236 {
237 set = cp->set_op->o_tmpcalloc( 1, sizeof( struct berval ),
238 cp->set_op->o_tmpmemctx );
239 BER_BVZERO( &set[ 0 ] );
240 break;
241
242 } else {
243 long llen, rlen;
244 BerVarray sset;
245
246 llen = slap_set_size( lset );
247 rlen = slap_set_size( rset );
248
249 /* dup the shortest */
250 if ( llen < rlen ) {
251 last = llen;
252 set = set_dup( cp, lset, SLAP_SET_LREF2REF( op_flags ) );
253 lset = NULL;
254 sset = rset;
255
256 } else {
257 last = rlen;
258 set = set_dup( cp, rset, SLAP_SET_RREF2REF( op_flags ) );
259 rset = NULL;
260 sset = lset;
261 }
262
263 if ( set == NULL ) {
264 break;
265 }
266
267 for ( i = 0; !BER_BVISNULL( &set[ i ] ); i++ ) {
268 for ( j = 0; !BER_BVISNULL( &sset[ j ] ); j++ ) {
269 if ( bvmatch( &set[ i ], &sset[ j ] ) ) {
270 break;
271 }
272 }
273
274 if ( BER_BVISNULL( &sset[ j ] ) ) {
275 cp->set_op->o_tmpfree( set[ i ].bv_val, cp->set_op->o_tmpmemctx );
276 set[ i ] = set[ --last ];
277 BER_BVZERO( &set[ last ] );
278 i--;
279 }
280 }
281 }
282 break;
283
284 case '+': /* string concatenation */
285 i = slap_set_size( rset );
286 j = slap_set_size( lset );
287
288 /* handle empty set cases */
289 if ( i == 0 || j == 0 ) {
290 set = cp->set_op->o_tmpcalloc( 1, sizeof( struct berval ),
291 cp->set_op->o_tmpmemctx );
292 if ( set == NULL ) {
293 break;
294 }
295 BER_BVZERO( &set[ 0 ] );
296 break;
297 }
298
299 set = cp->set_op->o_tmpcalloc( i * j + 1, sizeof( struct berval ),
300 cp->set_op->o_tmpmemctx );
301 if ( set == NULL ) {
302 break;
303 }
304
305 for ( last = 0, i = 0; !BER_BVISNULL( &lset[ i ] ); i++ ) {
306 for ( j = 0; !BER_BVISNULL( &rset[ j ] ); j++ ) {
307 struct berval bv;
308 long k;
309
310 /* don't concatenate with the empty string */
311 if ( BER_BVISEMPTY( &lset[ i ] ) ) {
312 ber_dupbv_x( &bv, &rset[ j ], cp->set_op->o_tmpmemctx );
313 if ( bv.bv_val == NULL ) {
314 ber_bvarray_free_x( set, cp->set_op->o_tmpmemctx );
315 set = NULL;
316 goto done;
317 }
318
319 } else if ( BER_BVISEMPTY( &rset[ j ] ) ) {
320 ber_dupbv_x( &bv, &lset[ i ], cp->set_op->o_tmpmemctx );
321 if ( bv.bv_val == NULL ) {
322 ber_bvarray_free_x( set, cp->set_op->o_tmpmemctx );
323 set = NULL;
324 goto done;
325 }
326
327 } else {
328 bv.bv_len = lset[ i ].bv_len + rset[ j ].bv_len;
329 bv.bv_val = cp->set_op->o_tmpalloc( bv.bv_len + 1,
330 cp->set_op->o_tmpmemctx );
331 if ( bv.bv_val == NULL ) {
332 ber_bvarray_free_x( set, cp->set_op->o_tmpmemctx );
333 set = NULL;
334 goto done;
335 }
336 AC_MEMCPY( bv.bv_val, lset[ i ].bv_val, lset[ i ].bv_len );
337 AC_MEMCPY( &bv.bv_val[ lset[ i ].bv_len ], rset[ j ].bv_val, rset[ j ].bv_len );
338 bv.bv_val[ bv.bv_len ] = '\0';
339 }
340
341 for ( k = 0; k < last; k++ ) {
342 if ( bvmatch( &set[ k ], &bv ) ) {
343 cp->set_op->o_tmpfree( bv.bv_val, cp->set_op->o_tmpmemctx );
344 break;
345 }
346 }
347
348 if ( k == last ) {
349 set[ last++ ] = bv;
350 }
351 }
352 }
353 BER_BVZERO( &set[ last ] );
354 break;
355
356 default:
357 break;
358 }
359
360 done:;
361 if ( lset ) slap_set_dispose( cp, lset, SLAP_SET_LREF2REF( op_flags ) );
362 if ( rset ) slap_set_dispose( cp, rset, SLAP_SET_RREF2REF( op_flags ) );
363
364 done2:;
365 if ( LogTest( LDAP_DEBUG_ACL ) ) {
366 if ( !set || BER_BVISNULL( set ) ) {
367 Debug( LDAP_DEBUG_ACL, " ACL set: empty\n" );
368
369 } else {
370 for ( i = 0; !BER_BVISNULL( &set[ i ] ); i++ ) {
371 Debug( LDAP_DEBUG_ACL, " ACL set[%ld]=%s\n", i, set[i].bv_val );
372 }
373 }
374 }
375
376 return set;
377 }
378
379 static BerVarray
set_chase(SLAP_SET_GATHER gatherer,SetCookie * cp,BerVarray set,AttributeDescription * desc,int closure)380 set_chase( SLAP_SET_GATHER gatherer,
381 SetCookie *cp, BerVarray set, AttributeDescription *desc, int closure )
382 {
383 BerVarray vals, nset;
384 int i;
385
386 if ( set == NULL ) {
387 set = cp->set_op->o_tmpcalloc( 1, sizeof( struct berval ),
388 cp->set_op->o_tmpmemctx );
389 if ( set != NULL ) {
390 BER_BVZERO( &set[ 0 ] );
391 }
392 return set;
393 }
394
395 if ( BER_BVISNULL( set ) ) {
396 return set;
397 }
398
399 nset = cp->set_op->o_tmpcalloc( 1, sizeof( struct berval ), cp->set_op->o_tmpmemctx );
400 if ( nset == NULL ) {
401 ber_bvarray_free_x( set, cp->set_op->o_tmpmemctx );
402 return NULL;
403 }
404 for ( i = 0; !BER_BVISNULL( &set[ i ] ); i++ ) {
405 vals = gatherer( cp, &set[ i ], desc );
406 if ( vals != NULL ) {
407 nset = slap_set_join( cp, nset, '|', vals );
408 }
409 }
410 ber_bvarray_free_x( set, cp->set_op->o_tmpmemctx );
411
412 if ( closure ) {
413 for ( i = 0; !BER_BVISNULL( &nset[ i ] ); i++ ) {
414 vals = gatherer( cp, &nset[ i ], desc );
415 if ( vals != NULL ) {
416 nset = slap_set_join( cp, nset, '|', vals );
417 if ( nset == NULL ) {
418 break;
419 }
420 }
421 }
422 }
423
424 return nset;
425 }
426
427
428 static BerVarray
set_parents(SetCookie * cp,BerVarray set)429 set_parents( SetCookie *cp, BerVarray set )
430 {
431 int i, j, last;
432 struct berval bv, pbv;
433 BerVarray nset, vals;
434
435 if ( set == NULL ) {
436 set = cp->set_op->o_tmpcalloc( 1, sizeof( struct berval ),
437 cp->set_op->o_tmpmemctx );
438 if ( set != NULL ) {
439 BER_BVZERO( &set[ 0 ] );
440 }
441 return set;
442 }
443
444 if ( BER_BVISNULL( &set[ 0 ] ) ) {
445 return set;
446 }
447
448 nset = cp->set_op->o_tmpcalloc( 1, sizeof( struct berval ), cp->set_op->o_tmpmemctx );
449 if ( nset == NULL ) {
450 ber_bvarray_free_x( set, cp->set_op->o_tmpmemctx );
451 return NULL;
452 }
453
454 BER_BVZERO( &nset[ 0 ] );
455
456 for ( i = 0; !BER_BVISNULL( &set[ i ] ); i++ ) {
457 int level = 1;
458
459 pbv = bv = set[ i ];
460 for ( ; !BER_BVISEMPTY( &pbv ); dnParent( &bv, &pbv ) ) {
461 level++;
462 bv = pbv;
463 }
464
465 vals = cp->set_op->o_tmpcalloc( level + 1, sizeof( struct berval ), cp->set_op->o_tmpmemctx );
466 if ( vals == NULL ) {
467 ber_bvarray_free_x( set, cp->set_op->o_tmpmemctx );
468 ber_bvarray_free_x( nset, cp->set_op->o_tmpmemctx );
469 return NULL;
470 }
471 BER_BVZERO( &vals[ 0 ] );
472 last = 0;
473
474 bv = set[ i ];
475 for ( j = 0 ; j < level ; j++ ) {
476 ber_dupbv_x( &vals[ last ], &bv, cp->set_op->o_tmpmemctx );
477 last++;
478 dnParent( &bv, &bv );
479 }
480 BER_BVZERO( &vals[ last ] );
481
482 nset = slap_set_join( cp, nset, '|', vals );
483 }
484
485 ber_bvarray_free_x( set, cp->set_op->o_tmpmemctx );
486
487 return nset;
488 }
489
490
491
492 static BerVarray
set_parent(SetCookie * cp,BerVarray set,int level)493 set_parent( SetCookie *cp, BerVarray set, int level )
494 {
495 int i, j, last;
496 struct berval bv;
497 BerVarray nset;
498
499 if ( set == NULL ) {
500 set = cp->set_op->o_tmpcalloc( 1, sizeof( struct berval ),
501 cp->set_op->o_tmpmemctx );
502 if ( set != NULL ) {
503 BER_BVZERO( &set[ 0 ] );
504 }
505 return set;
506 }
507
508 if ( BER_BVISNULL( &set[ 0 ] ) ) {
509 return set;
510 }
511
512 nset = cp->set_op->o_tmpcalloc( slap_set_size( set ) + 1, sizeof( struct berval ), cp->set_op->o_tmpmemctx );
513 if ( nset == NULL ) {
514 ber_bvarray_free_x( set, cp->set_op->o_tmpmemctx );
515 return NULL;
516 }
517
518 BER_BVZERO( &nset[ 0 ] );
519 last = 0;
520
521 for ( i = 0; !BER_BVISNULL( &set[ i ] ); i++ ) {
522 bv = set[ i ];
523
524 for ( j = 0 ; j < level ; j++ ) {
525 dnParent( &bv, &bv );
526 }
527
528 for ( j = 0; !BER_BVISNULL( &nset[ j ] ); j++ ) {
529 if ( bvmatch( &bv, &nset[ j ] ) )
530 {
531 break;
532 }
533 }
534
535 if ( BER_BVISNULL( &nset[ j ] ) ) {
536 ber_dupbv_x( &nset[ last ], &bv, cp->set_op->o_tmpmemctx );
537 last++;
538 }
539 }
540
541 BER_BVZERO( &nset[ last ] );
542
543 ber_bvarray_free_x( set, cp->set_op->o_tmpmemctx );
544
545 return nset;
546 }
547
548 int
slap_set_filter(SLAP_SET_GATHER gatherer,SetCookie * cp,struct berval * fbv,struct berval * user,struct berval * target,BerVarray * results)549 slap_set_filter( SLAP_SET_GATHER gatherer,
550 SetCookie *cp, struct berval *fbv,
551 struct berval *user, struct berval *target, BerVarray *results )
552 {
553 #define STACK_SIZE 64
554 #define IS_SET(x) ( (unsigned long)(x) >= 256 )
555 #define IS_OP(x) ( (unsigned long)(x) < 256 )
556 #define SF_ERROR(x) do { rc = -1; goto _error; } while ( 0 )
557 #define SF_TOP() ( (BerVarray)( ( stp < 0 ) ? 0 : stack[ stp ] ) )
558 #define SF_POP() ( (BerVarray)( ( stp < 0 ) ? 0 : stack[ stp-- ] ) )
559 #define SF_PUSH(x) do { \
560 if ( stp >= ( STACK_SIZE - 1 ) ) SF_ERROR( overflow ); \
561 stack[ ++stp ] = (BerVarray)(long)(x); \
562 } while ( 0 )
563
564 BerVarray set, lset;
565 BerVarray stack[ STACK_SIZE ] = { 0 };
566 int len, rc, stp;
567 unsigned long op;
568 char c, *filter = fbv->bv_val;
569
570 if ( results ) {
571 *results = NULL;
572 }
573
574 stp = -1;
575 while ( ( c = *filter++ ) ) {
576 set = NULL;
577 switch ( c ) {
578 case ' ':
579 case '\t':
580 case '\x0A':
581 case '\x0D':
582 break;
583
584 case '(' /* ) */ :
585 if ( IS_SET( SF_TOP() ) ) {
586 SF_ERROR( syntax );
587 }
588 SF_PUSH( c );
589 break;
590
591 case /* ( */ ')':
592 set = SF_POP();
593 if ( IS_OP( set ) ) {
594 SF_ERROR( syntax );
595 }
596 if ( SF_TOP() == (void *)'(' /* ) */ ) {
597 SF_POP();
598 SF_PUSH( set );
599 set = NULL;
600
601 } else if ( IS_OP( SF_TOP() ) ) {
602 op = (unsigned long)SF_POP();
603 lset = SF_POP();
604 SF_POP();
605 set = slap_set_join( cp, lset, op, set );
606 if ( set == NULL ) {
607 SF_ERROR( memory );
608 }
609 SF_PUSH( set );
610 set = NULL;
611
612 } else {
613 SF_ERROR( syntax );
614 }
615 break;
616
617 case '|': /* union */
618 case '&': /* intersection */
619 case '+': /* string concatenation */
620 set = SF_POP();
621 if ( IS_OP( set ) ) {
622 SF_ERROR( syntax );
623 }
624 if ( SF_TOP() == 0 || SF_TOP() == (void *)'(' /* ) */ ) {
625 SF_PUSH( set );
626 set = NULL;
627
628 } else if ( IS_OP( SF_TOP() ) ) {
629 op = (unsigned long)SF_POP();
630 lset = SF_POP();
631 set = slap_set_join( cp, lset, op, set );
632 if ( set == NULL ) {
633 SF_ERROR( memory );
634 }
635 SF_PUSH( set );
636 set = NULL;
637
638 } else {
639 SF_ERROR( syntax );
640 }
641 SF_PUSH( c );
642 break;
643
644 case '[' /* ] */:
645 if ( ( SF_TOP() == (void *)'/' ) || IS_SET( SF_TOP() ) ) {
646 SF_ERROR( syntax );
647 }
648 for ( len = 0; ( c = *filter++ ) && ( c != /* [ */ ']' ); len++ )
649 ;
650 if ( c == 0 ) {
651 SF_ERROR( syntax );
652 }
653
654 set = cp->set_op->o_tmpcalloc( 2, sizeof( struct berval ),
655 cp->set_op->o_tmpmemctx );
656 if ( set == NULL ) {
657 SF_ERROR( memory );
658 }
659 set->bv_val = cp->set_op->o_tmpcalloc( len + 1, sizeof( char ),
660 cp->set_op->o_tmpmemctx );
661 if ( BER_BVISNULL( set ) ) {
662 SF_ERROR( memory );
663 }
664 AC_MEMCPY( set->bv_val, &filter[ - len - 1 ], len );
665 set->bv_len = len;
666 SF_PUSH( set );
667 set = NULL;
668 break;
669
670 case '-':
671 if ( ( SF_TOP() == (void *)'/' )
672 && ( *filter == '*' || ASCII_DIGIT( *filter ) ) )
673 {
674 SF_POP();
675
676 if ( *filter == '*' ) {
677 set = set_parents( cp, SF_POP() );
678 filter++;
679
680 } else {
681 char *next = NULL;
682 long parent = strtol( filter, &next, 10 );
683
684 if ( next == filter ) {
685 SF_ERROR( syntax );
686 }
687
688 set = SF_POP();
689 if ( parent != 0 ) {
690 set = set_parent( cp, set, parent );
691 }
692 filter = next;
693 }
694
695 if ( set == NULL ) {
696 SF_ERROR( memory );
697 }
698
699 SF_PUSH( set );
700 set = NULL;
701 break;
702 } else {
703 c = *filter++;
704 if ( c != '>' ) {
705 SF_ERROR( syntax );
706 }
707 /* fall through to next case */
708 }
709
710 case '/':
711 if ( IS_OP( SF_TOP() ) ) {
712 SF_ERROR( syntax );
713 }
714 SF_PUSH( '/' );
715 break;
716
717 default:
718 if ( !AD_LEADCHAR( c ) ) {
719 SF_ERROR( syntax );
720 }
721 filter--;
722 for ( len = 1;
723 ( c = filter[ len ] ) && AD_CHAR( c );
724 len++ )
725 {
726 /* count */
727 if ( c == '-' && !AD_CHAR( filter[ len + 1 ] ) ) {
728 break;
729 }
730 }
731 if ( len == 4
732 && memcmp( "this", filter, len ) == 0 )
733 {
734 assert( !BER_BVISNULL( target ) );
735 if ( ( SF_TOP() == (void *)'/' ) || IS_SET( SF_TOP() ) ) {
736 SF_ERROR( syntax );
737 }
738 set = cp->set_op->o_tmpcalloc( 2, sizeof( struct berval ),
739 cp->set_op->o_tmpmemctx );
740 if ( set == NULL ) {
741 SF_ERROR( memory );
742 }
743 ber_dupbv_x( set, target, cp->set_op->o_tmpmemctx );
744 if ( BER_BVISNULL( set ) ) {
745 SF_ERROR( memory );
746 }
747 BER_BVZERO( &set[ 1 ] );
748
749 } else if ( len == 4
750 && memcmp( "user", filter, len ) == 0 )
751 {
752 if ( ( SF_TOP() == (void *)'/' ) || IS_SET( SF_TOP() ) ) {
753 SF_ERROR( syntax );
754 }
755 if ( BER_BVISNULL( user ) ) {
756 SF_ERROR( memory );
757 }
758 set = cp->set_op->o_tmpcalloc( 2, sizeof( struct berval ),
759 cp->set_op->o_tmpmemctx );
760 if ( set == NULL ) {
761 SF_ERROR( memory );
762 }
763 ber_dupbv_x( set, user, cp->set_op->o_tmpmemctx );
764 BER_BVZERO( &set[ 1 ] );
765
766 } else if ( SF_TOP() != (void *)'/' ) {
767 SF_ERROR( syntax );
768
769 } else {
770 struct berval fb2;
771 AttributeDescription *ad = NULL;
772 const char *text = NULL;
773
774 SF_POP();
775 fb2.bv_val = filter;
776 fb2.bv_len = len;
777
778 if ( slap_bv2ad( &fb2, &ad, &text ) != LDAP_SUCCESS ) {
779 SF_ERROR( syntax );
780 }
781
782 /* NOTE: ad must have distinguishedName syntax
783 * or expand in an LDAP URI if c == '*'
784 */
785
786 set = set_chase( gatherer,
787 cp, SF_POP(), ad, c == '*' );
788 if ( set == NULL ) {
789 SF_ERROR( memory );
790 }
791 if ( c == '*' ) {
792 len++;
793 }
794 }
795 filter += len;
796 SF_PUSH( set );
797 set = NULL;
798 break;
799 }
800 }
801
802 set = SF_POP();
803 if ( IS_OP( set ) ) {
804 SF_ERROR( syntax );
805 }
806 if ( SF_TOP() == 0 ) {
807 /* FIXME: ok ? */ ;
808
809 } else if ( IS_OP( SF_TOP() ) ) {
810 op = (unsigned long)SF_POP();
811 lset = SF_POP();
812 set = slap_set_join( cp, lset, op, set );
813 if ( set == NULL ) {
814 SF_ERROR( memory );
815 }
816
817 } else {
818 SF_ERROR( syntax );
819 }
820
821 rc = slap_set_isempty( set ) ? 0 : 1;
822 if ( results ) {
823 *results = set;
824 set = NULL;
825 }
826
827 _error:
828 if ( IS_SET( set ) ) {
829 ber_bvarray_free_x( set, cp->set_op->o_tmpmemctx );
830 }
831 while ( ( set = SF_POP() ) ) {
832 if ( IS_SET( set ) ) {
833 ber_bvarray_free_x( set, cp->set_op->o_tmpmemctx );
834 }
835 }
836 return rc;
837 }
838