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