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