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