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