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