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