]> git.sur5r.net Git - openldap/blob - servers/slapd/result.c
Add validation.
[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         static AccessControlState acl_state_init = ACL_STATE_INIT;
632         AccessControlState acl_state;
633
634         AttributeDescription *ad_entry = slap_schema.si_ad_entry;
635
636         if (op->o_callback && op->o_callback->sc_sendentry) {
637                 return op->o_callback->sc_sendentry( be, conn, op, e, attrs,
638                         attrsonly, ctrls );
639         }
640
641 #ifdef NEW_LOGGING
642         LDAP_LOG(( "operation", LDAP_LEVEL_ENTRY,
643                    "send_search_entry: conn %d  dn=\"%s\"%s\n",
644                    op->o_connid, e->e_dn,
645                    attrsonly ? " (attrsOnly)" : "" ));
646 #else
647         Debug( LDAP_DEBUG_TRACE,
648                 "=> send_search_entry: dn=\"%s\"%s\n",
649                 e->e_dn, attrsonly ? " (attrsOnly)" : "", 0 );
650 #endif
651
652         if ( ! access_allowed( be, conn, op, e,
653                 ad_entry, NULL, ACL_READ, NULL ) )
654         {
655 #ifdef NEW_LOGGING
656                 LDAP_LOG(( "acl", LDAP_LEVEL_INFO,
657                            "send_search_entry: conn %d access to entry (%s) not allowed\n",
658                            op->o_connid, e->e_dn ));
659 #else
660                 Debug( LDAP_DEBUG_ACL,
661                         "send_search_entry: access to entry not allowed\n",
662                     0, 0, 0 );
663 #endif
664
665                 return( 1 );
666         }
667
668         edn = e->e_ndn;
669
670         ber_init_w_nullc( ber, LBER_USE_DER );
671
672 #ifdef LDAP_CONNECTIONLESS
673         if (conn->c_is_udp) {
674             rc = ber_write(ber, (char *)&op->o_peeraddr, sizeof(struct sockaddr), 0);
675             if (rc != sizeof(struct sockaddr)) {
676 #ifdef NEW_LOGGING
677                 LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
678                            "send_search_entry: conn %d  ber_printf failed\n",
679                            conn ? conn->c_connid : 0 ));
680 #else
681                 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
682 #endif
683                 ber_free_buf( ber );
684                 return;
685             }
686         }
687         if (conn->c_is_udp && op->o_protocol == LDAP_VERSION2) {
688             rc = ber_printf( ber, "{is{t{O{" /*}}}*/,
689                 op->o_msgid, "", LDAP_RES_SEARCH_ENTRY, &e->e_name );
690         } else
691 #endif
692         {
693             rc = ber_printf( ber, "{it{O{" /*}}}*/, op->o_msgid,
694                 LDAP_RES_SEARCH_ENTRY, &e->e_name );
695         }
696
697         if ( rc == -1 ) {
698 #ifdef NEW_LOGGING
699                 LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
700                            "send_search_entry: conn %d  ber_printf failed\n",
701                            op->o_connid ));
702 #else
703                 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
704 #endif
705
706                 ber_free_buf( ber );
707                 send_ldap_result( conn, op, LDAP_OTHER,
708                     NULL, "encoding DN error", NULL, NULL );
709                 goto error_return;
710         }
711
712         /* check for special all user attributes ("*") type */
713         userattrs = ( attrs == NULL ) ? 1
714                 : an_find( attrs, &AllUser );
715
716         /* check for special all operational attributes ("+") type */
717         opattrs = ( attrs == NULL ) ? 0
718                 : an_find( attrs, &AllOper );
719
720         for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
721                 AttributeDescription *desc = a->a_desc;
722
723                 if ( attrs == NULL ) {
724                         /* all attrs request, skip operational attributes */
725                         if( is_at_operational( desc->ad_type ) ) {
726                                 continue;
727                         }
728
729                 } else {
730                         /* specific attrs requested */
731                         if ( is_at_operational( desc->ad_type ) ) {
732                                 if( !opattrs && !ad_inlist( desc, attrs ) ) {
733                                         continue;
734                                 }
735
736                         } else {
737                                 if (!userattrs && !ad_inlist( desc, attrs ) ) {
738                                         continue;
739                                 }
740                         }
741                 }
742
743                 acl_state = acl_state_init;
744
745                 if ( ! access_allowed( be, conn, op, e, desc, NULL,
746                         ACL_READ, &acl_state ) )
747                 {
748 #ifdef NEW_LOGGING
749                         LDAP_LOG(( "acl", LDAP_LEVEL_INFO, "send_search_entry: "
750                                 "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: "
754                                 "access to attribute %s not allowed\n",
755                             desc->ad_cname.bv_val, 0, 0 );
756 #endif
757                         continue;
758                 }
759
760                 if (( rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname )) == -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_buf( ber );
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].bv_val != NULL; i++ ) {
777                                 if ( ! access_allowed( be, conn, op, e,
778                                         desc, &a->a_vals[i], ACL_READ, &acl_state ) )
779                                 {
780 #ifdef NEW_LOGGING
781                                         LDAP_LOG(( "acl", LDAP_LEVEL_INFO,
782                                                 "send_search_entry: conn %d "
783                                                 "access to attribute %s, value %d not allowed\n",
784                                                 op->o_connid, desc->ad_cname.bv_val, i ));
785 #else
786                                         Debug( LDAP_DEBUG_ACL,
787                                                 "acl: access to attribute %s, value %d not allowed\n",
788                                         desc->ad_cname.bv_val, i, 0 );
789 #endif
790
791                                         continue;
792                                 }
793
794                                 if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
795 #ifdef NEW_LOGGING
796                                         LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
797                                                 "send_search_entry: conn %d  ber_printf failed.\n",
798                                                 op->o_connid ));
799 #else
800                                         Debug( LDAP_DEBUG_ANY,
801                                             "ber_printf failed\n", 0, 0, 0 );
802 #endif
803
804                                         ber_free_buf( ber );
805                                         send_ldap_result( conn, op, LDAP_OTHER,
806                                                 NULL, "encoding values error", NULL, NULL );
807                                         goto error_return;
808                                 }
809                         }
810                 }
811
812                 if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
813 #ifdef NEW_LOGGING
814                         LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
815                                 "send_search_entry: conn %d  ber_printf failed\n",
816                                 op->o_connid ));
817 #else
818                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
819 #endif
820
821                         ber_free_buf( ber );
822                         send_ldap_result( conn, op, LDAP_OTHER,
823                             NULL, "encode end error", NULL, NULL );
824                         goto error_return;
825                 }
826         }
827
828         /* eventually will loop through generated operational attributes */
829         /* only have subschemaSubentry implemented */
830         aa = backend_operational( be, conn, op, e, attrs, opattrs );
831         
832         for (a = aa ; a != NULL; a = a->a_next ) {
833                 AttributeDescription *desc = a->a_desc;
834
835                 if ( attrs == NULL ) {
836                         /* all attrs request, skip operational attributes */
837                         if( is_at_operational( desc->ad_type ) ) {
838                                 continue;
839                         }
840
841                 } else {
842                         /* specific attrs requested */
843                         if( is_at_operational( desc->ad_type ) ) {
844                                 if( !opattrs && !ad_inlist( desc, attrs ) ) {
845                                         continue;
846                                 }
847                         } else {
848                                 if (!userattrs && !ad_inlist( desc, attrs ) )
849                                 {
850                                         continue;
851                                 }
852                         }
853                 }
854
855                 acl_state = acl_state_init;
856
857                 if ( ! access_allowed( be, conn, op, e, desc, NULL,
858                         ACL_READ, &acl_state ) )
859                 {
860 #ifdef NEW_LOGGING
861                         LDAP_LOG(( "acl", LDAP_LEVEL_INFO,
862                                 "send_search_entry: conn %s "
863                                 "access to attribute %s not allowed\n",
864                                 op->o_connid, desc->ad_cname.bv_val ));
865 #else
866                         Debug( LDAP_DEBUG_ACL, "acl: access to attribute %s not allowed\n",
867                             desc->ad_cname.bv_val, 0, 0 );
868 #endif
869
870                         continue;
871                 }
872
873                 rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname );
874                 if ( rc == -1 ) {
875 #ifdef NEW_LOGGING
876                         LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
877                                 "send_search_entry: conn %d  ber_printf failed\n",
878                                 op->o_connid ));
879 #else
880                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
881 #endif
882
883                         ber_free_buf( ber );
884                         send_ldap_result( conn, op, LDAP_OTHER,
885                             NULL, "encoding description error", NULL, NULL );
886                         attrs_free( aa );
887                         goto error_return;
888                 }
889
890                 if ( ! attrsonly ) {
891                         for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
892                                 if ( ! access_allowed( be, conn, op, e,
893                                         desc, &a->a_vals[i], ACL_READ, &acl_state ) )
894                                 {
895 #ifdef NEW_LOGGING
896                                         LDAP_LOG(( "acl", LDAP_LEVEL_INFO,
897                                                 "send_search_entry: conn %d "
898                                                 "access to %s, value %d not allowed\n",
899                                                 op->o_connid, desc->ad_cname.bv_val, i ));
900 #else
901                                         Debug( LDAP_DEBUG_ACL,
902                                                 "acl: access to attribute %s, value %d not allowed\n",
903                                         desc->ad_cname.bv_val, i, 0 );
904 #endif
905
906                                         continue;
907                                 }
908
909                                 if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
910 #ifdef NEW_LOGGING
911                                         LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
912                                                    "send_search_entry: conn %d  ber_printf failed\n",
913                                                    op->o_connid ));
914 #else
915                                         Debug( LDAP_DEBUG_ANY,
916                                             "ber_printf failed\n", 0, 0, 0 );
917 #endif
918
919                                         ber_free_buf( ber );
920                                         send_ldap_result( conn, op, LDAP_OTHER,
921                                                 NULL, "encoding values error", NULL, NULL );
922                                         attrs_free( aa );
923                                         goto error_return;
924                                 }
925                         }
926                 }
927
928                 if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
929 #ifdef NEW_LOGGING
930                         LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
931                                    "send_search_entry: conn %d  ber_printf failed\n",
932                                    op->o_connid ));
933 #else
934                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
935 #endif
936
937                         ber_free_buf( ber );
938                         send_ldap_result( conn, op, LDAP_OTHER,
939                             NULL, "encode end error", NULL, NULL );
940                         attrs_free( aa );
941                         goto error_return;
942                 }
943         }
944
945         attrs_free( aa );
946
947         rc = ber_printf( ber, /*{{{*/ "}N}N}" );
948
949 #ifdef LDAP_CONNECTIONLESS
950         if (conn->c_is_udp && op->o_protocol == LDAP_VERSION2 && rc != -1)
951                 rc = ber_printf( ber, "}" );
952 #endif
953         if ( rc == -1 ) {
954 #ifdef NEW_LOGGING
955                 LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
956                            "send_search_entry: conn %d ber_printf failed\n",
957                            op->o_connid ));
958 #else
959                 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
960 #endif
961
962                 ber_free_buf( ber );
963                 send_ldap_result( conn, op, LDAP_OTHER,
964                         NULL, "encode entry end error", NULL, NULL );
965                 return( 1 );
966         }
967
968         bytes = send_ldap_ber( conn, ber );
969         ber_free_buf( ber );
970
971         if ( bytes < 0 ) {
972 #ifdef NEW_LOGGING
973                 LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
974                            "send_ldap_response: conn %d  ber write failed.\n",
975                            op->o_connid ));
976 #else
977                 Debug( LDAP_DEBUG_ANY,
978                         "send_ldap_response: ber write failed\n",
979                         0, 0, 0 );
980 #endif
981
982                 return -1;
983         }
984
985         ldap_pvt_thread_mutex_lock( &num_sent_mutex );
986         num_bytes_sent += bytes;
987         num_entries_sent++;
988         num_pdu_sent++;
989         ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
990
991         Statslog( LDAP_DEBUG_STATS2, "conn=%ld op=%ld ENTRY dn=\"%s\"\n",
992             (long) conn->c_connid, (long) op->o_opid, e->e_dn, 0, 0 );
993
994 #ifdef NEW_LOGGING
995         LDAP_LOG(( "operation", LDAP_LEVEL_ENTRY,
996                    "send_search_entry: conn %d exit.\n",
997                    op->o_connid ));
998 #else
999         Debug( LDAP_DEBUG_TRACE, "<= send_search_entry\n", 0, 0, 0 );
1000 #endif
1001
1002         rc = 0;
1003
1004 error_return:;
1005         return( rc );
1006 }
1007
1008 int
1009 send_search_reference(
1010     Backend     *be,
1011     Connection  *conn,
1012     Operation   *op,
1013     Entry       *e,
1014         BerVarray refs,
1015         LDAPControl **ctrls,
1016     BerVarray *v2refs
1017 )
1018 {
1019         char            berbuf[256];
1020         BerElement      *ber = (BerElement *)berbuf;
1021         int rc;
1022         int bytes;
1023
1024         AttributeDescription *ad_ref = slap_schema.si_ad_ref;
1025         AttributeDescription *ad_entry = slap_schema.si_ad_entry;
1026
1027 #ifdef NEW_LOGGING
1028         LDAP_LOG(( "operation", LDAP_LEVEL_ENTRY,
1029                 "send_search_reference: conn %d  dn=\"%s\"\n",
1030                 op->o_connid, e->e_dn ));
1031 #else
1032         Debug( LDAP_DEBUG_TRACE,
1033                 "=> send_search_reference: dn=\"%s\"\n",
1034                 e->e_dn, 0, 0 );
1035 #endif
1036
1037
1038         if ( ! access_allowed( be, conn, op, e,
1039                 ad_entry, NULL, ACL_READ, NULL ) )
1040         {
1041 #ifdef NEW_LOGGING
1042                 LDAP_LOG(( "acl", LDAP_LEVEL_INFO,
1043                         "send_search_reference: conn %d access to entry %s not allowed\n",
1044                         op->o_connid, e->e_dn ));
1045 #else
1046                 Debug( LDAP_DEBUG_ACL,
1047                         "send_search_reference: access to entry not allowed\n",
1048                     0, 0, 0 );
1049 #endif
1050
1051                 return( 1 );
1052         }
1053
1054         if ( ! access_allowed( be, conn, op, e,
1055                 ad_ref, NULL, ACL_READ, NULL ) )
1056         {
1057 #ifdef NEW_LOGGING
1058                 LDAP_LOG(( "acl", LDAP_LEVEL_INFO,
1059                         "send_search_reference: conn %d access to reference not allowed.\n",
1060                         op->o_connid ));
1061 #else
1062                 Debug( LDAP_DEBUG_ACL,
1063                         "send_search_reference: access to reference not allowed\n",
1064                     0, 0, 0 );
1065 #endif
1066
1067                 return( 1 );
1068         }
1069
1070         if( refs == NULL ) {
1071 #ifdef NEW_LOGGING
1072                 LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
1073                         "send_search_reference: null ref in (%s).\n",
1074                         op->o_connid, e->e_dn ));
1075 #else
1076                 Debug( LDAP_DEBUG_ANY,
1077                         "send_search_reference: null ref in (%s)\n", 
1078                         e->e_dn, 0, 0 );
1079 #endif
1080
1081                 return( 1 );
1082         }
1083
1084         if( op->o_protocol < LDAP_VERSION3 ) {
1085                 /* save the references for the result */
1086                 if( refs[0].bv_val != NULL ) {
1087                         value_add( v2refs, refs );
1088                 }
1089                 return 0;
1090         }
1091
1092         ber_init_w_nullc( ber, LBER_USE_DER );
1093
1094         rc = ber_printf( ber, "{it{W}N}", op->o_msgid,
1095                 LDAP_RES_SEARCH_REFERENCE, refs );
1096
1097         if ( rc == -1 ) {
1098 #ifdef NEW_LOGGING
1099                 LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
1100                         "send_search_reference: conn %d ber_printf failed.\n",
1101                         op->o_connid ));
1102 #else
1103                 Debug( LDAP_DEBUG_ANY,
1104                         "send_search_reference: ber_printf failed\n", 0, 0, 0 );
1105 #endif
1106
1107                 ber_free_buf( ber );
1108                 send_ldap_result( conn, op, LDAP_OTHER,
1109                         NULL, "encode DN error", NULL, NULL );
1110                 return -1;
1111         }
1112
1113         bytes = send_ldap_ber( conn, ber );
1114         ber_free_buf( ber );
1115
1116         ldap_pvt_thread_mutex_lock( &num_sent_mutex );
1117         num_bytes_sent += bytes;
1118         num_refs_sent++;
1119         num_pdu_sent++;
1120         ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
1121
1122         Statslog( LDAP_DEBUG_STATS2, "conn=%ld op=%ld REF dn=\"%s\"\n",
1123                 (long) conn->c_connid, (long) op->o_opid, e->e_dn, 0, 0 );
1124
1125 #ifdef NEW_LOGGING
1126         LDAP_LOG(( "operation", LDAP_LEVEL_ENTRY,
1127                 "send_search_reference: conn %d exit.\n", op->o_connid ));
1128 #else
1129         Debug( LDAP_DEBUG_TRACE, "<= send_search_reference\n", 0, 0, 0 );
1130 #endif
1131
1132         return 0;
1133 }
1134
1135
1136 int
1137 str2result(
1138     char        *s,
1139     int         *code,
1140     char        **matched,
1141     char        **info
1142 )
1143 {
1144         int     rc;
1145         char    *c;
1146
1147         *code = LDAP_SUCCESS;
1148         *matched = NULL;
1149         *info = NULL;
1150
1151         if ( strncasecmp( s, "RESULT", 6 ) != 0 ) {
1152 #ifdef NEW_LOGGING
1153                 LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
1154                            "str2result: (%s), expecting \"RESULT\"\n", s ));
1155 #else
1156                 Debug( LDAP_DEBUG_ANY, "str2result (%s) expecting \"RESULT\"\n",
1157                     s, 0, 0 );
1158 #endif
1159
1160
1161                 return( -1 );
1162         }
1163
1164         rc = 0;
1165         while ( (s = strchr( s, '\n' )) != NULL ) {
1166                 *s++ = '\0';
1167                 if ( *s == '\0' ) {
1168                         break;
1169                 }
1170                 if ( (c = strchr( s, ':' )) != NULL ) {
1171                         c++;
1172                 }
1173
1174                 if ( strncasecmp( s, "code", 4 ) == 0 ) {
1175                         if ( c != NULL ) {
1176                                 *code = atoi( c );
1177                         }
1178                 } else if ( strncasecmp( s, "matched", 7 ) == 0 ) {
1179                         if ( c != NULL ) {
1180                                 *matched = c;
1181                         }
1182                 } else if ( strncasecmp( s, "info", 4 ) == 0 ) {
1183                         if ( c != NULL ) {
1184                                 *info = c;
1185                         }
1186                 } else {
1187 #ifdef NEW_LOGGING
1188                         LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
1189                                 "str2result: (%s) unknown.\n", s ));
1190 #else
1191                         Debug( LDAP_DEBUG_ANY, "str2result (%s) unknown\n",
1192                             s, 0, 0 );
1193 #endif
1194
1195                         rc = -1;
1196                 }
1197         }
1198
1199         return( rc );
1200 }