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