~ttx/openldap/lucid-gssapi-495418

« back to all changes in this revision

Viewing changes to servers/slapd/result.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathias Gug
  • Date: 2008-07-10 14:45:49 UTC
  • Revision ID: james.westby@ubuntu.com-20080710144549-wck73med0e72gfyo
Tags: upstream-2.4.10
ImportĀ upstreamĀ versionĀ 2.4.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* result.c - routines to send ldap results, errors, and referrals */
 
2
/* $OpenLDAP: pkg/ldap/servers/slapd/result.c,v 1.289.2.14 2008/05/28 16:28:18 quanah Exp $ */
 
3
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 
4
 *
 
5
 * Copyright 1998-2008 The OpenLDAP Foundation.
 
6
 * All rights reserved.
 
7
 *
 
8
 * Redistribution and use in source and binary forms, with or without
 
9
 * modification, are permitted only as authorized by the OpenLDAP
 
10
 * Public License.
 
11
 *
 
12
 * A copy of this license is available in the file LICENSE in the
 
13
 * top-level directory of the distribution or, alternatively, at
 
14
 * <http://www.OpenLDAP.org/license.html>.
 
15
 */
 
16
/* Portions Copyright (c) 1995 Regents of the University of Michigan.
 
17
 * All rights reserved.
 
18
 *
 
19
 * Redistribution and use in source and binary forms are permitted
 
20
 * provided that this notice is preserved and that due credit is given
 
21
 * to the University of Michigan at Ann Arbor. The name of the University
 
22
 * may not be used to endorse or promote products derived from this
 
23
 * software without specific prior written permission. This software
 
24
 * is provided ``as is'' without express or implied warranty.
 
25
 */
 
26
 
 
27
#include "portable.h"
 
28
 
 
29
#include <stdio.h>
 
30
 
 
31
#include <ac/socket.h>
 
32
#include <ac/errno.h>
 
33
#include <ac/string.h>
 
34
#include <ac/ctype.h>
 
35
#include <ac/time.h>
 
36
#include <ac/unistd.h>
 
37
 
 
38
#include "slap.h"
 
39
 
 
40
const struct berval slap_dummy_bv = BER_BVNULL;
 
41
 
 
42
int slap_null_cb( Operation *op, SlapReply *rs )
 
43
{
 
44
        return 0;
 
45
}
 
46
 
 
47
int slap_freeself_cb( Operation *op, SlapReply *rs )
 
48
{
 
49
        assert( op->o_callback != NULL );
 
50
 
 
51
        op->o_tmpfree( op->o_callback, op->o_tmpmemctx );
 
52
        op->o_callback = NULL;
 
53
 
 
54
        return SLAP_CB_CONTINUE;
 
55
}
 
56
 
 
57
static char *v2ref( BerVarray ref, const char *text )
 
58
{
 
59
        size_t len = 0, i = 0;
 
60
        char *v2;
 
61
 
 
62
        if(ref == NULL) {
 
63
                if (text) {
 
64
                        return ch_strdup(text);
 
65
                } else {
 
66
                        return NULL;
 
67
                }
 
68
        }
 
69
        
 
70
        if ( text != NULL ) {
 
71
                len = strlen( text );
 
72
                if (text[len-1] != '\n') {
 
73
                    i = 1;
 
74
                }
 
75
        }
 
76
 
 
77
        v2 = ch_malloc( len+i+sizeof("Referral:") );
 
78
 
 
79
        if( text != NULL ) {
 
80
                strcpy(v2, text);
 
81
                if( i ) {
 
82
                        v2[len++] = '\n';
 
83
                }
 
84
        }
 
85
        strcpy( v2+len, "Referral:" );
 
86
        len += sizeof("Referral:");
 
87
 
 
88
        for( i=0; ref[i].bv_val != NULL; i++ ) {
 
89
                v2 = ch_realloc( v2, len + ref[i].bv_len + 1 );
 
90
                v2[len-1] = '\n';
 
91
                AC_MEMCPY(&v2[len], ref[i].bv_val, ref[i].bv_len );
 
92
                len += ref[i].bv_len;
 
93
                if (ref[i].bv_val[ref[i].bv_len-1] != '/') {
 
94
                        ++len;
 
95
                }
 
96
        }
 
97
 
 
98
        v2[len-1] = '\0';
 
99
        return v2;
 
100
}
 
101
 
 
102
ber_tag_t
 
103
slap_req2res( ber_tag_t tag )
 
104
{
 
105
        switch( tag ) {
 
106
        case LDAP_REQ_ADD:
 
107
        case LDAP_REQ_BIND:
 
108
        case LDAP_REQ_COMPARE:
 
109
        case LDAP_REQ_EXTENDED:
 
110
        case LDAP_REQ_MODIFY:
 
111
        case LDAP_REQ_MODRDN:
 
112
                tag++;
 
113
                break;
 
114
 
 
115
        case LDAP_REQ_DELETE:
 
116
                tag = LDAP_RES_DELETE;
 
117
                break;
 
118
 
 
119
        case LDAP_REQ_ABANDON:
 
120
        case LDAP_REQ_UNBIND:
 
121
                tag = LBER_SEQUENCE;
 
122
                break;
 
123
 
 
124
        case LDAP_REQ_SEARCH:
 
125
                tag = LDAP_RES_SEARCH_RESULT;
 
126
                break;
 
127
 
 
128
        default:
 
129
                tag = LBER_SEQUENCE;
 
130
        }
 
131
 
 
132
        return tag;
 
133
}
 
134
 
 
135
static long send_ldap_ber(
 
136
        Connection *conn,
 
137
        BerElement *ber )
 
138
{
 
139
        ber_len_t bytes;
 
140
 
 
141
        ber_get_option( ber, LBER_OPT_BER_BYTES_TO_WRITE, &bytes );
 
142
 
 
143
        /* write only one pdu at a time - wait til it's our turn */
 
144
        ldap_pvt_thread_mutex_lock( &conn->c_write_mutex );
 
145
 
 
146
        /* lock the connection */ 
 
147
        ldap_pvt_thread_mutex_lock( &conn->c_mutex );
 
148
 
 
149
        /* write the pdu */
 
150
        while( 1 ) {
 
151
                int err;
 
152
 
 
153
                if ( connection_state_closing( conn ) ) {
 
154
                        ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
 
155
                        ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
 
156
 
 
157
                        return 0;
 
158
                }
 
159
 
 
160
                if ( ber_flush2( conn->c_sb, ber, LBER_FLUSH_FREE_NEVER ) == 0 ) {
 
161
                        break;
 
162
                }
 
163
 
 
164
                err = sock_errno();
 
165
 
 
166
                /*
 
167
                 * we got an error.  if it's ewouldblock, we need to
 
168
                 * wait on the socket being writable.  otherwise, figure
 
169
                 * it's a hard error and return.
 
170
                 */
 
171
 
 
172
                Debug( LDAP_DEBUG_CONNS, "ber_flush2 failed errno=%d reason=\"%s\"\n",
 
173
                    err, sock_errstr(err), 0 );
 
174
 
 
175
                if ( err != EWOULDBLOCK && err != EAGAIN ) {
 
176
                        connection_closing( conn, "connection lost on write" );
 
177
 
 
178
                        ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
 
179
                        ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
 
180
 
 
181
                        return( -1 );
 
182
                }
 
183
 
 
184
                /* wait for socket to be write-ready */
 
185
                conn->c_writewaiter = 1;
 
186
                slapd_set_write( conn->c_sd, 1 );
 
187
 
 
188
                ldap_pvt_thread_cond_wait( &conn->c_write_cv, &conn->c_mutex );
 
189
                conn->c_writewaiter = 0;
 
190
        }
 
191
 
 
192
        ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
 
193
        ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
 
194
 
 
195
        return bytes;
 
196
}
 
197
 
 
198
static int
 
199
send_ldap_control( BerElement *ber, LDAPControl *c )
 
200
{
 
201
        int rc;
 
202
 
 
203
        assert( c != NULL );
 
204
 
 
205
        rc = ber_printf( ber, "{s" /*}*/, c->ldctl_oid );
 
206
 
 
207
        if( c->ldctl_iscritical ) {
 
208
                rc = ber_printf( ber, "b",
 
209
                        (ber_int_t) c->ldctl_iscritical ) ;
 
210
                if( rc == -1 ) return rc;
 
211
        }
 
212
 
 
213
        if( c->ldctl_value.bv_val != NULL ) {
 
214
                rc = ber_printf( ber, "O", &c->ldctl_value ); 
 
215
                if( rc == -1 ) return rc;
 
216
        }
 
217
 
 
218
        rc = ber_printf( ber, /*{*/"N}" );
 
219
        if( rc == -1 ) return rc;
 
220
 
 
221
        return 0;
 
222
}
 
223
 
 
224
static int
 
225
send_ldap_controls( Operation *o, BerElement *ber, LDAPControl **c )
 
226
{
 
227
        int rc;
 
228
 
 
229
        if( c == NULL )
 
230
                return 0;
 
231
 
 
232
        rc = ber_printf( ber, "t{"/*}*/, LDAP_TAG_CONTROLS );
 
233
        if( rc == -1 ) return rc;
 
234
 
 
235
        for( ; *c != NULL; c++) {
 
236
                rc = send_ldap_control( ber, *c );
 
237
                if( rc == -1 ) return rc;
 
238
        }
 
239
 
 
240
#ifdef SLAP_CONTROL_X_SORTEDRESULTS
 
241
        /* this is a hack to avoid having to modify op->s_ctrls */
 
242
        if( o->o_sortedresults ) {
 
243
                BerElementBuffer berbuf;
 
244
                BerElement *sber = (BerElement *) &berbuf;
 
245
                LDAPControl sorted;
 
246
                BER_BVZERO( &sorted.ldctl_value );
 
247
                sorted.ldctl_oid = LDAP_CONTROL_SORTRESPONSE;
 
248
                sorted.ldctl_iscritical = 0;
 
249
 
 
250
                ber_init2( sber, NULL, LBER_USE_DER );
 
251
 
 
252
                ber_printf( sber, "{e}", LDAP_UNWILLING_TO_PERFORM );
 
253
 
 
254
                if( ber_flatten2( ber, &sorted.ldctl_value, 0 ) == -1 ) {
 
255
                        return -1;
 
256
                }
 
257
 
 
258
                (void) ber_free_buf( ber );
 
259
 
 
260
                rc = send_ldap_control( ber, &sorted );
 
261
                if( rc == -1 ) return rc;
 
262
        }
 
263
#endif
 
264
 
 
265
        rc = ber_printf( ber, /*{*/"N}" );
 
266
 
 
267
        return rc;
 
268
}
 
269
 
 
270
/*
 
271
 * slap_response_play()
 
272
 *
 
273
 * plays the callback list; rationale: a callback can
 
274
 *   - remove itself from the list, by setting op->o_callback = NULL;
 
275
 *     malloc()'ed callbacks should free themselves from inside the
 
276
 *     sc_response() function.
 
277
 *   - replace itself with another (list of) callback(s), by setting
 
278
 *     op->o_callback = a new (list of) callback(s); in this case, it
 
279
 *     is the callback's responsibility to to append existing subsequent
 
280
 *     callbacks to the end of the list that is passed to the sc_response()
 
281
 *     function.
 
282
 *   - modify the list of subsequent callbacks by modifying the value
 
283
 *     of the sc_next field from inside the sc_response() function; this
 
284
 *     case does not require any handling from inside slap_response_play()
 
285
 *
 
286
 * To stop execution of the playlist, the sc_response() function must return
 
287
 * a value different from SLAP_SC_CONTINUE.
 
288
 *
 
289
 * The same applies to slap_cleanup_play(); only, there is no means to stop
 
290
 * execution of the playlist, since all cleanup functions must be called.
 
291
 */
 
292
static int
 
293
slap_response_play(
 
294
        Operation *op,
 
295
        SlapReply *rs )
 
296
{
 
297
        int rc;
 
298
 
 
299
        slap_callback   *sc = op->o_callback, **scp;
 
300
 
 
301
        rc = SLAP_CB_CONTINUE;
 
302
        for ( scp = &sc; *scp; ) {
 
303
                slap_callback *sc_next = (*scp)->sc_next, **sc_nextp = &(*scp)->sc_next;
 
304
 
 
305
                op->o_callback = *scp;
 
306
                if ( op->o_callback->sc_response ) {
 
307
                        rc = op->o_callback->sc_response( op, rs );
 
308
                        if ( op->o_callback == NULL ) {
 
309
                                /* the callback has been removed;
 
310
                                 * repair the list */
 
311
                                *scp = sc_next;
 
312
                                sc_nextp = scp;
 
313
 
 
314
                        } else if ( op->o_callback != *scp ) {
 
315
                                /* a new callback has been inserted
 
316
                                 * in place of the existing one; repair the list */
 
317
                                *scp = op->o_callback;
 
318
                                sc_nextp = scp;
 
319
                        }
 
320
                        if ( rc != SLAP_CB_CONTINUE ) break;
 
321
                }
 
322
                scp = sc_nextp;
 
323
        }
 
324
 
 
325
        op->o_callback = sc;
 
326
        return rc;
 
327
}
 
328
 
 
329
static int
 
330
slap_cleanup_play(
 
331
        Operation *op,
 
332
        SlapReply *rs )
 
333
{
 
334
        slap_callback   *sc = op->o_callback, **scp;
 
335
 
 
336
        for ( scp = &sc; *scp; ) {
 
337
                slap_callback *sc_next = (*scp)->sc_next, **sc_nextp = &(*scp)->sc_next;
 
338
 
 
339
                op->o_callback = *scp;
 
340
                if ( op->o_callback->sc_cleanup ) {
 
341
                        (void)op->o_callback->sc_cleanup( op, rs );
 
342
                        if ( op->o_callback == NULL ) {
 
343
                                /* the callback has been removed;
 
344
                                 * repair the list */
 
345
                                *scp = sc_next;
 
346
                                sc_nextp = scp;
 
347
 
 
348
                        } else if ( op->o_callback != *scp ) {
 
349
                                /* a new callback has been inserted
 
350
                                 * after the existing one; repair the list */
 
351
                                /* a new callback has been inserted
 
352
                                 * in place of the existing one; repair the list */
 
353
                                *scp = op->o_callback;
 
354
                                sc_nextp = scp;
 
355
                        }
 
356
                        /* don't care about the result; do all cleanup */
 
357
                }
 
358
                scp = sc_nextp;
 
359
        }
 
360
 
 
361
        op->o_callback = sc;
 
362
        return LDAP_SUCCESS;
 
363
}
 
364
 
 
365
static int
 
366
send_ldap_response(
 
367
        Operation *op,
 
368
        SlapReply *rs )
 
369
{
 
370
        BerElementBuffer berbuf;
 
371
        BerElement      *ber = (BerElement *) &berbuf;
 
372
        int             rc = LDAP_SUCCESS;
 
373
        long    bytes;
 
374
 
 
375
        if ( rs->sr_err == SLAPD_ABANDON || op->o_abandon ) {
 
376
                rc = SLAPD_ABANDON;
 
377
                goto clean2;
 
378
        }
 
379
 
 
380
        if ( op->o_callback ) {
 
381
                rc = slap_response_play( op, rs );
 
382
                if ( rc != SLAP_CB_CONTINUE ) {
 
383
                        goto clean2;
 
384
                }
 
385
        }
 
386
 
 
387
#ifdef LDAP_CONNECTIONLESS
 
388
        if (op->o_conn && op->o_conn->c_is_udp)
 
389
                ber = op->o_res_ber;
 
390
        else
 
391
#endif
 
392
        {
 
393
                ber_init_w_nullc( ber, LBER_USE_DER );
 
394
                ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
 
395
        }
 
396
 
 
397
        Debug( LDAP_DEBUG_TRACE,
 
398
                "send_ldap_response: msgid=%d tag=%lu err=%d\n",
 
399
                rs->sr_msgid, rs->sr_tag, rs->sr_err );
 
400
 
 
401
        if( rs->sr_ref ) {
 
402
                Debug( LDAP_DEBUG_ARGS, "send_ldap_response: ref=\"%s\"\n",
 
403
                        rs->sr_ref[0].bv_val ? rs->sr_ref[0].bv_val : "NULL",
 
404
                        NULL, NULL );
 
405
        }
 
406
 
 
407
#ifdef LDAP_CONNECTIONLESS
 
408
        if (op->o_conn && op->o_conn->c_is_udp &&
 
409
                op->o_protocol == LDAP_VERSION2 )
 
410
        {
 
411
                rc = ber_printf( ber, "t{ess" /*"}"*/,
 
412
                        rs->sr_tag, rs->sr_err,
 
413
                rs->sr_matched == NULL ? "" : rs->sr_matched,
 
414
                rs->sr_text == NULL ? "" : rs->sr_text );
 
415
        } else 
 
416
#endif
 
417
        if ( rs->sr_type == REP_INTERMEDIATE ) {
 
418
            rc = ber_printf( ber, "{it{" /*"}}"*/,
 
419
                        rs->sr_msgid, rs->sr_tag );
 
420
 
 
421
        } else {
 
422
            rc = ber_printf( ber, "{it{ess" /*"}}"*/,
 
423
                rs->sr_msgid, rs->sr_tag, rs->sr_err,
 
424
                rs->sr_matched == NULL ? "" : rs->sr_matched,
 
425
                rs->sr_text == NULL ? "" : rs->sr_text );
 
426
        }
 
427
 
 
428
        if( rc != -1 ) {
 
429
                if ( rs->sr_ref != NULL ) {
 
430
                        assert( rs->sr_err == LDAP_REFERRAL );
 
431
                        rc = ber_printf( ber, "t{W}",
 
432
                                LDAP_TAG_REFERRAL, rs->sr_ref );
 
433
                } else {
 
434
                        assert( rs->sr_err != LDAP_REFERRAL );
 
435
                }
 
436
        }
 
437
 
 
438
        if( rc != -1 && rs->sr_type == REP_SASL && rs->sr_sasldata != NULL ) {
 
439
                rc = ber_printf( ber, "tO",
 
440
                        LDAP_TAG_SASL_RES_CREDS, rs->sr_sasldata );
 
441
        }
 
442
 
 
443
        if( rc != -1 &&
 
444
                ( rs->sr_type == REP_EXTENDED || rs->sr_type == REP_INTERMEDIATE ))
 
445
        {
 
446
                if ( rs->sr_rspoid != NULL ) {
 
447
                        rc = ber_printf( ber, "ts",
 
448
                                rs->sr_type == REP_EXTENDED
 
449
                                        ? LDAP_TAG_EXOP_RES_OID : LDAP_TAG_IM_RES_OID,
 
450
                                rs->sr_rspoid );
 
451
                }
 
452
                if( rc != -1 && rs->sr_rspdata != NULL ) {
 
453
                        rc = ber_printf( ber, "tO",
 
454
                                rs->sr_type == REP_EXTENDED
 
455
                                        ? LDAP_TAG_EXOP_RES_VALUE : LDAP_TAG_IM_RES_VALUE,
 
456
                                rs->sr_rspdata );
 
457
                }
 
458
        }
 
459
 
 
460
        if( rc != -1 ) {
 
461
                rc = ber_printf( ber, /*"{"*/ "N}" );
 
462
        }
 
463
 
 
464
        if( rc != -1 ) {
 
465
                rc = send_ldap_controls( op, ber, rs->sr_ctrls );
 
466
        }
 
467
 
 
468
        if( rc != -1 ) {
 
469
                rc = ber_printf( ber, /*"{"*/ "N}" );
 
470
        }
 
471
 
 
472
#ifdef LDAP_CONNECTIONLESS
 
473
        if( op->o_conn && op->o_conn->c_is_udp && op->o_protocol == LDAP_VERSION2
 
474
                && rc != -1 )
 
475
        {
 
476
                rc = ber_printf( ber, /*"{"*/ "N}" );
 
477
        }
 
478
#endif
 
479
                
 
480
        if ( rc == -1 ) {
 
481
                Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
 
482
 
 
483
#ifdef LDAP_CONNECTIONLESS
 
484
                if (!op->o_conn || op->o_conn->c_is_udp == 0)
 
485
#endif
 
486
                {
 
487
                        ber_free_buf( ber );
 
488
                }
 
489
                goto cleanup;
 
490
        }
 
491
 
 
492
        /* send BER */
 
493
        bytes = send_ldap_ber( op->o_conn, ber );
 
494
#ifdef LDAP_CONNECTIONLESS
 
495
        if (!op->o_conn || op->o_conn->c_is_udp == 0)
 
496
#endif
 
497
        {
 
498
                ber_free_buf( ber );
 
499
        }
 
500
 
 
501
        if ( bytes < 0 ) {
 
502
                Debug( LDAP_DEBUG_ANY,
 
503
                        "send_ldap_response: ber write failed\n",
 
504
                        0, 0, 0 );
 
505
 
 
506
                goto cleanup;
 
507
        }
 
508
 
 
509
        ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex );
 
510
        ldap_pvt_mp_add_ulong( op->o_counters->sc_pdu, 1 );
 
511
        ldap_pvt_mp_add_ulong( op->o_counters->sc_bytes, (unsigned long)bytes );
 
512
        ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex );
 
513
 
 
514
cleanup:;
 
515
        /* Tell caller that we did this for real, as opposed to being
 
516
         * overridden by a callback
 
517
         */
 
518
        rc = SLAP_CB_CONTINUE;
 
519
 
 
520
clean2:;
 
521
        if ( op->o_callback ) {
 
522
                (void)slap_cleanup_play( op, rs );
 
523
        }
 
524
 
 
525
        if ( rs->sr_flags & REP_MATCHED_MUSTBEFREED ) {
 
526
                rs->sr_flags ^= REP_MATCHED_MUSTBEFREED; /* paranoia */
 
527
                if ( rs->sr_matched ) {
 
528
                        free( (char *)rs->sr_matched );
 
529
                        rs->sr_matched = NULL;
 
530
                }
 
531
        }
 
532
 
 
533
        if ( rs->sr_flags & REP_REF_MUSTBEFREED ) {
 
534
                rs->sr_flags ^= REP_REF_MUSTBEFREED; /* paranoia */
 
535
                if ( rs->sr_ref ) {
 
536
                        ber_bvarray_free( rs->sr_ref );
 
537
                        rs->sr_ref = NULL;
 
538
                }
 
539
        }
 
540
 
 
541
        return rc;
 
542
}
 
543
 
 
544
 
 
545
void
 
546
send_ldap_disconnect( Operation *op, SlapReply *rs )
 
547
{
 
548
#define LDAP_UNSOLICITED_ERROR(e) \
 
549
        (  (e) == LDAP_PROTOCOL_ERROR \
 
550
        || (e) == LDAP_STRONG_AUTH_REQUIRED \
 
551
        || (e) == LDAP_UNAVAILABLE )
 
552
 
 
553
        assert( LDAP_UNSOLICITED_ERROR( rs->sr_err ) );
 
554
 
 
555
        rs->sr_type = REP_EXTENDED;
 
556
 
 
557
        Debug( LDAP_DEBUG_TRACE,
 
558
                "send_ldap_disconnect %d:%s\n",
 
559
                rs->sr_err, rs->sr_text ? rs->sr_text : "", NULL );
 
560
 
 
561
        if ( op->o_protocol < LDAP_VERSION3 ) {
 
562
                rs->sr_rspoid = NULL;
 
563
                rs->sr_tag = slap_req2res( op->o_tag );
 
564
                rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0;
 
565
 
 
566
        } else {
 
567
                rs->sr_rspoid = LDAP_NOTICE_DISCONNECT;
 
568
                rs->sr_tag = LDAP_RES_EXTENDED;
 
569
                rs->sr_msgid = LDAP_RES_UNSOLICITED;
 
570
        }
 
571
 
 
572
        if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) {
 
573
                Statslog( LDAP_DEBUG_STATS,
 
574
                        "%s DISCONNECT tag=%lu err=%d text=%s\n",
 
575
                        op->o_log_prefix, rs->sr_tag, rs->sr_err,
 
576
                        rs->sr_text ? rs->sr_text : "", 0 );
 
577
        }
 
578
}
 
579
 
 
580
void
 
581
slap_send_ldap_result( Operation *op, SlapReply *rs )
 
582
{
 
583
        char *tmp = NULL;
 
584
        const char *otext = rs->sr_text;
 
585
        BerVarray oref = rs->sr_ref;
 
586
 
 
587
        rs->sr_type = REP_RESULT;
 
588
 
 
589
        /* Propagate Abandons so that cleanup callbacks can be processed */
 
590
        if ( rs->sr_err == SLAPD_ABANDON || op->o_abandon )
 
591
                goto abandon;
 
592
 
 
593
        assert( !LDAP_API_ERROR( rs->sr_err ) );
 
594
 
 
595
        Debug( LDAP_DEBUG_TRACE,
 
596
                "send_ldap_result: %s p=%d\n",
 
597
                op->o_log_prefix, op->o_protocol, 0 );
 
598
 
 
599
        Debug( LDAP_DEBUG_ARGS,
 
600
                "send_ldap_result: err=%d matched=\"%s\" text=\"%s\"\n",
 
601
                rs->sr_err, rs->sr_matched ? rs->sr_matched : "",
 
602
                rs->sr_text ? rs->sr_text : "" );
 
603
 
 
604
 
 
605
        if( rs->sr_ref ) {
 
606
                Debug( LDAP_DEBUG_ARGS,
 
607
                        "send_ldap_result: referral=\"%s\"\n",
 
608
                        rs->sr_ref[0].bv_val ? rs->sr_ref[0].bv_val : "NULL",
 
609
                        NULL, NULL );
 
610
        }
 
611
 
 
612
        assert( rs->sr_err != LDAP_PARTIAL_RESULTS );
 
613
 
 
614
        if ( rs->sr_err == LDAP_REFERRAL ) {
 
615
                if( op->o_domain_scope ) rs->sr_ref = NULL;
 
616
 
 
617
                if( rs->sr_ref == NULL ) {
 
618
                        rs->sr_err = LDAP_NO_SUCH_OBJECT;
 
619
                } else if ( op->o_protocol < LDAP_VERSION3 ) {
 
620
                        rs->sr_err = LDAP_PARTIAL_RESULTS;
 
621
                }
 
622
        }
 
623
 
 
624
        if ( op->o_protocol < LDAP_VERSION3 ) {
 
625
                tmp = v2ref( rs->sr_ref, rs->sr_text );
 
626
                rs->sr_text = tmp;
 
627
                rs->sr_ref = NULL;
 
628
        }
 
629
 
 
630
abandon:
 
631
        rs->sr_tag = slap_req2res( op->o_tag );
 
632
        rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0;
 
633
 
 
634
        if ( rs->sr_flags & REP_REF_MUSTBEFREED ) {
 
635
                if ( rs->sr_ref == NULL ) {
 
636
                        rs->sr_flags ^= REP_REF_MUSTBEFREED;
 
637
                        ber_bvarray_free( oref );
 
638
                }
 
639
                oref = NULL; /* send_ldap_response() will free rs->sr_ref if != NULL */
 
640
        }
 
641
 
 
642
        if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) {
 
643
                if ( op->o_tag == LDAP_REQ_SEARCH ) {
 
644
                        char nbuf[64];
 
645
                        snprintf( nbuf, sizeof nbuf, "%d nentries=%d",
 
646
                                rs->sr_err, rs->sr_nentries );
 
647
 
 
648
                        Statslog( LDAP_DEBUG_STATS,
 
649
                        "%s SEARCH RESULT tag=%lu err=%s text=%s\n",
 
650
                                op->o_log_prefix, rs->sr_tag, nbuf,
 
651
                                rs->sr_text ? rs->sr_text : "", 0 );
 
652
                } else {
 
653
                        Statslog( LDAP_DEBUG_STATS,
 
654
                                "%s RESULT tag=%lu err=%d text=%s\n",
 
655
                                op->o_log_prefix, rs->sr_tag, rs->sr_err,
 
656
                                rs->sr_text ? rs->sr_text : "", 0 );
 
657
                }
 
658
        }
 
659
 
 
660
        if( tmp != NULL ) ch_free(tmp);
 
661
        rs->sr_text = otext;
 
662
        rs->sr_ref = oref;
 
663
}
 
664
 
 
665
void
 
666
send_ldap_sasl( Operation *op, SlapReply *rs )
 
667
{
 
668
        rs->sr_type = REP_SASL;
 
669
        Debug( LDAP_DEBUG_TRACE, "send_ldap_sasl: err=%d len=%ld\n",
 
670
                rs->sr_err,
 
671
                rs->sr_sasldata ? (long) rs->sr_sasldata->bv_len : -1, NULL );
 
672
 
 
673
        rs->sr_tag = slap_req2res( op->o_tag );
 
674
        rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0;
 
675
 
 
676
        if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) {
 
677
                Statslog( LDAP_DEBUG_STATS,
 
678
                        "%s RESULT tag=%lu err=%d text=%s\n",
 
679
                        op->o_log_prefix, rs->sr_tag, rs->sr_err,
 
680
                        rs->sr_text ? rs->sr_text : "", 0 );
 
681
        }
 
682
}
 
683
 
 
684
void
 
685
slap_send_ldap_extended( Operation *op, SlapReply *rs )
 
686
{
 
687
        rs->sr_type = REP_EXTENDED;
 
688
 
 
689
        Debug( LDAP_DEBUG_TRACE,
 
690
                "send_ldap_extended: err=%d oid=%s len=%ld\n",
 
691
                rs->sr_err,
 
692
                rs->sr_rspoid ? rs->sr_rspoid : "",
 
693
                rs->sr_rspdata != NULL ? rs->sr_rspdata->bv_len : 0 );
 
694
 
 
695
        rs->sr_tag = slap_req2res( op->o_tag );
 
696
        rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0;
 
697
 
 
698
        if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) {
 
699
                Statslog( LDAP_DEBUG_STATS,
 
700
                        "%s RESULT oid=%s err=%d text=%s\n",
 
701
                        op->o_log_prefix, rs->sr_rspoid ? rs->sr_rspoid : "",
 
702
                        rs->sr_err, rs->sr_text ? rs->sr_text : "", 0 );
 
703
        }
 
704
}
 
705
 
 
706
void
 
707
slap_send_ldap_intermediate( Operation *op, SlapReply *rs )
 
708
{
 
709
        rs->sr_type = REP_INTERMEDIATE;
 
710
        Debug( LDAP_DEBUG_TRACE,
 
711
                "send_ldap_intermediate: err=%d oid=%s len=%ld\n",
 
712
                rs->sr_err,
 
713
                rs->sr_rspoid ? rs->sr_rspoid : "",
 
714
                rs->sr_rspdata != NULL ? rs->sr_rspdata->bv_len : 0 );
 
715
        rs->sr_tag = LDAP_RES_INTERMEDIATE;
 
716
        rs->sr_msgid = op->o_msgid;
 
717
        if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) {
 
718
                Statslog( LDAP_DEBUG_STATS2,
 
719
                        "%s INTERM oid=%s\n",
 
720
                        op->o_log_prefix,
 
721
                        rs->sr_rspoid ? rs->sr_rspoid : "", 0, 0, 0 );
 
722
        }
 
723
}
 
724
 
 
725
/*
 
726
 * returns:
 
727
 *
 
728
 * LDAP_SUCCESS                 entry sent
 
729
 * LDAP_OTHER                   entry not sent (other)
 
730
 * LDAP_INSUFFICIENT_ACCESS     entry not sent (ACL)
 
731
 * LDAP_UNAVAILABLE             entry not sent (connection closed)
 
732
 * LDAP_SIZELIMIT_EXCEEDED      entry not sent (caller must send sizelimitExceeded)
 
733
 */
 
734
 
 
735
int
 
736
slap_send_search_entry( Operation *op, SlapReply *rs )
 
737
{
 
738
        BerElementBuffer berbuf;
 
739
        BerElement      *ber = (BerElement *) &berbuf;
 
740
        Attribute       *a;
 
741
        int             i, j, rc = LDAP_UNAVAILABLE, bytes;
 
742
        char            *edn;
 
743
        int             userattrs;
 
744
        AccessControlState acl_state = ACL_STATE_INIT;
 
745
        int                      attrsonly;
 
746
        AttributeDescription *ad_entry = slap_schema.si_ad_entry;
 
747
 
 
748
        /* a_flags: array of flags telling if the i-th element will be
 
749
         *          returned or filtered out
 
750
         * e_flags: array of a_flags
 
751
         */
 
752
        char **e_flags = NULL;
 
753
 
 
754
        if ( op->ors_slimit >= 0 && rs->sr_nentries >= op->ors_slimit ) {
 
755
                return LDAP_SIZELIMIT_EXCEEDED;
 
756
        }
 
757
 
 
758
        /* Every 64 entries, check for thread pool pause */
 
759
        if ( ( ( rs->sr_nentries & 0x3f ) == 0x3f ) &&
 
760
                ldap_pvt_thread_pool_pausing( &connection_pool ) > 0 )
 
761
        {
 
762
                return LDAP_BUSY;
 
763
        }
 
764
 
 
765
        rs->sr_type = REP_SEARCH;
 
766
 
 
767
        /* eventually will loop through generated operational attribute types
 
768
         * currently implemented types include:
 
769
         *      entryDN, subschemaSubentry, and hasSubordinates */
 
770
        /* NOTE: moved before overlays callback circling because
 
771
         * they may modify entry and other stuff in rs */
 
772
        /* check for special all operational attributes ("+") type */
 
773
        /* FIXME: maybe we could set this flag at the operation level;
 
774
         * however, in principle the caller of send_search_entry() may
 
775
         * change the attribute list at each call */
 
776
        rs->sr_attr_flags = slap_attr_flags( rs->sr_attrs );
 
777
 
 
778
        rc = backend_operational( op, rs );
 
779
        if ( rc ) {
 
780
                goto error_return;
 
781
        }
 
782
 
 
783
        if ( op->o_callback ) {
 
784
                rc = slap_response_play( op, rs );
 
785
                if ( rc != SLAP_CB_CONTINUE ) {
 
786
                        goto error_return;
 
787
                }
 
788
        }
 
789
 
 
790
        Debug( LDAP_DEBUG_TRACE, "=> send_search_entry: conn %lu dn=\"%s\"%s\n",
 
791
                op->o_connid, rs->sr_entry->e_name.bv_val,
 
792
                op->ors_attrsonly ? " (attrsOnly)" : "" );
 
793
 
 
794
        attrsonly = op->ors_attrsonly;
 
795
 
 
796
        if ( !access_allowed( op, rs->sr_entry, ad_entry, NULL, ACL_READ, NULL )) {
 
797
                Debug( LDAP_DEBUG_ACL,
 
798
                        "send_search_entry: conn %lu access to entry (%s) not allowed\n", 
 
799
                        op->o_connid, rs->sr_entry->e_name.bv_val, 0 );
 
800
 
 
801
                rc = LDAP_INSUFFICIENT_ACCESS;
 
802
                goto error_return;
 
803
        }
 
804
 
 
805
        edn = rs->sr_entry->e_nname.bv_val;
 
806
 
 
807
        if ( op->o_res_ber ) {
 
808
                /* read back control or LDAP_CONNECTIONLESS */
 
809
            ber = op->o_res_ber;
 
810
        } else {
 
811
                struct berval   bv;
 
812
 
 
813
                bv.bv_len = entry_flatsize( rs->sr_entry, 0 );
 
814
                bv.bv_val = op->o_tmpalloc( bv.bv_len, op->o_tmpmemctx );
 
815
 
 
816
                ber_init2( ber, &bv, LBER_USE_DER );
 
817
                ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
 
818
        }
 
819
 
 
820
#ifdef LDAP_CONNECTIONLESS
 
821
        if ( op->o_conn && op->o_conn->c_is_udp ) {
 
822
                /* CONNECTIONLESS */
 
823
                if ( op->o_protocol == LDAP_VERSION2 ) {
 
824
                rc = ber_printf(ber, "t{O{" /*}}*/,
 
825
                                LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name );
 
826
                } else {
 
827
                rc = ber_printf( ber, "{it{O{" /*}}}*/, op->o_msgid,
 
828
                                LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name );
 
829
                }
 
830
        } else
 
831
#endif
 
832
        if ( op->o_res_ber ) {
 
833
                /* read back control */
 
834
            rc = ber_printf( ber, "{O{" /*}}*/, &rs->sr_entry->e_name );
 
835
        } else {
 
836
            rc = ber_printf( ber, "{it{O{" /*}}}*/, op->o_msgid,
 
837
                        LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name );
 
838
        }
 
839
 
 
840
        if ( rc == -1 ) {
 
841
                Debug( LDAP_DEBUG_ANY, 
 
842
                        "send_search_entry: conn %lu  ber_printf failed\n", 
 
843
                        op->o_connid, 0, 0 );
 
844
 
 
845
                if ( op->o_res_ber == NULL ) ber_free_buf( ber );
 
846
                send_ldap_error( op, rs, LDAP_OTHER, "encoding DN error" );
 
847
                rc = rs->sr_err;
 
848
                goto error_return;
 
849
        }
 
850
 
 
851
        /* check for special all user attributes ("*") type */
 
852
        userattrs = SLAP_USERATTRS( rs->sr_attr_flags );
 
853
 
 
854
        /* create an array of arrays of flags. Each flag corresponds
 
855
         * to particular value of attribute and equals 1 if value matches
 
856
         * to ValuesReturnFilter or 0 if not
 
857
         */     
 
858
        if ( op->o_vrFilter != NULL ) {
 
859
                int     k = 0;
 
860
                size_t  size;
 
861
 
 
862
                for ( a = rs->sr_entry->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
 
863
                        for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++;
 
864
                }
 
865
 
 
866
                size = i * sizeof(char *) + k;
 
867
                if ( size > 0 ) {
 
868
                        char    *a_flags;
 
869
                        e_flags = slap_sl_calloc ( 1, i * sizeof(char *) + k, op->o_tmpmemctx );
 
870
                        if( e_flags == NULL ) {
 
871
                        Debug( LDAP_DEBUG_ANY, 
 
872
                                        "send_search_entry: conn %lu slap_sl_calloc failed\n",
 
873
                                        op->o_connid ? op->o_connid : 0, 0, 0 );
 
874
                                ber_free( ber, 1 );
 
875
        
 
876
                                send_ldap_error( op, rs, LDAP_OTHER, "out of memory" );
 
877
                                goto error_return;
 
878
                        }
 
879
                        a_flags = (char *)(e_flags + i);
 
880
                        memset( a_flags, 0, k );
 
881
                        for ( a=rs->sr_entry->e_attrs, i=0; a != NULL; a=a->a_next, i++ ) {
 
882
                                for ( j = 0; a->a_vals[j].bv_val != NULL; j++ );
 
883
                                e_flags[i] = a_flags;
 
884
                                a_flags += j;
 
885
                        }
 
886
        
 
887
                        rc = filter_matched_values(op, rs->sr_entry->e_attrs, &e_flags) ; 
 
888
                        if ( rc == -1 ) {
 
889
                                Debug( LDAP_DEBUG_ANY, "send_search_entry: "
 
890
                                        "conn %lu matched values filtering failed\n",
 
891
                                        op->o_connid ? op->o_connid : 0, 0, 0 );
 
892
                                if ( op->o_res_ber == NULL ) ber_free_buf( ber );
 
893
                                send_ldap_error( op, rs, LDAP_OTHER,
 
894
                                        "matched values filtering error" );
 
895
                                rc = rs->sr_err;
 
896
                                goto error_return;
 
897
                        }
 
898
                }
 
899
        }
 
900
 
 
901
        for ( a = rs->sr_entry->e_attrs, j = 0; a != NULL; a = a->a_next, j++ ) {
 
902
                AttributeDescription *desc = a->a_desc;
 
903
                int finish = 0;
 
904
 
 
905
                if ( rs->sr_attrs == NULL ) {
 
906
                        /* all user attrs request, skip operational attributes */
 
907
                        if( is_at_operational( desc->ad_type ) ) {
 
908
                                continue;
 
909
                        }
 
910
 
 
911
                } else {
 
912
                        /* specific attrs requested */
 
913
                        if ( is_at_operational( desc->ad_type ) ) {
 
914
                                /* if not explicitly requested */
 
915
                                if ( !ad_inlist( desc, rs->sr_attrs )) {
 
916
                                        /* if not all op attrs requested, skip */
 
917
                                        if ( !SLAP_OPATTRS( rs->sr_attr_flags ))
 
918
                                                continue;
 
919
                                        /* if DSA-specific and replicating, skip */
 
920
                                        if ( op->o_sync != SLAP_CONTROL_NONE &&
 
921
                                                desc->ad_type->sat_usage == LDAP_SCHEMA_DSA_OPERATION )
 
922
                                                continue;
 
923
                                }
 
924
                        } else {
 
925
                                if ( !userattrs && !ad_inlist( desc, rs->sr_attrs ) ) {
 
926
                                        continue;
 
927
                                }
 
928
                        }
 
929
                }
 
930
 
 
931
                if ( attrsonly ) {
 
932
                        if ( ! access_allowed( op, rs->sr_entry, desc, NULL,
 
933
                                ACL_READ, &acl_state ) )
 
934
                        {
 
935
                                Debug( LDAP_DEBUG_ACL, "send_search_entry: "
 
936
                                        "conn %lu access to attribute %s not allowed\n",
 
937
                                        op->o_connid, desc->ad_cname.bv_val, 0 );
 
938
                                continue;
 
939
                        }
 
940
 
 
941
                        if (( rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname )) == -1 ) {
 
942
                                Debug( LDAP_DEBUG_ANY, 
 
943
                                        "send_search_entry: conn %lu  ber_printf failed\n", 
 
944
                                        op->o_connid, 0, 0 );
 
945
 
 
946
                                if ( op->o_res_ber == NULL ) ber_free_buf( ber );
 
947
                                send_ldap_error( op, rs, LDAP_OTHER,
 
948
                                        "encoding description error");
 
949
                                rc = rs->sr_err;
 
950
                                goto error_return;
 
951
                        }
 
952
                        finish = 1;
 
953
 
 
954
                } else {
 
955
                        int first = 1;
 
956
                        for ( i = 0; a->a_nvals[i].bv_val != NULL; i++ ) {
 
957
                                if ( ! access_allowed( op, rs->sr_entry,
 
958
                                        desc, &a->a_nvals[i], ACL_READ, &acl_state ) )
 
959
                                {
 
960
                                        Debug( LDAP_DEBUG_ACL,
 
961
                                                "send_search_entry: conn %lu "
 
962
                                                "access to attribute %s, value #%d not allowed\n",
 
963
                                                op->o_connid, desc->ad_cname.bv_val, i );
 
964
 
 
965
                                        continue;
 
966
                                }
 
967
 
 
968
                                if ( op->o_vrFilter && e_flags[j][i] == 0 ){
 
969
                                        continue;
 
970
                                }
 
971
 
 
972
                                if ( first ) {
 
973
                                        first = 0;
 
974
                                        finish = 1;
 
975
                                        if (( rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname )) == -1 ) {
 
976
                                                Debug( LDAP_DEBUG_ANY,
 
977
                                                        "send_search_entry: conn %lu  ber_printf failed\n", 
 
978
                                                        op->o_connid, 0, 0 );
 
979
 
 
980
                                                if ( op->o_res_ber == NULL ) ber_free_buf( ber );
 
981
                                                send_ldap_error( op, rs, LDAP_OTHER,
 
982
                                                        "encoding description error");
 
983
                                                rc = rs->sr_err;
 
984
                                                goto error_return;
 
985
                                        }
 
986
                                }
 
987
                                if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
 
988
                                        Debug( LDAP_DEBUG_ANY,
 
989
                                                "send_search_entry: conn %lu  "
 
990
                                                "ber_printf failed.\n", op->o_connid, 0, 0 );
 
991
 
 
992
                                        if ( op->o_res_ber == NULL ) ber_free_buf( ber );
 
993
                                        send_ldap_error( op, rs, LDAP_OTHER,
 
994
                                                "encoding values error" );
 
995
                                        rc = rs->sr_err;
 
996
                                        goto error_return;
 
997
                                }
 
998
                        }
 
999
                }
 
1000
 
 
1001
                if ( finish && ( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
 
1002
                        Debug( LDAP_DEBUG_ANY,
 
1003
                                "send_search_entry: conn %lu ber_printf failed\n", 
 
1004
                                op->o_connid, 0, 0 );
 
1005
 
 
1006
                        if ( op->o_res_ber == NULL ) ber_free_buf( ber );
 
1007
                        send_ldap_error( op, rs, LDAP_OTHER, "encode end error" );
 
1008
                        rc = rs->sr_err;
 
1009
                        goto error_return;
 
1010
                }
 
1011
        }
 
1012
 
 
1013
        /* NOTE: moved before overlays callback circling because
 
1014
         * they may modify entry and other stuff in rs */
 
1015
        if ( rs->sr_operational_attrs != NULL && op->o_vrFilter != NULL ) {
 
1016
                int     k = 0;
 
1017
                size_t  size;
 
1018
 
 
1019
                for ( a = rs->sr_operational_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
 
1020
                        for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++;
 
1021
                }
 
1022
 
 
1023
                size = i * sizeof(char *) + k;
 
1024
                if ( size > 0 ) {
 
1025
                        char    *a_flags, **tmp;
 
1026
                
 
1027
                        /*
 
1028
                         * Reuse previous memory - we likely need less space
 
1029
                         * for operational attributes
 
1030
                         */
 
1031
                        tmp = slap_sl_realloc( e_flags, i * sizeof(char *) + k,
 
1032
                                op->o_tmpmemctx );
 
1033
                        if ( tmp == NULL ) {
 
1034
                                Debug( LDAP_DEBUG_ANY,
 
1035
                                        "send_search_entry: conn %lu "
 
1036
                                        "not enough memory "
 
1037
                                        "for matched values filtering\n",
 
1038
                                        op->o_connid, 0, 0 );
 
1039
                                if ( op->o_res_ber == NULL ) ber_free_buf( ber );
 
1040
                                send_ldap_error( op, rs, LDAP_OTHER,
 
1041
                                        "not enough memory for matched values filtering" );
 
1042
                                goto error_return;
 
1043
                        }
 
1044
                        e_flags = tmp;
 
1045
                        a_flags = (char *)(e_flags + i);
 
1046
                        memset( a_flags, 0, k );
 
1047
                        for ( a = rs->sr_operational_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
 
1048
                                for ( j = 0; a->a_vals[j].bv_val != NULL; j++ );
 
1049
                                e_flags[i] = a_flags;
 
1050
                                a_flags += j;
 
1051
                        }
 
1052
                        rc = filter_matched_values(op, rs->sr_operational_attrs, &e_flags) ; 
 
1053
                    
 
1054
                        if ( rc == -1 ) {
 
1055
                                Debug( LDAP_DEBUG_ANY,
 
1056
                                        "send_search_entry: conn %lu "
 
1057
                                        "matched values filtering failed\n", 
 
1058
                                        op->o_connid ? op->o_connid : 0, 0, 0);
 
1059
                                if ( op->o_res_ber == NULL ) ber_free_buf( ber );
 
1060
                                send_ldap_error( op, rs, LDAP_OTHER,
 
1061
                                        "matched values filtering error" );
 
1062
                                rc = rs->sr_err;
 
1063
                                goto error_return;
 
1064
                        }
 
1065
                }
 
1066
        }
 
1067
 
 
1068
        for (a = rs->sr_operational_attrs, j=0; a != NULL; a = a->a_next, j++ ) {
 
1069
                AttributeDescription *desc = a->a_desc;
 
1070
 
 
1071
                if ( rs->sr_attrs == NULL ) {
 
1072
                        /* all user attrs request, skip operational attributes */
 
1073
                        if( is_at_operational( desc->ad_type ) ) {
 
1074
                                continue;
 
1075
                        }
 
1076
 
 
1077
                } else {
 
1078
                        /* specific attrs requested */
 
1079
                        if( is_at_operational( desc->ad_type ) ) {
 
1080
                                if ( !SLAP_OPATTRS( rs->sr_attr_flags ) && 
 
1081
                                        !ad_inlist( desc, rs->sr_attrs ) )
 
1082
                                {
 
1083
                                        continue;
 
1084
                                }
 
1085
                        } else {
 
1086
                                if ( !userattrs && !ad_inlist( desc, rs->sr_attrs ) ) {
 
1087
                                        continue;
 
1088
                                }
 
1089
                        }
 
1090
                }
 
1091
 
 
1092
                if ( ! access_allowed( op, rs->sr_entry, desc, NULL,
 
1093
                        ACL_READ, &acl_state ) )
 
1094
                {
 
1095
                        Debug( LDAP_DEBUG_ACL,
 
1096
                                "send_search_entry: conn %lu "
 
1097
                                "access to attribute %s not allowed\n",
 
1098
                                op->o_connid, desc->ad_cname.bv_val, 0 );
 
1099
 
 
1100
                        continue;
 
1101
                }
 
1102
 
 
1103
                rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname );
 
1104
                if ( rc == -1 ) {
 
1105
                        Debug( LDAP_DEBUG_ANY,
 
1106
                                "send_search_entry: conn %lu  "
 
1107
                                "ber_printf failed\n", op->o_connid, 0, 0 );
 
1108
 
 
1109
                        if ( op->o_res_ber == NULL ) ber_free_buf( ber );
 
1110
                        send_ldap_error( op, rs, LDAP_OTHER,
 
1111
                                "encoding description error" );
 
1112
                        rc = rs->sr_err;
 
1113
                        goto error_return;
 
1114
                }
 
1115
 
 
1116
                if ( ! attrsonly ) {
 
1117
                        for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
 
1118
                                if ( ! access_allowed( op, rs->sr_entry,
 
1119
                                        desc, &a->a_vals[i], ACL_READ, &acl_state ) )
 
1120
                                {
 
1121
                                        Debug( LDAP_DEBUG_ACL,
 
1122
                                                "send_search_entry: conn %lu "
 
1123
                                                "access to %s, value %d not allowed\n",
 
1124
                                                op->o_connid, desc->ad_cname.bv_val, i );
 
1125
 
 
1126
                                        continue;
 
1127
                                }
 
1128
 
 
1129
                                if ( op->o_vrFilter && e_flags[j][i] == 0 ){
 
1130
                                        continue;
 
1131
                                }
 
1132
 
 
1133
                                if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
 
1134
                                        Debug( LDAP_DEBUG_ANY,
 
1135
                                                "send_search_entry: conn %lu  ber_printf failed\n", 
 
1136
                                                op->o_connid, 0, 0 );
 
1137
 
 
1138
                                        if ( op->o_res_ber == NULL ) ber_free_buf( ber );
 
1139
                                        send_ldap_error( op, rs, LDAP_OTHER,
 
1140
                                                "encoding values error" );
 
1141
                                        rc = rs->sr_err;
 
1142
                                        goto error_return;
 
1143
                                }
 
1144
                        }
 
1145
                }
 
1146
 
 
1147
                if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
 
1148
                        Debug( LDAP_DEBUG_ANY,
 
1149
                                "send_search_entry: conn %lu  ber_printf failed\n",
 
1150
                                op->o_connid, 0, 0 );
 
1151
 
 
1152
                        if ( op->o_res_ber == NULL ) ber_free_buf( ber );
 
1153
                        send_ldap_error( op, rs, LDAP_OTHER, "encode end error" );
 
1154
                        rc = rs->sr_err;
 
1155
                        goto error_return;
 
1156
                }
 
1157
        }
 
1158
 
 
1159
        /* free e_flags */
 
1160
        if ( e_flags ) {
 
1161
                slap_sl_free( e_flags, op->o_tmpmemctx );
 
1162
                e_flags = NULL;
 
1163
        }
 
1164
 
 
1165
        rc = ber_printf( ber, /*{{*/ "}N}" );
 
1166
 
 
1167
        if( rc != -1 ) {
 
1168
                rc = send_ldap_controls( op, ber, rs->sr_ctrls );
 
1169
        }
 
1170
 
 
1171
        if( rc != -1 ) {
 
1172
#ifdef LDAP_CONNECTIONLESS
 
1173
                if( op->o_conn && op->o_conn->c_is_udp ) {
 
1174
                        if ( op->o_protocol != LDAP_VERSION2 ) {
 
1175
                                rc = ber_printf( ber, /*{*/ "N}" );
 
1176
                        }
 
1177
                } else
 
1178
#endif
 
1179
                if ( op->o_res_ber == NULL ) {
 
1180
                        rc = ber_printf( ber, /*{*/ "N}" );
 
1181
                }
 
1182
        }
 
1183
 
 
1184
        if ( rc == -1 ) {
 
1185
                Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
 
1186
 
 
1187
                if ( op->o_res_ber == NULL ) ber_free_buf( ber );
 
1188
                send_ldap_error( op, rs, LDAP_OTHER, "encode entry end error" );
 
1189
                rc = rs->sr_err;
 
1190
                goto error_return;
 
1191
        }
 
1192
 
 
1193
        if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) {
 
1194
                be_entry_release_rw( op, rs->sr_entry, 0 );
 
1195
                rs->sr_flags ^= REP_ENTRY_MUSTRELEASE;
 
1196
                rs->sr_entry = NULL;
 
1197
        }
 
1198
 
 
1199
        if ( op->o_res_ber == NULL ) {
 
1200
                bytes = send_ldap_ber( op->o_conn, ber );
 
1201
                ber_free_buf( ber );
 
1202
 
 
1203
                if ( bytes < 0 ) {
 
1204
                        Debug( LDAP_DEBUG_ANY,
 
1205
                                "send_search_entry: conn %lu  ber write failed.\n", 
 
1206
                                op->o_connid, 0, 0 );
 
1207
 
 
1208
                        rc = LDAP_UNAVAILABLE;
 
1209
                        goto error_return;
 
1210
                }
 
1211
                rs->sr_nentries++;
 
1212
 
 
1213
                ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex );
 
1214
                ldap_pvt_mp_add_ulong( op->o_counters->sc_bytes, (unsigned long)bytes );
 
1215
                ldap_pvt_mp_add_ulong( op->o_counters->sc_entries, 1 );
 
1216
                ldap_pvt_mp_add_ulong( op->o_counters->sc_pdu, 1 );
 
1217
                ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex );
 
1218
        }
 
1219
 
 
1220
        Statslog( LDAP_DEBUG_STATS2, "%s ENTRY dn=\"%s\"\n",
 
1221
            op->o_log_prefix, edn, 0, 0, 0 );
 
1222
 
 
1223
        Debug( LDAP_DEBUG_TRACE,
 
1224
                "<= send_search_entry: conn %lu exit.\n", op->o_connid, 0, 0 );
 
1225
 
 
1226
        rc = LDAP_SUCCESS;
 
1227
 
 
1228
error_return:;
 
1229
        if ( op->o_callback ) {
 
1230
                (void)slap_cleanup_play( op, rs );
 
1231
        }
 
1232
 
 
1233
        if ( e_flags ) {
 
1234
                slap_sl_free( e_flags, op->o_tmpmemctx );
 
1235
        }
 
1236
 
 
1237
        if ( rs->sr_operational_attrs ) {
 
1238
                attrs_free( rs->sr_operational_attrs );
 
1239
                rs->sr_operational_attrs = NULL;
 
1240
        }
 
1241
        rs->sr_attr_flags = SLAP_ATTRS_UNDEFINED;
 
1242
 
 
1243
        /* FIXME: I think rs->sr_type should be explicitly set to
 
1244
         * REP_SEARCH here. That's what it was when we entered this
 
1245
         * function. send_ldap_error may have changed it, but we
 
1246
         * should set it back so that the cleanup functions know
 
1247
         * what they're doing.
 
1248
         */
 
1249
        if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH 
 
1250
                && rs->sr_entry 
 
1251
                && ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) ) 
 
1252
        {
 
1253
                entry_free( rs->sr_entry );
 
1254
                rs->sr_entry = NULL;
 
1255
                rs->sr_flags &= ~REP_ENTRY_MUSTBEFREED;
 
1256
        }
 
1257
 
 
1258
        return( rc );
 
1259
}
 
1260
 
 
1261
int
 
1262
slap_send_search_reference( Operation *op, SlapReply *rs )
 
1263
{
 
1264
        BerElementBuffer berbuf;
 
1265
        BerElement      *ber = (BerElement *) &berbuf;
 
1266
        int rc = 0;
 
1267
        int bytes;
 
1268
 
 
1269
        AttributeDescription *ad_ref = slap_schema.si_ad_ref;
 
1270
        AttributeDescription *ad_entry = slap_schema.si_ad_entry;
 
1271
 
 
1272
        rs->sr_type = REP_SEARCHREF;
 
1273
        if ( op->o_callback ) {
 
1274
                rc = slap_response_play( op, rs );
 
1275
                if ( rc != SLAP_CB_CONTINUE ) {
 
1276
                        goto rel;
 
1277
                }
 
1278
        }
 
1279
 
 
1280
        Debug( LDAP_DEBUG_TRACE,
 
1281
                "=> send_search_reference: dn=\"%s\"\n",
 
1282
                rs->sr_entry ? rs->sr_entry->e_name.bv_val : "(null)", 0, 0 );
 
1283
 
 
1284
        if (  rs->sr_entry && ! access_allowed( op, rs->sr_entry,
 
1285
                ad_entry, NULL, ACL_READ, NULL ) )
 
1286
        {
 
1287
                Debug( LDAP_DEBUG_ACL,
 
1288
                        "send_search_reference: access to entry not allowed\n",
 
1289
                    0, 0, 0 );
 
1290
                rc = 1;
 
1291
                goto rel;
 
1292
        }
 
1293
 
 
1294
        if ( rs->sr_entry && ! access_allowed( op, rs->sr_entry,
 
1295
                ad_ref, NULL, ACL_READ, NULL ) )
 
1296
        {
 
1297
                Debug( LDAP_DEBUG_ACL,
 
1298
                        "send_search_reference: access "
 
1299
                        "to reference not allowed\n",
 
1300
                    0, 0, 0 );
 
1301
                rc = 1;
 
1302
                goto rel;
 
1303
        }
 
1304
 
 
1305
        if( op->o_domain_scope ) {
 
1306
                Debug( LDAP_DEBUG_ANY,
 
1307
                        "send_search_reference: domainScope control in (%s)\n", 
 
1308
                        rs->sr_entry->e_dn, 0, 0 );
 
1309
                rc = 0;
 
1310
                goto rel;
 
1311
        }
 
1312
 
 
1313
        if( rs->sr_ref == NULL ) {
 
1314
                Debug( LDAP_DEBUG_ANY,
 
1315
                        "send_search_reference: null ref in (%s)\n", 
 
1316
                        rs->sr_entry ? rs->sr_entry->e_dn : "(null)", 0, 0 );
 
1317
                rc = 1;
 
1318
                goto rel;
 
1319
        }
 
1320
 
 
1321
        if( op->o_protocol < LDAP_VERSION3 ) {
 
1322
                rc = 0;
 
1323
                /* save the references for the result */
 
1324
                if( rs->sr_ref[0].bv_val != NULL ) {
 
1325
                        if( value_add( &rs->sr_v2ref, rs->sr_ref ) )
 
1326
                                rc = LDAP_OTHER;
 
1327
                }
 
1328
                goto rel;
 
1329
        }
 
1330
 
 
1331
#ifdef LDAP_CONNECTIONLESS
 
1332
        if( op->o_conn && op->o_conn->c_is_udp ) {
 
1333
                ber = op->o_res_ber;
 
1334
        } else
 
1335
#endif
 
1336
        {
 
1337
                ber_init_w_nullc( ber, LBER_USE_DER );
 
1338
                ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
 
1339
        }
 
1340
 
 
1341
        rc = ber_printf( ber, "{it{W}" /*"}"*/ , op->o_msgid,
 
1342
                LDAP_RES_SEARCH_REFERENCE, rs->sr_ref );
 
1343
 
 
1344
        if( rc != -1 ) {
 
1345
                rc = send_ldap_controls( op, ber, rs->sr_ctrls );
 
1346
        }
 
1347
 
 
1348
        if( rc != -1 ) {
 
1349
                rc = ber_printf( ber, /*"{"*/ "N}" );
 
1350
        }
 
1351
 
 
1352
        if ( rc == -1 ) {
 
1353
                Debug( LDAP_DEBUG_ANY,
 
1354
                        "send_search_reference: ber_printf failed\n", 0, 0, 0 );
 
1355
 
 
1356
#ifdef LDAP_CONNECTIONLESS
 
1357
                if (!op->o_conn || op->o_conn->c_is_udp == 0)
 
1358
#endif
 
1359
                ber_free_buf( ber );
 
1360
                send_ldap_error( op, rs, LDAP_OTHER, "encode DN error" );
 
1361
                goto rel;
 
1362
        }
 
1363
 
 
1364
        rc = 0;
 
1365
        if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) {
 
1366
                be_entry_release_rw( op, rs->sr_entry, 0 );
 
1367
                rs->sr_flags ^= REP_ENTRY_MUSTRELEASE;
 
1368
                rs->sr_entry = NULL;
 
1369
        }
 
1370
 
 
1371
#ifdef LDAP_CONNECTIONLESS
 
1372
        if (!op->o_conn || op->o_conn->c_is_udp == 0) {
 
1373
#endif
 
1374
        bytes = send_ldap_ber( op->o_conn, ber );
 
1375
        ber_free_buf( ber );
 
1376
 
 
1377
        if ( bytes < 0 ) {
 
1378
                rc = LDAP_UNAVAILABLE;
 
1379
        } else {
 
1380
                ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex );
 
1381
                ldap_pvt_mp_add_ulong( op->o_counters->sc_bytes, (unsigned long)bytes );
 
1382
                ldap_pvt_mp_add_ulong( op->o_counters->sc_refs, 1 );
 
1383
                ldap_pvt_mp_add_ulong( op->o_counters->sc_pdu, 1 );
 
1384
                ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex );
 
1385
        }
 
1386
#ifdef LDAP_CONNECTIONLESS
 
1387
        }
 
1388
#endif
 
1389
        if ( rs->sr_ref != NULL ) {
 
1390
                int     r;
 
1391
 
 
1392
                for ( r = 0; !BER_BVISNULL( &rs->sr_ref[ r ] ); r++ ) {
 
1393
                        Statslog( LDAP_DEBUG_STATS2, "%s REF #%d \"%s\"\n",
 
1394
                                op->o_log_prefix, r, rs->sr_ref[0].bv_val,
 
1395
                                0, 0 );
 
1396
                }
 
1397
 
 
1398
        } else {
 
1399
                Statslog( LDAP_DEBUG_STATS2, "%s REF \"(null)\"\n",
 
1400
                        op->o_log_prefix, 0, 0, 0, 0 );
 
1401
        }
 
1402
 
 
1403
        Debug( LDAP_DEBUG_TRACE, "<= send_search_reference\n", 0, 0, 0 );
 
1404
 
 
1405
rel:
 
1406
        if ( op->o_callback ) {
 
1407
                (void)slap_cleanup_play( op, rs );
 
1408
        }
 
1409
 
 
1410
        return rc;
 
1411
}
 
1412
 
 
1413
int
 
1414
str2result(
 
1415
    char        *s,
 
1416
    int         *code,
 
1417
    char        **matched,
 
1418
    char        **info )
 
1419
{
 
1420
        int     rc;
 
1421
        char    *c;
 
1422
 
 
1423
        *code = LDAP_SUCCESS;
 
1424
        *matched = NULL;
 
1425
        *info = NULL;
 
1426
 
 
1427
        if ( strncasecmp( s, "RESULT", STRLENOF( "RESULT" ) ) != 0 ) {
 
1428
                Debug( LDAP_DEBUG_ANY, "str2result (%s) expecting \"RESULT\"\n",
 
1429
                    s, 0, 0 );
 
1430
 
 
1431
                return( -1 );
 
1432
        }
 
1433
 
 
1434
        rc = 0;
 
1435
        while ( (s = strchr( s, '\n' )) != NULL ) {
 
1436
                *s++ = '\0';
 
1437
                if ( *s == '\0' ) {
 
1438
                        break;
 
1439
                }
 
1440
                if ( (c = strchr( s, ':' )) != NULL ) {
 
1441
                        c++;
 
1442
                }
 
1443
 
 
1444
                if ( strncasecmp( s, "code", STRLENOF( "code" ) ) == 0 ) {
 
1445
                        char    *next = NULL;
 
1446
                        long    retcode;
 
1447
 
 
1448
                        if ( c == NULL ) {
 
1449
                                Debug( LDAP_DEBUG_ANY, "str2result (%s) missing value\n",
 
1450
                                    s, 0, 0 );
 
1451
                                rc = -1;
 
1452
                                continue;
 
1453
                        }
 
1454
 
 
1455
                        while ( isspace( (unsigned char) c[ 0 ] ) ) c++;
 
1456
                        if ( c[ 0 ] == '\0' ) {
 
1457
                                Debug( LDAP_DEBUG_ANY, "str2result (%s) missing or empty value\n",
 
1458
                                    s, 0, 0 );
 
1459
                                rc = -1;
 
1460
                                continue;
 
1461
                        }
 
1462
 
 
1463
                        retcode = strtol( c, &next, 10 );
 
1464
                        if ( next == NULL || next == c ) {
 
1465
                                Debug( LDAP_DEBUG_ANY, "str2result (%s) unable to parse value\n",
 
1466
                                    s, 0, 0 );
 
1467
                                rc = -1;
 
1468
                                continue;
 
1469
                        }
 
1470
 
 
1471
                        while ( isspace( (unsigned char) next[ 0 ] ) ) next++;
 
1472
                        if ( next[ 0 ] != '\0' ) {
 
1473
                                Debug( LDAP_DEBUG_ANY, "str2result (%s) extra cruft after value\n",
 
1474
                                    s, 0, 0 );
 
1475
                                rc = -1;
 
1476
                                continue;
 
1477
                        }
 
1478
 
 
1479
                        /* FIXME: what if it's larger that max int? */
 
1480
                        *code = (int)retcode;
 
1481
 
 
1482
                } else if ( strncasecmp( s, "matched", STRLENOF( "matched" ) ) == 0 ) {
 
1483
                        if ( c != NULL ) {
 
1484
                                *matched = c;
 
1485
                        }
 
1486
                } else if ( strncasecmp( s, "info", STRLENOF( "info" ) ) == 0 ) {
 
1487
                        if ( c != NULL ) {
 
1488
                                *info = c;
 
1489
                        }
 
1490
                } else {
 
1491
                        Debug( LDAP_DEBUG_ANY, "str2result (%s) unknown\n",
 
1492
                            s, 0, 0 );
 
1493
 
 
1494
                        rc = -1;
 
1495
                }
 
1496
        }
 
1497
 
 
1498
        return( rc );
 
1499
}
 
1500
 
 
1501
int slap_read_controls(
 
1502
        Operation *op,
 
1503
        SlapReply *rs,
 
1504
        Entry *e,
 
1505
        const struct berval *oid,
 
1506
        LDAPControl **ctrl )
 
1507
{
 
1508
        int rc;
 
1509
        struct berval bv;
 
1510
        BerElementBuffer berbuf;
 
1511
        BerElement *ber = (BerElement *) &berbuf;
 
1512
        LDAPControl c;
 
1513
        Operation myop;
 
1514
 
 
1515
        Debug( LDAP_DEBUG_ANY, "slap_read_controls: (%s) %s\n",
 
1516
                oid->bv_val, e->e_dn, 0 );
 
1517
 
 
1518
        rs->sr_entry = e;
 
1519
        rs->sr_attrs = ( oid == &slap_pre_read_bv ) ?
 
1520
                op->o_preread_attrs : op->o_postread_attrs; 
 
1521
 
 
1522
        bv.bv_len = entry_flatsize( rs->sr_entry, 0 );
 
1523
        bv.bv_val = op->o_tmpalloc( bv.bv_len, op->o_tmpmemctx );
 
1524
 
 
1525
        ber_init2( ber, &bv, LBER_USE_DER );
 
1526
        ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
 
1527
 
 
1528
        /* create new operation */
 
1529
        myop = *op;
 
1530
        /* FIXME: o_bd needed for ACL */
 
1531
        myop.o_bd = op->o_bd;
 
1532
        myop.o_res_ber = ber;
 
1533
        myop.o_callback = NULL;
 
1534
        myop.ors_slimit = 1;
 
1535
 
 
1536
        rc = slap_send_search_entry( &myop, rs );
 
1537
        if( rc ) return rc;
 
1538
 
 
1539
        rc = ber_flatten2( ber, &c.ldctl_value, 0 );
 
1540
 
 
1541
        if( rc == LBER_ERROR ) return LDAP_OTHER;
 
1542
 
 
1543
        c.ldctl_oid = oid->bv_val;
 
1544
        c.ldctl_iscritical = 0;
 
1545
 
 
1546
        if ( *ctrl == NULL ) {
 
1547
                /* first try */
 
1548
                *ctrl = (LDAPControl *) slap_sl_calloc( 1, sizeof(LDAPControl), NULL );
 
1549
        } else {
 
1550
                /* retry: free previous try */
 
1551
                slap_sl_free( (*ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
 
1552
        }
 
1553
 
 
1554
        **ctrl = c;
 
1555
        return LDAP_SUCCESS;
 
1556
}
 
1557
 
 
1558
/* Map API errors to protocol errors... */
 
1559
int
 
1560
slap_map_api2result( SlapReply *rs )
 
1561
{
 
1562
        switch(rs->sr_err) {
 
1563
        case LDAP_SERVER_DOWN:
 
1564
                return LDAP_UNAVAILABLE;
 
1565
        case LDAP_LOCAL_ERROR:
 
1566
                return LDAP_OTHER;
 
1567
        case LDAP_ENCODING_ERROR:
 
1568
        case LDAP_DECODING_ERROR:
 
1569
                return LDAP_PROTOCOL_ERROR;
 
1570
        case LDAP_TIMEOUT:
 
1571
                return LDAP_UNAVAILABLE;
 
1572
        case LDAP_AUTH_UNKNOWN:
 
1573
                return LDAP_AUTH_METHOD_NOT_SUPPORTED;
 
1574
        case LDAP_FILTER_ERROR:
 
1575
                rs->sr_text = "Filter error";
 
1576
                return LDAP_OTHER;
 
1577
        case LDAP_USER_CANCELLED:
 
1578
                rs->sr_text = "User cancelled";
 
1579
                return LDAP_OTHER;
 
1580
        case LDAP_PARAM_ERROR:
 
1581
                return LDAP_PROTOCOL_ERROR;
 
1582
        case LDAP_NO_MEMORY:
 
1583
                return LDAP_OTHER;
 
1584
        case LDAP_CONNECT_ERROR:
 
1585
                return LDAP_UNAVAILABLE;
 
1586
        case LDAP_NOT_SUPPORTED:
 
1587
                return LDAP_UNWILLING_TO_PERFORM;
 
1588
        case LDAP_CONTROL_NOT_FOUND:
 
1589
                return LDAP_PROTOCOL_ERROR;
 
1590
        case LDAP_NO_RESULTS_RETURNED:
 
1591
                return LDAP_NO_SUCH_OBJECT;
 
1592
        case LDAP_MORE_RESULTS_TO_RETURN:
 
1593
                rs->sr_text = "More results to return";
 
1594
                return LDAP_OTHER;
 
1595
        case LDAP_CLIENT_LOOP:
 
1596
        case LDAP_REFERRAL_LIMIT_EXCEEDED:
 
1597
                return LDAP_LOOP_DETECT;
 
1598
        default:
 
1599
                if ( LDAP_API_ERROR(rs->sr_err) ) return LDAP_OTHER;
 
1600
                return rs->sr_err;
 
1601
        }
 
1602
}
 
1603
 
 
1604
 
 
1605
slap_mask_t
 
1606
slap_attr_flags( AttributeName *an )
 
1607
{
 
1608
        slap_mask_t     flags = SLAP_ATTRS_UNDEFINED;
 
1609
 
 
1610
        if ( an == NULL ) {
 
1611
                flags |= ( SLAP_OPATTRS_NO | SLAP_USERATTRS_YES );
 
1612
 
 
1613
        } else {
 
1614
                flags |= an_find( an, &AllOper )
 
1615
                        ? SLAP_OPATTRS_YES : SLAP_OPATTRS_NO;
 
1616
                flags |= an_find( an, &AllUser )
 
1617
                        ? SLAP_USERATTRS_YES : SLAP_USERATTRS_NO;
 
1618
        }
 
1619
 
 
1620
        return flags;
 
1621
}
 
1622