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