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