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