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