]> git.sur5r.net Git - openldap/blob - servers/slapd/result.c
LCUP Response Control Code
[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, ERR, 
137                         "send_ldap_ber: conn %lu  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 int
169 send_ldap_controls( BerElement *ber, LDAPControl **c )
170 {
171         int rc;
172         if( c == NULL ) return 0;
173
174         rc = ber_printf( ber, "t{"/*}*/, LDAP_TAG_CONTROLS );
175         if( rc == -1 ) return rc;
176
177         for( ; *c != NULL; c++) {
178                 rc = ber_printf( ber, "{s" /*}*/, (*c)->ldctl_oid );
179
180                 if( (*c)->ldctl_iscritical ) {
181                         rc = ber_printf( ber, "b",
182                                 (ber_int_t) (*c)->ldctl_iscritical ) ;
183                         if( rc == -1 ) return rc;
184                 }
185
186                 if( (*c)->ldctl_value.bv_val != NULL ) {
187                         rc = ber_printf( ber, "O", &((*c)->ldctl_value)); 
188                         if( rc == -1 ) return rc;
189                 }
190
191                 rc = ber_printf( ber, /*{*/"N}" );
192                 if( rc == -1 ) return rc;
193         }
194
195         rc = ber_printf( ber, /*{*/"N}" );
196
197         return rc;
198 }
199
200 static void
201 send_ldap_response(
202     Connection  *conn,
203     Operation   *op,
204         ber_tag_t       tag,
205         ber_int_t       msgid,
206     ber_int_t   err,
207     const char  *matched,
208     const char  *text,
209         BerVarray       ref,
210         const char      *resoid,
211         struct berval   *resdata,
212         struct berval   *sasldata,
213         LDAPControl **ctrls
214 )
215 {
216         char berbuf[256];
217         BerElement      *ber = (BerElement *)berbuf;
218         int             rc;
219         long    bytes;
220
221         if (op->o_callback && op->o_callback->sc_response) {
222                 op->o_callback->sc_response( conn, op, tag, msgid, err, matched,
223                         text, ref, resoid, resdata, sasldata, ctrls );
224                 return;
225         }
226                 
227 #ifndef LDAP_CLIENT_UPDATE
228         assert( ctrls == NULL ); /* ctrls not implemented */
229 #endif /* LDAP_CLIENT_UPDATE */
230
231         ber_init_w_nullc( ber, LBER_USE_DER );
232
233 #ifdef NEW_LOGGING
234         LDAP_LOG( OPERATION, ENTRY, 
235                 "send_ldap_response:  msgid=%d tag=%lu err=%d\n",
236                 msgid, tag, err );
237 #else
238         Debug( LDAP_DEBUG_TRACE,
239                 "send_ldap_response: msgid=%d tag=%lu err=%d\n",
240                 msgid, tag, err );
241 #endif
242
243         if( ref ) {
244 #ifdef NEW_LOGGING
245                 LDAP_LOG( OPERATION, ARGS, 
246                         "send_ldap_response: conn %lu  ref=\"%s\"\n",
247                         conn ? conn->c_connid : 0, 
248                         ref[0].bv_val ? ref[0].bv_val : "NULL" , 0 );
249 #else
250                 Debug( LDAP_DEBUG_ARGS, "send_ldap_response: ref=\"%s\"\n",
251                         ref[0].bv_val ? ref[0].bv_val : "NULL",
252                         NULL, NULL );
253 #endif
254         }
255
256 #ifdef LDAP_CONNECTIONLESS
257         if (conn->c_is_udp) {
258             rc = ber_write(ber, (char *)&op->o_peeraddr, sizeof(struct sockaddr), 0);
259             if (rc != sizeof(struct sockaddr)) {
260 #ifdef NEW_LOGGING
261                 LDAP_LOG( OPERATION, ERR, 
262                         "send_ldap_response: conn %lu  ber_write failed\n",
263                         conn ? conn->c_connid : 0 , 0, 0);
264 #else
265                 Debug( LDAP_DEBUG_ANY, "ber_write failed\n", 0, 0, 0 );
266 #endif
267                 ber_free_buf( ber );
268                 return;
269             }
270         }
271         if (conn->c_is_udp && op->o_protocol == LDAP_VERSION2) {
272             rc = ber_printf( ber, "{is{t{ess" /*"}}}"*/,
273                 msgid, "", tag, err,
274                 matched == NULL ? "" : matched,
275                 text == NULL ? "" : text );
276         } else
277 #endif
278         {
279             rc = ber_printf( ber, "{it{ess" /*"}}"*/,
280                 msgid, tag, err,
281                 matched == NULL ? "" : matched,
282                 text == NULL ? "" : text );
283         }
284
285         if( rc != -1 ) {
286                 if ( ref != NULL ) {
287                         assert( err == LDAP_REFERRAL );
288                         rc = ber_printf( ber, "t{W}",
289                                 LDAP_TAG_REFERRAL, ref );
290                 } else {
291                         assert( err != LDAP_REFERRAL );
292                 }
293         }
294
295         if( rc != -1 && sasldata != NULL ) {
296                 rc = ber_printf( ber, "tO",
297                         LDAP_TAG_SASL_RES_CREDS, sasldata );
298         }
299
300         if( rc != -1 && resoid != NULL ) {
301                 rc = ber_printf( ber, "ts",
302                         LDAP_TAG_EXOP_RES_OID, resoid );
303         }
304
305         if( rc != -1 && resdata != NULL ) {
306                 rc = ber_printf( ber, "tO",
307                         LDAP_TAG_EXOP_RES_VALUE, resdata );
308         }
309
310         if( rc != -1 ) {
311                 rc = ber_printf( ber, /*"{"*/ "N}" );
312         }
313
314         if( rc != -1 && ctrls != NULL ) {
315                 rc = send_ldap_controls( ber, ctrls );
316         }
317
318         if( rc != -1 ) {
319                 rc = ber_printf( ber, /*"{"*/ "N}" );
320         }
321
322 #ifdef LDAP_CONNECTIONLESS
323         if( conn->c_is_udp && op->o_protocol == LDAP_VERSION2 && rc != -1 ) {
324                 rc = ber_printf( ber, /*"{"*/ "N}" );
325         }
326 #endif
327
328         if ( rc == -1 ) {
329 #ifdef NEW_LOGGING
330                 LDAP_LOG( OPERATION, ERR, 
331                         "send_ldap_response: conn %lu  ber_printf failed\n",
332                         conn ? conn->c_connid : 0, 0, 0 );
333 #else
334                 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
335 #endif
336
337                 ber_free_buf( ber );
338                 return;
339         }
340
341         /* send BER */
342         bytes = send_ldap_ber( conn, ber );
343         ber_free_buf( ber );
344
345         if ( bytes < 0 ) {
346 #ifdef NEW_LOGGING
347                 LDAP_LOG( OPERATION, ERR, 
348                         "send_ldap_response: conn %lu ber write failed\n",
349                         conn ? conn->c_connid : 0, 0, 0 );
350 #else
351                 Debug( LDAP_DEBUG_ANY,
352                         "send_ldap_response: ber write failed\n",
353                         0, 0, 0 );
354 #endif
355
356                 return;
357         }
358
359         ldap_pvt_thread_mutex_lock( &num_sent_mutex );
360         num_bytes_sent += bytes;
361         num_pdu_sent++;
362         ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
363         return;
364 }
365
366
367 void
368 send_ldap_disconnect(
369     Connection  *conn,
370     Operation   *op,
371     ber_int_t   err,
372     const char  *text
373 )
374 {
375         ber_tag_t tag;
376         ber_int_t msgid;
377         char *reqoid;
378
379 #define LDAP_UNSOLICITED_ERROR(e) \
380         (  (e) == LDAP_PROTOCOL_ERROR \
381         || (e) == LDAP_STRONG_AUTH_REQUIRED \
382         || (e) == LDAP_UNAVAILABLE )
383
384         assert( LDAP_UNSOLICITED_ERROR( err ) );
385
386 #ifdef NEW_LOGGING
387         LDAP_LOG( OPERATION, ENTRY, 
388                 "send_ldap_disconnect: conn %lu  %d:%s\n",
389                 conn ? conn->c_connid : 0, err, text ? text : "" );
390 #else
391         Debug( LDAP_DEBUG_TRACE,
392                 "send_ldap_disconnect %d:%s\n",
393                 err, text ? text : "", NULL );
394 #endif
395
396
397         if ( op->o_protocol < LDAP_VERSION3 ) {
398                 reqoid = NULL;
399                 tag = req2res( op->o_tag );
400                 msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0;
401
402         } else {
403                 reqoid = LDAP_NOTICE_DISCONNECT;
404                 tag = LDAP_RES_EXTENDED;
405                 msgid = 0;
406         }
407
408         send_ldap_response( conn, op, tag, msgid,
409                 err, NULL, text, NULL,
410                 reqoid, NULL, NULL, NULL );
411
412         Statslog( LDAP_DEBUG_STATS,
413             "conn=%lu op=%lu DISCONNECT tag=%lu err=%d text=%s\n",
414                 op->o_connid, op->o_opid, tag, err, text ? text : "" );
415 }
416
417 void
418 send_ldap_result(
419     Connection  *conn,
420     Operation   *op,
421     ber_int_t   err,
422     const char  *matched,
423     const char  *text,
424         BerVarray ref,
425         LDAPControl **ctrls
426 )
427 {
428         ber_tag_t tag;
429         ber_int_t msgid;
430         char *tmp = NULL;
431
432         assert( !LDAP_API_ERROR( err ) );
433
434 #ifdef NEW_LOGGING
435         LDAP_LOG( OPERATION, ENTRY, 
436                 "send_ldap_result : conn %lu      op=%lu p=%d\n",
437                 op->o_connid, op->o_opid, op->o_protocol );
438 #else
439         Debug( LDAP_DEBUG_TRACE,
440                 "send_ldap_result: conn=%lu op=%lu p=%d\n",
441                 op->o_connid, op->o_opid, op->o_protocol );
442 #endif
443
444 #ifdef NEW_LOGGING
445         LDAP_LOG( OPERATION, ARGS, 
446                 "send_ldap_result: err=%d matched=\"%s\" text=\"%s\"\n",
447                 err, matched ? matched : "", text ? text : "" );
448 #else
449         Debug( LDAP_DEBUG_ARGS,
450                 "send_ldap_result: err=%d matched=\"%s\" text=\"%s\"\n",
451                 err, matched ?  matched : "", text ? text : "" );
452 #endif
453
454
455         if( ref ) {
456 #ifdef NEW_LOGGING
457                 LDAP_LOG( OPERATION, ARGS, 
458                         "send_ldap_result: referral=\"%s\"\n",
459                         ref[0].bv_val ? ref[0].bv_val : "NULL", 0, 0 );
460 #else
461                 Debug( LDAP_DEBUG_ARGS,
462                         "send_ldap_result: referral=\"%s\"\n",
463                         ref[0].bv_val ? ref[0].bv_val : "NULL",
464                         NULL, NULL );
465 #endif
466         }
467
468         assert( err != LDAP_PARTIAL_RESULTS );
469
470         if ( err == LDAP_REFERRAL ) {
471                 if( ref == NULL ) {
472                         err = LDAP_NO_SUCH_OBJECT;
473                 } else if ( op->o_protocol < LDAP_VERSION3 ) {
474                         err = LDAP_PARTIAL_RESULTS;
475                 }
476         }
477
478         if ( op->o_protocol < LDAP_VERSION3 ) {
479                 tmp = v2ref( ref, text );
480                 text = tmp;
481                 ref = NULL;
482         }
483
484         tag = req2res( op->o_tag );
485         msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0;
486
487         send_ldap_response( conn, op, tag, msgid,
488                 err, matched, text, ref,
489                 NULL, NULL, NULL, ctrls );
490
491         Statslog( LDAP_DEBUG_STATS,
492             "conn=%lu op=%lu RESULT tag=%lu err=%d text=%s\n",
493                 op->o_connid, op->o_opid, tag, err, text ? text : "" );
494
495         if( tmp != NULL ) {
496                 ch_free(tmp);
497         }
498 }
499
500 void
501 send_ldap_sasl(
502     Connection  *conn,
503     Operation   *op,
504     ber_int_t   err,
505     const char  *matched,
506     const char  *text,
507         BerVarray ref,
508         LDAPControl **ctrls,
509         struct berval *cred
510 )
511 {
512         ber_tag_t tag;
513         ber_int_t msgid;
514
515 #ifdef NEW_LOGGING
516         LDAP_LOG( OPERATION, ENTRY, 
517                 "send_ldap_sasl: conn %lu err=%d len=%lu\n",
518                 op->o_connid, err, cred ? cred->bv_len : -1 );
519 #else
520         Debug( LDAP_DEBUG_TRACE, "send_ldap_sasl: err=%d len=%ld\n",
521                 err, cred ? (long) cred->bv_len : -1, NULL );
522 #endif
523
524
525         tag = req2res( op->o_tag );
526         msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0;
527
528         send_ldap_response( conn, op, tag, msgid,
529                 err, matched, text, ref,
530                 NULL, NULL, cred, ctrls  );
531 }
532
533 void
534 send_ldap_extended(
535     Connection  *conn,
536     Operation   *op,
537     ber_int_t   err,
538     const char  *matched,
539     const char  *text,
540     BerVarray   refs,
541     const char          *rspoid,
542         struct berval *rspdata,
543         LDAPControl **ctrls
544 )
545 {
546         ber_tag_t tag;
547         ber_int_t msgid;
548
549 #ifdef NEW_LOGGING
550         LDAP_LOG( OPERATION, ENTRY, 
551                 "send_ldap_extended: err=%d oid=%s len=%ld\n",
552                 err, rspoid ? rspoid : "",
553                 rspdata != NULL ? rspdata->bv_len : 0 );
554 #else
555         Debug( LDAP_DEBUG_TRACE,
556                 "send_ldap_extended err=%d oid=%s len=%ld\n",
557                 err,
558                 rspoid ? rspoid : "",
559                 rspdata != NULL ? rspdata->bv_len : 0 );
560 #endif
561
562
563         tag = req2res( op->o_tag );
564         msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0;
565
566         send_ldap_response( conn, op, tag, msgid,
567                 err, matched, text, refs,
568                 rspoid, rspdata, NULL, ctrls );
569 }
570
571
572 void
573 send_search_result(
574     Connection  *conn,
575     Operation   *op,
576     ber_int_t   err,
577     const char  *matched,
578         const char      *text,
579     BerVarray   refs,
580         LDAPControl **ctrls,
581     int         nentries
582 )
583 {
584         ber_tag_t tag;
585         ber_int_t msgid;
586         char *tmp = NULL;
587
588         assert( !LDAP_API_ERROR( err ) );
589
590         if (op->o_callback && op->o_callback->sc_sresult) {
591                 op->o_callback->sc_sresult(conn, op, err, matched, text, refs,
592                         ctrls, nentries);
593                 return;
594         }
595
596 #ifdef NEW_LOGGING
597         LDAP_LOG( OPERATION, ENTRY, 
598                 "send_search_result: err=%d matched=\"%s\" text=\"%s\"\n",
599                 err, matched ? matched : "", text ? text : "" );
600 #else
601         Debug( LDAP_DEBUG_TRACE,
602                 "send_search_result: err=%d matched=\"%s\" text=\"%s\"\n",
603                 err, matched ?  matched : "", text ? text : "" );
604 #endif
605
606
607         assert( err != LDAP_PARTIAL_RESULTS );
608
609         if( op->o_protocol < LDAP_VERSION3 ) {
610                 /* send references in search results */
611                 if( err == LDAP_REFERRAL ) {
612                         err = LDAP_PARTIAL_RESULTS;
613                 }
614
615                 tmp = v2ref( refs, text );
616                 text = tmp;
617                 refs = NULL;
618
619         } else {
620                 /* don't send references in search results */
621                 assert( refs == NULL );
622                 refs = NULL;
623
624                 if( err == LDAP_REFERRAL ) {
625                         err = LDAP_SUCCESS;
626                 }
627         }
628
629         tag = req2res( op->o_tag );
630         msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0;
631
632         send_ldap_response( conn, op, tag, msgid,
633                 err, matched, text, refs,
634                 NULL, NULL, NULL, ctrls );
635
636         {
637         char nbuf[64];
638         snprintf( nbuf, sizeof nbuf, "%d nentries=%d", err, nentries );
639
640         Statslog( LDAP_DEBUG_STATS,
641             "conn=%lu op=%lu SEARCH RESULT tag=%lu err=%s text=%s\n",
642                 op->o_connid, op->o_opid, tag, nbuf, text ? text : "" );
643         }
644
645         if (tmp != NULL) {
646             ch_free(tmp);
647         }
648 }
649
650 int
651 send_search_entry(
652     Backend     *be,
653     Connection  *conn,
654     Operation   *op,
655     Entry       *e,
656     AttributeName       *attrs,
657     int         attrsonly,
658         LDAPControl **ctrls
659 )
660 {
661         char            berbuf[256];
662         BerElement      *ber = (BerElement *)berbuf;
663         Attribute       *a, *aa;
664         int             i, j, rc=-1, bytes;
665         char            *edn;
666         int             userattrs;
667         int             opattrs;
668         static AccessControlState acl_state_init = ACL_STATE_INIT;
669         AccessControlState acl_state;
670
671         AttributeDescription *ad_entry = slap_schema.si_ad_entry;
672
673         /* a_flags: array of flags telling if the i-th element will be
674          *          returned or filtered out
675          * e_flags: array of a_flags
676          */
677         char **e_flags = NULL;
678
679         if (op->o_callback && op->o_callback->sc_sendentry) {
680                 return op->o_callback->sc_sendentry( be, conn, op, e, attrs,
681                         attrsonly, ctrls );
682         }
683
684 #ifdef NEW_LOGGING
685         LDAP_LOG( OPERATION, ENTRY, 
686                 "send_search_entry: conn %lu    dn=\"%s\"%s\n",
687                 op->o_connid, e->e_dn, attrsonly ? " (attrsOnly)" : "" );
688 #else
689         Debug( LDAP_DEBUG_TRACE,
690                 "=> send_search_entry: dn=\"%s\"%s\n",
691                 e->e_dn, attrsonly ? " (attrsOnly)" : "", 0 );
692 #endif
693
694         if ( ! access_allowed( be, conn, op, e,
695                 ad_entry, NULL, ACL_READ, NULL ) )
696         {
697 #ifdef NEW_LOGGING
698                 LDAP_LOG( ACL, INFO, 
699                         "send_search_entry: conn %lu access to entry (%s) not allowed\n", 
700                         op->o_connid, e->e_dn, 0 );
701 #else
702                 Debug( LDAP_DEBUG_ACL,
703                         "send_search_entry: access to entry not allowed\n",
704                     0, 0, 0 );
705 #endif
706
707                 return( 1 );
708         }
709
710         edn = e->e_ndn;
711
712         ber_init_w_nullc( ber, LBER_USE_DER );
713
714 #ifdef LDAP_CONNECTIONLESS
715         if (conn->c_is_udp) {
716             rc = ber_write(ber, (char *)&op->o_peeraddr, sizeof(struct sockaddr), 0);
717             if (rc != sizeof(struct sockaddr)) {
718 #ifdef NEW_LOGGING
719                 LDAP_LOG( OPERATION, ERR, 
720                         "send_search_entry: conn %lu  ber_printf failed\n",
721                         conn ? conn->c_connid : 0, 0, 0 );
722 #else
723                 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
724 #endif
725                 ber_free_buf( ber );
726                 return( 1 );
727             }
728         }
729         if (conn->c_is_udp && op->o_protocol == LDAP_VERSION2) {
730             rc = ber_printf( ber, "{is{t{O{" /*}}}*/,
731                 op->o_msgid, "", LDAP_RES_SEARCH_ENTRY, &e->e_name );
732         } else
733 #endif /* LDAP_CONNECTIONLESS */
734         {
735             rc = ber_printf( ber, "{it{O{" /*}}}*/, op->o_msgid,
736                 LDAP_RES_SEARCH_ENTRY, &e->e_name );
737         }
738
739         if ( rc == -1 ) {
740 #ifdef NEW_LOGGING
741                 LDAP_LOG( OPERATION, ERR, 
742                         "send_search_entry: conn %lu  ber_printf failed\n", 
743                         op->o_connid, 0, 0 );
744 #else
745                 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
746 #endif
747
748                 ber_free_buf( ber );
749                 send_ldap_result( conn, op, LDAP_OTHER,
750                     NULL, "encoding DN error", NULL, NULL );
751                 goto error_return;
752         }
753
754         /* check for special all user attributes ("*") type */
755         userattrs = ( attrs == NULL ) ? 1
756                 : an_find( attrs, &AllUser );
757
758         /* check for special all operational attributes ("+") type */
759         opattrs = ( attrs == NULL ) ? 0
760                 : an_find( attrs, &AllOper );
761
762         /* create an array of arrays of flags. Each flag corresponds
763          * to particular value of attribute and equals 1 if value matches
764          * to ValuesReturnFilter or 0 if not
765          */     
766         if ( op->vrFilter != NULL ) {
767                 int     k = 0;
768                 size_t  size;
769
770                 for ( a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
771                         for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++;
772                 }
773
774                 size = i * sizeof(char *) + k;
775                 if ( size > 0 ) {
776                         char    *a_flags;
777                         e_flags = ch_calloc ( 1, i * sizeof(char *) + k );
778                         a_flags = (char *)(e_flags + i);
779                         memset( a_flags, 0, k );
780                         for ( a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
781                                 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ );
782                                 e_flags[i] = a_flags;
783                                 a_flags += j;
784                         }
785         
786                         rc = filter_matched_values(be, conn, op, e->e_attrs, &e_flags) ; 
787                         if ( rc == -1 ) {
788 #ifdef NEW_LOGGING
789                                 LDAP_LOG( OPERATION, ERR, 
790                                         "send_search_entry: conn %lu matched values filtering failed\n",
791                                         conn ? conn->c_connid : 0, 0, 0 );
792 #else
793                         Debug( LDAP_DEBUG_ANY,
794                                         "matched values filtering failed\n", 0, 0, 0 );
795 #endif
796                                 ber_free( ber, 1 );
797         
798                                 send_ldap_result( conn, op, LDAP_OTHER,
799                                         NULL, "matched values filtering error", 
800                                         NULL, NULL );
801                                 goto error_return;
802                         }
803                 }
804         }
805
806         for ( a = e->e_attrs, j = 0; a != NULL; a = a->a_next, j++ ) {
807                 AttributeDescription *desc = a->a_desc;
808
809                 if ( attrs == NULL ) {
810                         /* all attrs request, skip operational attributes */
811                         if( is_at_operational( desc->ad_type ) ) {
812                                 continue;
813                         }
814
815                 } else {
816                         /* specific attrs requested */
817                         if ( is_at_operational( desc->ad_type ) ) {
818                                 if( !opattrs && !ad_inlist( desc, attrs ) ) {
819                                         continue;
820                                 }
821
822                         } else {
823                                 if (!userattrs && !ad_inlist( desc, attrs ) ) {
824                                         continue;
825                                 }
826                         }
827                 }
828
829                 acl_state = acl_state_init;
830
831                 if ( ! access_allowed( be, conn, op, e, desc, NULL,
832                         ACL_READ, &acl_state ) )
833                 {
834 #ifdef NEW_LOGGING
835                         LDAP_LOG( ACL, INFO, 
836                                 "send_search_entry: conn %lu  access to attribute %s not "
837                                 "allowed\n", op->o_connid, desc->ad_cname.bv_val, 0 );
838 #else
839                         Debug( LDAP_DEBUG_ACL, "acl: "
840                                 "access to attribute %s not allowed\n",
841                             desc->ad_cname.bv_val, 0, 0 );
842 #endif
843                         continue;
844                 }
845
846                 if (( rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname )) == -1 ) {
847 #ifdef NEW_LOGGING
848                         LDAP_LOG( OPERATION, ERR, 
849                                 "send_search_entry: conn %lu  ber_printf failed\n", 
850                                 op->o_connid, 0, 0 );
851 #else
852                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
853 #endif
854
855                         ber_free_buf( ber );
856                         send_ldap_result( conn, op, LDAP_OTHER,
857                             NULL, "encoding description error", NULL, NULL );
858                         goto error_return;
859                 }
860
861                 if ( ! attrsonly ) {
862                         for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
863                                 if ( ! access_allowed( be, conn, op, e,
864                                         desc, &a->a_vals[i], ACL_READ, &acl_state ) )
865                                 {
866 #ifdef NEW_LOGGING
867                                         LDAP_LOG( ACL, INFO, 
868                                                 "send_search_entry: conn %lu "
869                                                 "access to attribute %s, value %d not allowed\n",
870                                                 op->o_connid, desc->ad_cname.bv_val, i );
871 #else
872                                         Debug( LDAP_DEBUG_ACL,
873                                                 "acl: access to attribute %s, "
874                                                 "value %d not allowed\n",
875                                                 desc->ad_cname.bv_val, i, 0 );
876 #endif
877
878                                         continue;
879                                 }
880
881                                 if ( op->vrFilter && e_flags[j][i] == 0 ){
882                                         continue;
883                                 }
884
885                                 if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
886 #ifdef NEW_LOGGING
887                                         LDAP_LOG( OPERATION, ERR, 
888                                                 "send_search_entry: conn %lu  "
889                                                 "ber_printf failed.\n", op->o_connid, 0, 0 );
890 #else
891                                         Debug( LDAP_DEBUG_ANY,
892                                             "ber_printf failed\n", 0, 0, 0 );
893 #endif
894
895                                         ber_free_buf( ber );
896                                         send_ldap_result( conn, op, LDAP_OTHER,
897                                                 NULL, "encoding values error",
898                                                 NULL, NULL );
899                                         goto error_return;
900                                 }
901                         }
902                 }
903
904                 if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
905 #ifdef NEW_LOGGING
906                         LDAP_LOG( OPERATION, ERR, 
907                                 "send_search_entry: conn %lu ber_printf failed\n", 
908                                 op->o_connid, 0, 0 );
909 #else
910                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
911 #endif
912
913                         ber_free_buf( ber );
914                         send_ldap_result( conn, op, LDAP_OTHER,
915                             NULL, "encode end error", NULL, NULL );
916                         goto error_return;
917                 }
918         }
919
920         /* eventually will loop through generated operational attributes */
921         /* only have subschemaSubentry implemented */
922         aa = backend_operational( be, conn, op, e, attrs, opattrs );
923
924         if ( aa != NULL && op->vrFilter != NULL ) {
925                 int     k = 0;
926                 size_t  size;
927
928                 for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) {
929                         for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++;
930                 }
931
932                 size = i * sizeof(char *) + k;
933                 if ( size > 0 ) {
934                         char    *a_flags, **tmp;
935                 
936                         /*
937                          * Reuse previous memory - we likely need less space
938                          * for operational attributes
939                          */
940                         tmp = ch_realloc ( e_flags, i * sizeof(char *) + k );
941                         if ( tmp == NULL ) {
942 #ifdef NEW_LOGGING
943                                 LDAP_LOG( OPERATION, ERR, 
944                                         "send_search_entry: conn %lu "
945                                         "not enough memory "
946                                         "for matched values filtering\n", 
947                                         conn ? conn->c_connid : 0, 0, 0);
948 #else
949                                 Debug( LDAP_DEBUG_ANY,
950                                         "send_search_entry: conn %lu "
951                                         "not enough memory "
952                                         "for matched values filtering\n",
953                                         conn ? conn->c_connid : 0, 0, 0 );
954 #endif
955                                 ber_free( ber, 1 );
956         
957                                 send_ldap_result( conn, op, LDAP_NO_MEMORY,
958                                         NULL, NULL, NULL, NULL );
959                                 goto error_return;
960                         }
961                         e_flags = tmp;
962                         a_flags = (char *)(e_flags + i);
963                         memset( a_flags, 0, k );
964                         for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) {
965                                 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ );
966                                 e_flags[i] = a_flags;
967                                 a_flags += j;
968                         }
969                         rc = filter_matched_values(be, conn, op, aa, &e_flags) ; 
970                     
971                         if ( rc == -1 ) {
972 #ifdef NEW_LOGGING
973                                 LDAP_LOG( OPERATION, ERR, 
974                                         "send_search_entry: conn %lu "
975                                         "matched values filtering failed\n", 
976                                         conn ? conn->c_connid : 0, 0, 0);
977 #else
978                                 Debug( LDAP_DEBUG_ANY,
979                                         "matched values filtering failed\n", 0, 0, 0 );
980 #endif
981                                 ber_free( ber, 1 );
982         
983                                 send_ldap_result( conn, op, LDAP_OTHER,
984                                         NULL, "matched values filtering error", 
985                                         NULL, NULL );
986                                 goto error_return;
987                         }
988                 }
989         }
990
991         for (a = aa, j=0; a != NULL; a = a->a_next, j++ ) {
992                 AttributeDescription *desc = a->a_desc;
993
994                 if ( attrs == NULL ) {
995                         /* all attrs request, skip operational attributes */
996                         if( is_at_operational( desc->ad_type ) ) {
997                                 continue;
998                         }
999
1000                 } else {
1001                         /* specific attrs requested */
1002                         if( is_at_operational( desc->ad_type ) ) {
1003                                 if( !opattrs && !ad_inlist( desc, attrs ) ) {
1004                                         continue;
1005                                 }
1006                         } else {
1007                                 if (!userattrs && !ad_inlist( desc, attrs ) )
1008                                 {
1009                                         continue;
1010                                 }
1011                         }
1012                 }
1013
1014                 acl_state = acl_state_init;
1015
1016                 if ( ! access_allowed( be, conn, op, e, desc, NULL,
1017                         ACL_READ, &acl_state ) )
1018                 {
1019 #ifdef NEW_LOGGING
1020                         LDAP_LOG( ACL, INFO, 
1021                                 "send_search_entry: conn %lu "
1022                                 "access to attribute %s not allowed\n",
1023                                 op->o_connid, desc->ad_cname.bv_val, 0 );
1024 #else
1025                         Debug( LDAP_DEBUG_ACL, "acl: access to attribute %s "
1026                                         "not allowed\n",
1027                                         desc->ad_cname.bv_val, 0, 0 );
1028 #endif
1029
1030                         continue;
1031                 }
1032
1033                 rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname );
1034                 if ( rc == -1 ) {
1035 #ifdef NEW_LOGGING
1036                         LDAP_LOG( OPERATION, ERR, 
1037                                 "send_search_entry: conn %lu  "
1038                                 "ber_printf failed\n", op->o_connid, 0, 0 );
1039 #else
1040                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
1041 #endif
1042
1043                         ber_free_buf( ber );
1044                         send_ldap_result( conn, op, LDAP_OTHER,
1045                             NULL, "encoding description error", NULL, NULL );
1046
1047                         attrs_free( aa );
1048                         goto error_return;
1049                 }
1050
1051                 if ( ! attrsonly ) {
1052                         for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
1053                                 if ( ! access_allowed( be, conn, op, e,
1054                                         desc, &a->a_vals[i], ACL_READ, &acl_state ) )
1055                                 {
1056 #ifdef NEW_LOGGING
1057                                         LDAP_LOG( ACL, INFO, 
1058                                                 "send_search_entry: conn %lu "
1059                                                 "access to %s, value %d not allowed\n",
1060                                                 op->o_connid, desc->ad_cname.bv_val, i );
1061 #else
1062                                         Debug( LDAP_DEBUG_ACL,
1063                                                 "acl: access to attribute %s, "
1064                                                 "value %d not allowed\n",
1065                                                 desc->ad_cname.bv_val, i, 0 );
1066 #endif
1067
1068                                         continue;
1069                                 }
1070
1071                                 if ( op->vrFilter && e_flags[j][i] == 0 ){
1072                                         continue;
1073                                 }
1074
1075                                 if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
1076 #ifdef NEW_LOGGING
1077                                         LDAP_LOG( OPERATION, ERR, 
1078                                                 "send_search_entry: conn %lu  ber_printf failed\n", 
1079                                                 op->o_connid, 0, 0 );
1080 #else
1081                                         Debug( LDAP_DEBUG_ANY,
1082                                             "ber_printf failed\n", 0, 0, 0 );
1083 #endif
1084
1085                                         ber_free_buf( ber );
1086                                         send_ldap_result( conn, op, LDAP_OTHER,
1087                                                 NULL, "encoding values error", 
1088                                                 NULL, NULL );
1089
1090                                         attrs_free( aa );
1091                                         goto error_return;
1092                                 }
1093                         }
1094                 }
1095
1096                 if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
1097 #ifdef NEW_LOGGING
1098                         LDAP_LOG( OPERATION, ERR, 
1099                                 "send_search_entry: conn %lu  ber_printf failed\n",
1100                                 op->o_connid, 0, 0 );
1101 #else
1102                         Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
1103 #endif
1104
1105                         ber_free_buf( ber );
1106                         send_ldap_result( conn, op, LDAP_OTHER,
1107                             NULL, "encode end error", NULL, NULL );
1108
1109                         attrs_free( aa );
1110                         goto error_return;
1111                 }
1112         }
1113
1114         /* free e_flags */
1115         if ( e_flags ) {
1116                 free( e_flags );
1117                 e_flags = NULL;
1118         }
1119
1120         attrs_free( aa );
1121         rc = ber_printf( ber, /*{{*/ "}N}" );
1122
1123         if( rc != -1 && ctrls != NULL ) {
1124                 rc = send_ldap_controls( ber, ctrls );
1125         }
1126
1127         if( rc != -1 ) {
1128                 rc = ber_printf( ber, /*{*/ "N}" );
1129         }
1130
1131 #ifdef LDAP_CONNECTIONLESS
1132         if (conn->c_is_udp && op->o_protocol == LDAP_VERSION2 && rc != -1)
1133                 rc = ber_printf( ber, "}" );
1134 #endif
1135         if ( rc == -1 ) {
1136 #ifdef NEW_LOGGING
1137                 LDAP_LOG( OPERATION, ERR, 
1138                         "send_search_entry: conn %lu ber_printf failed\n", 
1139                         op->o_connid, 0, 0 );
1140 #else
1141                 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
1142 #endif
1143
1144                 ber_free_buf( ber );
1145                 send_ldap_result( conn, op, LDAP_OTHER,
1146                         NULL, "encode entry end error", NULL, NULL );
1147                 return( 1 );
1148         }
1149
1150         bytes = op->o_noop ? 0 : send_ldap_ber( conn, ber );
1151         ber_free_buf( ber );
1152
1153         if ( bytes < 0 ) {
1154 #ifdef NEW_LOGGING
1155                 LDAP_LOG( OPERATION, ERR, 
1156                            "send_search_entry: conn %lu  ber write failed.\n", 
1157                            op->o_connid, 0, 0 );
1158 #else
1159                 Debug( LDAP_DEBUG_ANY,
1160                         "send_search_entry: ber write failed\n",
1161                         0, 0, 0 );
1162 #endif
1163
1164                 return -1;
1165         }
1166
1167         ldap_pvt_thread_mutex_lock( &num_sent_mutex );
1168         num_bytes_sent += bytes;
1169         num_entries_sent++;
1170         num_pdu_sent++;
1171         ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
1172
1173         Statslog( LDAP_DEBUG_STATS2, "conn=%lu op=%lu ENTRY dn=\"%s\"\n",
1174             conn->c_connid, op->o_opid, e->e_dn, 0, 0 );
1175
1176 #ifdef NEW_LOGGING
1177         LDAP_LOG( OPERATION, ENTRY, 
1178                 "send_search_entry: conn %lu exit.\n", op->o_connid, 0, 0 );
1179 #else
1180         Debug( LDAP_DEBUG_TRACE, "<= send_search_entry\n", 0, 0, 0 );
1181 #endif
1182
1183         rc = 0;
1184
1185 error_return:;
1186         if ( e_flags ) free( e_flags );
1187         return( rc );
1188 }
1189
1190 int
1191 send_search_reference(
1192     Backend     *be,
1193     Connection  *conn,
1194     Operation   *op,
1195     Entry       *e,
1196         BerVarray refs,
1197         LDAPControl **ctrls,
1198     BerVarray *v2refs
1199 )
1200 {
1201         char            berbuf[256];
1202         BerElement      *ber = (BerElement *)berbuf;
1203         int rc;
1204         int bytes;
1205
1206         AttributeDescription *ad_ref = slap_schema.si_ad_ref;
1207         AttributeDescription *ad_entry = slap_schema.si_ad_entry;
1208
1209 #ifdef NEW_LOGGING
1210         LDAP_LOG( OPERATION, ENTRY, 
1211                 "send_search_reference: conn %lu  dn=\"%s\"\n", 
1212                 op->o_connid, e ? e->e_dn : "(null)", 0 );
1213 #else
1214         Debug( LDAP_DEBUG_TRACE,
1215                 "=> send_search_reference: dn=\"%s\"\n",
1216                 e ? e->e_dn : "(null)", 0, 0 );
1217 #endif
1218
1219
1220         if (  e && ! access_allowed( be, conn, op, e,
1221                 ad_entry, NULL, ACL_READ, NULL ) )
1222         {
1223 #ifdef NEW_LOGGING
1224                 LDAP_LOG( ACL, INFO, 
1225                         "send_search_reference: conn %lu        "
1226                         "access to entry %s not allowed\n",
1227                         op->o_connid, e->e_dn, 0 );
1228 #else
1229                 Debug( LDAP_DEBUG_ACL,
1230                         "send_search_reference: access to entry not allowed\n",
1231                     0, 0, 0 );
1232 #endif
1233
1234                 return( 1 );
1235         }
1236
1237         if ( e && ! access_allowed( be, conn, op, e,
1238                 ad_ref, NULL, ACL_READ, NULL ) )
1239         {
1240 #ifdef NEW_LOGGING
1241                 LDAP_LOG( ACL, INFO, 
1242                         "send_search_reference: conn %lu access "
1243                         "to reference not allowed.\n", op->o_connid, 0, 0 );
1244 #else
1245                 Debug( LDAP_DEBUG_ACL,
1246                         "send_search_reference: access "
1247                         "to reference not allowed\n",
1248                     0, 0, 0 );
1249 #endif
1250
1251                 return( 1 );
1252         }
1253
1254         if( refs == NULL ) {
1255 #ifdef NEW_LOGGING
1256                 LDAP_LOG( OPERATION, ERR, 
1257                         "send_search_reference: conn %lu null ref in (%s).\n",
1258                         op->o_connid, e ? e->e_dn : "(null)", 0 );
1259 #else
1260                 Debug( LDAP_DEBUG_ANY,
1261                         "send_search_reference: null ref in (%s)\n", 
1262                         e ? e->e_dn : "(null)", 0, 0 );
1263 #endif
1264
1265                 return( 1 );
1266         }
1267
1268         if( op->o_protocol < LDAP_VERSION3 ) {
1269                 /* save the references for the result */
1270                 if( refs[0].bv_val != NULL ) {
1271                         value_add( v2refs, refs );
1272                 }
1273                 return 0;
1274         }
1275
1276         ber_init_w_nullc( ber, LBER_USE_DER );
1277
1278         rc = ber_printf( ber, "{it{W}" /*"}"*/ , op->o_msgid,
1279                 LDAP_RES_SEARCH_REFERENCE, refs );
1280
1281         if( rc != -1 && ctrls != NULL ) {
1282                 rc = send_ldap_controls( ber, ctrls );
1283         }
1284
1285         if( rc != -1 ) {
1286                 rc = ber_printf( ber, /*"{"*/ "N}", op->o_msgid,
1287                         LDAP_RES_SEARCH_REFERENCE, refs );
1288         }
1289
1290         if ( rc == -1 ) {
1291 #ifdef NEW_LOGGING
1292                 LDAP_LOG( OPERATION, ERR, 
1293                         "send_search_reference: conn %lu        "
1294                         "ber_printf failed.\n", op->o_connid, 0, 0 );
1295 #else
1296                 Debug( LDAP_DEBUG_ANY,
1297                         "send_search_reference: ber_printf failed\n", 0, 0, 0 );
1298 #endif
1299
1300                 ber_free_buf( ber );
1301                 send_ldap_result( conn, op, LDAP_OTHER,
1302                         NULL, "encode DN error", NULL, NULL );
1303                 return -1;
1304         }
1305
1306         bytes = op->o_noop ? 0 : send_ldap_ber( conn, ber );
1307         ber_free_buf( ber );
1308
1309         ldap_pvt_thread_mutex_lock( &num_sent_mutex );
1310         num_bytes_sent += bytes;
1311         num_refs_sent++;
1312         num_pdu_sent++;
1313         ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
1314
1315         Statslog( LDAP_DEBUG_STATS2, "conn=%lu op=%lu REF dn=\"%s\"\n",
1316                 conn->c_connid, op->o_opid, e ? e->e_dn : "(null)", 0, 0 );
1317
1318 #ifdef NEW_LOGGING
1319         LDAP_LOG( OPERATION, ENTRY, 
1320                 "send_search_reference: conn %lu exit.\n", op->o_connid, 0, 0 );
1321 #else
1322         Debug( LDAP_DEBUG_TRACE, "<= send_search_reference\n", 0, 0, 0 );
1323 #endif
1324
1325         return 0;
1326 }
1327
1328
1329 int
1330 str2result(
1331     char        *s,
1332     int         *code,
1333     char        **matched,
1334     char        **info
1335 )
1336 {
1337         int     rc;
1338         char    *c;
1339
1340         *code = LDAP_SUCCESS;
1341         *matched = NULL;
1342         *info = NULL;
1343
1344         if ( strncasecmp( s, "RESULT", 6 ) != 0 ) {
1345 #ifdef NEW_LOGGING
1346                 LDAP_LOG( OPERATION, INFO, 
1347                         "str2result: (%s), expecting \"RESULT\"\n", s, 0, 0 );
1348 #else
1349                 Debug( LDAP_DEBUG_ANY, "str2result (%s) expecting \"RESULT\"\n",
1350                     s, 0, 0 );
1351 #endif
1352
1353                 return( -1 );
1354         }
1355
1356         rc = 0;
1357         while ( (s = strchr( s, '\n' )) != NULL ) {
1358                 *s++ = '\0';
1359                 if ( *s == '\0' ) {
1360                         break;
1361                 }
1362                 if ( (c = strchr( s, ':' )) != NULL ) {
1363                         c++;
1364                 }
1365
1366                 if ( strncasecmp( s, "code", 4 ) == 0 ) {
1367                         if ( c != NULL ) {
1368                                 *code = atoi( c );
1369                         }
1370                 } else if ( strncasecmp( s, "matched", 7 ) == 0 ) {
1371                         if ( c != NULL ) {
1372                                 *matched = c;
1373                         }
1374                 } else if ( strncasecmp( s, "info", 4 ) == 0 ) {
1375                         if ( c != NULL ) {
1376                                 *info = c;
1377                         }
1378                 } else {
1379 #ifdef NEW_LOGGING
1380                         LDAP_LOG( OPERATION, INFO, "str2result: (%s) unknown.\n", s, 0, 0 );
1381 #else
1382                         Debug( LDAP_DEBUG_ANY, "str2result (%s) unknown\n",
1383                             s, 0, 0 );
1384 #endif
1385
1386                         rc = -1;
1387                 }
1388         }
1389
1390         return( rc );
1391 }