1 /* $NetBSD: sets.c,v 1.1.1.7 2018/02/06 01:53:15 christos Exp $ */ 2 3 /* $OpenLDAP$ */ 4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 2000-2017 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.1.1.7 2018/02/06 01:53:15 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 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 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 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 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 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", 0, 0, 0 ); 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, 0 ); 372 } 373 } 374 } 375 376 return set; 377 } 378 379 static BerVarray 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 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 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 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