]> git.sur5r.net Git - openldap/blob - servers/slapd/result.c
mostly new logging
[openldap] / servers / slapd / result.c
1 /* result.c - routines to send ldap results, errors, and referrals */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/socket.h>
13 #include <ac/errno.h>
14 #include <ac/string.h>
15 #include <ac/ctype.h>
16 #include <ac/time.h>
17 #include <ac/unistd.h>
18
19 #include "slap.h"
20
21 static char *v2ref( BerVarray ref, const char *text )
22 {
23         size_t len = 0, i = 0;
24         char *v2;
25
26         if(ref == NULL) {
27                 if (text) {
28                         return ch_strdup(text);
29                 } else {
30                         return NULL;
31                 }
32         }
33         
34         if ( text != NULL ) {
35                 len = strlen( text );
36                 if (text[len-1] != '\n') {
37                     i = 1;
38                 }
39         }
40
41         v2 = ch_malloc( len+i+sizeof("Referral:") );
42         if( text != NULL ) {
43                 strcpy(v2, text);
44                 if( i ) {
45                         v2[len++] = '\n';
46                 }
47         }
48         strcpy( v2+len, "Referral:" );
49         len += sizeof("Referral:");
50
51         for( i=0; ref[i].bv_val != NULL; i++ ) {
52                 v2 = ch_realloc( v2, len + ref[i].bv_len + 1 );
53                 v2[len-1] = '\n';
54                 AC_MEMCPY(&v2[len], ref[i].bv_val, ref[i].bv_len );
55                 len += ref[i].bv_len;
56                 if (ref[i].bv_val[ref[i].bv_len-1] != '/') {
57                         ++len;
58                 }
59         }
60
61         v2[len-1] = '\0';
62         return v2;
63 }
64
65 static ber_tag_t req2res( ber_tag_t tag )
66 {
67         switch( tag ) {
68         case LDAP_REQ_ADD:
69         case LDAP_REQ_BIND:
70         case LDAP_REQ_COMPARE:
71         case LDAP_REQ_EXTENDED:
72         case LDAP_REQ_MODIFY:
73         case LDAP_REQ_MODRDN:
74                 tag++;
75                 break;
76
77         case LDAP_REQ_DELETE:
78                 tag = LDAP_RES_DELETE;
79                 break;
80
81         case LDAP_REQ_ABANDON:
82         case LDAP_REQ_UNBIND:
83                 tag = LBER_SEQUENCE;
84                 break;
85
86         case LDAP_REQ_SEARCH:
87                 tag = LDAP_RES_SEARCH_RESULT;
88                 break;
89
90         default:
91                 tag = LBER_SEQUENCE;
92         }
93
94         return tag;
95 }
96
97 static long send_ldap_ber(
98         Connection *conn,
99         BerElement *ber )
100 {
101         ber_len_t bytes;
102
103         ber_get_option( ber, LBER_OPT_BER_BYTES_TO_WRITE, &bytes );
104
105         /* write only one pdu at a time - wait til it's our turn */
106         ldap_pvt_thread_mutex_lock( &conn->c_write_mutex );
107
108         /* lock the connection */ 
109         ldap_pvt_thread_mutex_lock( &conn->c_mutex );
110
111         /* write the pdu */
112         while( 1 ) {
113                 int err;
114                 ber_socket_t    sd;
115
116                 if ( connection_state_closing( conn ) ) {
117                         ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
118                         ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
119
120                         return 0;
121                 }
122
123                 if ( ber_flush( conn->c_sb, ber, 0 ) == 0 ) {
124                         break;
125                 }
126
127                 err = errno;
128
129                 /*
130                  * we got an error.  if it's ewouldblock, we need to
131                  * wait on the socket being writable.  otherwise, figure
132                  * it's a hard error and return.
133                  */
134
135 #ifdef NEW_LOGGING
136                 LDAP_LOG( OPERATION, ERR, 
137                         "send_ldap_ber: conn %lu  ber_flush failed err=%d (%s)\n",
138                         conn ? conn->c_connid : 0, err, sock_errstr(err) );
139 #else
140                 Debug( LDAP_DEBUG_CONNS, "ber_flush failed errno=%d reason=\"%s\"\n",
141                     err, sock_errstr(err), 0 );
142 #endif
143
144                 if ( err != EWOULDBLOCK && err != EAGAIN ) {
145                         connection_closing( conn );
146
147                         ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
148                         ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
149
150                         return( -1 );
151                 }
152
153                 /* wait for socket to be write-ready */
154                 conn->c_writewaiter = 1;
155                 ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_GET_FD, &sd );
156                 slapd_set_write( sd, 1 );
157
158                 ldap_pvt_thread_cond_wait( &conn->c_write_cv, &conn->c_mutex );
159                 conn->c_writewaiter = 0;
160         }
161
162         ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
163         ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
164
165         return bytes;
166 }
167
168 static 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, ENTRY, 
201                 "send_ldap_response:  msgid=%d tag=%lu err=%d\n",
202                 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, 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" , 0 );
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, ERR, 
229                         "send_ldap_response: conn %lu  ber_write failed\n",
230                         conn ? conn->c_connid : 0 , 0, 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, ERR, 
289                         "send_ldap_response: conn %lu  ber_printf failed\n",
290                         conn ? conn->c_connid : 0, 0, 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, ERR, 
306                         "send_ldap_response: conn %lu ber write failed\n",
307                         conn ? conn->c_connid : 0, 0, 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, 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, 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, ARGS, 
404                 "send_ldap_result: err=%d matched=\"%s\" text=\"%s\"\n",
405                 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, ARGS, 
416                         "send_ldap_result: referral=\"%s\"\n",
417                         ref[0].bv_val ? ref[0].bv_val : "NULL", 0, 0 );
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, 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, ENTRY, 
509                 "send_ldap_extended: err=%d oid=%s len=%ld\n",
510                 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, ENTRY, 
556                 "send_search_result: err=%d matched=\"%s\" text=\"%s\"\n",
557                 err, matched ? matched : "", text ? text : "" );
558 #else
559         Debug( LDAP_DEBUG_TRACE,
560                 "send_search_result: err=%d matched=\"%s\" text=\"%s\"\n",
561                 err, matched ?  matched : "", text ? text : "" );
562 #endif
563
564
565         assert( err != LDAP_PARTIAL_RESULTS );
566
567         if( op->o_protocol < LDAP_VERSION3 ) {
568                 /* send references in search results */
569                 if( err == LDAP_REFERRAL ) {
570                         err = LDAP_PARTIAL_RESULTS;
571                 }
572
573                 tmp = v2ref( refs, text );
574                 text = tmp;
575                 refs = NULL;
576
577         } else {
578                 /* don't send references in search results */
579                 assert( refs == NULL );
580                 refs = NULL;
581
582                 if( err == LDAP_REFERRAL ) {
583                         err = LDAP_SUCCESS;
584                 }
585         }
586
587         tag = req2res( op->o_tag );
588         msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0;
589
590         send_ldap_response( conn, op, tag, msgid,
591                 err, matched, text, refs,
592                 NULL, NULL, NULL, ctrls );
593
594         {
595         char nbuf[64];
596         snprintf( nbuf, sizeof nbuf, "%d nentries=%d", err, nentries );
597
598         Statslog( LDAP_DEBUG_STATS,
599             "conn=%lu op=%lu SEARCH RESULT tag=%lu err=%s text=%s\n",
600                 op->o_connid, op->o_opid, tag, nbuf, text ? text : "" );
601         }
602
603         if (tmp != NULL) {
604             ch_free(tmp);
605         }
606 }
607
608 static struct berval AllUser = { sizeof(LDAP_ALL_USER_ATTRIBUTES)-1,
609         LDAP_ALL_USER_ATTRIBUTES };
610 static struct berval AllOper = { sizeof(LDAP_ALL_OPERATIONAL_ATTRIBUTES)-1,
611         LDAP_ALL_OPERATIONAL_ATTRIBUTES };
612
613 int
614 send_search_entry(
615     Backend     *be,
616     Connection  *conn,
617     Operation   *op,
618     Entry       *e,
619     AttributeName       *attrs,
620     int         attrsonly,
621         LDAPControl **ctrls
622 )
623 {
624         char            berbuf[256];
625         BerElement      *ber = (BerElement *)berbuf;
626         Attribute       *a, *aa;
627         int             i, j, rc=-1, bytes;
628         char            *edn;
629         int             userattrs;
630         int             opattrs;
631         static AccessControlState acl_state_init = ACL_STATE_INIT;
632         AccessControlState acl_state;
633
634         AttributeDescription *ad_entry = slap_schema.si_ad_entry;
635
636         /* a_flags: array of flags telling if the i-th element will be
637          *          returned or filtered out
638          * e_flags: array of a_flags
639          */
640         char *a_flags, **e_flags;
641
642         if (op->o_callback && op->o_callback->sc_sendentry) {
643                 return op->o_callback->sc_sendentry( be, conn, op, e, attrs,
644                         attrsonly, ctrls );
645         }
646
647 #ifdef NEW_LOGGING
648         LDAP_LOG( OPERATION, ENTRY, 
649                 "send_search_entry: conn %lu    dn=\"%s\"%s\n",
650                 op->o_connid, e->e_dn, attrsonly ? " (attrsOnly)" : "" );
651 #else
652         Debug( LDAP_DEBUG_TRACE,
653                 "=> send_search_entry: dn=\"%s\"%s\n",
654                 e->e_dn, attrsonly ? " (attrsOnly)" : "", 0 );
655 #endif
656
657         if ( ! access_allowed( be, conn, op, e,
658                 ad_entry, NULL, ACL_READ, NULL ) )
659         {
660 #ifdef NEW_LOGGING
661                 LDAP_LOG( ACL, INFO, 
662                         "send_search_entry: conn %lu access to entry (%s) not allowed\n", 
663                         op->o_connid, e->e_dn, 0 );
664 #else
665                 Debug( LDAP_DEBUG_ACL,
666                         "send_search_entry: access to entry not allowed\n",
667                     0, 0, 0 );
668 #endif
669
670                 return( 1 );
671         }
672
673         edn = e->e_ndn;
674
675         ber_init_w_nullc( ber, LBER_USE_DER );
676
677 #ifdef LDAP_CONNECTIONLESS
678         if (conn->c_is_udp) {
679             rc = ber_write(ber, (char *)&op->o_peeraddr, sizeof(struct sockaddr), 0);
680             if (rc != sizeof(struct sockaddr)) {
681 #ifdef NEW_LOGGING
682                 LDAP_LOG( OPERATION, ERR, 
683                         "send_search_entry: conn %lu  ber_printf failed\n",
684                         conn ? conn->c_connid : 0, 0, 0 );
685 #else
686                 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
687 #endif
688                 ber_free_buf( ber );
689                 return;
690             }
691         }
692         if (conn->c_is_udp && op->o_protocol == LDAP_VERSION2) {
693             rc = ber_printf( ber, "{is{t{O{" /*}}}*/,
694                 op->o_msgid, "", LDAP_RES_SEARCH_ENTRY, &e->e_name );
695         } else
696 #endif /* LDAP_CONNECTIONLESS */
697         {
698             rc = ber_printf( ber, "{it{O{" /*}}}*/, op->o_msgid,
699                 LDAP_RES_SEARCH_ENTRY, &e->e_name );
700         }
701
702         if ( rc == -1 ) {
703 #ifdef NEW_LOGGING
704                 LDAP_LOG( OPERATION, ERR, 
705                         "send_search_entry: conn %lu  ber_printf failed\n", 
706                         op->o_connid, 0, 0 );
707 #else
708                 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
709 #endif
710
711                 ber_free_buf( ber );
712                 send_ldap_result( conn, op, LDAP_OTHER,
713                     NULL, "encoding DN error", NULL, NULL );
714                 goto error_return;
715         }
716
717         /* check for special all user attributes ("*") type */
718         userattrs = ( attrs == NULL ) ? 1
719                 : an_find( attrs, &AllUser );
720
721         /* check for special all operational attributes ("+") type */
722         opattrs = ( attrs == NULL ) ? 0
723                 : an_find( attrs, &AllOper );
724
725         /* create an array of arrays of flags. Each flag corresponds
726          * to particular value of attribute and equals 1 if value matches
727          * to ValuesReturnFilter or 0 if not
728          */     
729         for ( a = e->e_attrs, i=0; a != NULL; a = a->a_next ) i++;
730         e_flags = ch_malloc ( i * sizeof(a_flags) );
731         
732         for ( a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
733                 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ );
734
735                 if( j ) {
736                         a_flags = ch_calloc ( j, sizeof(char) );
737                         /* If no ValuesReturnFilter control return everything */
738                         if ( op->vrFilter == NULL ) {
739                                 memset(a_flags, 1, j);
740                         }
741                 } else {
742                         a_flags = NULL;
743                 }
744                 e_flags[i] = a_flags; 
745         }
746
747         if ( op->vrFilter != NULL ) { 
748                 rc = filter_matched_values(be, conn, op, e->e_attrs, &e_flags) ; 
749             
750                 if ( rc == -1 ) {
751 #ifdef NEW_LOGGING
752                         LDAP_LOG( OPERATION, ERR, 
753                                 "send_search_entry: conn %lu matched values filtering failed\n",
754                                 conn ? conn->c_connid : 0, 0, 0 );
755 #else
756                 Debug( LDAP_DEBUG_ANY,
757                                 "matched values filtering failed\n", 0, 0, 0 );
758 #endif
759                         ber_free( ber, 1 );
760
761                         /* free e_flags */
762                         for ( a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
763                                 free( e_flags[i] );
764                         }
765                         free( e_flags );
766
767                         send_ldap_result( conn, op, LDAP_OTHER,
768                                 NULL, "matched values filtering error", 
769                                 NULL, NULL );
770                         goto error_return;
771                 }
772         }
773
774         for ( a = e->e_attrs, j = 0; a != NULL; a = a->a_next, j++ ) {
775                 AttributeDescription *desc = a->a_desc;
776
777                 if ( attrs == NULL ) {
778                         /* all attrs request, skip operational attributes */
779                         if( is_at_operational( desc->ad_type ) ) {
780                                 continue;
781                         }
782
783                 } else {
784                         /* specific attrs requested */
785                         if ( is_at_operational( desc->ad_type ) ) {
786                                 if( !opattrs && !ad_inlist( desc, attrs ) ) {
787                                         continue;
788                                 }
789
790                         } else {
791                                 if (!userattrs && !ad_inlist( desc, attrs ) ) {
792                                         continue;
793                                 }
794                         }
795                 }
796
797                 acl_state = acl_state_init;
798
799                 if ( ! access_allowed( be, conn, op, e, desc, NULL,
800                         ACL_READ, &acl_state ) )
801                 {
802 #ifdef NEW_LOGGING
803                         LDAP_LOG( ACL, INFO, 
804                                 "send_search_entry: conn %lu  access to attribute %s not "
805                                 "allowed\n", op->o_connid, desc->ad_cname.bv_val, 0 );
806 #else
807                         Debug( LDAP_DEBUG_ACL, "acl: "
808                                 "access to attribute %s not allowed\n",
809                             desc->ad_cname.bv_val, 0, 0 );
810 #endif
811                         continue;
812                 }
813
814                 if (( rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname )) == -1 ) {
815 #ifdef NEW_LOGGING
816                         LDAP_LOG( OPERATION, ERR, 
817                                 "send_search_entry: conn %lu  ber_printf failed\n", 
818                                 op->o_connid, 0, 0 );
819 #else
820                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
821 #endif
822
823                         ber_free_buf( ber );
824                         /* free e_flags */
825                         for ( a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
826                                 free( e_flags[i] );
827                         }
828                         free( e_flags );
829                         send_ldap_result( conn, op, LDAP_OTHER,
830                             NULL, "encoding description error", NULL, NULL );
831                         goto error_return;
832                 }
833
834                 if ( ! attrsonly ) {
835                         for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
836                                 if ( ! access_allowed( be, conn, op, e,
837                                         desc, &a->a_vals[i], ACL_READ, &acl_state ) )
838                                 {
839 #ifdef NEW_LOGGING
840                                         LDAP_LOG( ACL, INFO, 
841                                                 "send_search_entry: conn %lu "
842                                                 "access to attribute %s, value %d not allowed\n",
843                                                 op->o_connid, desc->ad_cname.bv_val, i );
844 #else
845                                         Debug( LDAP_DEBUG_ACL,
846                                                 "acl: access to attribute %s, "
847                                                 "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, ERR, 
861                                                 "send_search_entry: conn %lu  "
862                                                 "ber_printf failed.\n", op->o_connid, 0, 0 );
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",
876                                                 NULL, NULL );
877                                         goto error_return;
878                                 }
879                         }
880                 }
881
882                 if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
883 #ifdef NEW_LOGGING
884                         LDAP_LOG( OPERATION, ERR, 
885                                 "send_search_entry: conn %lu ber_printf failed\n", 
886                                 op->o_connid, 0, 0 );
887 #else
888                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
889 #endif
890
891                         ber_free_buf( ber );
892                         /* free e_flags */
893                         for ( a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
894                                 free( e_flags[i] );
895                         }
896                         free( e_flags );
897                         send_ldap_result( conn, op, LDAP_OTHER,
898                             NULL, "encode end error", NULL, NULL );
899                         goto error_return;
900                 }
901         }
902
903         /* free e_flags */
904         for ( a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
905                 free( e_flags[i] );
906         }
907         free( e_flags );
908
909         /* eventually will loop through generated operational attributes */
910         /* only have subschemaSubentry implemented */
911         aa = backend_operational( be, conn, op, e, attrs, opattrs );
912
913         for ( a = aa, i=0; a != NULL; a = a->a_next ) i++;
914         e_flags = ch_malloc ( i * sizeof(a_flags) );
915         
916         for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) {
917                 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ );
918
919                 a_flags = ch_calloc ( j, sizeof(char) );
920                 /* If no ValuesReturnFilter control return everything */
921                 if ( op->vrFilter == NULL ){
922                     memset(a_flags, 1, j);
923                 }
924                 e_flags[i] = a_flags; 
925         }
926
927         if ( op->vrFilter != NULL ) {
928                 rc = filter_matched_values(be, conn, op, aa, &e_flags) ; 
929             
930                 if ( rc == -1 ) {
931 #ifdef NEW_LOGGING
932                         LDAP_LOG( OPERATION, ERR, 
933                                 "send_search_entry: conn %lu "
934                                 "matched values filtering failed\n", 
935                                 conn ? conn->c_connid : 0, 0, 0);
936 #else
937                 Debug( LDAP_DEBUG_ANY,
938                                 "matched values filtering failed\n", 0, 0, 0 );
939 #endif
940                         ber_free( ber, 1 );
941
942                         /* free e_flags */
943                         for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) {
944                                 free( e_flags[i] );
945                         }
946                         free( e_flags );
947
948                         send_ldap_result( conn, op, LDAP_OTHER,
949                                 NULL, "matched values filtering error", 
950                                 NULL, NULL );
951                         goto error_return;
952                 }
953         }
954
955         for (a = aa, j=0; a != NULL; a = a->a_next, j++ ) {
956                 AttributeDescription *desc = a->a_desc;
957
958                 if ( attrs == NULL ) {
959                         /* all attrs request, skip operational attributes */
960                         if( is_at_operational( desc->ad_type ) ) {
961                                 continue;
962                         }
963
964                 } else {
965                         /* specific attrs requested */
966                         if( is_at_operational( desc->ad_type ) ) {
967                                 if( !opattrs && !ad_inlist( desc, attrs ) ) {
968                                         continue;
969                                 }
970                         } else {
971                                 if (!userattrs && !ad_inlist( desc, attrs ) )
972                                 {
973                                         continue;
974                                 }
975                         }
976                 }
977
978                 acl_state = acl_state_init;
979
980                 if ( ! access_allowed( be, conn, op, e, desc, NULL,
981                         ACL_READ, &acl_state ) )
982                 {
983 #ifdef NEW_LOGGING
984                         LDAP_LOG( ACL, INFO, 
985                                 "send_search_entry: conn %lu "
986                                 "access to attribute %s not allowed\n",
987                                 op->o_connid, desc->ad_cname.bv_val, 0 );
988 #else
989                         Debug( LDAP_DEBUG_ACL, "acl: access to attribute %s "
990                                         "not allowed\n",
991                                         desc->ad_cname.bv_val, 0, 0 );
992 #endif
993
994                         continue;
995                 }
996
997                 rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname );
998                 if ( rc == -1 ) {
999 #ifdef NEW_LOGGING
1000                         LDAP_LOG( OPERATION, ERR, 
1001                                 "send_search_entry: conn %lu  "
1002                                 "ber_printf failed\n", op->o_connid, 0, 0 );
1003 #else
1004                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
1005 #endif
1006
1007                         ber_free_buf( ber );
1008                         send_ldap_result( conn, op, LDAP_OTHER,
1009                             NULL, "encoding description error", NULL, NULL );
1010                         /* free e_flags */
1011                         for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) {
1012                                 free( e_flags[i] );
1013                         }
1014                         free( e_flags );
1015
1016                         attrs_free( aa );
1017                         goto error_return;
1018                 }
1019
1020                 if ( ! attrsonly ) {
1021                         for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
1022                                 if ( ! access_allowed( be, conn, op, e,
1023                                         desc, &a->a_vals[i], ACL_READ, &acl_state ) )
1024                                 {
1025 #ifdef NEW_LOGGING
1026                                         LDAP_LOG( ACL, INFO, 
1027                                                 "send_search_entry: conn %lu "
1028                                                 "access to %s, value %d not allowed\n",
1029                                                 op->o_connid, desc->ad_cname.bv_val, i );
1030 #else
1031                                         Debug( LDAP_DEBUG_ACL,
1032                                                 "acl: access to attribute %s, "
1033                                                 "value %d not allowed\n",
1034                                                 desc->ad_cname.bv_val, i, 0 );
1035 #endif
1036
1037                                         continue;
1038                                 }
1039
1040                                 if ( e_flags[j][i] == 0 ){
1041                                         continue;
1042                                 }
1043
1044                                 if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
1045 #ifdef NEW_LOGGING
1046                                         LDAP_LOG( OPERATION, ERR, 
1047                                                 "send_search_entry: conn %lu  ber_printf failed\n", 
1048                                                 op->o_connid, 0, 0 );
1049 #else
1050                                         Debug( LDAP_DEBUG_ANY,
1051                                             "ber_printf failed\n", 0, 0, 0 );
1052 #endif
1053
1054                                         ber_free_buf( ber );
1055                                         send_ldap_result( conn, op, LDAP_OTHER,
1056                                                 NULL, "encoding values error", 
1057                                                 NULL, NULL );
1058                                         /* free e_flags */
1059                                         for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) {
1060                                                 free( e_flags[i] );
1061                                         }
1062                                         free( e_flags );
1063
1064                                         attrs_free( aa );
1065                                         goto error_return;
1066                                 }
1067                         }
1068                 }
1069
1070                 if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
1071 #ifdef NEW_LOGGING
1072                         LDAP_LOG( OPERATION, ERR, 
1073                                 "send_search_entry: conn %lu  ber_printf failed\n",
1074                                 op->o_connid, 0, 0 );
1075 #else
1076                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
1077 #endif
1078
1079                         ber_free_buf( ber );
1080                         send_ldap_result( conn, op, LDAP_OTHER,
1081                             NULL, "encode end error", NULL, NULL );
1082                         /* free e_flags */
1083                         for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) {
1084                                 free( e_flags[i] );
1085                         }
1086                         free( e_flags );
1087
1088                         attrs_free( aa );
1089                         goto error_return;
1090                 }
1091         }
1092
1093         /* free e_flags */
1094         for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) {
1095                 free( e_flags[i] );
1096         }
1097         free( e_flags );
1098
1099         attrs_free( aa );
1100         rc = ber_printf( ber, /*{{{*/ "}N}N}" );
1101
1102 #ifdef LDAP_CONNECTIONLESS
1103         if (conn->c_is_udp && op->o_protocol == LDAP_VERSION2 && rc != -1)
1104                 rc = ber_printf( ber, "}" );
1105 #endif
1106         if ( rc == -1 ) {
1107 #ifdef NEW_LOGGING
1108                 LDAP_LOG( OPERATION, ERR, 
1109                         "send_search_entry: conn %lu ber_printf failed\n", 
1110                         op->o_connid, 0, 0 );
1111 #else
1112                 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
1113 #endif
1114
1115                 ber_free_buf( ber );
1116                 send_ldap_result( conn, op, LDAP_OTHER,
1117                         NULL, "encode entry end error", NULL, NULL );
1118                 return( 1 );
1119         }
1120
1121         bytes = send_ldap_ber( conn, ber );
1122         ber_free_buf( ber );
1123
1124         if ( bytes < 0 ) {
1125 #ifdef NEW_LOGGING
1126                 LDAP_LOG( OPERATION, ERR, 
1127                            "send_search_entry: conn %lu  ber write failed.\n", 
1128                            op->o_connid, 0, 0 );
1129 #else
1130                 Debug( LDAP_DEBUG_ANY,
1131                         "send_search_entry: ber write failed\n",
1132                         0, 0, 0 );
1133 #endif
1134
1135                 return -1;
1136         }
1137
1138         ldap_pvt_thread_mutex_lock( &num_sent_mutex );
1139         num_bytes_sent += bytes;
1140         num_entries_sent++;
1141         num_pdu_sent++;
1142         ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
1143
1144         Statslog( LDAP_DEBUG_STATS2, "conn=%lu op=%lu ENTRY dn=\"%s\"\n",
1145             conn->c_connid, op->o_opid, e->e_dn, 0, 0 );
1146
1147 #ifdef NEW_LOGGING
1148         LDAP_LOG( OPERATION, ENTRY, 
1149                 "send_search_entry: conn %lu exit.\n", op->o_connid, 0, 0 );
1150 #else
1151         Debug( LDAP_DEBUG_TRACE, "<= send_search_entry\n", 0, 0, 0 );
1152 #endif
1153
1154         rc = 0;
1155
1156 error_return:;
1157         return( rc );
1158 }
1159
1160 int
1161 send_search_reference(
1162     Backend     *be,
1163     Connection  *conn,
1164     Operation   *op,
1165     Entry       *e,
1166         BerVarray refs,
1167         LDAPControl **ctrls,
1168     BerVarray *v2refs
1169 )
1170 {
1171         char            berbuf[256];
1172         BerElement      *ber = (BerElement *)berbuf;
1173         int rc;
1174         int bytes;
1175
1176         AttributeDescription *ad_ref = slap_schema.si_ad_ref;
1177         AttributeDescription *ad_entry = slap_schema.si_ad_entry;
1178
1179 #ifdef NEW_LOGGING
1180         LDAP_LOG( OPERATION, ENTRY, 
1181                 "send_search_reference: conn %lu  dn=\"%s\"\n", 
1182                 op->o_connid, e->e_dn, 0 );
1183 #else
1184         Debug( LDAP_DEBUG_TRACE,
1185                 "=> send_search_reference: dn=\"%s\"\n",
1186                 e->e_dn, 0, 0 );
1187 #endif
1188
1189
1190         if ( ! access_allowed( be, conn, op, e,
1191                 ad_entry, NULL, ACL_READ, NULL ) )
1192         {
1193 #ifdef NEW_LOGGING
1194                 LDAP_LOG( ACL, INFO, 
1195                         "send_search_reference: conn %lu        "
1196                         "access to entry %s not allowed\n", op->o_connid, e->e_dn, 0 );
1197 #else
1198                 Debug( LDAP_DEBUG_ACL,
1199                         "send_search_reference: access to entry not allowed\n",
1200                     0, 0, 0 );
1201 #endif
1202
1203                 return( 1 );
1204         }
1205
1206         if ( ! access_allowed( be, conn, op, e,
1207                 ad_ref, NULL, ACL_READ, NULL ) )
1208         {
1209 #ifdef NEW_LOGGING
1210                 LDAP_LOG( ACL, INFO, 
1211                         "send_search_reference: conn %lu access "
1212                         "to reference not allowed.\n", op->o_connid, 0, 0 );
1213 #else
1214                 Debug( LDAP_DEBUG_ACL,
1215                         "send_search_reference: access "
1216                         "to reference not allowed\n",
1217                     0, 0, 0 );
1218 #endif
1219
1220                 return( 1 );
1221         }
1222
1223         if( refs == NULL ) {
1224 #ifdef NEW_LOGGING
1225                 LDAP_LOG( OPERATION, ERR, 
1226                         "send_search_reference: conn %lu null ref in (%s).\n",
1227                         op->o_connid, e->e_dn, 0 );
1228 #else
1229                 Debug( LDAP_DEBUG_ANY,
1230                         "send_search_reference: null ref in (%s)\n", 
1231                         e->e_dn, 0, 0 );
1232 #endif
1233
1234                 return( 1 );
1235         }
1236
1237         if( op->o_protocol < LDAP_VERSION3 ) {
1238                 /* save the references for the result */
1239                 if( refs[0].bv_val != NULL ) {
1240                         value_add( v2refs, refs );
1241                 }
1242                 return 0;
1243         }
1244
1245         ber_init_w_nullc( ber, LBER_USE_DER );
1246
1247         rc = ber_printf( ber, "{it{W}N}", op->o_msgid,
1248                 LDAP_RES_SEARCH_REFERENCE, refs );
1249
1250         if ( rc == -1 ) {
1251 #ifdef NEW_LOGGING
1252                 LDAP_LOG( OPERATION, ERR, 
1253                         "send_search_reference: conn %lu        "
1254                         "ber_printf failed.\n", op->o_connid, 0, 0 );
1255 #else
1256                 Debug( LDAP_DEBUG_ANY,
1257                         "send_search_reference: ber_printf failed\n", 0, 0, 0 );
1258 #endif
1259
1260                 ber_free_buf( ber );
1261                 send_ldap_result( conn, op, LDAP_OTHER,
1262                         NULL, "encode DN error", NULL, NULL );
1263                 return -1;
1264         }
1265
1266         bytes = send_ldap_ber( conn, ber );
1267         ber_free_buf( ber );
1268
1269         ldap_pvt_thread_mutex_lock( &num_sent_mutex );
1270         num_bytes_sent += bytes;
1271         num_refs_sent++;
1272         num_pdu_sent++;
1273         ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
1274
1275         Statslog( LDAP_DEBUG_STATS2, "conn=%lu op=%lu REF dn=\"%s\"\n",
1276                 conn->c_connid, op->o_opid, e->e_dn, 0, 0 );
1277
1278 #ifdef NEW_LOGGING
1279         LDAP_LOG( OPERATION, ENTRY, 
1280                 "send_search_reference: conn %lu exit.\n", op->o_connid, 0, 0 );
1281 #else
1282         Debug( LDAP_DEBUG_TRACE, "<= send_search_reference\n", 0, 0, 0 );
1283 #endif
1284
1285         return 0;
1286 }
1287
1288
1289 int
1290 str2result(
1291     char        *s,
1292     int         *code,
1293     char        **matched,
1294     char        **info
1295 )
1296 {
1297         int     rc;
1298         char    *c;
1299
1300         *code = LDAP_SUCCESS;
1301         *matched = NULL;
1302         *info = NULL;
1303
1304         if ( strncasecmp( s, "RESULT", 6 ) != 0 ) {
1305 #ifdef NEW_LOGGING
1306                 LDAP_LOG( OPERATION, INFO, 
1307                         "str2result: (%s), expecting \"RESULT\"\n", s, 0, 0 );
1308 #else
1309                 Debug( LDAP_DEBUG_ANY, "str2result (%s) expecting \"RESULT\"\n",
1310                     s, 0, 0 );
1311 #endif
1312
1313                 return( -1 );
1314         }
1315
1316         rc = 0;
1317         while ( (s = strchr( s, '\n' )) != NULL ) {
1318                 *s++ = '\0';
1319                 if ( *s == '\0' ) {
1320                         break;
1321                 }
1322                 if ( (c = strchr( s, ':' )) != NULL ) {
1323                         c++;
1324                 }
1325
1326                 if ( strncasecmp( s, "code", 4 ) == 0 ) {
1327                         if ( c != NULL ) {
1328                                 *code = atoi( c );
1329                         }
1330                 } else if ( strncasecmp( s, "matched", 7 ) == 0 ) {
1331                         if ( c != NULL ) {
1332                                 *matched = c;
1333                         }
1334                 } else if ( strncasecmp( s, "info", 4 ) == 0 ) {
1335                         if ( c != NULL ) {
1336                                 *info = c;
1337                         }
1338                 } else {
1339 #ifdef NEW_LOGGING
1340                         LDAP_LOG( OPERATION, INFO, "str2result: (%s) unknown.\n", s, 0, 0 );
1341 #else
1342                         Debug( LDAP_DEBUG_ANY, "str2result (%s) unknown\n",
1343                             s, 0, 0 );
1344 #endif
1345
1346                         rc = -1;
1347                 }
1348         }
1349
1350         return( rc );
1351 }