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