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