]> git.sur5r.net Git - openldap/blob - servers/slapd/result.c
allow 'all' vs. 'any' sasl-authz-policy
[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 = LDAP_SUCCESS;
293         long    bytes;
294
295         if (op->o_callback) {
296                 slap_callback *sc = op->o_callback;
297                 rc = SLAP_CB_CONTINUE;
298                 for ( ; op->o_callback; ) {
299                         if ( op->o_callback->sc_response ) {
300                                 rc = op->o_callback->sc_response( op, rs );
301                                 if ( rc != SLAP_CB_CONTINUE ) break;
302                         }
303                         op->o_callback = op->o_callback->sc_next;
304                 }
305                 op->o_callback = sc;
306                 if ( rc != SLAP_CB_CONTINUE ) goto cleanup;
307         }
308
309 #ifdef LDAP_CONNECTIONLESS
310         if (op->o_conn && op->o_conn->c_is_udp)
311                 ber = op->o_res_ber;
312         else
313 #endif
314         {
315                 ber_init_w_nullc( ber, LBER_USE_DER );
316                 ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
317         }
318
319 #ifdef NEW_LOGGING
320         LDAP_LOG( OPERATION, ENTRY, 
321                 "send_ldap_response:  msgid=%d tag=%lu err=%d\n",
322                 rs->sr_msgid, rs->sr_tag, rs->sr_err );
323 #else
324         Debug( LDAP_DEBUG_TRACE,
325                 "send_ldap_response: msgid=%d tag=%lu err=%d\n",
326                 rs->sr_msgid, rs->sr_tag, rs->sr_err );
327 #endif
328
329         if( rs->sr_ref ) {
330 #ifdef NEW_LOGGING
331                 LDAP_LOG( OPERATION, ARGS, 
332                         "send_ldap_response: conn %lu  ref=\"%s\"\n",
333                         op->o_connid,
334                         rs->sr_ref[0].bv_val ? rs->sr_ref[0].bv_val : "NULL" , 0 );
335 #else
336                 Debug( LDAP_DEBUG_ARGS, "send_ldap_response: ref=\"%s\"\n",
337                         rs->sr_ref[0].bv_val ? rs->sr_ref[0].bv_val : "NULL",
338                         NULL, NULL );
339 #endif
340         }
341
342 #ifdef LDAP_CONNECTIONLESS
343         if (op->o_conn && op->o_conn->c_is_udp &&
344                 op->o_protocol == LDAP_VERSION2 )
345         {
346                 rc = ber_printf( ber, "t{ess" /*"}}"*/,
347                         rs->sr_tag, rs->sr_err,
348                 rs->sr_matched == NULL ? "" : rs->sr_matched,
349                 rs->sr_text == NULL ? "" : rs->sr_text );
350         } else 
351 #endif
352         if ( rs->sr_type == REP_INTERMEDIATE ) {
353             rc = ber_printf( ber, "{it{" /*"}}"*/,
354                         rs->sr_msgid, rs->sr_tag );
355
356         } else {
357             rc = ber_printf( ber, "{it{ess" /*"}}"*/,
358                 rs->sr_msgid, rs->sr_tag, rs->sr_err,
359                 rs->sr_matched == NULL ? "" : rs->sr_matched,
360                 rs->sr_text == NULL ? "" : rs->sr_text );
361         }
362
363         if( rc != -1 ) {
364                 if ( rs->sr_ref != NULL ) {
365                         assert( rs->sr_err == LDAP_REFERRAL );
366                         rc = ber_printf( ber, "t{W}",
367                                 LDAP_TAG_REFERRAL, rs->sr_ref );
368                 } else {
369                         assert( rs->sr_err != LDAP_REFERRAL );
370                 }
371         }
372
373         if( rc != -1 && rs->sr_type == REP_SASL && rs->sr_sasldata != NULL ) {
374                 rc = ber_printf( ber, "tO",
375                         LDAP_TAG_SASL_RES_CREDS, rs->sr_sasldata );
376         }
377
378         if( rc != -1 &&
379                 ( rs->sr_type == REP_EXTENDED || rs->sr_type == REP_INTERMEDIATE ))
380         {
381                 if ( rs->sr_rspoid != NULL ) {
382                         rc = ber_printf( ber, "ts",
383                                 LDAP_TAG_EXOP_RES_OID, rs->sr_rspoid );
384                 }
385                 if( rc != -1 && rs->sr_rspdata != NULL ) {
386                         rc = ber_printf( ber, "tO",
387                                 LDAP_TAG_EXOP_RES_VALUE, rs->sr_rspdata );
388                 }
389         }
390
391         if( rc != -1 ) {
392                 rc = ber_printf( ber, /*"{"*/ "N}" );
393         }
394
395         if( rc != -1 ) {
396                 rc = send_ldap_controls( op, ber, rs->sr_ctrls );
397         }
398
399         if( rc != -1 ) {
400                 rc = ber_printf( ber, /*"{"*/ "N}" );
401         }
402
403 #ifdef LDAP_CONNECTIONLESS
404         if( op->o_conn && op->o_conn->c_is_udp && op->o_protocol == LDAP_VERSION2 && rc != -1 ) {
405                 rc = ber_printf( ber, /*"{"*/ "N}" );
406         }
407 #endif
408                 
409         if ( rc == -1 ) {
410 #ifdef NEW_LOGGING
411                 LDAP_LOG( OPERATION, ERR, 
412                         "send_ldap_response: conn %lu  ber_printf failed\n",
413                         op->o_connid, 0, 0 );
414 #else
415                 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
416 #endif
417
418 #ifdef LDAP_CONNECTIONLESS
419                 if (!op->o_conn || op->o_conn->c_is_udp == 0)
420 #endif
421                 ber_free_buf( ber );
422                 goto cleanup;
423         }
424
425         /* send BER */
426         bytes = send_ldap_ber( op->o_conn, ber );
427 #ifdef LDAP_CONNECTIONLESS
428         if (!op->o_conn || op->o_conn->c_is_udp == 0)
429 #endif
430         ber_free_buf( ber );
431
432         if ( bytes < 0 ) {
433 #ifdef NEW_LOGGING
434                 LDAP_LOG( OPERATION, ERR, 
435                         "send_ldap_response: conn %lu ber write failed\n",
436                         op->o_connid ? op->o_connid : 0, 0, 0 );
437 #else
438                 Debug( LDAP_DEBUG_ANY,
439                         "send_ldap_response: ber write failed\n",
440                         0, 0, 0 );
441 #endif
442
443                 goto cleanup;
444         }
445
446 #ifdef LDAP_SLAPI
447         if ( op->o_pb ) {
448                 slapi_pblock_set( op->o_pb, SLAPI_RESULT_CODE, (void *)rs->sr_err );
449                 slapi_pblock_set( op->o_pb, SLAPI_RESULT_MATCHED, (void *)rs->sr_matched );
450                 slapi_pblock_set( op->o_pb, SLAPI_RESULT_TEXT, (void *)rs->sr_text );
451         }
452 #endif /* LDAP_SLAPI */
453
454         ldap_pvt_thread_mutex_lock( &num_sent_mutex );
455         num_bytes_sent += bytes;
456         num_pdu_sent++;
457         ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
458
459 cleanup:;
460         if ( rs->sr_matched && rs->sr_flags & REP_MATCHED_MUSTBEFREED ) {
461                 free( (char *)rs->sr_matched );
462                 rs->sr_matched = NULL;
463         }
464
465         if (op->o_callback) {
466                 slap_callback *sc = op->o_callback;
467                 for ( ; op->o_callback; op->o_callback = op->o_callback->sc_next ) {
468                         if ( op->o_callback->sc_cleanup ) {
469                                 op->o_callback->sc_cleanup( op, rs );
470                         }
471                 }
472                 op->o_callback = sc;
473         }
474
475         return;
476 }
477
478
479 void
480 send_ldap_disconnect( Operation *op, SlapReply *rs )
481 {
482 #define LDAP_UNSOLICITED_ERROR(e) \
483         (  (e) == LDAP_PROTOCOL_ERROR \
484         || (e) == LDAP_STRONG_AUTH_REQUIRED \
485         || (e) == LDAP_UNAVAILABLE )
486
487         assert( LDAP_UNSOLICITED_ERROR( rs->sr_err ) );
488
489         rs->sr_type = REP_EXTENDED;
490
491 #ifdef NEW_LOGGING
492         LDAP_LOG( OPERATION, ENTRY, 
493                 "send_ldap_disconnect: conn %lu  %d:%s\n",
494                 op->o_connid, rs->sr_err, rs->sr_text ? rs->sr_text : "" );
495 #else
496         Debug( LDAP_DEBUG_TRACE,
497                 "send_ldap_disconnect %d:%s\n",
498                 rs->sr_err, rs->sr_text ? rs->sr_text : "", NULL );
499 #endif
500
501
502         if ( op->o_protocol < LDAP_VERSION3 ) {
503                 rs->sr_rspoid = NULL;
504                 rs->sr_tag = req2res( op->o_tag );
505                 rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0;
506
507         } else {
508                 rs->sr_rspoid = LDAP_NOTICE_DISCONNECT;
509                 rs->sr_tag = LDAP_RES_EXTENDED;
510                 rs->sr_msgid = 0;
511         }
512
513         send_ldap_response( op, rs );
514
515         Statslog( LDAP_DEBUG_STATS,
516             "conn=%lu op=%lu DISCONNECT tag=%lu err=%d text=%s\n",
517                 op->o_connid, op->o_opid, rs->sr_tag, rs->sr_err, rs->sr_text ? rs->sr_text : "" );
518 }
519
520 void
521 slap_send_ldap_result( Operation *op, SlapReply *rs )
522 {
523         char *tmp = NULL;
524         const char *otext = rs->sr_text;
525         BerVarray oref = rs->sr_ref;
526
527         rs->sr_type = REP_RESULT;
528
529         assert( !LDAP_API_ERROR( rs->sr_err ) && ( rs->sr_err >= 0 ));
530
531 #ifdef NEW_LOGGING
532         LDAP_LOG( OPERATION, ENTRY, 
533                 "send_ldap_result: conn %lu op=%lu p=%d\n",
534                 op->o_connid, op->o_opid, op->o_protocol );
535 #else
536         Debug( LDAP_DEBUG_TRACE,
537                 "send_ldap_result: conn=%lu op=%lu p=%d\n",
538                 op->o_connid, op->o_opid, op->o_protocol );
539 #endif
540
541 #ifdef NEW_LOGGING
542         LDAP_LOG( OPERATION, ARGS, 
543                 "send_ldap_result: err=%d matched=\"%s\" text=\"%s\"\n",
544                 rs->sr_err, rs->sr_matched ? rs->sr_matched : "",
545                 rs->sr_text ? rs->sr_text : "" );
546 #else
547         Debug( LDAP_DEBUG_ARGS,
548                 "send_ldap_result: err=%d matched=\"%s\" text=\"%s\"\n",
549                 rs->sr_err, rs->sr_matched ? rs->sr_matched : "",
550                 rs->sr_text ? rs->sr_text : "" );
551 #endif
552
553
554         if( rs->sr_ref ) {
555 #ifdef NEW_LOGGING
556                 LDAP_LOG( OPERATION, ARGS, 
557                         "send_ldap_result: referral=\"%s\"\n",
558                         rs->sr_ref[0].bv_val ? rs->sr_ref[0].bv_val : "NULL", 0, 0 );
559 #else
560                 Debug( LDAP_DEBUG_ARGS,
561                         "send_ldap_result: referral=\"%s\"\n",
562                         rs->sr_ref[0].bv_val ? rs->sr_ref[0].bv_val : "NULL",
563                         NULL, NULL );
564 #endif
565         }
566
567         assert( rs->sr_err != LDAP_PARTIAL_RESULTS );
568
569         if ( rs->sr_err == LDAP_REFERRAL ) {
570 #ifdef LDAP_CONTROL_X_DOMAIN_SCOPE
571                 if( op->o_domain_scope ) {
572                         rs->sr_ref = NULL;
573                 }
574 #endif
575                 if( rs->sr_ref == NULL ) {
576                         rs->sr_err = LDAP_NO_SUCH_OBJECT;
577                 } else if ( op->o_protocol < LDAP_VERSION3 ) {
578                         rs->sr_err = LDAP_PARTIAL_RESULTS;
579                 }
580         }
581
582 #ifdef LDAP_SLAPI
583         /*
584          * Call pre-result plugins. To avoid infinite recursion plugins
585          * should just set SLAPI_RESULT_CODE rather than sending a
586          * result if they wish to change the result.
587          */
588         if ( op->o_pb ) {
589                 slapi_int_pblock_set_operation( op->o_pb, op );
590                 slapi_pblock_set( op->o_pb, SLAPI_RESULT_CODE, (void *)rs->sr_err );
591                 slapi_pblock_set( op->o_pb, SLAPI_RESULT_TEXT, (void *)rs->sr_text );
592                 slapi_pblock_set( op->o_pb, SLAPI_RESULT_MATCHED, (void *)rs->sr_matched );
593
594                 (void) doPluginFNs( op->o_bd, SLAPI_PLUGIN_PRE_RESULT_FN, op->o_pb );
595         }
596 #endif /* LDAP_SLAPI */
597
598         if ( op->o_protocol < LDAP_VERSION3 ) {
599                 tmp = v2ref( rs->sr_ref, rs->sr_text );
600                 rs->sr_text = tmp;
601                 rs->sr_ref = NULL;
602         }
603
604         rs->sr_tag = req2res( op->o_tag );
605         rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0;
606
607         send_ldap_response( op, rs );
608
609         if ( op->o_tag == LDAP_REQ_SEARCH ) {
610                 char nbuf[64];
611                 snprintf( nbuf, sizeof nbuf, "%d nentries=%d",
612                         rs->sr_err, rs->sr_nentries );
613
614                 Statslog( LDAP_DEBUG_STATS,
615                 "conn=%lu op=%lu SEARCH RESULT tag=%lu err=%s text=%s\n",
616                         op->o_connid, op->o_opid, rs->sr_tag, nbuf,
617                         rs->sr_text ? rs->sr_text : "" );
618         } else {
619                 Statslog( LDAP_DEBUG_STATS,
620                         "conn=%lu op=%lu RESULT tag=%lu err=%d text=%s\n",
621                         op->o_connid, op->o_opid, rs->sr_tag, rs->sr_err,
622                         rs->sr_text ? rs->sr_text : "" );
623         }
624
625         if( tmp != NULL ) ch_free(tmp);
626         rs->sr_text = otext;
627         rs->sr_ref = oref;
628 }
629
630 void
631 send_ldap_sasl( Operation *op, SlapReply *rs )
632 {
633         rs->sr_type = REP_SASL;
634 #ifdef NEW_LOGGING
635         LDAP_LOG( OPERATION, ENTRY, 
636                 "send_ldap_sasl: conn %lu err=%d len=%lu\n",
637                 op->o_connid, rs->sr_err,
638                 rs->sr_sasldata ? rs->sr_sasldata->bv_len : -1 );
639 #else
640         Debug( LDAP_DEBUG_TRACE, "send_ldap_sasl: err=%d len=%ld\n",
641                 rs->sr_err,
642                 rs->sr_sasldata ? (long) rs->sr_sasldata->bv_len : -1, NULL );
643 #endif
644
645         rs->sr_tag = req2res( op->o_tag );
646         rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0;
647
648         send_ldap_response( op, rs );
649 }
650
651 void
652 slap_send_ldap_extended( Operation *op, SlapReply *rs )
653 {
654         rs->sr_type = REP_EXTENDED;
655
656 #ifdef NEW_LOGGING
657         LDAP_LOG( OPERATION, ENTRY, 
658                 "send_ldap_extended: err=%d oid=%s len=%ld\n",
659                 rs->sr_err, rs->sr_rspoid ? rs->sr_rspoid : "",
660                 rs->sr_rspdata != NULL ? rs->sr_rspdata->bv_len : 0 );
661 #else
662         Debug( LDAP_DEBUG_TRACE,
663                 "send_ldap_extended: err=%d oid=%s len=%ld\n",
664                 rs->sr_err,
665                 rs->sr_rspoid ? rs->sr_rspoid : "",
666                 rs->sr_rspdata != NULL ? rs->sr_rspdata->bv_len : 0 );
667 #endif
668
669         rs->sr_tag = req2res( op->o_tag );
670         rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0;
671
672         send_ldap_response( op, rs );
673 }
674
675 void
676 slap_send_ldap_intermediate( Operation *op, SlapReply *rs )
677 {
678         rs->sr_type = REP_INTERMEDIATE;
679 #ifdef NEW_LOGGING
680         LDAP_LOG( OPERATION, ENTRY,
681                 "send_ldap_intermediate: err=%d oid=%s len=%ld\n",
682                 rs->sr_err, rs->sr_rspoid ? rs->sr_rspoid : "",
683                 rs->sr_rspdata != NULL ? rs->sr_rspdata->bv_len : 0 );
684 #else
685         Debug( LDAP_DEBUG_TRACE,
686                 "send_ldap_intermediate: err=%d oid=%s len=%ld\n",
687                 rs->sr_err,
688                 rs->sr_rspoid ? rs->sr_rspoid : "",
689                 rs->sr_rspdata != NULL ? rs->sr_rspdata->bv_len : 0 );
690 #endif
691         rs->sr_tag = LDAP_RES_INTERMEDIATE;
692         rs->sr_msgid = op->o_msgid;
693         send_ldap_response( op, rs );
694 }
695
696 int
697 slap_send_search_entry( Operation *op, SlapReply *rs )
698 {
699         BerElementBuffer berbuf;
700         BerElement      *ber = (BerElement *) &berbuf;
701         Attribute       *a, *aa;
702         int             i, j, rc=-1, bytes;
703         char            *edn;
704         int             userattrs;
705         int             opattrs;
706         AccessControlState acl_state = ACL_STATE_INIT;
707 #ifdef LDAP_SLAPI
708         /* Support for computed attribute plugins */
709         computed_attr_context    ctx;
710         AttributeName   *anp;
711 #endif
712         AttributeDescription *ad_entry = slap_schema.si_ad_entry;
713
714         /* a_flags: array of flags telling if the i-th element will be
715          *          returned or filtered out
716          * e_flags: array of a_flags
717          */
718         char **e_flags = NULL;
719
720         rs->sr_type = REP_SEARCH;
721         if (op->o_callback) {
722                 slap_callback *sc = op->o_callback;
723                 rc = SLAP_CB_CONTINUE;
724                 for ( ; op->o_callback; ) {
725                         if ( op->o_callback->sc_response ) {
726                                 rc = op->o_callback->sc_response( op, rs );
727                                 if ( rc != SLAP_CB_CONTINUE ) break;
728                         }
729                         op->o_callback = op->o_callback->sc_next;
730                 }
731                 op->o_callback = sc;
732                 if ( rc != SLAP_CB_CONTINUE ) goto error_return;
733         }
734
735 #ifdef NEW_LOGGING
736         LDAP_LOG( OPERATION, ENTRY, "send_search_entry: conn %lu        dn=\"%s\"%s\n",
737                 op->o_connid, rs->sr_entry->e_name.bv_val,
738                 op->ors_attrsonly ? " (attrsOnly)" : "" );
739 #else
740         Debug( LDAP_DEBUG_TRACE, "=> send_search_entry: dn=\"%s\"%s\n",
741                 rs->sr_entry->e_name.bv_val,
742                 op->ors_attrsonly ? " (attrsOnly)" : "", 0 );
743 #endif
744
745         if ( !access_allowed( op, rs->sr_entry, ad_entry, NULL, ACL_READ, NULL )) {
746 #ifdef NEW_LOGGING
747                 LDAP_LOG( ACL, INFO, 
748                         "send_search_entry: conn %lu access to entry (%s) not allowed\n", 
749                         op->o_connid, rs->sr_entry->e_name.bv_val, 0 );
750 #else
751                 Debug( LDAP_DEBUG_ACL,
752                         "send_search_entry: access to entry not allowed\n",
753                     0, 0, 0 );
754 #endif
755
756                 rc = 1;
757                 goto error_return;
758         }
759
760         edn = rs->sr_entry->e_nname.bv_val;
761
762         if ( op->o_res_ber ) {
763                 /* read back control or LDAP_CONNECTIONLESS */
764             ber = op->o_res_ber;
765         } else {
766                 ber_len_t       siz, len;
767                 struct berval   bv;
768
769                 entry_flatsize( rs->sr_entry, &siz, &len, 0 );
770                 bv.bv_len = siz + len;
771                 bv.bv_val = op->o_tmpalloc(bv.bv_len, op->o_tmpmemctx );
772
773                 ber_init2( ber, &bv, LBER_USE_DER );
774                 ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
775         }
776
777 #ifdef LDAP_CONNECTIONLESS
778         if ( op->o_conn && op->o_conn->c_is_udp ) {
779                 /* CONNECTIONLESS */
780                 if ( op->o_protocol == LDAP_VERSION2 ) {
781                 rc = ber_printf(ber, "t{O{" /*}}*/,
782                                 LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name );
783                 } else {
784                 rc = ber_printf( ber, "{it{O{" /*}}}*/, op->o_msgid,
785                                 LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name );
786                 }
787         } else
788 #endif
789         if ( op->o_res_ber ) {
790                 /* read back control */
791             rc = ber_printf( ber, "{O{" /*}}*/, &rs->sr_entry->e_name );
792         } else {
793             rc = ber_printf( ber, "{it{O{" /*}}}*/, op->o_msgid,
794                         LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name );
795         }
796
797         if ( rc == -1 ) {
798 #ifdef NEW_LOGGING
799                 LDAP_LOG( OPERATION, ERR, 
800                         "send_search_entry: conn %lu  ber_printf failed\n", 
801                         op->o_connid, 0, 0 );
802 #else
803                 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
804 #endif
805
806                 if ( op->o_res_ber == NULL ) ber_free_buf( ber );
807                 send_ldap_error( op, rs, LDAP_OTHER, "encoding DN error" );
808                 goto error_return;
809         }
810
811         /* check for special all user attributes ("*") type */
812         userattrs = ( rs->sr_attrs == NULL ) ? 1
813                 : an_find( rs->sr_attrs, &AllUser );
814
815         /* check for special all operational attributes ("+") type */
816         opattrs = ( rs->sr_attrs == NULL ) ? 0
817                 : an_find( rs->sr_attrs, &AllOper );
818
819         /* create an array of arrays of flags. Each flag corresponds
820          * to particular value of attribute and equals 1 if value matches
821          * to ValuesReturnFilter or 0 if not
822          */     
823         if ( op->o_vrFilter != NULL ) {
824                 int     k = 0;
825                 size_t  size;
826
827                 for ( a = rs->sr_entry->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
828                         for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++;
829                 }
830
831                 size = i * sizeof(char *) + k;
832                 if ( size > 0 ) {
833                         char    *a_flags;
834                         e_flags = sl_calloc ( 1, i * sizeof(char *) + k, op->o_tmpmemctx );
835                         if( e_flags == NULL ) {
836 #ifdef NEW_LOGGING
837                                 LDAP_LOG( OPERATION, ERR, 
838                                         "send_search_entry: conn %lu sl_calloc failed\n",
839                                         op->o_connid ? op->o_connid : 0, 0, 0 );
840 #else
841                         Debug( LDAP_DEBUG_ANY, 
842                                         "send_search_entry: sl_calloc failed\n", 0, 0, 0 );
843 #endif
844                                 ber_free( ber, 1 );
845         
846                                 send_ldap_error( op, rs, LDAP_OTHER, "out of memory" );
847                                 goto error_return;
848                         }
849                         a_flags = (char *)(e_flags + i);
850                         memset( a_flags, 0, k );
851                         for ( a=rs->sr_entry->e_attrs, i=0; a != NULL; a=a->a_next, i++ ) {
852                                 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ );
853                                 e_flags[i] = a_flags;
854                                 a_flags += j;
855                         }
856         
857                         rc = filter_matched_values(op, rs->sr_entry->e_attrs, &e_flags) ; 
858                         if ( rc == -1 ) {
859 #ifdef NEW_LOGGING
860                                 LDAP_LOG( OPERATION, ERR, "send_search_entry: "
861                                         "conn %lu matched values filtering failed\n",
862                                         op->o_connid ? op->o_connid : 0, 0, 0 );
863 #else
864                         Debug( LDAP_DEBUG_ANY,
865                                         "matched values filtering failed\n", 0, 0, 0 );
866 #endif
867                                 if ( op->o_res_ber == NULL ) ber_free_buf( ber );
868                                 send_ldap_error( op, rs, LDAP_OTHER,
869                                         "matched values filtering error" );
870                                 goto error_return;
871                         }
872                 }
873         }
874
875         for ( a = rs->sr_entry->e_attrs, j = 0; a != NULL; a = a->a_next, j++ ) {
876                 AttributeDescription *desc = a->a_desc;
877
878                 if ( rs->sr_attrs == NULL ) {
879                         /* all attrs request, skip operational attributes */
880                         if( is_at_operational( desc->ad_type ) ) {
881                                 continue;
882                         }
883
884                 } else {
885                         /* specific attrs requested */
886                         if ( is_at_operational( desc->ad_type ) ) {
887                                 if( !opattrs && !ad_inlist( desc, rs->sr_attrs ) ) {
888                                         continue;
889                                 }
890
891                         } else {
892                                 if (!userattrs && !ad_inlist( desc, rs->sr_attrs ) ) {
893                                         continue;
894                                 }
895                         }
896                 }
897
898                 if ( ! access_allowed( op, rs->sr_entry, desc, NULL,
899                         ACL_READ, &acl_state ) )
900                 {
901 #ifdef NEW_LOGGING
902                         LDAP_LOG( ACL, INFO, 
903                                 "send_search_entry: conn %lu  access to attribute %s not "
904                                 "allowed\n", op->o_connid, desc->ad_cname.bv_val, 0 );
905 #else
906                         Debug( LDAP_DEBUG_ACL, "acl: "
907                                 "access to attribute %s not allowed\n",
908                             desc->ad_cname.bv_val, 0, 0 );
909 #endif
910                         continue;
911                 }
912
913                 if (( rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname )) == -1 ) {
914 #ifdef NEW_LOGGING
915                         LDAP_LOG( OPERATION, ERR, 
916                                 "send_search_entry: conn %lu  ber_printf failed\n", 
917                                 op->o_connid, 0, 0 );
918 #else
919                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
920 #endif
921
922                         if ( op->o_res_ber == NULL ) ber_free_buf( ber );
923                         send_ldap_error( op, rs, LDAP_OTHER, "encoding description error");
924                         goto error_return;
925                 }
926
927                 if ( ! op->ors_attrsonly ) {
928                         for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
929                                 if ( ! access_allowed( op, rs->sr_entry,
930                                         desc, &a->a_vals[i], ACL_READ, &acl_state ) )
931                                 {
932 #ifdef NEW_LOGGING
933                                         LDAP_LOG( ACL, INFO, 
934                                                 "send_search_entry: conn %lu "
935                                                 "access to attribute %s, value %d not allowed\n",
936                                                 op->o_connid, desc->ad_cname.bv_val, i );
937 #else
938                                         Debug( LDAP_DEBUG_ACL,
939                                                 "acl: access to attribute %s, "
940                                                 "value %d not allowed\n",
941                                                 desc->ad_cname.bv_val, i, 0 );
942 #endif
943
944                                         continue;
945                                 }
946
947                                 if ( op->o_vrFilter && e_flags[j][i] == 0 ){
948                                         continue;
949                                 }
950
951                                 if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
952 #ifdef NEW_LOGGING
953                                         LDAP_LOG( OPERATION, ERR, 
954                                                 "send_search_entry: conn %lu  "
955                                                 "ber_printf failed.\n", op->o_connid, 0, 0 );
956 #else
957                                         Debug( LDAP_DEBUG_ANY,
958                                             "ber_printf failed\n", 0, 0, 0 );
959 #endif
960
961                                         if ( op->o_res_ber == NULL ) ber_free_buf( ber );
962                                         send_ldap_error( op, rs, LDAP_OTHER,
963                                                 "encoding values error" );
964                                         goto error_return;
965                                 }
966                         }
967                 }
968
969                 if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
970 #ifdef NEW_LOGGING
971                         LDAP_LOG( OPERATION, ERR, 
972                                 "send_search_entry: conn %lu ber_printf failed\n", 
973                                 op->o_connid, 0, 0 );
974 #else
975                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
976 #endif
977
978                         if ( op->o_res_ber == NULL ) ber_free_buf( ber );
979                         send_ldap_error( op, rs, LDAP_OTHER, "encode end error" );
980                         goto error_return;
981                 }
982         }
983
984         /* eventually will loop through generated operational attributes */
985         /* only have subschemaSubentry and numSubordinates are implemented */
986         aa = backend_operational( op, rs, opattrs );
987
988         if ( aa != NULL && op->o_vrFilter != NULL ) {
989                 int     k = 0;
990                 size_t  size;
991
992                 for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) {
993                         for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++;
994                 }
995
996                 size = i * sizeof(char *) + k;
997                 if ( size > 0 ) {
998                         char    *a_flags, **tmp;
999                 
1000                         /*
1001                          * Reuse previous memory - we likely need less space
1002                          * for operational attributes
1003                          */
1004                         tmp = sl_realloc( e_flags, i * sizeof(char *) + k,
1005                                 op->o_tmpmemctx );
1006                         if ( tmp == NULL ) {
1007 #ifdef NEW_LOGGING
1008                                 LDAP_LOG( OPERATION, ERR, 
1009                                         "send_search_entry: conn %lu "
1010                                         "not enough memory "
1011                                         "for matched values filtering\n", 
1012                                         op->o_connid, 0, 0);
1013 #else
1014                                 Debug( LDAP_DEBUG_ANY,
1015                                         "send_search_entry: conn %lu "
1016                                         "not enough memory "
1017                                         "for matched values filtering\n",
1018                                         op->o_connid, 0, 0 );
1019 #endif
1020                                 if ( op->o_res_ber == NULL ) ber_free_buf( ber );
1021                                 send_ldap_error( op, rs, LDAP_OTHER,
1022                                         "not enough memory for matched values filtering" );
1023                                 goto error_return;
1024                         }
1025                         e_flags = tmp;
1026                         a_flags = (char *)(e_flags + i);
1027                         memset( a_flags, 0, k );
1028                         for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) {
1029                                 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ );
1030                                 e_flags[i] = a_flags;
1031                                 a_flags += j;
1032                         }
1033                         rc = filter_matched_values(op, aa, &e_flags) ; 
1034                     
1035                         if ( rc == -1 ) {
1036 #ifdef NEW_LOGGING
1037                                 LDAP_LOG( OPERATION, ERR, 
1038                                         "send_search_entry: conn %lu "
1039                                         "matched values filtering failed\n", 
1040                                         op->o_connid ? op->o_connid : 0, 0, 0);
1041 #else
1042                                 Debug( LDAP_DEBUG_ANY,
1043                                         "matched values filtering failed\n", 0, 0, 0 );
1044 #endif
1045                                 if ( op->o_res_ber == NULL ) ber_free_buf( ber );
1046                                 send_ldap_error( op, rs, LDAP_OTHER,
1047                                         "matched values filtering error" );
1048                                 goto error_return;
1049                         }
1050                 }
1051         }
1052
1053         for (a = aa, j=0; a != NULL; a = a->a_next, j++ ) {
1054                 AttributeDescription *desc = a->a_desc;
1055
1056                 if ( rs->sr_attrs == NULL ) {
1057                         /* all attrs request, skip operational attributes */
1058                         if( is_at_operational( desc->ad_type ) ) {
1059                                 continue;
1060                         }
1061
1062                 } else {
1063                         /* specific attrs requested */
1064                         if( is_at_operational( desc->ad_type ) ) {
1065                                 if( !opattrs && !ad_inlist( desc, rs->sr_attrs ) ) {
1066                                         continue;
1067                                 }
1068                         } else {
1069                                 if (!userattrs && !ad_inlist( desc, rs->sr_attrs ) ) {
1070                                         continue;
1071                                 }
1072                         }
1073                 }
1074
1075                 if ( ! access_allowed( op, rs->sr_entry, desc, NULL,
1076                         ACL_READ, &acl_state ) )
1077                 {
1078 #ifdef NEW_LOGGING
1079                         LDAP_LOG( ACL, INFO, 
1080                                 "send_search_entry: conn %lu "
1081                                 "access to attribute %s not allowed\n",
1082                                 op->o_connid, desc->ad_cname.bv_val, 0 );
1083 #else
1084                         Debug( LDAP_DEBUG_ACL, "send_search_entry: access to attribute %s "
1085                                 "not allowed\n", desc->ad_cname.bv_val, 0, 0 );
1086 #endif
1087
1088                         continue;
1089                 }
1090
1091                 rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname );
1092                 if ( rc == -1 ) {
1093 #ifdef NEW_LOGGING
1094                         LDAP_LOG( OPERATION, ERR, 
1095                                 "send_search_entry: conn %lu  "
1096                                 "ber_printf failed\n", op->o_connid, 0, 0 );
1097 #else
1098                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
1099 #endif
1100
1101                         if ( op->o_res_ber == NULL ) ber_free_buf( ber );
1102                         send_ldap_error( op, rs, LDAP_OTHER, "encoding description error" );
1103                         attrs_free( aa );
1104                         goto error_return;
1105                 }
1106
1107                 if ( ! op->ors_attrsonly ) {
1108                         for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
1109                                 if ( ! access_allowed( op, rs->sr_entry,
1110                                         desc, &a->a_vals[i], ACL_READ, &acl_state ) )
1111                                 {
1112 #ifdef NEW_LOGGING
1113                                         LDAP_LOG( ACL, INFO, 
1114                                                 "send_search_entry: conn %lu "
1115                                                 "access to %s, value %d not allowed\n",
1116                                                 op->o_connid, desc->ad_cname.bv_val, i );
1117 #else
1118                                         Debug( LDAP_DEBUG_ACL,
1119                                                 "send_search_entry: access to attribute %s, "
1120                                                 "value %d not allowed\n",
1121                                                 desc->ad_cname.bv_val, i, 0 );
1122 #endif
1123
1124                                         continue;
1125                                 }
1126
1127                                 if ( op->o_vrFilter && e_flags[j][i] == 0 ){
1128                                         continue;
1129                                 }
1130
1131                                 if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
1132 #ifdef NEW_LOGGING
1133                                         LDAP_LOG( OPERATION, ERR, 
1134                                                 "send_search_entry: conn %lu  ber_printf failed\n", 
1135                                                 op->o_connid, 0, 0 );
1136 #else
1137                                         Debug( LDAP_DEBUG_ANY,
1138                                             "ber_printf failed\n", 0, 0, 0 );
1139 #endif
1140
1141                                         if ( op->o_res_ber == NULL ) ber_free_buf( ber );
1142                                         send_ldap_error( op, rs, LDAP_OTHER,
1143                                                 "encoding values error" );
1144                                         attrs_free( aa );
1145                                         goto error_return;
1146                                 }
1147                         }
1148                 }
1149
1150                 if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
1151 #ifdef NEW_LOGGING
1152                         LDAP_LOG( OPERATION, ERR, 
1153                                 "send_search_entry: conn %lu  ber_printf failed\n",
1154                                 op->o_connid, 0, 0 );
1155 #else
1156                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
1157 #endif
1158
1159                         if ( op->o_res_ber == NULL ) ber_free_buf( ber );
1160                         send_ldap_error( op, rs, LDAP_OTHER, "encode end error" );
1161                         attrs_free( aa );
1162                         goto error_return;
1163                 }
1164         }
1165
1166 #ifdef LDAP_SLAPI
1167         /*
1168          * First, setup the computed attribute context that is
1169          * passed to all plugins.
1170          */
1171         if ( op->o_pb ) {
1172                 ctx.cac_pb = op->o_pb;
1173                 ctx.cac_attrs = rs->sr_attrs;
1174                 ctx.cac_attrsonly = op->ors_attrsonly;
1175                 ctx.cac_userattrs = userattrs;
1176                 ctx.cac_opattrs = opattrs;
1177                 ctx.cac_acl_state = acl_state;
1178                 ctx.cac_private = (void *)ber;
1179
1180                 /*
1181                  * For each client requested attribute, call the plugins.
1182                  */
1183                 if ( rs->sr_attrs != NULL ) {
1184                         for ( anp = rs->sr_attrs; anp->an_name.bv_val != NULL; anp++ ) {
1185                                 rc = compute_evaluator( &ctx, anp->an_name.bv_val,
1186                                         rs->sr_entry, slapi_int_compute_output_ber );
1187                                 if ( rc == 1 ) {
1188                                         break;
1189                                 }
1190                         }
1191                 } else {
1192                         /*
1193                          * Technically we shouldn't be returning operational attributes
1194                          * when the user requested only user attributes. We'll let the
1195                          * plugin decide whether to be naughty or not.
1196                          */
1197                         rc = compute_evaluator( &ctx, "*",
1198                                 rs->sr_entry, slapi_int_compute_output_ber );
1199                 }
1200                 if ( rc == 1 ) {
1201                         if ( op->o_res_ber == NULL ) ber_free_buf( ber );
1202                         send_ldap_error( op, rs, LDAP_OTHER, "computed attribute error" );
1203                         goto error_return;
1204                 }
1205         }
1206 #endif /* LDAP_SLAPI */
1207
1208         /* free e_flags */
1209         if ( e_flags ) {
1210                 sl_free( e_flags, op->o_tmpmemctx );
1211                 e_flags = NULL;
1212         }
1213
1214         attrs_free( aa );
1215         rc = ber_printf( ber, /*{{*/ "}N}" );
1216
1217         if( rc != -1 ) {
1218                 rc = send_ldap_controls( op, ber, rs->sr_ctrls );
1219         }
1220
1221         if( rc != -1 ) {
1222 #ifdef LDAP_CONNECTIONLESS
1223                 if( op->o_conn && op->o_conn->c_is_udp ) {
1224                         if ( op->o_protocol != LDAP_VERSION2 ) {
1225                                 rc = ber_printf( ber, /*{*/ "N}" );
1226                         }
1227                 } else
1228 #endif
1229                 if ( op->o_res_ber == NULL ) {
1230                         rc = ber_printf( ber, /*{*/ "N}" );
1231                 }
1232         }
1233
1234         if ( rc == -1 ) {
1235 #ifdef NEW_LOGGING
1236                 LDAP_LOG( OPERATION, ERR, 
1237                         "send_search_entry: conn %lu ber_printf failed\n", 
1238                         op->o_connid, 0, 0 );
1239 #else
1240                 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
1241 #endif
1242
1243                 if ( op->o_res_ber == NULL ) ber_free_buf( ber );
1244                 send_ldap_error( op, rs, LDAP_OTHER, "encode entry end error" );
1245                 rc = 1;
1246                 goto error_return;
1247         }
1248
1249         if ( op->o_res_ber == NULL ) {
1250                 bytes = op->o_noop ? 0 : send_ldap_ber( op->o_conn, ber );
1251                 ber_free_buf( ber );
1252
1253                 if ( bytes < 0 ) {
1254 #ifdef NEW_LOGGING
1255                         LDAP_LOG( OPERATION, ERR, 
1256                                 "send_search_entry: conn %lu  ber write failed.\n", 
1257                                 op->o_connid, 0, 0 );
1258 #else
1259                         Debug( LDAP_DEBUG_ANY,
1260                                 "send_search_entry: ber write failed\n",
1261                                 0, 0, 0 );
1262 #endif
1263
1264                         rc = -1;
1265                         goto error_return;
1266                 }
1267                 rs->sr_nentries++;
1268
1269                 ldap_pvt_thread_mutex_lock( &num_sent_mutex );
1270                 num_bytes_sent += bytes;
1271                 num_entries_sent++;
1272                 num_pdu_sent++;
1273                 ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
1274         }
1275
1276         Statslog( LDAP_DEBUG_STATS2, "conn=%lu op=%lu ENTRY dn=\"%s\"\n",
1277             op->o_connid, op->o_opid, rs->sr_entry->e_dn, 0, 0 );
1278
1279 #ifdef NEW_LOGGING
1280         LDAP_LOG( OPERATION, ENTRY, 
1281                 "send_search_entry: conn %lu exit.\n", op->o_connid, 0, 0 );
1282 #else
1283         Debug( LDAP_DEBUG_TRACE, "<= send_search_entry\n", 0, 0, 0 );
1284 #endif
1285
1286         rc = 0;
1287
1288 error_return:;
1289         /* FIXME: I think rs->sr_type should be explicitly set to
1290          * REP_SEARCH here. That's what it was when we entered this
1291          * function. send_ldap_error may have changed it, but we
1292          * should set it back so that the cleanup functions know
1293          * what they're doing.
1294          */
1295         if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH 
1296                 && rs->sr_entry 
1297                 && (rs->sr_flags & REP_ENTRY_MUSTBEFREED) ) 
1298         {
1299                 entry_free( rs->sr_entry );
1300                 rs->sr_entry = NULL;
1301                 rs->sr_flags &= ~REP_ENTRY_MUSTBEFREED;
1302         }
1303
1304         if ( e_flags ) sl_free( e_flags, op->o_tmpmemctx );
1305
1306         if (op->o_callback) {
1307                 slap_callback *sc = op->o_callback;
1308                 for ( ; op->o_callback; op->o_callback = op->o_callback->sc_next ) {
1309                         if ( op->o_callback->sc_cleanup ) {
1310                                 op->o_callback->sc_cleanup( op, rs );
1311                         }
1312                 }
1313                 op->o_callback = sc;
1314         }
1315         return( rc );
1316 }
1317
1318 int
1319 slap_send_search_reference( Operation *op, SlapReply *rs )
1320 {
1321         BerElementBuffer berbuf;
1322         BerElement      *ber = (BerElement *) &berbuf;
1323         int rc = 0;
1324         int bytes;
1325
1326         AttributeDescription *ad_ref = slap_schema.si_ad_ref;
1327         AttributeDescription *ad_entry = slap_schema.si_ad_entry;
1328
1329         rs->sr_type = REP_SEARCHREF;
1330         if (op->o_callback) {
1331                 slap_callback *sc = op->o_callback;
1332                 rc = SLAP_CB_CONTINUE;
1333                 for ( ; op->o_callback; ) {
1334                         if ( op->o_callback->sc_response ) {
1335                                 rc = op->o_callback->sc_response( op, rs );
1336                                 if ( rc != SLAP_CB_CONTINUE ) break;
1337                         }
1338                         op->o_callback = op->o_callback->sc_next;
1339                 }
1340                 op->o_callback = sc;
1341                 if ( rc != SLAP_CB_CONTINUE ) goto rel;
1342         }
1343
1344 #ifdef NEW_LOGGING
1345         LDAP_LOG( OPERATION, ENTRY, 
1346                 "send_search_reference: conn %lu  dn=\"%s\"\n", 
1347                 op->o_connid,
1348                 rs->sr_entry ? rs->sr_entry->e_name.bv_val : "(null)", 0 );
1349 #else
1350         Debug( LDAP_DEBUG_TRACE,
1351                 "=> send_search_reference: dn=\"%s\"\n",
1352                 rs->sr_entry ? rs->sr_entry->e_name.bv_val : "(null)", 0, 0 );
1353 #endif
1354
1355         if (  rs->sr_entry && ! access_allowed( op, rs->sr_entry,
1356                 ad_entry, NULL, ACL_READ, NULL ) )
1357         {
1358 #ifdef NEW_LOGGING
1359                 LDAP_LOG( ACL, INFO, 
1360                         "send_search_reference: conn %lu        "
1361                         "access to entry %s not allowed\n",
1362                         op->o_connid, rs->sr_entry->e_dn, 0 );
1363 #else
1364                 Debug( LDAP_DEBUG_ACL,
1365                         "send_search_reference: access to entry not allowed\n",
1366                     0, 0, 0 );
1367 #endif
1368                 rc = 1;
1369                 goto rel;
1370         }
1371
1372         if ( rs->sr_entry && ! access_allowed( op, rs->sr_entry,
1373                 ad_ref, NULL, ACL_READ, NULL ) )
1374         {
1375 #ifdef NEW_LOGGING
1376                 LDAP_LOG( ACL, INFO, 
1377                         "send_search_reference: conn %lu access "
1378                         "to reference not allowed.\n", op->o_connid, 0, 0 );
1379 #else
1380                 Debug( LDAP_DEBUG_ACL,
1381                         "send_search_reference: access "
1382                         "to reference not allowed\n",
1383                     0, 0, 0 );
1384 #endif
1385                 rc = 1;
1386                 goto rel;
1387         }
1388
1389 #ifdef LDAP_CONTROL_X_DOMAIN_SCOPE
1390         if( op->o_domain_scope ) {
1391 #ifdef NEW_LOGGING
1392                 LDAP_LOG( OPERATION, ERR, 
1393                         "send_search_reference: conn %lu domainScope control in (%s).\n",
1394                         op->o_connid, rs->sr_entry->e_dn, 0 );
1395 #else
1396                 Debug( LDAP_DEBUG_ANY,
1397                         "send_search_reference: domainScope control in (%s)\n", 
1398                         rs->sr_entry->e_dn, 0, 0 );
1399 #endif
1400                 rc = 0;
1401                 goto rel;
1402         }
1403 #endif
1404
1405         if( rs->sr_ref == NULL ) {
1406 #ifdef NEW_LOGGING
1407                 LDAP_LOG( OPERATION, ERR, 
1408                         "send_search_reference: conn %lu null ref in (%s).\n",
1409                         op->o_connid, rs->sr_entry ? rs->sr_entry->e_dn : "(null)", 0 );
1410 #else
1411                 Debug( LDAP_DEBUG_ANY,
1412                         "send_search_reference: null ref in (%s)\n", 
1413                         rs->sr_entry ? rs->sr_entry->e_dn : "(null)", 0, 0 );
1414 #endif
1415                 rc = 1;
1416                 goto rel;
1417         }
1418
1419         if( op->o_protocol < LDAP_VERSION3 ) {
1420                 rc = 0;
1421                 /* save the references for the result */
1422                 if( rs->sr_ref[0].bv_val != NULL ) {
1423                         if( value_add( &rs->sr_v2ref, rs->sr_ref ) )
1424                                 rc = LDAP_OTHER;
1425                 }
1426                 goto rel;
1427         }
1428
1429 #ifdef LDAP_CONNECTIONLESS
1430         if( op->o_conn && op->o_conn->c_is_udp ) {
1431                 ber = op->o_res_ber;
1432         } else
1433 #endif
1434         {
1435                 ber_init_w_nullc( ber, LBER_USE_DER );
1436                 ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
1437         }
1438
1439         rc = ber_printf( ber, "{it{W}" /*"}"*/ , op->o_msgid,
1440                 LDAP_RES_SEARCH_REFERENCE, rs->sr_ref );
1441
1442         if( rc != -1 ) {
1443                 rc = send_ldap_controls( op, ber, rs->sr_ctrls );
1444         }
1445
1446         if( rc != -1 ) {
1447                 rc = ber_printf( ber, /*"{"*/ "N}" );
1448         }
1449
1450         if ( rc == -1 ) {
1451 #ifdef NEW_LOGGING
1452                 LDAP_LOG( OPERATION, ERR, 
1453                         "send_search_reference: conn %lu        "
1454                         "ber_printf failed.\n", op->o_connid, 0, 0 );
1455 #else
1456                 Debug( LDAP_DEBUG_ANY,
1457                         "send_search_reference: ber_printf failed\n", 0, 0, 0 );
1458 #endif
1459
1460 #ifdef LDAP_CONNECTIONLESS
1461                 if (!op->o_conn || op->o_conn->c_is_udp == 0)
1462 #endif
1463                 ber_free_buf( ber );
1464                 send_ldap_error( op, rs, LDAP_OTHER, "encode DN error" );
1465                 goto rel;
1466         }
1467
1468 #ifdef LDAP_CONNECTIONLESS
1469         if (!op->o_conn || op->o_conn->c_is_udp == 0) {
1470 #endif
1471         bytes = op->o_noop ? 0 : send_ldap_ber( op->o_conn, ber );
1472         ber_free_buf( ber );
1473
1474         ldap_pvt_thread_mutex_lock( &num_sent_mutex );
1475         num_bytes_sent += bytes;
1476         num_refs_sent++;
1477         num_pdu_sent++;
1478         ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
1479 #ifdef LDAP_CONNECTIONLESS
1480         }
1481 #endif
1482
1483         Statslog( LDAP_DEBUG_STATS2, "conn=%lu op=%lu REF dn=\"%s\"\n",
1484                 op->o_connid, op->o_opid, rs->sr_entry ? rs->sr_entry->e_dn : "(null)", 0, 0 );
1485
1486 #ifdef NEW_LOGGING
1487         LDAP_LOG( OPERATION, ENTRY, 
1488                 "send_search_reference: conn %lu exit.\n", op->o_connid, 0, 0 );
1489 #else
1490         Debug( LDAP_DEBUG_TRACE, "<= send_search_reference\n", 0, 0, 0 );
1491 #endif
1492
1493 rel:
1494         if (op->o_callback) {
1495                 slap_callback *sc = op->o_callback;
1496                 for ( ; op->o_callback; op->o_callback = op->o_callback->sc_next ) {
1497                         if ( op->o_callback->sc_cleanup ) {
1498                                 op->o_callback->sc_cleanup( op, rs );
1499                         }
1500                 }
1501                 op->o_callback = sc;
1502         }
1503         return rc;
1504 }
1505
1506 int
1507 str2result(
1508     char        *s,
1509     int         *code,
1510     char        **matched,
1511     char        **info
1512 )
1513 {
1514         int     rc;
1515         char    *c;
1516
1517         *code = LDAP_SUCCESS;
1518         *matched = NULL;
1519         *info = NULL;
1520
1521         if ( strncasecmp( s, "RESULT", 6 ) != 0 ) {
1522 #ifdef NEW_LOGGING
1523                 LDAP_LOG( OPERATION, INFO, 
1524                         "str2result: (%s), expecting \"RESULT\"\n", s, 0, 0 );
1525 #else
1526                 Debug( LDAP_DEBUG_ANY, "str2result (%s) expecting \"RESULT\"\n",
1527                     s, 0, 0 );
1528 #endif
1529
1530                 return( -1 );
1531         }
1532
1533         rc = 0;
1534         while ( (s = strchr( s, '\n' )) != NULL ) {
1535                 *s++ = '\0';
1536                 if ( *s == '\0' ) {
1537                         break;
1538                 }
1539                 if ( (c = strchr( s, ':' )) != NULL ) {
1540                         c++;
1541                 }
1542
1543                 if ( strncasecmp( s, "code", 4 ) == 0 ) {
1544                         if ( c != NULL ) {
1545                                 *code = atoi( c );
1546                         }
1547                 } else if ( strncasecmp( s, "matched", 7 ) == 0 ) {
1548                         if ( c != NULL ) {
1549                                 *matched = c;
1550                         }
1551                 } else if ( strncasecmp( s, "info", 4 ) == 0 ) {
1552                         if ( c != NULL ) {
1553                                 *info = c;
1554                         }
1555                 } else {
1556 #ifdef NEW_LOGGING
1557                         LDAP_LOG( OPERATION, INFO, "str2result: (%s) unknown.\n", s, 0, 0 );
1558 #else
1559                         Debug( LDAP_DEBUG_ANY, "str2result (%s) unknown\n",
1560                             s, 0, 0 );
1561 #endif
1562
1563                         rc = -1;
1564                 }
1565         }
1566
1567         return( rc );
1568 }
1569
1570 int slap_read_controls(
1571         Operation *op,
1572         SlapReply *rs,
1573         Entry *e,
1574         const struct berval *oid,
1575         LDAPControl **ctrl )
1576 {
1577         int rc;
1578         struct berval bv;
1579         BerElementBuffer berbuf;
1580         BerElement *ber = (BerElement *) &berbuf;
1581         LDAPControl c;
1582         ber_len_t       siz, len;
1583         Operation myop;
1584
1585 #ifdef NEW_LOGGING
1586         LDAP_LOG( OPERATION, INFO, "slap_read_controls: (%s) %s\n",
1587                 oid->bv_val, e->e_dn, 0 );
1588 #else
1589         Debug( LDAP_DEBUG_ANY, "slap_read_controls: (%s) %s\n",
1590                 oid->bv_val, e->e_dn, 0 );
1591 #endif
1592
1593         rs->sr_entry = e;
1594         rs->sr_attrs = ( oid == &slap_pre_read_bv ) ?
1595                 op->o_preread_attrs : op->o_postread_attrs; 
1596
1597         entry_flatsize( rs->sr_entry, &siz, &len, 0 );
1598         bv.bv_len = siz + len;
1599         bv.bv_val = op->o_tmpalloc(bv.bv_len, op->o_tmpmemctx );
1600
1601         ber_init2( ber, &bv, LBER_USE_DER );
1602         ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
1603
1604         /* create new operation */
1605         myop = *op;
1606         myop.o_bd = NULL;
1607         myop.o_res_ber = ber;
1608
1609         rc = slap_send_search_entry( &myop, rs );
1610         if( rc ) return rc;
1611
1612         rc = ber_flatten2( ber, &c.ldctl_value, 0 );
1613
1614         if( rc == LBER_ERROR ) return LDAP_OTHER;
1615
1616         c.ldctl_oid = oid->bv_val;
1617         c.ldctl_iscritical = 0;
1618
1619         *ctrl = sl_calloc( 1, sizeof(LDAPControl), NULL );
1620         **ctrl = c;
1621         return LDAP_SUCCESS;
1622 }