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