slap.h 13.7 KB
Newer Older
Ondřej Kuzník's avatar
Ondřej Kuzník committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/* slap.h - stand alone ldap server include file */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 *
 * Copyright 1998-2015 The OpenLDAP Foundation.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in the file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
 */
/* Portions Copyright (c) 1995 Regents of the University of Michigan.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that this notice is preserved and that due credit is given
 * to the University of Michigan at Ann Arbor. The name of the University
 * may not be used to endorse or promote products derived from this
 * software without specific prior written permission. This software
 * is provided ``as is'' without express or implied warranty.
 */

#ifndef _SLAP_H_
#define _SLAP_H_

#include "ldap_defaults.h"

#include <stdio.h>
#include <ac/stdlib.h>

#include <sys/types.h>
#include <ac/syslog.h>
#include <ac/regex.h>
#include <ac/signal.h>
#include <ac/socket.h>
#include <ac/time.h>
#include <ac/param.h>

#include "avl.h"

#ifndef ldap_debug
#define ldap_debug slap_debug
#endif

#include "ldap_log.h"

#include <ldap.h>
#include <ldap_schema.h>

#include "lber_pvt.h"
#include "ldap_pvt.h"
#include "ldap_pvt_thread.h"
#include "ldap_queue.h"

#include <event2/event.h>

LDAP_BEGIN_DECL

/*
 * SLAPD Memory allocation macros
 *
 * Unlike ch_*() routines, these routines do not assert() upon
 * allocation error.  They are intended to be used instead of
 * ch_*() routines where the caller has implemented proper
 * checking for and handling of allocation errors.
 *
 * Patches to convert ch_*() calls to SLAP_*() calls welcomed.
 */
#define SLAP_MALLOC(s) ber_memalloc( ( s ) )
#define SLAP_CALLOC(n, s) ber_memcalloc( ( n ), ( s ) )
#define SLAP_REALLOC(p, s) ber_memrealloc( ( p ), ( s ) )
#define SLAP_FREE(p) ber_memfree( ( p ) )
#define SLAP_VFREE(v) ber_memvfree( (void **)( v ) )
#define SLAP_STRDUP(s) ber_strdup( ( s ) )
#define SLAP_STRNDUP(s, l) ber_strndup( ( s ), ( l ) )

#define SERVICE_NAME OPENLDAP_PACKAGE "-slapd"
#define SLAPD_ANONYMOUS ""
#define SLAP_STRING_UNKNOWN "unknown"

#define SLAP_MAX_WORKER_THREADS ( 16 )

#define SLAP_SB_MAX_INCOMING_DEFAULT ( ( 1 << 18 ) - 1 )
#define SLAP_SB_MAX_INCOMING_AUTH ( ( 1 << 24 ) - 1 )

Ondřej Kuzník's avatar
Ondřej Kuzník committed
90
91
#define SLAP_CONN_MAX_PDUS_PER_CYCLE_DEFAULT 10

Ondřej Kuzník's avatar
Ondřej Kuzník committed
92
93
94
95
96
#define SLAP_TEXT_BUFLEN ( 256 )

/* unknown config file directive */
#define SLAP_CONF_UNKNOWN ( -1026 )

97
98
#define BER_BV_OPTIONAL( bv ) ( BER_BVISNULL( bv ) ? NULL : ( bv ) )

Ondřej Kuzník's avatar
Ondřej Kuzník committed
99
100
101
102
LDAP_SLAPD_V (int) slap_debug;

typedef unsigned long slap_mask_t;

Ondřej Kuzník's avatar
Ondřej Kuzník committed
103
typedef struct Backend Backend;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
104
typedef struct Connection Connection;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
105
typedef struct Operation Operation;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/* end of forward declarations */

typedef union Sockaddr {
    struct sockaddr sa_addr;
    struct sockaddr_in sa_in_addr;
#ifdef LDAP_PF_INET6
    struct sockaddr_storage sa_storage;
    struct sockaddr_in6 sa_in6_addr;
#endif
#ifdef LDAP_PF_LOCAL
    struct sockaddr_un sa_un_addr;
#endif
} Sockaddr;

#ifdef LDAP_PF_INET6
extern int slap_inet4or6;
#endif

124
typedef LDAP_CIRCLEQ_HEAD(BeSt, Backend) slap_b_head;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
125
126

LDAP_SLAPD_V (slap_b_head) backend;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
127
128
LDAP_SLAPD_V (ldap_pvt_thread_mutex_t) backend_mutex;
LDAP_SLAPD_V (Backend *) current_backend;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
129

Ondřej Kuzník's avatar
Ondřej Kuzník committed
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
LDAP_SLAPD_V (int) slapMode;
#define SLAP_UNDEFINED_MODE 0x0000
#define SLAP_SERVER_MODE 0x0001
#define SLAP_TOOL_MODE 0x0002
#define SLAP_MODE 0x0003

#define SLAP_SERVER_RUNNING 0x8000

#define SB_TLS_DEFAULT ( -1 )
#define SB_TLS_OFF 0
#define SB_TLS_ON 1
#define SB_TLS_CRITICAL 2

typedef struct slap_keepalive {
    int sk_idle;
    int sk_probes;
    int sk_interval;
} slap_keepalive;

typedef struct slap_bindconf {
    struct berval sb_uri;
    int sb_version;
    int sb_tls;
    int sb_method;
    int sb_timeout_api;
    int sb_timeout_net;
    struct berval sb_binddn;
    struct berval sb_cred;
    struct berval sb_saslmech;
    char *sb_secprops;
    struct berval sb_realm;
    struct berval sb_authcId;
    struct berval sb_authzId;
    slap_keepalive sb_keepalive;
#ifdef HAVE_TLS
    void *sb_tls_ctx;
    char *sb_tls_cert;
    char *sb_tls_key;
    char *sb_tls_cacert;
    char *sb_tls_cacertdir;
    char *sb_tls_reqcert;
    char *sb_tls_reqsan;
    char *sb_tls_cipher_suite;
    char *sb_tls_protocol_min;
    char *sb_tls_ecname;
#ifdef HAVE_OPENSSL
    char *sb_tls_crlcheck;
#endif
    int sb_tls_int_reqcert;
    int sb_tls_int_reqsan;
    int sb_tls_do_init;
#endif
} slap_bindconf;

typedef struct slap_verbmasks {
    struct berval word;
    const slap_mask_t mask;
} slap_verbmasks;

typedef struct slap_cf_aux_table {
    struct berval key;
    int off;
    char type;
    char quote;
    void *aux;
} slap_cf_aux_table;

typedef int slap_cf_aux_table_parse_x( struct berval *val,
        void *bc,
        slap_cf_aux_table *tab0,
        const char *tabmsg,
        int unparse );

#define SLAP_RESTRICT_OP_ADD 0x0001U
#define SLAP_RESTRICT_OP_BIND 0x0002U
#define SLAP_RESTRICT_OP_COMPARE 0x0004U
#define SLAP_RESTRICT_OP_DELETE 0x0008U
#define SLAP_RESTRICT_OP_EXTENDED 0x0010U
#define SLAP_RESTRICT_OP_MODIFY 0x0020U
#define SLAP_RESTRICT_OP_RENAME 0x0040U
#define SLAP_RESTRICT_OP_SEARCH 0x0080U
#define SLAP_RESTRICT_OP_MASK 0x00FFU

#define SLAP_RESTRICT_READONLY 0x80000000U

#define SLAP_RESTRICT_EXOP_START_TLS 0x0100U
#define SLAP_RESTRICT_EXOP_MODIFY_PASSWD 0x0200U
#define SLAP_RESTRICT_EXOP_WHOAMI 0x0400U
#define SLAP_RESTRICT_EXOP_CANCEL 0x0800U
#define SLAP_RESTRICT_EXOP_MASK 0xFF00U

#define SLAP_RESTRICT_OP_READS \
    ( SLAP_RESTRICT_OP_COMPARE | SLAP_RESTRICT_OP_SEARCH )
#define SLAP_RESTRICT_OP_WRITES \
    ( SLAP_RESTRICT_OP_ADD | SLAP_RESTRICT_OP_DELETE | SLAP_RESTRICT_OP_MODIFY | SLAP_RESTRICT_OP_RENAME )
#define SLAP_RESTRICT_OP_ALL \
    ( SLAP_RESTRICT_OP_READS | SLAP_RESTRICT_OP_WRITES | SLAP_RESTRICT_OP_BIND | SLAP_RESTRICT_OP_EXTENDED )

typedef struct config_reply_s ConfigReply; /* config.h */

typedef struct Listener Listener;

Ondřej Kuzník's avatar
Ondřej Kuzník committed
232
233
234
235
236
typedef enum {
    LLOAD_FEATURE_VC = 1 << 0,
    LLOAD_FEATURE_PROXYAUTHZ = 1 << 1,
} lload_features_t;

Ondřej Kuzník's avatar
Ondřej Kuzník committed
237
238
239
240
241
242
enum lload_tls_type {
    LLOAD_CLEARTEXT = 0,
    LLOAD_LDAPS,
    LLOAD_STARTTLS,
};

Ondřej Kuzník's avatar
Ondřej Kuzník committed
243
/* Can hold mutex when locking a linked connection */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
244
245
struct Backend {
    struct slap_bindconf b_bindconf;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
246
    ldap_pvt_thread_mutex_t b_mutex;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
247
248
249
250
251

    int b_proto, b_port;
    enum lload_tls_type b_tls;
    char *b_host;

252
253
254
255
    int b_retry_timeout, b_failed;
    struct event *b_retry_event;
    struct timeval b_retry_tv;

Ondřej Kuzník's avatar
Ondřej Kuzník committed
256
    int b_numconns, b_numbindconns;
257
    int b_bindavail, b_active, b_opening;
258
    LDAP_CIRCLEQ_HEAD(ConnSt, Connection) b_conns, b_bindconns;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
259

260
261
262
    long b_max_pending, b_max_conn_pending;
    long b_n_ops_executing;

263
    LDAP_CIRCLEQ_ENTRY(Backend) b_next;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
264
265
};

Ondřej Kuzník's avatar
Ondřej Kuzník committed
266
267
typedef int (*OperationHandler)( Operation *op, BerElement *ber );

Ondřej Kuzník's avatar
Ondřej Kuzník committed
268
/* connection state (protected by c_mutex) */
269
enum sc_state {
Ondřej Kuzník's avatar
Ondřej Kuzník committed
270
    SLAP_C_INVALID = 0, /* MUST BE ZERO (0) */
271
    SLAP_C_READY,       /* ready */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
272
    SLAP_C_CLOSING,     /* closing */
273
    SLAP_C_ACTIVE,      /* exclusive operation (tls setup, ...) in progress */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
274
275
    SLAP_C_BINDING,     /* binding */
};
276
277
278
279
enum sc_type {
    SLAP_C_OPEN = 0, /* regular connection */
    SLAP_C_BIND, /* connection used to handle bind client requests if VC not enabled */
};
280
281
282
/*
 * represents a connection from an ldap client/to ldap server
 */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
283
struct Connection {
284
    enum sc_state c_state; /* connection state */
285
    enum sc_type c_type;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
286
    ber_socket_t c_fd;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
287

288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
/*
 * Connection reference counting:
 * - connection has a reference counter in c_refcnt
 * - also a liveness/validity token is added to c_refcnt during
 *   connection_init, its existence is tracked in c_live and is usually the
 *   only one that prevents it from being destroyed
 * - anyone who needs to be able to lock the connection after unlocking it has
 *   to use CONNECTION_UNLOCK_INCREF, they are then responsible that
 *   CONNECTION_LOCK_DECREF+CONNECTION_UNLOCK_OR_DESTROY is used when they are
 *   done with it
 * - when a connection is considered dead, use (UPSTREAM|CLIENT)_DESTROY on a
 *   locked connection, it might get disposed of or if anyone still holds a
 *   token, it just gets unlocked and it's the last token holder's
 *   responsibility to run *_UNLOCK_OR_DESTROY
 * - (UPSTREAM|CLIENT)_LOCK_DESTROY is a shorthand for locking, decreasing
 *   refcount and (UPSTREAM|CLIENT)_DESTROY
 */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
305
    ldap_pvt_thread_mutex_t c_mutex; /* protect the connection */
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
    int c_refcnt, c_live;
#define CONNECTION_LOCK(c) ldap_pvt_thread_mutex_lock( &(c)->c_mutex )
#define CONNECTION_UNLOCK(c) ldap_pvt_thread_mutex_unlock( &(c)->c_mutex )
#define CONNECTION_LOCK_DECREF(c) \
    do { \
        CONNECTION_LOCK(c); \
        (c)->c_refcnt--; \
    } while (0)
#define CONNECTION_UNLOCK_INCREF(c) \
    do { \
        (c)->c_refcnt++; \
        CONNECTION_UNLOCK(c); \
    } while (0)
#define CONNECTION_UNLOCK_OR_DESTROY(type, c) \
    do { \
        assert( (c)->c_refcnt >= 0 ); \
        if ( !( c )->c_refcnt ) { \
            Debug( LDAP_DEBUG_TRACE, "%s: destroying " #type " connection connid=%lu\n", \
                    __func__, (c)->c_connid ); \
            type##_destroy( (c) ); \
            (c) = NULL; \
        } else { \
            CONNECTION_UNLOCK(c); \
        } \
    } while (0)
#define CONNECTION_DESTROY(type, c) \
    do { \
        (c)->c_refcnt -= (c)->c_live; \
        (c)->c_live = 0; \
        CONNECTION_UNLOCK_OR_DESTROY(type, c); \
    } while (0)

#define UPSTREAM_UNLOCK_OR_DESTROY(c) \
    CONNECTION_UNLOCK_OR_DESTROY(upstream, c);
#define UPSTREAM_DESTROY(c) CONNECTION_DESTROY(upstream, c)
#define UPSTREAM_LOCK_DESTROY(c) \
    do { \
        CONNECTION_LOCK_DECREF(c); \
        UPSTREAM_DESTROY(c); \
    } while (0);

#define CLIENT_UNLOCK_OR_DESTROY(c) CONNECTION_UNLOCK_OR_DESTROY(client, c);
#define CLIENT_DESTROY(c) CONNECTION_DESTROY(client, c)
#define CLIENT_LOCK_DESTROY(c) \
    do { \
        CONNECTION_LOCK_DECREF(c); \
        CLIENT_DESTROY(c); \
    } while (0);

    Sockbuf *c_sb; /* ber connection stuff */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
356
357
358
359
360
361

    /* set by connection_init */
    unsigned long c_connid;    /* unique id of this connection */
    struct berval c_peer_name; /* peer name (trans=addr:port) */
    time_t c_starttime;        /* when the connection was opened */

Ondřej Kuzník's avatar
Ondřej Kuzník committed
362
363
    time_t c_activitytime;  /* when the connection was last used */
    ber_int_t c_next_msgid; /* msgid of the next message */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
364

365
    /* must not be used while holding either mutex */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
366
367
368
369
    struct event *c_read_event, *c_write_event;

    /* can only be changed by binding thread */
    struct berval c_sasl_bind_mech; /* mech in progress */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
370
371
    struct berval c_auth;           /* authcDN (possibly in progress) */

Ondřej Kuzník's avatar
Ondřej Kuzník committed
372
#ifdef LDAP_API_FEATURE_VERIFY_CREDENTIALS
Ondřej Kuzník's avatar
Ondřej Kuzník committed
373
    struct berval c_vc_cookie;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
374
#endif /* LDAP_API_FEATURE_VERIFY_CREDENTIALS */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
375

Ondřej Kuzník's avatar
Ondřej Kuzník committed
376
377
    /* Can be held while acquiring c_mutex to inject things into c_ops or
     * destroy the connection */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
378
379
    ldap_pvt_thread_mutex_t c_io_mutex; /* only one pdu written at a time */

Ondřej Kuzník's avatar
Ondřej Kuzník committed
380
381
    BerElement *c_currentber; /* ber we're attempting to read */
    BerElement *c_pendingber; /* ber we're attempting to write */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
382

Ondřej Kuzník's avatar
Ondřej Kuzník committed
383
384
    TAvlnode *c_ops; /* Operations pending on the connection */

Ondřej Kuzník's avatar
Ondřej Kuzník committed
385
#define CONN_IS_TLS 1
386
#define CONN_IS_BIND 4
Ondřej Kuzník's avatar
Ondřej Kuzník committed
387
388
389
#define CONN_IS_IPC 8

#ifdef HAVE_TLS
Ondřej Kuzník's avatar
Ondřej Kuzník committed
390
391
    enum lload_tls_type c_is_tls; /* true if this LDAP over raw TLS */
    char c_needs_tls_accept;      /* true if SSL_accept should be called */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
392
393
394
395
396
#endif

    long c_n_ops_executing; /* num of ops currently executing */
    long c_n_ops_completed; /* num of ops completed */

397
    /* Upstream: Protected by its backend's mutex */
398
    LDAP_CIRCLEQ_ENTRY( Connection ) c_next;
399

Ondřej Kuzník's avatar
Ondřej Kuzník committed
400
401
402
    void *c_private;
};

Ondřej Kuzník's avatar
Ondřej Kuzník committed
403
404
405
406
407
408
enum op_state {
    SLAP_OP_NOT_FREEING = 0,
    SLAP_OP_FREEING_UPSTREAM = 1 << 0,
    SLAP_OP_FREEING_CLIENT = 1 << 1,
};

Ondřej Kuzník's avatar
Ondřej Kuzník committed
409
struct Operation {
Ondřej Kuzník's avatar
Ondřej Kuzník committed
410
411
412
413
414
415
416
417
418
    Connection *o_client;
    unsigned long o_client_connid;
    int o_client_live, o_client_refcnt;
    ber_int_t o_client_msgid;

    Connection *o_upstream;
    unsigned long o_upstream_connid;
    int o_upstream_live, o_upstream_refcnt;
    ber_int_t o_upstream_msgid;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
419

Ondřej Kuzník's avatar
Ondřej Kuzník committed
420
    enum op_state o_freeing;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
421
422
423
424
425
426
    ber_tag_t o_tag;

    BerElement *o_ber;
    BerValue o_request, o_ctrls;
};

Ondřej Kuzník's avatar
Ondřej Kuzník committed
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
#ifdef LDAP_DEBUG
#ifdef LDAP_SYSLOG
#ifdef LOG_LOCAL4
#define SLAP_DEFAULT_SYSLOG_USER LOG_LOCAL4
#endif /* LOG_LOCAL4 */

#define Statslog( level, fmt, connid, opid, arg1, arg2, arg3 ) \
    Log( (level), ldap_syslog_level, (fmt), (connid), (opid), \
            ( arg1 ), ( arg2 ), ( arg3 ) )
#define StatslogTest( level ) ( ( ldap_debug | ldap_syslog ) & ( level ) )
#else /* !LDAP_SYSLOG */
#define Statslog( level, fmt, connid, opid, arg1, arg2, arg3 ) \
    do { \
        if ( ldap_debug & (level) ) \
            lutil_debug( ldap_debug, (level), (fmt), (connid), (opid), \
                    ( arg1 ), ( arg2 ), ( arg3 ) ); \
    } while (0)
#define StatslogTest( level ) ( ldap_debug & ( level ) )
#endif /* !LDAP_SYSLOG */
#else /* !LDAP_DEBUG */
#define Statslog( level, fmt, connid, opid, arg1, arg2, arg3 ) ( (void)0 )
#define StatslogTest( level ) ( 0 )
#endif /* !LDAP_DEBUG */

/*
 * listener; need to access it from monitor backend
 */
struct Listener {
    struct berval sl_url;
    struct berval sl_name;
    mode_t sl_perms;
#ifdef HAVE_TLS
    int sl_is_tls;
#endif
    struct event_base *base;
    struct evconnlistener *listener;
    int sl_mute; /* Listener is temporarily disabled due to emfile */
    int sl_busy; /* Listener is busy (accept thread activated) */
    ber_socket_t sl_sd;
    Sockaddr sl_sa;
#define sl_addr sl_sa.sa_in_addr
#define LDAP_TCP_BUFFER
#ifdef LDAP_TCP_BUFFER
    int sl_tcp_rmem; /* custom TCP read buffer size */
    int sl_tcp_wmem; /* custom TCP write buffer size */
#endif
};

LDAP_END_DECL

#include "proto-slap.h"

#endif /* _SLAP_H_ */