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