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