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