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