]> git.sur5r.net Git - openldap/blob - servers/slapd/result.c
Change recover logic
[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 **e_flags = NULL;
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         if ( op->vrFilter != NULL ) {
730                 int k = 0;
731                 char *a_flags;
732
733                 for ( a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
734                         for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++;
735                 }
736                 e_flags = ch_calloc ( 1, i * sizeof(char *) + k );
737                 a_flags = (char *)(e_flags + i);
738                 for ( a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
739                         for ( j = 0; a->a_vals[j].bv_val != NULL; j++ );
740                         e_flags[i] = a_flags;
741                         a_flags += j;
742                 }
743
744                 rc = filter_matched_values(be, conn, op, e->e_attrs, &e_flags) ; 
745                 if ( rc == -1 ) {
746 #ifdef NEW_LOGGING
747                         LDAP_LOG( OPERATION, ERR, 
748                                 "send_search_entry: conn %lu matched values filtering failed\n",
749                                 conn ? conn->c_connid : 0, 0, 0 );
750 #else
751                 Debug( LDAP_DEBUG_ANY,
752                                 "matched values filtering failed\n", 0, 0, 0 );
753 #endif
754                         ber_free( ber, 1 );
755
756                         send_ldap_result( conn, op, LDAP_OTHER,
757                                 NULL, "matched values filtering error", 
758                                 NULL, NULL );
759                         goto error_return;
760                 }
761         }
762
763         for ( a = e->e_attrs, j = 0; a != NULL; a = a->a_next, j++ ) {
764                 AttributeDescription *desc = a->a_desc;
765
766                 if ( attrs == NULL ) {
767                         /* all attrs request, skip operational attributes */
768                         if( is_at_operational( desc->ad_type ) ) {
769                                 continue;
770                         }
771
772                 } else {
773                         /* specific attrs requested */
774                         if ( is_at_operational( desc->ad_type ) ) {
775                                 if( !opattrs && !ad_inlist( desc, attrs ) ) {
776                                         continue;
777                                 }
778
779                         } else {
780                                 if (!userattrs && !ad_inlist( desc, attrs ) ) {
781                                         continue;
782                                 }
783                         }
784                 }
785
786                 acl_state = acl_state_init;
787
788                 if ( ! access_allowed( be, conn, op, e, desc, NULL,
789                         ACL_READ, &acl_state ) )
790                 {
791 #ifdef NEW_LOGGING
792                         LDAP_LOG( ACL, INFO, 
793                                 "send_search_entry: conn %lu  access to attribute %s not "
794                                 "allowed\n", op->o_connid, desc->ad_cname.bv_val, 0 );
795 #else
796                         Debug( LDAP_DEBUG_ACL, "acl: "
797                                 "access to attribute %s not allowed\n",
798                             desc->ad_cname.bv_val, 0, 0 );
799 #endif
800                         continue;
801                 }
802
803                 if (( rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname )) == -1 ) {
804 #ifdef NEW_LOGGING
805                         LDAP_LOG( OPERATION, ERR, 
806                                 "send_search_entry: conn %lu  ber_printf failed\n", 
807                                 op->o_connid, 0, 0 );
808 #else
809                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
810 #endif
811
812                         ber_free_buf( ber );
813                         send_ldap_result( conn, op, LDAP_OTHER,
814                             NULL, "encoding description error", NULL, NULL );
815                         goto error_return;
816                 }
817
818                 if ( ! attrsonly ) {
819                         for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
820                                 if ( ! access_allowed( be, conn, op, e,
821                                         desc, &a->a_vals[i], ACL_READ, &acl_state ) )
822                                 {
823 #ifdef NEW_LOGGING
824                                         LDAP_LOG( ACL, INFO, 
825                                                 "send_search_entry: conn %lu "
826                                                 "access to attribute %s, value %d not allowed\n",
827                                                 op->o_connid, desc->ad_cname.bv_val, i );
828 #else
829                                         Debug( LDAP_DEBUG_ACL,
830                                                 "acl: access to attribute %s, "
831                                                 "value %d not allowed\n",
832                                                 desc->ad_cname.bv_val, i, 0 );
833 #endif
834
835                                         continue;
836                                 }
837
838                                 if ( op->vrFilter && e_flags[j][i] == 0 ){
839                                         continue;
840                                 }
841
842                                 if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
843 #ifdef NEW_LOGGING
844                                         LDAP_LOG( OPERATION, ERR, 
845                                                 "send_search_entry: conn %lu  "
846                                                 "ber_printf failed.\n", op->o_connid, 0, 0 );
847 #else
848                                         Debug( LDAP_DEBUG_ANY,
849                                             "ber_printf failed\n", 0, 0, 0 );
850 #endif
851
852                                         ber_free_buf( ber );
853                                         send_ldap_result( conn, op, LDAP_OTHER,
854                                                 NULL, "encoding values error",
855                                                 NULL, NULL );
856                                         goto error_return;
857                                 }
858                         }
859                 }
860
861                 if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
862 #ifdef NEW_LOGGING
863                         LDAP_LOG( OPERATION, ERR, 
864                                 "send_search_entry: conn %lu ber_printf failed\n", 
865                                 op->o_connid, 0, 0 );
866 #else
867                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
868 #endif
869
870                         ber_free_buf( ber );
871                         send_ldap_result( conn, op, LDAP_OTHER,
872                             NULL, "encode end error", NULL, NULL );
873                         goto error_return;
874                 }
875         }
876
877         /* free e_flags */
878         if ( e_flags ) {
879                 free( e_flags );
880                 e_flags = NULL;
881         }
882
883         /* eventually will loop through generated operational attributes */
884         /* only have subschemaSubentry implemented */
885         aa = backend_operational( be, conn, op, e, attrs, opattrs );
886
887         if ( aa != NULL && op->vrFilter != NULL ) {
888                 int k = 0;
889                 char *a_flags;
890
891                 for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) {
892                         for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++;
893                 }
894                 e_flags = ch_calloc ( 1, i * sizeof(char *) + k );
895                 a_flags = (char *)(e_flags + i);
896                 for ( a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
897                         for ( j = 0; a->a_vals[j].bv_val != NULL; j++ );
898                         e_flags[i] = a_flags;
899                         a_flags += j;
900                 }
901                 rc = filter_matched_values(be, conn, op, aa, &e_flags) ; 
902             
903                 if ( rc == -1 ) {
904 #ifdef NEW_LOGGING
905                         LDAP_LOG( OPERATION, ERR, 
906                                 "send_search_entry: conn %lu "
907                                 "matched values filtering failed\n", 
908                                 conn ? conn->c_connid : 0, 0, 0);
909 #else
910                 Debug( LDAP_DEBUG_ANY,
911                                 "matched values filtering failed\n", 0, 0, 0 );
912 #endif
913                         ber_free( ber, 1 );
914
915                         send_ldap_result( conn, op, LDAP_OTHER,
916                                 NULL, "matched values filtering error", 
917                                 NULL, NULL );
918                         goto error_return;
919                 }
920         }
921
922         for (a = aa, j=0; a != NULL; a = a->a_next, j++ ) {
923                 AttributeDescription *desc = a->a_desc;
924
925                 if ( attrs == NULL ) {
926                         /* all attrs request, skip operational attributes */
927                         if( is_at_operational( desc->ad_type ) ) {
928                                 continue;
929                         }
930
931                 } else {
932                         /* specific attrs requested */
933                         if( is_at_operational( desc->ad_type ) ) {
934                                 if( !opattrs && !ad_inlist( desc, attrs ) ) {
935                                         continue;
936                                 }
937                         } else {
938                                 if (!userattrs && !ad_inlist( desc, attrs ) )
939                                 {
940                                         continue;
941                                 }
942                         }
943                 }
944
945                 acl_state = acl_state_init;
946
947                 if ( ! access_allowed( be, conn, op, e, desc, NULL,
948                         ACL_READ, &acl_state ) )
949                 {
950 #ifdef NEW_LOGGING
951                         LDAP_LOG( ACL, INFO, 
952                                 "send_search_entry: conn %lu "
953                                 "access to attribute %s not allowed\n",
954                                 op->o_connid, desc->ad_cname.bv_val, 0 );
955 #else
956                         Debug( LDAP_DEBUG_ACL, "acl: access to attribute %s "
957                                         "not allowed\n",
958                                         desc->ad_cname.bv_val, 0, 0 );
959 #endif
960
961                         continue;
962                 }
963
964                 rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname );
965                 if ( rc == -1 ) {
966 #ifdef NEW_LOGGING
967                         LDAP_LOG( OPERATION, ERR, 
968                                 "send_search_entry: conn %lu  "
969                                 "ber_printf failed\n", op->o_connid, 0, 0 );
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
978                         attrs_free( aa );
979                         goto error_return;
980                 }
981
982                 if ( ! attrsonly ) {
983                         for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
984                                 if ( ! access_allowed( be, conn, op, e,
985                                         desc, &a->a_vals[i], ACL_READ, &acl_state ) )
986                                 {
987 #ifdef NEW_LOGGING
988                                         LDAP_LOG( ACL, INFO, 
989                                                 "send_search_entry: conn %lu "
990                                                 "access to %s, value %d not allowed\n",
991                                                 op->o_connid, desc->ad_cname.bv_val, i );
992 #else
993                                         Debug( LDAP_DEBUG_ACL,
994                                                 "acl: access to attribute %s, "
995                                                 "value %d not allowed\n",
996                                                 desc->ad_cname.bv_val, i, 0 );
997 #endif
998
999                                         continue;
1000                                 }
1001
1002                                 if ( op->vrFilter && e_flags[j][i] == 0 ){
1003                                         continue;
1004                                 }
1005
1006                                 if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
1007 #ifdef NEW_LOGGING
1008                                         LDAP_LOG( OPERATION, ERR, 
1009                                                 "send_search_entry: conn %lu  ber_printf failed\n", 
1010                                                 op->o_connid, 0, 0 );
1011 #else
1012                                         Debug( LDAP_DEBUG_ANY,
1013                                             "ber_printf failed\n", 0, 0, 0 );
1014 #endif
1015
1016                                         ber_free_buf( ber );
1017                                         send_ldap_result( conn, op, LDAP_OTHER,
1018                                                 NULL, "encoding values error", 
1019                                                 NULL, NULL );
1020
1021                                         attrs_free( aa );
1022                                         goto error_return;
1023                                 }
1024                         }
1025                 }
1026
1027                 if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
1028 #ifdef NEW_LOGGING
1029                         LDAP_LOG( OPERATION, ERR, 
1030                                 "send_search_entry: conn %lu  ber_printf failed\n",
1031                                 op->o_connid, 0, 0 );
1032 #else
1033                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
1034 #endif
1035
1036                         ber_free_buf( ber );
1037                         send_ldap_result( conn, op, LDAP_OTHER,
1038                             NULL, "encode end error", NULL, NULL );
1039
1040                         attrs_free( aa );
1041                         goto error_return;
1042                 }
1043         }
1044
1045         /* free e_flags */
1046         if ( e_flags ) {
1047                 free( e_flags );
1048                 e_flags = NULL;
1049         }
1050
1051         attrs_free( aa );
1052         rc = ber_printf( ber, /*{{{*/ "}N}N}" );
1053
1054 #ifdef LDAP_CONNECTIONLESS
1055         if (conn->c_is_udp && op->o_protocol == LDAP_VERSION2 && rc != -1)
1056                 rc = ber_printf( ber, "}" );
1057 #endif
1058         if ( rc == -1 ) {
1059 #ifdef NEW_LOGGING
1060                 LDAP_LOG( OPERATION, ERR, 
1061                         "send_search_entry: conn %lu ber_printf failed\n", 
1062                         op->o_connid, 0, 0 );
1063 #else
1064                 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
1065 #endif
1066
1067                 ber_free_buf( ber );
1068                 send_ldap_result( conn, op, LDAP_OTHER,
1069                         NULL, "encode entry end error", NULL, NULL );
1070                 return( 1 );
1071         }
1072
1073         bytes = send_ldap_ber( conn, ber );
1074         ber_free_buf( ber );
1075
1076         if ( bytes < 0 ) {
1077 #ifdef NEW_LOGGING
1078                 LDAP_LOG( OPERATION, ERR, 
1079                            "send_search_entry: conn %lu  ber write failed.\n", 
1080                            op->o_connid, 0, 0 );
1081 #else
1082                 Debug( LDAP_DEBUG_ANY,
1083                         "send_search_entry: ber write failed\n",
1084                         0, 0, 0 );
1085 #endif
1086
1087                 return -1;
1088         }
1089
1090         ldap_pvt_thread_mutex_lock( &num_sent_mutex );
1091         num_bytes_sent += bytes;
1092         num_entries_sent++;
1093         num_pdu_sent++;
1094         ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
1095
1096         Statslog( LDAP_DEBUG_STATS2, "conn=%lu op=%lu ENTRY dn=\"%s\"\n",
1097             conn->c_connid, op->o_opid, e->e_dn, 0, 0 );
1098
1099 #ifdef NEW_LOGGING
1100         LDAP_LOG( OPERATION, ENTRY, 
1101                 "send_search_entry: conn %lu exit.\n", op->o_connid, 0, 0 );
1102 #else
1103         Debug( LDAP_DEBUG_TRACE, "<= send_search_entry\n", 0, 0, 0 );
1104 #endif
1105
1106         rc = 0;
1107
1108 error_return:;
1109         if ( e_flags ) free( e_flags );
1110         return( rc );
1111 }
1112
1113 int
1114 send_search_reference(
1115     Backend     *be,
1116     Connection  *conn,
1117     Operation   *op,
1118     Entry       *e,
1119         BerVarray refs,
1120         LDAPControl **ctrls,
1121     BerVarray *v2refs
1122 )
1123 {
1124         char            berbuf[256];
1125         BerElement      *ber = (BerElement *)berbuf;
1126         int rc;
1127         int bytes;
1128
1129         AttributeDescription *ad_ref = slap_schema.si_ad_ref;
1130         AttributeDescription *ad_entry = slap_schema.si_ad_entry;
1131
1132 #ifdef NEW_LOGGING
1133         LDAP_LOG( OPERATION, ENTRY, 
1134                 "send_search_reference: conn %lu  dn=\"%s\"\n", 
1135                 op->o_connid, e->e_dn, 0 );
1136 #else
1137         Debug( LDAP_DEBUG_TRACE,
1138                 "=> send_search_reference: dn=\"%s\"\n",
1139                 e->e_dn, 0, 0 );
1140 #endif
1141
1142
1143         if ( ! access_allowed( be, conn, op, e,
1144                 ad_entry, NULL, ACL_READ, NULL ) )
1145         {
1146 #ifdef NEW_LOGGING
1147                 LDAP_LOG( ACL, INFO, 
1148                         "send_search_reference: conn %lu        "
1149                         "access to entry %s not allowed\n", op->o_connid, e->e_dn, 0 );
1150 #else
1151                 Debug( LDAP_DEBUG_ACL,
1152                         "send_search_reference: access to entry not allowed\n",
1153                     0, 0, 0 );
1154 #endif
1155
1156                 return( 1 );
1157         }
1158
1159         if ( ! access_allowed( be, conn, op, e,
1160                 ad_ref, NULL, ACL_READ, NULL ) )
1161         {
1162 #ifdef NEW_LOGGING
1163                 LDAP_LOG( ACL, INFO, 
1164                         "send_search_reference: conn %lu access "
1165                         "to reference not allowed.\n", op->o_connid, 0, 0 );
1166 #else
1167                 Debug( LDAP_DEBUG_ACL,
1168                         "send_search_reference: access "
1169                         "to reference not allowed\n",
1170                     0, 0, 0 );
1171 #endif
1172
1173                 return( 1 );
1174         }
1175
1176         if( refs == NULL ) {
1177 #ifdef NEW_LOGGING
1178                 LDAP_LOG( OPERATION, ERR, 
1179                         "send_search_reference: conn %lu null ref in (%s).\n",
1180                         op->o_connid, e->e_dn, 0 );
1181 #else
1182                 Debug( LDAP_DEBUG_ANY,
1183                         "send_search_reference: null ref in (%s)\n", 
1184                         e->e_dn, 0, 0 );
1185 #endif
1186
1187                 return( 1 );
1188         }
1189
1190         if( op->o_protocol < LDAP_VERSION3 ) {
1191                 /* save the references for the result */
1192                 if( refs[0].bv_val != NULL ) {
1193                         value_add( v2refs, refs );
1194                 }
1195                 return 0;
1196         }
1197
1198         ber_init_w_nullc( ber, LBER_USE_DER );
1199
1200         rc = ber_printf( ber, "{it{W}N}", op->o_msgid,
1201                 LDAP_RES_SEARCH_REFERENCE, refs );
1202
1203         if ( rc == -1 ) {
1204 #ifdef NEW_LOGGING
1205                 LDAP_LOG( OPERATION, ERR, 
1206                         "send_search_reference: conn %lu        "
1207                         "ber_printf failed.\n", op->o_connid, 0, 0 );
1208 #else
1209                 Debug( LDAP_DEBUG_ANY,
1210                         "send_search_reference: ber_printf failed\n", 0, 0, 0 );
1211 #endif
1212
1213                 ber_free_buf( ber );
1214                 send_ldap_result( conn, op, LDAP_OTHER,
1215                         NULL, "encode DN error", NULL, NULL );
1216                 return -1;
1217         }
1218
1219         bytes = send_ldap_ber( conn, ber );
1220         ber_free_buf( ber );
1221
1222         ldap_pvt_thread_mutex_lock( &num_sent_mutex );
1223         num_bytes_sent += bytes;
1224         num_refs_sent++;
1225         num_pdu_sent++;
1226         ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
1227
1228         Statslog( LDAP_DEBUG_STATS2, "conn=%lu op=%lu REF dn=\"%s\"\n",
1229                 conn->c_connid, op->o_opid, e->e_dn, 0, 0 );
1230
1231 #ifdef NEW_LOGGING
1232         LDAP_LOG( OPERATION, ENTRY, 
1233                 "send_search_reference: conn %lu exit.\n", op->o_connid, 0, 0 );
1234 #else
1235         Debug( LDAP_DEBUG_TRACE, "<= send_search_reference\n", 0, 0, 0 );
1236 #endif
1237
1238         return 0;
1239 }
1240
1241
1242 int
1243 str2result(
1244     char        *s,
1245     int         *code,
1246     char        **matched,
1247     char        **info
1248 )
1249 {
1250         int     rc;
1251         char    *c;
1252
1253         *code = LDAP_SUCCESS;
1254         *matched = NULL;
1255         *info = NULL;
1256
1257         if ( strncasecmp( s, "RESULT", 6 ) != 0 ) {
1258 #ifdef NEW_LOGGING
1259                 LDAP_LOG( OPERATION, INFO, 
1260                         "str2result: (%s), expecting \"RESULT\"\n", s, 0, 0 );
1261 #else
1262                 Debug( LDAP_DEBUG_ANY, "str2result (%s) expecting \"RESULT\"\n",
1263                     s, 0, 0 );
1264 #endif
1265
1266                 return( -1 );
1267         }
1268
1269         rc = 0;
1270         while ( (s = strchr( s, '\n' )) != NULL ) {
1271                 *s++ = '\0';
1272                 if ( *s == '\0' ) {
1273                         break;
1274                 }
1275                 if ( (c = strchr( s, ':' )) != NULL ) {
1276                         c++;
1277                 }
1278
1279                 if ( strncasecmp( s, "code", 4 ) == 0 ) {
1280                         if ( c != NULL ) {
1281                                 *code = atoi( c );
1282                         }
1283                 } else if ( strncasecmp( s, "matched", 7 ) == 0 ) {
1284                         if ( c != NULL ) {
1285                                 *matched = c;
1286                         }
1287                 } else if ( strncasecmp( s, "info", 4 ) == 0 ) {
1288                         if ( c != NULL ) {
1289                                 *info = c;
1290                         }
1291                 } else {
1292 #ifdef NEW_LOGGING
1293                         LDAP_LOG( OPERATION, INFO, "str2result: (%s) unknown.\n", s, 0, 0 );
1294 #else
1295                         Debug( LDAP_DEBUG_ANY, "str2result (%s) unknown\n",
1296                             s, 0, 0 );
1297 #endif
1298
1299                         rc = -1;
1300                 }
1301         }
1302
1303         return( rc );
1304 }