1 /* $NetBSD: result.c,v 1.4 2025/09/05 21:16:25 christos Exp $ */ 2 3 /* result.c - routines to send ldap results, errors, and referrals */ 4 /* $OpenLDAP$ */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 1998-2024 The OpenLDAP Foundation. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted only as authorized by the OpenLDAP 12 * Public License. 13 * 14 * A copy of this license is available in the file LICENSE in the 15 * top-level directory of the distribution or, alternatively, at 16 * <http://www.OpenLDAP.org/license.html>. 17 */ 18 /* Portions Copyright (c) 1995 Regents of the University of Michigan. 19 * All rights reserved. 20 * 21 * Redistribution and use in source and binary forms are permitted 22 * provided that this notice is preserved and that due credit is given 23 * to the University of Michigan at Ann Arbor. The name of the University 24 * may not be used to endorse or promote products derived from this 25 * software without specific prior written permission. This software 26 * is provided ``as is'' without express or implied warranty. 27 */ 28 29 #include <sys/cdefs.h> 30 __RCSID("$NetBSD: result.c,v 1.4 2025/09/05 21:16:25 christos Exp $"); 31 32 #include "portable.h" 33 34 #include <stdio.h> 35 36 #include <ac/socket.h> 37 #include <ac/errno.h> 38 #include <ac/string.h> 39 #include <ac/ctype.h> 40 #include <ac/time.h> 41 #include <ac/unistd.h> 42 43 #include "slap.h" 44 45 #if SLAP_STATS_ETIME 46 #define ETIME_SETUP \ 47 struct timeval now; \ 48 char timestr[64]; \ 49 (void) gettimeofday( &now, NULL ); \ 50 now.tv_sec -= op->o_time; \ 51 now.tv_usec -= op->o_tusec; \ 52 if ( now.tv_usec < 0 ) { \ 53 --now.tv_sec; now.tv_usec += 1000000; \ 54 } \ 55 sprintf(timestr, "qtime=%d.%06d etime=%d.%06d", \ 56 (int)op->o_qtime.tv_sec, (int)op->o_qtime.tv_usec, \ 57 (int)now.tv_sec, (int)now.tv_usec); 58 #define ETIME_LOGFMT "%s " 59 #define StatslogEtime(lvl,fmt,pfx,tag,err,...) \ 60 Debug(lvl,fmt,pfx,tag,err,timestr,__VA_ARGS__) 61 #else 62 #define ETIME_SETUP 63 #define ETIME_LOGFMT "" 64 #define StatslogEtime Debug 65 #endif /* SLAP_STATS_ETIME */ 66 67 const struct berval slap_dummy_bv = BER_BVNULL; 68 69 int slap_null_cb( Operation *op, SlapReply *rs ) 70 { 71 return 0; 72 } 73 74 int slap_freeself_cb( Operation *op, SlapReply *rs ) 75 { 76 assert( op->o_callback != NULL ); 77 78 op->o_tmpfree( op->o_callback, op->o_tmpmemctx ); 79 op->o_callback = NULL; 80 81 return SLAP_CB_CONTINUE; 82 } 83 84 static char *v2ref( BerVarray ref, const char *text ) 85 { 86 size_t len = 0, i = 0; 87 char *v2; 88 89 if(ref == NULL) { 90 if (text) { 91 return ch_strdup(text); 92 } else { 93 return NULL; 94 } 95 } 96 97 if ( text != NULL ) { 98 len = strlen( text ); 99 if (text[len-1] != '\n') { 100 i = 1; 101 } 102 } 103 104 v2 = ch_malloc( len+i+sizeof("Referral:") ); 105 106 if( text != NULL ) { 107 strcpy(v2, text); 108 if( i ) { 109 v2[len++] = '\n'; 110 } 111 } 112 strcpy( v2+len, "Referral:" ); 113 len += sizeof("Referral:"); 114 115 for( i=0; ref[i].bv_val != NULL; i++ ) { 116 v2 = ch_realloc( v2, len + ref[i].bv_len + 1 ); 117 v2[len-1] = '\n'; 118 AC_MEMCPY(&v2[len], ref[i].bv_val, ref[i].bv_len ); 119 len += ref[i].bv_len; 120 if (ref[i].bv_val[ref[i].bv_len-1] != '/') { 121 ++len; 122 } 123 } 124 125 v2[len-1] = '\0'; 126 return v2; 127 } 128 129 ber_tag_t 130 slap_req2res( ber_tag_t tag ) 131 { 132 switch( tag ) { 133 case LDAP_REQ_ADD: 134 case LDAP_REQ_BIND: 135 case LDAP_REQ_COMPARE: 136 case LDAP_REQ_EXTENDED: 137 case LDAP_REQ_MODIFY: 138 case LDAP_REQ_MODRDN: 139 tag++; 140 break; 141 142 case LDAP_REQ_DELETE: 143 tag = LDAP_RES_DELETE; 144 break; 145 146 case LDAP_REQ_ABANDON: 147 case LDAP_REQ_UNBIND: 148 tag = LBER_SEQUENCE; 149 break; 150 151 case LDAP_REQ_SEARCH: 152 tag = LDAP_RES_SEARCH_RESULT; 153 break; 154 155 default: 156 tag = LBER_SEQUENCE; 157 } 158 159 return tag; 160 } 161 162 /* 163 * SlapReply debugging enabled by USE_RS_ASSERT. 164 * 165 * Disabled by default, but compiled in (but still unused) when 166 * LDAP_TEST. #define USE_RS_ASSERT as nonzero to enable some 167 * assertions which check the SlapReply. USE_RS_ASSERT = 2 or higher 168 * check aggressively, currently some code fail these tests. 169 * 170 * Environment variable $NO_RS_ASSERT controls how USE_RS_ASSERT handles 171 * errors. > 0: ignore errors, 0: abort (the default), < 0: just warn. 172 * 173 * Wrap LDAP operation calls in macros SLAP_OP() & co from proto-slap.h 174 * to check the SlapReply. contrib/slapd-tools/wrap_slap_ops converts 175 * source code to use the macros. 176 */ 177 #if defined(LDAP_TEST) || (defined(USE_RS_ASSERT) && (USE_RS_ASSERT)) 178 179 int rs_suppress_assert = 0; 180 181 /* RS_ASSERT() helper function */ 182 void rs_assert_(const char*file, unsigned line, const char*fn, const char*cond) 183 { 184 int no_assert = rs_suppress_assert, save_errno = errno; 185 const char *s; 186 187 if ( no_assert >= 0 ) { 188 if ( no_assert == 0 && (s = getenv( "NO_RS_ASSERT" )) && *s ) { 189 no_assert = rs_suppress_assert = atoi( s ); 190 } 191 if ( no_assert > 0 ) { 192 errno = save_errno; 193 return; 194 } 195 } 196 197 #ifdef rs_assert_ /* proto-slap.h #defined away the fn parameter */ 198 fprintf( stderr,"%s:%u: " "RS_ASSERT(%s) failed.\n", file,line,cond ); 199 #else 200 fprintf( stderr,"%s:%u: %s: RS_ASSERT(%s) failed.\n", file,line,fn,cond ); 201 #endif 202 fflush( stderr ); 203 204 errno = save_errno; 205 /* $NO_RS_ASSERT > 0: ignore rs_asserts, 0: abort, < 0: just warn */ 206 if ( !no_assert /* from $NO_RS_ASSERT */ ) abort(); 207 } 208 209 /* SlapReply is consistent */ 210 void 211 (rs_assert_ok)( const SlapReply *rs ) 212 { 213 const slap_mask_t flags = rs->sr_flags; 214 215 if ( flags & REP_ENTRY_MASK ) { 216 RS_ASSERT( !(flags & REP_ENTRY_MUSTRELEASE) 217 || !(flags & (REP_ENTRY_MASK ^ REP_ENTRY_MUSTRELEASE)) ); 218 RS_ASSERT( rs->sr_entry != NULL ); 219 RS_ASSERT( (1 << rs->sr_type) & 220 ((1 << REP_SEARCH) | (1 << REP_SEARCHREF) | 221 (1 << REP_RESULT) | (1 << REP_GLUE_RESULT)) ); 222 } 223 #if defined(USE_RS_ASSERT) && (USE_RS_ASSERT) > 1 /* TODO: Enable when safe */ 224 if ( (flags & (REP_MATCHED_MASK | REP_REF_MASK | REP_CTRLS_MASK)) ) { 225 RS_ASSERT( !(flags & REP_MATCHED_MASK) || rs->sr_matched ); 226 RS_ASSERT( !(flags & REP_CTRLS_MASK ) || rs->sr_ctrls ); 227 /* Note: LDAP_REFERRAL + !sr_ref is OK, becomes LDAP_NO_SUCH_OBJECT */ 228 } 229 #if (USE_RS_ASSERT) > 2 230 if ( rs->sr_err == LDAP_SUCCESS ) { 231 RS_ASSERT( rs->sr_text == NULL ); 232 RS_ASSERT( rs->sr_matched == NULL ); 233 } 234 #endif 235 #endif 236 } 237 238 /* Ready for calling a new backend operation */ 239 void 240 (rs_assert_ready)( const SlapReply *rs ) 241 { 242 RS_ASSERT( !rs->sr_entry ); 243 #if defined(USE_RS_ASSERT) && (USE_RS_ASSERT) > 1 /* TODO: Enable when safe */ 244 RS_ASSERT( !rs->sr_text ); 245 RS_ASSERT( !rs->sr_ref ); 246 RS_ASSERT( !rs->sr_matched ); 247 RS_ASSERT( !rs->sr_ctrls ); 248 RS_ASSERT( !rs->sr_flags ); 249 #if (USE_RS_ASSERT) > 2 250 RS_ASSERT( rs->sr_err == LDAP_SUCCESS ); 251 #endif 252 #else 253 RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); 254 #endif 255 } 256 257 /* Backend operation done */ 258 void 259 (rs_assert_done)( const SlapReply *rs ) 260 { 261 #if defined(USE_RS_ASSERT) && (USE_RS_ASSERT) > 1 /* TODO: Enable when safe */ 262 RS_ASSERT( !(rs->sr_flags & ~(REP_ENTRY_MODIFIABLE|REP_NO_OPERATIONALS)) ); 263 rs_assert_ok( rs ); 264 #else 265 RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MUSTFLUSH) ); 266 #endif 267 } 268 269 #endif /* LDAP_TEST || USE_RS_ASSERT */ 270 271 /* Reset a used SlapReply whose contents has been flushed (freed/released) */ 272 void 273 (rs_reinit)( SlapReply *rs, slap_reply_t type ) 274 { 275 rs_reinit( rs, type ); /* proto-slap.h macro */ 276 } 277 278 /* Obey and clear rs->sr_flags & REP_ENTRY_MASK. Clear sr_entry if freed. */ 279 void 280 rs_flush_entry( Operation *op, SlapReply *rs, slap_overinst *on ) 281 { 282 rs_assert_ok( rs ); 283 284 if ( (rs->sr_flags & REP_ENTRY_MUSTFLUSH) && rs->sr_entry != NULL ) { 285 if ( !(rs->sr_flags & REP_ENTRY_MUSTRELEASE) ) { 286 entry_free( rs->sr_entry ); 287 } else if ( on != NULL ) { 288 overlay_entry_release_ov( op, rs->sr_entry, 0, on ); 289 } else { 290 be_entry_release_rw( op, rs->sr_entry, 0 ); 291 } 292 rs->sr_entry = NULL; 293 } 294 295 rs->sr_flags &= ~REP_ENTRY_MASK; 296 } 297 298 /* Set rs->sr_entry after obeying and clearing sr_flags & REP_ENTRY_MASK. */ 299 void 300 rs_replace_entry( Operation *op, SlapReply *rs, slap_overinst *on, Entry *e ) 301 { 302 rs_flush_entry( op, rs, on ); 303 rs->sr_entry = e; 304 } 305 306 /* 307 * Ensure rs->sr_entry is modifiable, by duplicating it if necessary. 308 * Obey sr_flags. Set REP_ENTRY_<MODIFIABLE, and MUSTBEFREED if duplicated>. 309 * Return nonzero if rs->sr_entry was replaced. 310 */ 311 int 312 rs_entry2modifiable( Operation *op, SlapReply *rs, slap_overinst *on ) 313 { 314 if ( rs->sr_flags & REP_ENTRY_MODIFIABLE ) { 315 rs_assert_ok( rs ); 316 return 0; 317 } 318 rs_replace_entry( op, rs, on, entry_dup( rs->sr_entry )); 319 rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED; 320 return 1; 321 } 322 323 /* Check for any callbacks that want to be informed about being blocked 324 * on output. These callbacks are expected to leave the callback list 325 * unmodified. Their result is ignored. 326 */ 327 static void 328 slap_writewait_play( 329 Operation *op ) 330 { 331 slap_callback *sc = op->o_callback; 332 333 for ( ; sc; sc = sc->sc_next ) { 334 if ( sc->sc_writewait ) 335 sc->sc_writewait( op, sc ); 336 } 337 } 338 339 static long send_ldap_ber( 340 Operation *op, 341 BerElement *ber ) 342 { 343 Connection *conn = op->o_conn; 344 ber_len_t bytes; 345 long ret = 0; 346 char *close_reason; 347 int do_resume = 0; 348 349 ber_get_option( ber, LBER_OPT_BER_BYTES_TO_WRITE, &bytes ); 350 351 /* write only one pdu at a time - wait til it's our turn */ 352 ldap_pvt_thread_mutex_lock( &conn->c_write1_mutex ); 353 if (( op->o_abandon && !op->o_cancel ) || !connection_valid( conn ) || 354 conn->c_writers < 0 ) { 355 ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex ); 356 return 0; 357 } 358 359 conn->c_writers++; 360 361 while ( conn->c_writers > 0 && conn->c_writing ) { 362 ldap_pvt_thread_cond_wait( &conn->c_write1_cv, &conn->c_write1_mutex ); 363 } 364 365 /* connection was closed under us */ 366 if ( conn->c_writers < 0 ) { 367 /* we're the last waiter, let the closer continue */ 368 if ( conn->c_writers == -1 ) 369 ldap_pvt_thread_cond_signal( &conn->c_write1_cv ); 370 conn->c_writers++; 371 ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex ); 372 return 0; 373 } 374 375 /* Our turn */ 376 conn->c_writing = 1; 377 378 /* write the pdu */ 379 while( 1 ) { 380 int err; 381 char ebuf[128]; 382 383 if ( ber_flush2( conn->c_sb, ber, LBER_FLUSH_FREE_NEVER ) == 0 ) { 384 ret = bytes; 385 break; 386 } 387 388 err = sock_errno(); 389 390 /* 391 * we got an error. if it's ewouldblock, we need to 392 * wait on the socket being writable. otherwise, figure 393 * it's a hard error and return. 394 */ 395 396 Debug( LDAP_DEBUG_CONNS, "ber_flush2 failed errno=%d reason=\"%s\"\n", 397 err, sock_errstr(err, ebuf, sizeof(ebuf)) ); 398 399 if ( err != EWOULDBLOCK && err != EAGAIN ) { 400 close_reason = "connection lost on write"; 401 fail: 402 conn->c_writers--; 403 conn->c_writing = 0; 404 ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex ); 405 ldap_pvt_thread_mutex_lock( &conn->c_mutex ); 406 /* conn may have been reused by the time we get the mutex */ 407 if ( op->o_connid == conn->c_connid ) 408 connection_closing( conn, close_reason ); 409 ldap_pvt_thread_mutex_unlock( &conn->c_mutex ); 410 return -1; 411 } 412 413 /* if writer is blocked and we're waiting for a pool pause, 414 * just drop this connection. 415 */ 416 if ( ldap_pvt_thread_pool_pausing( &connection_pool ) > 0 ) { 417 close_reason = "writer blocked and pool pause pending"; 418 goto fail; 419 } 420 421 /* wait for socket to be write-ready */ 422 do_resume = 1; 423 conn->c_writewaiter = 1; 424 ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex ); 425 slap_writewait_play( op ); 426 err = slapd_wait_writer( conn->c_sd ); 427 conn->c_writewaiter = 0; 428 ldap_pvt_thread_mutex_lock( &conn->c_write1_mutex ); 429 /* 0 is timeout, so we close it. 430 * -1 is an error, close it. 431 */ 432 if ( err <= 0 ) { 433 if ( err == 0 ) 434 close_reason = "writetimeout"; 435 else 436 close_reason = "connection lost on writewait"; 437 goto fail; 438 } 439 440 if ( conn->c_writers < 0 ) { 441 ret = 0; 442 break; 443 } 444 } 445 446 conn->c_writing = 0; 447 if ( conn->c_writers < 0 ) { 448 /* shutting down, don't resume any ops */ 449 do_resume = 0; 450 conn->c_writers++; 451 if ( !conn->c_writers ) 452 ldap_pvt_thread_cond_signal( &conn->c_write1_cv ); 453 } else { 454 conn->c_writers--; 455 /* other writers are waiting, don't resume any ops */ 456 if ( conn->c_writers ) 457 do_resume = 0; 458 ldap_pvt_thread_cond_signal( &conn->c_write1_cv ); 459 } 460 ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex ); 461 462 /* If there are no more writers, release a pending op */ 463 if ( do_resume ) 464 connection_write_resume( conn ); 465 466 return ret; 467 } 468 469 static int 470 send_ldap_control( BerElement *ber, LDAPControl *c ) 471 { 472 int rc; 473 474 assert( c != NULL ); 475 476 rc = ber_printf( ber, "{s" /*}*/, c->ldctl_oid ); 477 478 if( c->ldctl_iscritical ) { 479 rc = ber_printf( ber, "b", 480 (ber_int_t) c->ldctl_iscritical ) ; 481 if( rc == -1 ) return rc; 482 } 483 484 if( c->ldctl_value.bv_val != NULL ) { 485 rc = ber_printf( ber, "O", &c->ldctl_value ); 486 if( rc == -1 ) return rc; 487 } 488 489 rc = ber_printf( ber, /*{*/"N}" ); 490 if( rc == -1 ) return rc; 491 492 return 0; 493 } 494 495 static int 496 send_ldap_controls( Operation *o, BerElement *ber, LDAPControl **c ) 497 { 498 int rc; 499 500 if( c == NULL ) 501 return 0; 502 503 rc = ber_printf( ber, "t{"/*}*/, LDAP_TAG_CONTROLS ); 504 if( rc == -1 ) return rc; 505 506 for( ; *c != NULL; c++) { 507 rc = send_ldap_control( ber, *c ); 508 if( rc == -1 ) return rc; 509 } 510 511 #ifdef SLAP_CONTROL_X_SORTEDRESULTS 512 /* this is a hack to avoid having to modify op->s_ctrls */ 513 if( o->o_sortedresults ) { 514 BerElementBuffer berbuf; 515 BerElement *sber = (BerElement *) &berbuf; 516 LDAPControl sorted; 517 BER_BVZERO( &sorted.ldctl_value ); 518 sorted.ldctl_oid = LDAP_CONTROL_SORTRESPONSE; 519 sorted.ldctl_iscritical = 0; 520 521 ber_init2( sber, NULL, LBER_USE_DER ); 522 523 ber_printf( sber, "{e}", LDAP_UNWILLING_TO_PERFORM ); 524 525 if( ber_flatten2( sber, &sorted.ldctl_value, 0 ) == -1 ) { 526 return -1; 527 } 528 529 (void) ber_free_buf( sber ); 530 531 rc = send_ldap_control( ber, &sorted ); 532 if( rc == -1 ) return rc; 533 } 534 #endif 535 536 rc = ber_printf( ber, /*{*/"N}" ); 537 538 return rc; 539 } 540 541 /* 542 * slap_response_play() 543 * 544 * plays the callback list; rationale: a callback can 545 * - remove itself from the list, by setting op->o_callback = NULL; 546 * malloc()'ed callbacks should free themselves from inside the 547 * sc_response() function. 548 * - replace itself with another (list of) callback(s), by setting 549 * op->o_callback = a new (list of) callback(s); in this case, it 550 * is the callback's responsibility to to append existing subsequent 551 * callbacks to the end of the list that is passed to the sc_response() 552 * function. 553 * - modify the list of subsequent callbacks by modifying the value 554 * of the sc_next field from inside the sc_response() function; this 555 * case does not require any handling from inside slap_response_play() 556 * 557 * To stop execution of the playlist, the sc_response() function must return 558 * a value different from SLAP_SC_CONTINUE. 559 * 560 * The same applies to slap_cleanup_play(); only, there is no means to stop 561 * execution of the playlist, since all cleanup functions must be called. 562 */ 563 static int 564 slap_response_play( 565 Operation *op, 566 SlapReply *rs ) 567 { 568 int rc; 569 570 slap_callback *sc = op->o_callback, **scp; 571 572 rc = SLAP_CB_CONTINUE; 573 for ( scp = ≻ *scp; ) { 574 slap_callback *sc_next = (*scp)->sc_next, **sc_nextp = &(*scp)->sc_next; 575 576 op->o_callback = *scp; 577 if ( op->o_callback->sc_response ) { 578 rc = op->o_callback->sc_response( op, rs ); 579 if ( op->o_callback == NULL ) { 580 /* the callback has been removed; 581 * repair the list */ 582 *scp = sc_next; 583 sc_nextp = scp; 584 585 } else if ( op->o_callback != *scp ) { 586 /* a new callback has been inserted 587 * in place of the existing one; repair the list */ 588 *scp = op->o_callback; 589 sc_nextp = scp; 590 } 591 if ( rc != SLAP_CB_CONTINUE ) break; 592 } 593 scp = sc_nextp; 594 } 595 596 op->o_callback = sc; 597 return rc; 598 } 599 600 static int 601 slap_cleanup_play( 602 Operation *op, 603 SlapReply *rs ) 604 { 605 slap_callback *sc = op->o_callback, **scp; 606 607 for ( scp = ≻ *scp; ) { 608 slap_callback *sc_next = (*scp)->sc_next, **sc_nextp = &(*scp)->sc_next; 609 610 op->o_callback = *scp; 611 if ( op->o_callback->sc_cleanup ) { 612 (void)op->o_callback->sc_cleanup( op, rs ); 613 if ( op->o_callback == NULL ) { 614 /* the callback has been removed; 615 * repair the list */ 616 *scp = sc_next; 617 sc_nextp = scp; 618 619 } else if ( op->o_callback != *scp ) { 620 /* a new callback has been inserted 621 * after the existing one; repair the list */ 622 /* a new callback has been inserted 623 * in place of the existing one; repair the list */ 624 *scp = op->o_callback; 625 sc_nextp = scp; 626 } 627 /* don't care about the result; do all cleanup */ 628 } 629 scp = sc_nextp; 630 } 631 632 op->o_callback = sc; 633 return LDAP_SUCCESS; 634 } 635 636 static int 637 send_ldap_response( 638 Operation *op, 639 SlapReply *rs ) 640 { 641 BerElementBuffer berbuf; 642 BerElement *ber = (BerElement *) &berbuf; 643 int rc = LDAP_SUCCESS; 644 long bytes; 645 646 /* op was actually aborted, bypass everything if client didn't Cancel */ 647 if (( rs->sr_err == SLAPD_ABANDON ) && !op->o_cancel ) { 648 rc = SLAPD_ABANDON; 649 goto clean2; 650 } 651 652 if ( op->o_callback ) { 653 rc = slap_response_play( op, rs ); 654 if ( rc != SLAP_CB_CONTINUE ) { 655 goto clean2; 656 } 657 } 658 659 /* op completed, connection aborted, bypass sending response */ 660 if ( op->o_abandon && !op->o_cancel ) { 661 rc = SLAPD_ABANDON; 662 goto clean2; 663 } 664 665 #ifdef LDAP_CONNECTIONLESS 666 if (op->o_conn && op->o_conn->c_is_udp) 667 ber = op->o_res_ber; 668 else 669 #endif 670 { 671 ber_init_w_nullc( ber, LBER_USE_DER ); 672 ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); 673 } 674 675 rc = rs->sr_err; 676 if ( rc == SLAPD_ABANDON && op->o_cancel ) 677 rc = LDAP_CANCELLED; 678 679 Debug( LDAP_DEBUG_TRACE, 680 "send_ldap_response: msgid=%d tag=%lu err=%d\n", 681 rs->sr_msgid, rs->sr_tag, rc ); 682 683 if( rs->sr_ref ) { 684 Debug( LDAP_DEBUG_ARGS, "send_ldap_response: ref=\"%s\"\n", 685 rs->sr_ref[0].bv_val ? rs->sr_ref[0].bv_val : "NULL" ); 686 } 687 688 #ifdef LDAP_CONNECTIONLESS 689 if (op->o_conn && op->o_conn->c_is_udp && 690 op->o_protocol == LDAP_VERSION2 ) 691 { 692 rc = ber_printf( ber, "t{ess" /*"}"*/, 693 rs->sr_tag, rc, 694 rs->sr_matched == NULL ? "" : rs->sr_matched, 695 rs->sr_text == NULL ? "" : rs->sr_text ); 696 } else 697 #endif 698 if ( rs->sr_type == REP_INTERMEDIATE ) { 699 rc = ber_printf( ber, "{it{" /*"}}"*/, 700 rs->sr_msgid, rs->sr_tag ); 701 702 } else { 703 rc = ber_printf( ber, "{it{ess" /*"}}"*/, 704 rs->sr_msgid, rs->sr_tag, rc, 705 rs->sr_matched == NULL ? "" : rs->sr_matched, 706 rs->sr_text == NULL ? "" : rs->sr_text ); 707 } 708 709 if( rc != -1 ) { 710 if ( rs->sr_ref != NULL ) { 711 assert( rs->sr_err == LDAP_REFERRAL ); 712 rc = ber_printf( ber, "t{W}", 713 LDAP_TAG_REFERRAL, rs->sr_ref ); 714 } else { 715 assert( rs->sr_err != LDAP_REFERRAL ); 716 } 717 } 718 719 if( rc != -1 && rs->sr_type == REP_SASL && rs->sr_sasldata != NULL ) { 720 rc = ber_printf( ber, "tO", 721 LDAP_TAG_SASL_RES_CREDS, rs->sr_sasldata ); 722 } 723 724 if( rc != -1 && 725 ( rs->sr_type == REP_EXTENDED || rs->sr_type == REP_INTERMEDIATE )) 726 { 727 if ( rs->sr_rspoid != NULL ) { 728 rc = ber_printf( ber, "ts", 729 rs->sr_type == REP_EXTENDED 730 ? LDAP_TAG_EXOP_RES_OID : LDAP_TAG_IM_RES_OID, 731 rs->sr_rspoid ); 732 } 733 if( rc != -1 && rs->sr_rspdata != NULL ) { 734 rc = ber_printf( ber, "tO", 735 rs->sr_type == REP_EXTENDED 736 ? LDAP_TAG_EXOP_RES_VALUE : LDAP_TAG_IM_RES_VALUE, 737 rs->sr_rspdata ); 738 } 739 } 740 741 if( rc != -1 ) { 742 rc = ber_printf( ber, /*"{"*/ "N}" ); 743 } 744 745 if( rc != -1 ) { 746 rc = send_ldap_controls( op, ber, rs->sr_ctrls ); 747 } 748 749 if( rc != -1 ) { 750 rc = ber_printf( ber, /*"{"*/ "N}" ); 751 } 752 753 #ifdef LDAP_CONNECTIONLESS 754 if( op->o_conn && op->o_conn->c_is_udp && op->o_protocol == LDAP_VERSION2 755 && rc != -1 ) 756 { 757 rc = ber_printf( ber, /*"{"*/ "N}" ); 758 } 759 #endif 760 761 if ( rc == -1 ) { 762 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n" ); 763 764 #ifdef LDAP_CONNECTIONLESS 765 if (!op->o_conn || op->o_conn->c_is_udp == 0) 766 #endif 767 { 768 ber_free_buf( ber ); 769 } 770 goto cleanup; 771 } 772 773 /* send BER */ 774 bytes = send_ldap_ber( op, ber ); 775 #ifdef LDAP_CONNECTIONLESS 776 if (!op->o_conn || op->o_conn->c_is_udp == 0) 777 #endif 778 { 779 ber_free_buf( ber ); 780 } 781 782 if ( bytes < 0 ) { 783 Debug( LDAP_DEBUG_ANY, 784 "send_ldap_response: ber write failed\n" ); 785 786 goto cleanup; 787 } 788 789 ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex ); 790 ldap_pvt_mp_add_ulong( op->o_counters->sc_pdu, 1 ); 791 ldap_pvt_mp_add_ulong( op->o_counters->sc_bytes, (unsigned long)bytes ); 792 ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex ); 793 794 cleanup:; 795 /* Tell caller that we did this for real, as opposed to being 796 * overridden by a callback 797 */ 798 rc = SLAP_CB_CONTINUE; 799 800 clean2:; 801 if ( op->o_callback ) { 802 (void)slap_cleanup_play( op, rs ); 803 } 804 805 if ( rs->sr_flags & REP_MATCHED_MUSTBEFREED ) { 806 rs->sr_flags ^= REP_MATCHED_MUSTBEFREED; /* paranoia */ 807 if ( rs->sr_matched ) { 808 free( (char *)rs->sr_matched ); 809 rs->sr_matched = NULL; 810 } 811 } 812 813 if ( rs->sr_flags & REP_REF_MUSTBEFREED ) { 814 rs->sr_flags ^= REP_REF_MUSTBEFREED; /* paranoia */ 815 if ( rs->sr_ref ) { 816 ber_bvarray_free( rs->sr_ref ); 817 rs->sr_ref = NULL; 818 } 819 } 820 821 if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) { 822 rs->sr_flags ^= REP_CTRLS_MUSTBEFREED; /* paranoia */ 823 if ( rs->sr_ctrls ) { 824 slap_free_ctrls( op, rs->sr_ctrls ); 825 rs->sr_ctrls = NULL; 826 } 827 } 828 829 return rc; 830 } 831 832 833 void 834 send_ldap_disconnect( Operation *op, SlapReply *rs ) 835 { 836 #define LDAP_UNSOLICITED_ERROR(e) \ 837 ( (e) == LDAP_PROTOCOL_ERROR \ 838 || (e) == LDAP_STRONG_AUTH_REQUIRED \ 839 || (e) == LDAP_UNAVAILABLE ) 840 841 Debug( LDAP_DEBUG_TRACE, 842 "send_ldap_disconnect %d:%s\n", 843 rs->sr_err, rs->sr_text ? rs->sr_text : "" ); 844 assert( LDAP_UNSOLICITED_ERROR( rs->sr_err ) ); 845 846 /* TODO: Flush the entry if sr_type == REP_SEARCH/REP_SEARCHREF? */ 847 RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); 848 rs->sr_flags &= ~REP_ENTRY_MASK; /* paranoia */ 849 850 rs->sr_type = REP_EXTENDED; 851 rs->sr_rspdata = NULL; 852 853 if ( op->o_protocol < LDAP_VERSION3 ) { 854 rs->sr_rspoid = NULL; 855 rs->sr_tag = slap_req2res( op->o_tag ); 856 rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0; 857 858 } else { 859 rs->sr_rspoid = LDAP_NOTICE_DISCONNECT; 860 rs->sr_tag = LDAP_RES_EXTENDED; 861 rs->sr_msgid = LDAP_RES_UNSOLICITED; 862 } 863 864 if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) { 865 ETIME_SETUP; 866 StatslogEtime( LDAP_DEBUG_STATS, 867 "%s DISCONNECT tag=%lu err=%d "ETIME_LOGFMT"text=%s\n", 868 op->o_log_prefix, rs->sr_tag, rs->sr_err, 869 rs->sr_text ? rs->sr_text : "" ); 870 } 871 } 872 873 void 874 slap_send_ldap_result( Operation *op, SlapReply *rs ) 875 { 876 char *tmp = NULL; 877 const char *otext = rs->sr_text; 878 BerVarray oref = rs->sr_ref; 879 880 rs->sr_type = REP_RESULT; 881 882 /* Propagate Abandons so that cleanup callbacks can be processed */ 883 if ( rs->sr_err == SLAPD_ABANDON || op->o_abandon ) 884 goto abandon; 885 886 Debug( LDAP_DEBUG_TRACE, 887 "send_ldap_result: %s p=%d\n", 888 op->o_log_prefix, op->o_protocol ); 889 Debug( LDAP_DEBUG_ARGS, 890 "send_ldap_result: err=%d matched=\"%s\" text=\"%s\"\n", 891 rs->sr_err, rs->sr_matched ? rs->sr_matched : "", 892 rs->sr_text ? rs->sr_text : "" ); 893 if( rs->sr_ref ) { 894 Debug( LDAP_DEBUG_ARGS, 895 "send_ldap_result: referral=\"%s\"\n", 896 rs->sr_ref[0].bv_val ? rs->sr_ref[0].bv_val : "NULL" ); 897 } 898 assert( !LDAP_API_ERROR( rs->sr_err ) ); 899 assert( rs->sr_err != LDAP_PARTIAL_RESULTS ); 900 901 if ( rs->sr_err == LDAP_REFERRAL ) { 902 if( op->o_domain_scope ) rs->sr_ref = NULL; 903 904 if( rs->sr_ref == NULL ) { 905 rs->sr_err = LDAP_NO_SUCH_OBJECT; 906 } else if ( op->o_protocol < LDAP_VERSION3 ) { 907 rs->sr_err = LDAP_PARTIAL_RESULTS; 908 } 909 } 910 911 if ( op->o_protocol < LDAP_VERSION3 ) { 912 tmp = v2ref( rs->sr_ref, rs->sr_text ); 913 rs->sr_text = tmp; 914 rs->sr_ref = NULL; 915 } 916 917 abandon: 918 rs->sr_tag = slap_req2res( op->o_tag ); 919 rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0; 920 921 if ( rs->sr_flags & REP_REF_MUSTBEFREED ) { 922 if ( rs->sr_ref == NULL ) { 923 rs->sr_flags ^= REP_REF_MUSTBEFREED; 924 ber_bvarray_free( oref ); 925 } 926 oref = NULL; /* send_ldap_response() will free rs->sr_ref if != NULL */ 927 } 928 929 if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) { 930 ETIME_SETUP; 931 if ( op->o_tag == LDAP_REQ_SEARCH ) { 932 StatslogEtime( LDAP_DEBUG_STATS, 933 "%s SEARCH RESULT tag=%lu err=%d "ETIME_LOGFMT"nentries=%d text=%s\n", 934 op->o_log_prefix, rs->sr_tag, rs->sr_err, 935 rs->sr_nentries, rs->sr_text ? rs->sr_text : "" ); 936 } else { 937 StatslogEtime( LDAP_DEBUG_STATS, 938 "%s RESULT tag=%lu err=%d "ETIME_LOGFMT"text=%s\n", 939 op->o_log_prefix, rs->sr_tag, rs->sr_err, 940 rs->sr_text ? rs->sr_text : "" ); 941 } 942 } 943 944 if( tmp != NULL ) ch_free(tmp); 945 rs->sr_text = otext; 946 rs->sr_ref = oref; 947 } 948 949 void 950 send_ldap_sasl( Operation *op, SlapReply *rs ) 951 { 952 Debug( LDAP_DEBUG_TRACE, "send_ldap_sasl: err=%d len=%ld\n", 953 rs->sr_err, 954 rs->sr_sasldata ? (long) rs->sr_sasldata->bv_len : -1 ); 955 956 RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); 957 rs->sr_flags &= ~REP_ENTRY_MASK; /* paranoia */ 958 959 rs->sr_type = REP_SASL; 960 rs->sr_tag = slap_req2res( op->o_tag ); 961 rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0; 962 963 if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) { 964 ETIME_SETUP; 965 StatslogEtime( LDAP_DEBUG_STATS, 966 "%s RESULT tag=%lu err=%d "ETIME_LOGFMT"text=%s\n", 967 op->o_log_prefix, rs->sr_tag, rs->sr_err, 968 rs->sr_text ? rs->sr_text : "" ); 969 } 970 } 971 972 void 973 slap_send_ldap_extended( Operation *op, SlapReply *rs ) 974 { 975 Debug( LDAP_DEBUG_TRACE, 976 "send_ldap_extended: err=%d oid=%s len=%ld\n", 977 rs->sr_err, 978 rs->sr_rspoid ? rs->sr_rspoid : "", 979 rs->sr_rspdata != NULL ? rs->sr_rspdata->bv_len : 0 ); 980 981 RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); 982 rs->sr_flags &= ~REP_ENTRY_MASK; /* paranoia */ 983 984 rs->sr_type = REP_EXTENDED; 985 rs->sr_tag = slap_req2res( op->o_tag ); 986 rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0; 987 988 if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) { 989 ETIME_SETUP; 990 StatslogEtime( LDAP_DEBUG_STATS, 991 "%s RESULT oid=%s err=%d "ETIME_LOGFMT"text=%s\n", 992 op->o_log_prefix, rs->sr_rspoid ? rs->sr_rspoid : "", 993 rs->sr_err, rs->sr_text ? rs->sr_text : "" ); 994 } 995 } 996 997 void 998 slap_send_ldap_intermediate( Operation *op, SlapReply *rs ) 999 { 1000 Debug( LDAP_DEBUG_TRACE, 1001 "send_ldap_intermediate: err=%d oid=%s len=%ld\n", 1002 rs->sr_err, 1003 rs->sr_rspoid ? rs->sr_rspoid : "", 1004 rs->sr_rspdata != NULL ? rs->sr_rspdata->bv_len : 0 ); 1005 1006 RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); 1007 rs->sr_flags &= ~REP_ENTRY_MASK; /* paranoia */ 1008 1009 rs->sr_type = REP_INTERMEDIATE; 1010 rs->sr_tag = LDAP_RES_INTERMEDIATE; 1011 rs->sr_msgid = op->o_msgid; 1012 if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) { 1013 Debug( LDAP_DEBUG_STATS2, 1014 "%s INTERMEDIATE oid=%s\n", 1015 op->o_log_prefix, 1016 rs->sr_rspoid ? rs->sr_rspoid : "" ); 1017 } 1018 } 1019 1020 #define set_ldap_error( rs, err, text ) do { \ 1021 (rs)->sr_err = err; (rs)->sr_text = text; } while(0) 1022 1023 /* 1024 * returns: 1025 * 1026 * LDAP_SUCCESS entry sent 1027 * LDAP_OTHER entry not sent (other) 1028 * LDAP_INSUFFICIENT_ACCESS entry not sent (ACL) 1029 * LDAP_UNAVAILABLE entry not sent (connection closed) 1030 * LDAP_SIZELIMIT_EXCEEDED entry not sent (caller must send sizelimitExceeded) 1031 */ 1032 1033 int 1034 slap_send_search_entry( Operation *op, SlapReply *rs ) 1035 { 1036 BerElementBuffer berbuf; 1037 BerElement *ber = (BerElement *) &berbuf; 1038 Attribute *a; 1039 int i, j, rc = LDAP_UNAVAILABLE, bytes; 1040 int userattrs; 1041 AccessControlState acl_state = ACL_STATE_INIT; 1042 int attrsonly; 1043 AttributeDescription *ad_entry = slap_schema.si_ad_entry; 1044 1045 /* a_flags: array of flags telling if the i-th element will be 1046 * returned or filtered out 1047 * e_flags: array of a_flags 1048 */ 1049 char **e_flags = NULL; 1050 1051 rs->sr_type = REP_SEARCH; 1052 1053 if ( op->ors_slimit >= 0 && rs->sr_nentries >= op->ors_slimit ) { 1054 rc = LDAP_SIZELIMIT_EXCEEDED; 1055 goto error_return; 1056 } 1057 1058 /* Every 64 entries, check for thread pool pause */ 1059 if ( ( ( rs->sr_nentries & 0x3f ) == 0x3f ) && 1060 ldap_pvt_thread_pool_pausing( &connection_pool ) > 0 ) 1061 { 1062 rc = LDAP_BUSY; 1063 goto error_return; 1064 } 1065 1066 /* eventually will loop through generated operational attribute types 1067 * currently implemented types include: 1068 * entryDN, subschemaSubentry, and hasSubordinates */ 1069 /* NOTE: moved before overlays callback circling because 1070 * they may modify entry and other stuff in rs */ 1071 /* check for special all operational attributes ("+") type */ 1072 /* FIXME: maybe we could set this flag at the operation level; 1073 * however, in principle the caller of send_search_entry() may 1074 * change the attribute list at each call */ 1075 rs->sr_attr_flags = slap_attr_flags( rs->sr_attrs ); 1076 1077 rc = backend_operational( op, rs ); 1078 if ( rc ) { 1079 goto error_return; 1080 } 1081 1082 if ( op->o_callback ) { 1083 rc = slap_response_play( op, rs ); 1084 if ( rc != SLAP_CB_CONTINUE ) { 1085 goto error_return; 1086 } 1087 } 1088 1089 Debug( LDAP_DEBUG_TRACE, "=> send_search_entry: conn %lu dn=\"%s\"%s\n", 1090 op->o_connid, rs->sr_entry->e_name.bv_val, 1091 op->ors_attrsonly ? " (attrsOnly)" : "" ); 1092 1093 attrsonly = op->ors_attrsonly; 1094 1095 if ( !access_allowed( op, rs->sr_entry, ad_entry, NULL, ACL_READ, NULL )) { 1096 Debug( LDAP_DEBUG_ACL, 1097 "send_search_entry: conn %lu access to entry (%s) not allowed\n", 1098 op->o_connid, rs->sr_entry->e_name.bv_val ); 1099 1100 rc = LDAP_INSUFFICIENT_ACCESS; 1101 goto error_return; 1102 } 1103 1104 if ( op->o_res_ber ) { 1105 /* read back control or LDAP_CONNECTIONLESS */ 1106 ber = op->o_res_ber; 1107 } else { 1108 struct berval bv; 1109 1110 bv.bv_len = entry_flatsize( rs->sr_entry, 0 ); 1111 bv.bv_val = op->o_tmpalloc( bv.bv_len, op->o_tmpmemctx ); 1112 1113 ber_init2( ber, &bv, LBER_USE_DER ); 1114 ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); 1115 } 1116 1117 #ifdef LDAP_CONNECTIONLESS 1118 if ( op->o_conn && op->o_conn->c_is_udp ) { 1119 /* CONNECTIONLESS */ 1120 if ( op->o_protocol == LDAP_VERSION2 ) { 1121 rc = ber_printf(ber, "t{O{" /*}}*/, 1122 LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name ); 1123 } else { 1124 rc = ber_printf( ber, "{it{O{" /*}}}*/, op->o_msgid, 1125 LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name ); 1126 } 1127 } else 1128 #endif 1129 if ( op->o_res_ber ) { 1130 /* read back control */ 1131 rc = ber_printf( ber, "t{O{" /*}}*/, 1132 LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name ); 1133 } else { 1134 rc = ber_printf( ber, "{it{O{" /*}}}*/, op->o_msgid, 1135 LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name ); 1136 } 1137 1138 if ( rc == -1 ) { 1139 Debug( LDAP_DEBUG_ANY, 1140 "send_search_entry: conn %lu ber_printf failed\n", 1141 op->o_connid ); 1142 1143 if ( op->o_res_ber == NULL ) ber_free_buf( ber ); 1144 set_ldap_error( rs, LDAP_OTHER, "encoding DN error" ); 1145 rc = rs->sr_err; 1146 goto error_return; 1147 } 1148 1149 /* check for special all user attributes ("*") type */ 1150 userattrs = SLAP_USERATTRS( rs->sr_attr_flags ); 1151 1152 /* create an array of arrays of flags. Each flag corresponds 1153 * to particular value of attribute and equals 1 if value matches 1154 * to ValuesReturnFilter or 0 if not 1155 */ 1156 if ( op->o_vrFilter != NULL ) { 1157 int k = 0; 1158 size_t size; 1159 1160 for ( a = rs->sr_entry->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) { 1161 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++; 1162 } 1163 1164 size = i * sizeof(char *) + k; 1165 if ( size > 0 ) { 1166 char *a_flags; 1167 e_flags = slap_sl_calloc ( 1, i * sizeof(char *) + k, op->o_tmpmemctx ); 1168 if( e_flags == NULL ) { 1169 Debug( LDAP_DEBUG_ANY, 1170 "send_search_entry: conn %lu slap_sl_calloc failed\n", 1171 op->o_connid ); 1172 ber_free( ber, 1 ); 1173 1174 set_ldap_error( rs, LDAP_OTHER, "out of memory" ); 1175 goto error_return; 1176 } 1177 a_flags = (char *)(e_flags + i); 1178 memset( a_flags, 0, k ); 1179 for ( a=rs->sr_entry->e_attrs, i=0; a != NULL; a=a->a_next, i++ ) { 1180 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ); 1181 e_flags[i] = a_flags; 1182 a_flags += j; 1183 } 1184 1185 rc = filter_matched_values(op, rs->sr_entry->e_attrs, &e_flags) ; 1186 if ( rc == -1 ) { 1187 Debug( LDAP_DEBUG_ANY, "send_search_entry: " 1188 "conn %lu matched values filtering failed\n", 1189 op->o_connid ); 1190 if ( op->o_res_ber == NULL ) ber_free_buf( ber ); 1191 set_ldap_error( rs, LDAP_OTHER, 1192 "matched values filtering error" ); 1193 rc = rs->sr_err; 1194 goto error_return; 1195 } 1196 } 1197 } 1198 1199 for ( a = rs->sr_entry->e_attrs, j = 0; a != NULL; a = a->a_next, j++ ) { 1200 AttributeDescription *desc = a->a_desc; 1201 int finish = 0; 1202 1203 if ( rs->sr_attrs == NULL ) { 1204 /* all user attrs request, skip operational attributes */ 1205 if( is_at_operational( desc->ad_type ) ) { 1206 continue; 1207 } 1208 1209 } else { 1210 /* specific attrs requested */ 1211 if ( is_at_operational( desc->ad_type ) ) { 1212 /* if not explicitly requested */ 1213 if ( !ad_inlist( desc, rs->sr_attrs )) { 1214 /* if not all op attrs requested, skip */ 1215 if ( !SLAP_OPATTRS( rs->sr_attr_flags )) 1216 continue; 1217 /* if DSA-specific and replicating, skip */ 1218 if ( op->o_sync != SLAP_CONTROL_NONE && 1219 desc->ad_type->sat_usage == LDAP_SCHEMA_DSA_OPERATION ) 1220 continue; 1221 } 1222 } else { 1223 if ( !userattrs && !ad_inlist( desc, rs->sr_attrs ) ) { 1224 continue; 1225 } 1226 } 1227 } 1228 1229 if ( attrsonly ) { 1230 if ( ! access_allowed( op, rs->sr_entry, desc, NULL, 1231 ACL_READ, &acl_state ) ) 1232 { 1233 Debug( LDAP_DEBUG_ACL, "send_search_entry: " 1234 "conn %lu access to attribute %s not allowed\n", 1235 op->o_connid, desc->ad_cname.bv_val ); 1236 continue; 1237 } 1238 1239 if (( rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname )) == -1 ) { 1240 Debug( LDAP_DEBUG_ANY, 1241 "send_search_entry: conn %lu ber_printf failed\n", 1242 op->o_connid ); 1243 1244 if ( op->o_res_ber == NULL ) ber_free_buf( ber ); 1245 set_ldap_error( rs, LDAP_OTHER, 1246 "encoding description error"); 1247 rc = rs->sr_err; 1248 goto error_return; 1249 } 1250 finish = 1; 1251 1252 } else { 1253 int first = 1; 1254 for ( i = 0; a->a_nvals[i].bv_val != NULL; i++ ) { 1255 if ( ! access_allowed( op, rs->sr_entry, 1256 desc, &a->a_nvals[i], ACL_READ, &acl_state ) ) 1257 { 1258 Debug( LDAP_DEBUG_ACL, 1259 "send_search_entry: conn %lu " 1260 "access to attribute %s, value #%d not allowed\n", 1261 op->o_connid, desc->ad_cname.bv_val, i ); 1262 1263 continue; 1264 } 1265 1266 if ( op->o_vrFilter && e_flags[j][i] == 0 ){ 1267 continue; 1268 } 1269 1270 if ( first ) { 1271 first = 0; 1272 finish = 1; 1273 if (( rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname )) == -1 ) { 1274 Debug( LDAP_DEBUG_ANY, 1275 "send_search_entry: conn %lu ber_printf failed\n", 1276 op->o_connid ); 1277 1278 if ( op->o_res_ber == NULL ) ber_free_buf( ber ); 1279 set_ldap_error( rs, LDAP_OTHER, 1280 "encoding description error"); 1281 rc = rs->sr_err; 1282 goto error_return; 1283 } 1284 } 1285 if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) { 1286 Debug( LDAP_DEBUG_ANY, 1287 "send_search_entry: conn %lu " 1288 "ber_printf failed.\n", op->o_connid ); 1289 1290 if ( op->o_res_ber == NULL ) ber_free_buf( ber ); 1291 set_ldap_error( rs, LDAP_OTHER, 1292 "encoding values error" ); 1293 rc = rs->sr_err; 1294 goto error_return; 1295 } 1296 } 1297 } 1298 1299 if ( finish && ( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) { 1300 Debug( LDAP_DEBUG_ANY, 1301 "send_search_entry: conn %lu ber_printf failed\n", 1302 op->o_connid ); 1303 1304 if ( op->o_res_ber == NULL ) ber_free_buf( ber ); 1305 set_ldap_error( rs, LDAP_OTHER, "encode end error" ); 1306 rc = rs->sr_err; 1307 goto error_return; 1308 } 1309 } 1310 1311 /* NOTE: moved before overlays callback circling because 1312 * they may modify entry and other stuff in rs */ 1313 if ( rs->sr_operational_attrs != NULL && op->o_vrFilter != NULL ) { 1314 int k = 0; 1315 size_t size; 1316 1317 for ( a = rs->sr_operational_attrs, i=0; a != NULL; a = a->a_next, i++ ) { 1318 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++; 1319 } 1320 1321 size = i * sizeof(char *) + k; 1322 if ( size > 0 ) { 1323 char *a_flags, **tmp; 1324 1325 /* 1326 * Reuse previous memory - we likely need less space 1327 * for operational attributes 1328 */ 1329 tmp = slap_sl_realloc( e_flags, i * sizeof(char *) + k, 1330 op->o_tmpmemctx ); 1331 if ( tmp == NULL ) { 1332 Debug( LDAP_DEBUG_ANY, 1333 "send_search_entry: conn %lu " 1334 "not enough memory " 1335 "for matched values filtering\n", 1336 op->o_connid ); 1337 if ( op->o_res_ber == NULL ) ber_free_buf( ber ); 1338 set_ldap_error( rs, LDAP_OTHER, 1339 "not enough memory for matched values filtering" ); 1340 goto error_return; 1341 } 1342 e_flags = tmp; 1343 a_flags = (char *)(e_flags + i); 1344 memset( a_flags, 0, k ); 1345 for ( a = rs->sr_operational_attrs, i=0; a != NULL; a = a->a_next, i++ ) { 1346 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ); 1347 e_flags[i] = a_flags; 1348 a_flags += j; 1349 } 1350 rc = filter_matched_values(op, rs->sr_operational_attrs, &e_flags) ; 1351 1352 if ( rc == -1 ) { 1353 Debug( LDAP_DEBUG_ANY, 1354 "send_search_entry: conn %lu " 1355 "matched values filtering failed\n", 1356 op->o_connid ); 1357 if ( op->o_res_ber == NULL ) ber_free_buf( ber ); 1358 set_ldap_error( rs, LDAP_OTHER, 1359 "matched values filtering error" ); 1360 rc = rs->sr_err; 1361 goto error_return; 1362 } 1363 } 1364 } 1365 1366 for (a = rs->sr_operational_attrs, j=0; a != NULL; a = a->a_next, j++ ) { 1367 AttributeDescription *desc = a->a_desc; 1368 1369 if ( rs->sr_attrs == NULL ) { 1370 /* all user attrs request, skip operational attributes */ 1371 if( is_at_operational( desc->ad_type ) ) { 1372 continue; 1373 } 1374 1375 } else { 1376 /* specific attrs requested */ 1377 if( is_at_operational( desc->ad_type ) ) { 1378 if ( !SLAP_OPATTRS( rs->sr_attr_flags ) && 1379 !ad_inlist( desc, rs->sr_attrs ) ) 1380 { 1381 continue; 1382 } 1383 /* if DSA-specific and replicating, skip */ 1384 if ( op->o_sync != SLAP_CONTROL_NONE && 1385 desc->ad_type->sat_usage == LDAP_SCHEMA_DSA_OPERATION ) 1386 continue; 1387 } else { 1388 if ( !userattrs && !ad_inlist( desc, rs->sr_attrs ) ) { 1389 continue; 1390 } 1391 } 1392 } 1393 1394 if ( ! access_allowed( op, rs->sr_entry, desc, NULL, 1395 ACL_READ, &acl_state ) ) 1396 { 1397 Debug( LDAP_DEBUG_ACL, 1398 "send_search_entry: conn %lu " 1399 "access to attribute %s not allowed\n", 1400 op->o_connid, desc->ad_cname.bv_val ); 1401 1402 continue; 1403 } 1404 1405 rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname ); 1406 if ( rc == -1 ) { 1407 Debug( LDAP_DEBUG_ANY, 1408 "send_search_entry: conn %lu " 1409 "ber_printf failed\n", op->o_connid ); 1410 1411 if ( op->o_res_ber == NULL ) ber_free_buf( ber ); 1412 set_ldap_error( rs, LDAP_OTHER, 1413 "encoding description error" ); 1414 rc = rs->sr_err; 1415 goto error_return; 1416 } 1417 1418 if ( ! attrsonly ) { 1419 for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) { 1420 if ( ! access_allowed( op, rs->sr_entry, 1421 desc, &a->a_vals[i], ACL_READ, &acl_state ) ) 1422 { 1423 Debug( LDAP_DEBUG_ACL, 1424 "send_search_entry: conn %lu " 1425 "access to %s, value %d not allowed\n", 1426 op->o_connid, desc->ad_cname.bv_val, i ); 1427 1428 continue; 1429 } 1430 1431 if ( op->o_vrFilter && e_flags[j][i] == 0 ){ 1432 continue; 1433 } 1434 1435 if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) { 1436 Debug( LDAP_DEBUG_ANY, 1437 "send_search_entry: conn %lu ber_printf failed\n", 1438 op->o_connid ); 1439 1440 if ( op->o_res_ber == NULL ) ber_free_buf( ber ); 1441 set_ldap_error( rs, LDAP_OTHER, 1442 "encoding values error" ); 1443 rc = rs->sr_err; 1444 goto error_return; 1445 } 1446 } 1447 } 1448 1449 if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) { 1450 Debug( LDAP_DEBUG_ANY, 1451 "send_search_entry: conn %lu ber_printf failed\n", 1452 op->o_connid ); 1453 1454 if ( op->o_res_ber == NULL ) ber_free_buf( ber ); 1455 set_ldap_error( rs, LDAP_OTHER, "encode end error" ); 1456 rc = rs->sr_err; 1457 goto error_return; 1458 } 1459 } 1460 1461 /* free e_flags */ 1462 if ( e_flags ) { 1463 slap_sl_free( e_flags, op->o_tmpmemctx ); 1464 e_flags = NULL; 1465 } 1466 1467 rc = ber_printf( ber, /*{{*/ "}N}" ); 1468 1469 if( rc != -1 ) { 1470 rc = send_ldap_controls( op, ber, rs->sr_ctrls ); 1471 } 1472 1473 if( rc != -1 ) { 1474 #ifdef LDAP_CONNECTIONLESS 1475 if( op->o_conn && op->o_conn->c_is_udp ) { 1476 if ( op->o_protocol != LDAP_VERSION2 ) { 1477 rc = ber_printf( ber, /*{*/ "N}" ); 1478 } 1479 } else 1480 #endif 1481 if ( op->o_res_ber == NULL ) { 1482 rc = ber_printf( ber, /*{*/ "N}" ); 1483 } 1484 } 1485 1486 if ( rc == -1 ) { 1487 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n" ); 1488 1489 if ( op->o_res_ber == NULL ) ber_free_buf( ber ); 1490 set_ldap_error( rs, LDAP_OTHER, "encode entry end error" ); 1491 rc = rs->sr_err; 1492 goto error_return; 1493 } 1494 1495 Debug( LDAP_DEBUG_STATS2, "%s ENTRY dn=\"%s\"\n", 1496 op->o_log_prefix, rs->sr_entry->e_nname.bv_val ); 1497 1498 rs_flush_entry( op, rs, NULL ); 1499 1500 if ( op->o_res_ber == NULL ) { 1501 bytes = send_ldap_ber( op, ber ); 1502 ber_free_buf( ber ); 1503 1504 if ( bytes < 0 ) { 1505 Debug( LDAP_DEBUG_ANY, 1506 "send_search_entry: conn %lu ber write failed.\n", 1507 op->o_connid ); 1508 1509 rc = LDAP_UNAVAILABLE; 1510 goto error_return; 1511 } 1512 rs->sr_nentries++; 1513 1514 ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex ); 1515 ldap_pvt_mp_add_ulong( op->o_counters->sc_bytes, (unsigned long)bytes ); 1516 ldap_pvt_mp_add_ulong( op->o_counters->sc_entries, 1 ); 1517 ldap_pvt_mp_add_ulong( op->o_counters->sc_pdu, 1 ); 1518 ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex ); 1519 } 1520 1521 Debug( LDAP_DEBUG_TRACE, 1522 "<= send_search_entry: conn %lu exit.\n", op->o_connid ); 1523 1524 rc = LDAP_SUCCESS; 1525 1526 error_return:; 1527 if ( op->o_callback ) { 1528 (void)slap_cleanup_play( op, rs ); 1529 } 1530 1531 if ( e_flags ) { 1532 slap_sl_free( e_flags, op->o_tmpmemctx ); 1533 } 1534 1535 /* FIXME: Can break if rs now contains an extended response */ 1536 if ( rs->sr_operational_attrs ) { 1537 attrs_free( rs->sr_operational_attrs ); 1538 rs->sr_operational_attrs = NULL; 1539 } 1540 rs->sr_attr_flags = SLAP_ATTRS_UNDEFINED; 1541 1542 if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH ) { 1543 rs_flush_entry( op, rs, NULL ); 1544 } else { 1545 RS_ASSERT( (rs->sr_flags & REP_ENTRY_MASK) == 0 ); 1546 } 1547 1548 if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) { 1549 rs->sr_flags ^= REP_CTRLS_MUSTBEFREED; /* paranoia */ 1550 if ( rs->sr_ctrls ) { 1551 slap_free_ctrls( op, rs->sr_ctrls ); 1552 rs->sr_ctrls = NULL; 1553 } 1554 } 1555 1556 return( rc ); 1557 } 1558 1559 int 1560 slap_send_search_reference( Operation *op, SlapReply *rs ) 1561 { 1562 BerElementBuffer berbuf; 1563 BerElement *ber = (BerElement *) &berbuf; 1564 int rc = 0; 1565 int bytes; 1566 char *edn = rs->sr_entry ? rs->sr_entry->e_name.bv_val : "(null)"; 1567 1568 AttributeDescription *ad_ref = slap_schema.si_ad_ref; 1569 AttributeDescription *ad_entry = slap_schema.si_ad_entry; 1570 1571 rs->sr_type = REP_SEARCHREF; 1572 if ( op->o_callback ) { 1573 rc = slap_response_play( op, rs ); 1574 if ( rc != SLAP_CB_CONTINUE ) { 1575 goto rel; 1576 } 1577 } 1578 1579 Debug( LDAP_DEBUG_TRACE, 1580 "=> send_search_reference: dn=\"%s\"\n", 1581 edn ); 1582 1583 if ( rs->sr_entry && ! access_allowed( op, rs->sr_entry, 1584 ad_entry, NULL, ACL_READ, NULL ) ) 1585 { 1586 Debug( LDAP_DEBUG_ACL, 1587 "send_search_reference: access to entry not allowed\n" ); 1588 rc = 1; 1589 goto rel; 1590 } 1591 1592 if ( rs->sr_entry && ! access_allowed( op, rs->sr_entry, 1593 ad_ref, NULL, ACL_READ, NULL ) ) 1594 { 1595 Debug( LDAP_DEBUG_ACL, 1596 "send_search_reference: access " 1597 "to reference not allowed\n" ); 1598 rc = 1; 1599 goto rel; 1600 } 1601 1602 if( op->o_domain_scope ) { 1603 Debug( LDAP_DEBUG_ANY, 1604 "send_search_reference: domainScope control in (%s)\n", 1605 edn ); 1606 rc = 0; 1607 goto rel; 1608 } 1609 1610 if( rs->sr_ref == NULL ) { 1611 Debug( LDAP_DEBUG_ANY, 1612 "send_search_reference: null ref in (%s)\n", 1613 edn ); 1614 rc = 1; 1615 goto rel; 1616 } 1617 1618 if( op->o_protocol < LDAP_VERSION3 ) { 1619 rc = 0; 1620 /* save the references for the result */ 1621 if( rs->sr_ref[0].bv_val != NULL ) { 1622 if( value_add( &rs->sr_v2ref, rs->sr_ref ) ) 1623 rc = LDAP_OTHER; 1624 } 1625 goto rel; 1626 } 1627 1628 #ifdef LDAP_CONNECTIONLESS 1629 if( op->o_conn && op->o_conn->c_is_udp ) { 1630 ber = op->o_res_ber; 1631 } else 1632 #endif 1633 { 1634 ber_init_w_nullc( ber, LBER_USE_DER ); 1635 ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); 1636 } 1637 1638 rc = ber_printf( ber, "{it{W}" /*"}"*/ , op->o_msgid, 1639 LDAP_RES_SEARCH_REFERENCE, rs->sr_ref ); 1640 1641 if( rc != -1 ) { 1642 rc = send_ldap_controls( op, ber, rs->sr_ctrls ); 1643 } 1644 1645 if( rc != -1 ) { 1646 rc = ber_printf( ber, /*"{"*/ "N}" ); 1647 } 1648 1649 if ( rc == -1 ) { 1650 Debug( LDAP_DEBUG_ANY, 1651 "send_search_reference: ber_printf failed\n" ); 1652 1653 #ifdef LDAP_CONNECTIONLESS 1654 if (!op->o_conn || op->o_conn->c_is_udp == 0) 1655 #endif 1656 ber_free_buf( ber ); 1657 set_ldap_error( rs, LDAP_OTHER, "encode DN error" ); 1658 goto rel; 1659 } 1660 1661 rc = 0; 1662 rs_flush_entry( op, rs, NULL ); 1663 1664 #ifdef LDAP_CONNECTIONLESS 1665 if (!op->o_conn || op->o_conn->c_is_udp == 0) { 1666 #endif 1667 bytes = send_ldap_ber( op, ber ); 1668 ber_free_buf( ber ); 1669 1670 if ( bytes < 0 ) { 1671 rc = LDAP_UNAVAILABLE; 1672 } else { 1673 ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex ); 1674 ldap_pvt_mp_add_ulong( op->o_counters->sc_bytes, (unsigned long)bytes ); 1675 ldap_pvt_mp_add_ulong( op->o_counters->sc_refs, 1 ); 1676 ldap_pvt_mp_add_ulong( op->o_counters->sc_pdu, 1 ); 1677 ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex ); 1678 } 1679 #ifdef LDAP_CONNECTIONLESS 1680 } 1681 #endif 1682 if ( rs->sr_ref != NULL ) { 1683 int r; 1684 1685 for ( r = 0; !BER_BVISNULL( &rs->sr_ref[ r ] ); r++ ) { 1686 Debug( LDAP_DEBUG_STATS2, "%s REF #%d \"%s\"\n", 1687 op->o_log_prefix, r, rs->sr_ref[0].bv_val ); 1688 } 1689 1690 } else { 1691 Debug( LDAP_DEBUG_STATS2, "%s REF \"(null)\"\n", 1692 op->o_log_prefix ); 1693 } 1694 1695 Debug( LDAP_DEBUG_TRACE, "<= send_search_reference\n" ); 1696 1697 if ( 0 ) { 1698 rel: 1699 rs_flush_entry( op, rs, NULL ); 1700 } 1701 1702 if ( op->o_callback ) { 1703 (void)slap_cleanup_play( op, rs ); 1704 } 1705 1706 if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) { 1707 rs->sr_flags ^= REP_CTRLS_MUSTBEFREED; /* paranoia */ 1708 if ( rs->sr_ctrls ) { 1709 slap_free_ctrls( op, rs->sr_ctrls ); 1710 rs->sr_ctrls = NULL; 1711 } 1712 } 1713 1714 return rc; 1715 } 1716 1717 int 1718 str2result( 1719 char *s, 1720 int *code, 1721 char **matched, 1722 char **info ) 1723 { 1724 int rc; 1725 char *c; 1726 1727 *code = LDAP_SUCCESS; 1728 *matched = NULL; 1729 *info = NULL; 1730 1731 if ( strncasecmp( s, "RESULT", STRLENOF( "RESULT" ) ) != 0 ) { 1732 Debug( LDAP_DEBUG_ANY, "str2result (%s) expecting \"RESULT\"\n", 1733 s ); 1734 1735 return( -1 ); 1736 } 1737 1738 rc = 0; 1739 while ( (s = strchr( s, '\n' )) != NULL ) { 1740 *s++ = '\0'; 1741 if ( *s == '\0' ) { 1742 break; 1743 } 1744 if ( (c = strchr( s, ':' )) != NULL ) { 1745 c++; 1746 } 1747 1748 if ( strncasecmp( s, "code", STRLENOF( "code" ) ) == 0 ) { 1749 char *next = NULL; 1750 long retcode; 1751 1752 if ( c == NULL ) { 1753 Debug( LDAP_DEBUG_ANY, "str2result (%s) missing value\n", 1754 s ); 1755 rc = -1; 1756 continue; 1757 } 1758 1759 while ( isspace( (unsigned char) c[ 0 ] ) ) c++; 1760 if ( c[ 0 ] == '\0' ) { 1761 Debug( LDAP_DEBUG_ANY, "str2result (%s) missing or empty value\n", 1762 s ); 1763 rc = -1; 1764 continue; 1765 } 1766 1767 retcode = strtol( c, &next, 10 ); 1768 if ( next == NULL || next == c ) { 1769 Debug( LDAP_DEBUG_ANY, "str2result (%s) unable to parse value\n", 1770 s ); 1771 rc = -1; 1772 continue; 1773 } 1774 1775 while ( isspace( (unsigned char) next[ 0 ] ) && next[ 0 ] != '\n' ) 1776 next++; 1777 if ( next[ 0 ] != '\0' && next[ 0 ] != '\n' ) { 1778 Debug( LDAP_DEBUG_ANY, "str2result (%s) extra cruft after value\n", 1779 s ); 1780 rc = -1; 1781 continue; 1782 } 1783 1784 /* FIXME: what if it's larger than max int? */ 1785 *code = (int)retcode; 1786 1787 } else if ( strncasecmp( s, "matched", STRLENOF( "matched" ) ) == 0 ) { 1788 if ( c != NULL ) { 1789 *matched = c; 1790 } 1791 } else if ( strncasecmp( s, "info", STRLENOF( "info" ) ) == 0 ) { 1792 if ( c != NULL ) { 1793 *info = c; 1794 } 1795 } else { 1796 Debug( LDAP_DEBUG_ANY, "str2result (%s) unknown\n", 1797 s ); 1798 1799 rc = -1; 1800 } 1801 } 1802 1803 return( rc ); 1804 } 1805 1806 int slap_read_controls( 1807 Operation *op, 1808 SlapReply *rs, 1809 Entry *e, 1810 const struct berval *oid, 1811 LDAPControl **ctrl ) 1812 { 1813 int rc; 1814 struct berval bv; 1815 BerElementBuffer berbuf; 1816 BerElement *ber = (BerElement *) &berbuf; 1817 LDAPControl c; 1818 Operation myop; 1819 1820 Debug( LDAP_DEBUG_STATS, "%s slap_read_controls: (%s) %s\n", 1821 op->o_log_prefix, oid->bv_val, e->e_dn ); 1822 1823 rs->sr_entry = e; 1824 rs->sr_attrs = ( oid == &slap_pre_read_bv ) ? 1825 op->o_preread_attrs : op->o_postread_attrs; 1826 1827 bv.bv_len = entry_flatsize( rs->sr_entry, 0 ); 1828 bv.bv_val = op->o_tmpalloc( bv.bv_len, op->o_tmpmemctx ); 1829 1830 ber_init2( ber, &bv, LBER_USE_DER ); 1831 ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); 1832 1833 /* create new operation */ 1834 myop = *op; 1835 /* FIXME: o_bd needed for ACL */ 1836 myop.o_bd = op->o_bd; 1837 myop.o_res_ber = ber; 1838 myop.o_callback = NULL; 1839 myop.ors_slimit = 1; 1840 myop.ors_attrsonly = 0; 1841 1842 rc = slap_send_search_entry( &myop, rs ); 1843 if( rc ) return rc; 1844 1845 rc = ber_flatten2( ber, &c.ldctl_value, 0 ); 1846 1847 if( rc == -1 ) return LDAP_OTHER; 1848 1849 c.ldctl_oid = oid->bv_val; 1850 c.ldctl_iscritical = 0; 1851 1852 if ( *ctrl == NULL ) { 1853 /* first try */ 1854 *ctrl = (LDAPControl *) slap_sl_calloc( 1, sizeof(LDAPControl), NULL ); 1855 } else { 1856 /* retry: free previous try */ 1857 slap_sl_free( (*ctrl)->ldctl_value.bv_val, op->o_tmpmemctx ); 1858 } 1859 1860 **ctrl = c; 1861 return LDAP_SUCCESS; 1862 } 1863 1864 /* Map API errors to protocol errors... */ 1865 int 1866 slap_map_api2result( SlapReply *rs ) 1867 { 1868 switch(rs->sr_err) { 1869 case LDAP_SERVER_DOWN: 1870 return LDAP_UNAVAILABLE; 1871 case LDAP_LOCAL_ERROR: 1872 return LDAP_OTHER; 1873 case LDAP_ENCODING_ERROR: 1874 case LDAP_DECODING_ERROR: 1875 return LDAP_PROTOCOL_ERROR; 1876 case LDAP_TIMEOUT: 1877 return LDAP_UNAVAILABLE; 1878 case LDAP_AUTH_UNKNOWN: 1879 return LDAP_AUTH_METHOD_NOT_SUPPORTED; 1880 case LDAP_FILTER_ERROR: 1881 rs->sr_text = "Filter error"; 1882 return LDAP_OTHER; 1883 case LDAP_USER_CANCELLED: 1884 rs->sr_text = "User cancelled"; 1885 return LDAP_OTHER; 1886 case LDAP_PARAM_ERROR: 1887 return LDAP_PROTOCOL_ERROR; 1888 case LDAP_NO_MEMORY: 1889 return LDAP_OTHER; 1890 case LDAP_CONNECT_ERROR: 1891 return LDAP_UNAVAILABLE; 1892 case LDAP_NOT_SUPPORTED: 1893 return LDAP_UNWILLING_TO_PERFORM; 1894 case LDAP_CONTROL_NOT_FOUND: 1895 return LDAP_PROTOCOL_ERROR; 1896 case LDAP_NO_RESULTS_RETURNED: 1897 return LDAP_NO_SUCH_OBJECT; 1898 case LDAP_MORE_RESULTS_TO_RETURN: 1899 rs->sr_text = "More results to return"; 1900 return LDAP_OTHER; 1901 case LDAP_CLIENT_LOOP: 1902 case LDAP_REFERRAL_LIMIT_EXCEEDED: 1903 return LDAP_LOOP_DETECT; 1904 default: 1905 if ( LDAP_API_ERROR(rs->sr_err) ) return LDAP_OTHER; 1906 return rs->sr_err; 1907 } 1908 } 1909 1910 1911 slap_mask_t 1912 slap_attr_flags( AttributeName *an ) 1913 { 1914 slap_mask_t flags = SLAP_ATTRS_UNDEFINED; 1915 1916 if ( an == NULL ) { 1917 flags |= ( SLAP_OPATTRS_NO | SLAP_USERATTRS_YES ); 1918 1919 } else { 1920 flags |= an_find( an, slap_bv_all_operational_attrs ) 1921 ? SLAP_OPATTRS_YES : SLAP_OPATTRS_NO; 1922 flags |= an_find( an, slap_bv_all_user_attrs ) 1923 ? SLAP_USERATTRS_YES : SLAP_USERATTRS_NO; 1924 } 1925 1926 return flags; 1927 } 1928