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