c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen#ifndef DB_LDAP_H
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen#define DB_LDAP_H
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
cfdaa223525f87c9c980a25cc7bb6770a248d76aTimo Sirainen/* Functions like ldap_bind() have been deprecated in OpenLDAP 2.3
cfdaa223525f87c9c980a25cc7bb6770a248d76aTimo Sirainen This define enables them until the code here can be refactored */
cfdaa223525f87c9c980a25cc7bb6770a248d76aTimo Sirainen#define LDAP_DEPRECATED 1
cfdaa223525f87c9c980a25cc7bb6770a248d76aTimo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen/* Maximum number of pending requests before delaying new requests. */
4f7c150ea0fb986d229379cda622cdcb2d827fd2Timo Sirainen#define DB_LDAP_MAX_PENDING_REQUESTS 8
fb3178a1924dae52151d88c4d4ded879df43dd3fTimo Sirainen/* connect() timeout to LDAP */
fb3178a1924dae52151d88c4d4ded879df43dd3fTimo Sirainen#define DB_LDAP_CONNECT_TIMEOUT_SECS 5
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen/* If LDAP connection is down, fail requests after waiting for this long. */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen#define DB_LDAP_REQUEST_DISCONNECT_TIMEOUT_SECS 4
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen/* If request is still in queue after this many seconds and other requests
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen have been replied, assume the request was lost and abort it. */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen#define DB_LDAP_REQUEST_LOST_TIMEOUT_SECS 60
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen/* If server disconnects us, don't reconnect if no requests have been sent
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen for this many seconds. */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen#define DB_LDAP_IDLE_RECONNECT_SECS 60
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen#include <ldap.h>
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainenstruct auth_request;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainenstruct ldap_connection;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainenstruct ldap_request;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainentypedef void db_search_callback_t(struct ldap_connection *conn,
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen struct ldap_request *request,
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen LDAPMessage *res);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainenstruct ldap_settings {
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen const char *hosts;
e65cc79f80577e83c706f0678c78e2c0bd91434fTimo Sirainen const char *uris;
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainen const char *dn;
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainen const char *dnpass;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen bool auth_bind;
f1ddb98e6b639394ae205b305be1ddcfab102578Timo Sirainen const char *auth_bind_userdn;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen bool tls;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen bool sasl_bind;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen const char *sasl_mech;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen const char *sasl_realm;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen const char *sasl_authz_id;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen const char *tls_ca_cert_file;
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen const char *tls_ca_cert_dir;
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen const char *tls_cert_file;
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen const char *tls_key_file;
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen const char *tls_cipher_suite;
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen const char *tls_require_cert;
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen const char *deref;
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen const char *scope;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen const char *base;
b567e0172c73dcf7642462e86962060358dd5f28Timo Sirainen unsigned int ldap_version;
b567e0172c73dcf7642462e86962060358dd5f28Timo Sirainen
f8464772990b52cb8de4553bc1135adcf72813b8Timo Sirainen const char *ldaprc_path;
f4a19b0cf11cdff437571708d9d788d02a906a00Timo Sirainen const char *debug_level;
f4a19b0cf11cdff437571708d9d788d02a906a00Timo Sirainen
10c5fd417af4ee30b68c967f5e7d5a49f4f149b5Timo Sirainen const char *user_attrs;
10c5fd417af4ee30b68c967f5e7d5a49f4f149b5Timo Sirainen const char *user_filter;
10c5fd417af4ee30b68c967f5e7d5a49f4f149b5Timo Sirainen const char *pass_attrs;
10c5fd417af4ee30b68c967f5e7d5a49f4f149b5Timo Sirainen const char *pass_filter;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen const char *iterate_attrs;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen const char *iterate_filter;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen const char *default_pass_scheme;
bf6c5e9028e7d8f31e92e5037b63c72a93ce3c5bTimo Sirainen bool userdb_warning_disable; /* deprecated for now at least */
e153e1205bc686fac815ce7bb534adcb36dfb722Timo Sirainen bool blocking;
1f18053d463f0294387b5e4dd11f9010bda9a24eTimo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen /* ... */
6332ef7522d7a77a18c1bec4fc80d92ee597336cTimo Sirainen int ldap_deref, ldap_scope, ldap_tls_require_cert_parsed;
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen uid_t uid;
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen gid_t gid;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen};
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenenum ldap_request_type {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen LDAP_REQUEST_TYPE_SEARCH,
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen LDAP_REQUEST_TYPE_BIND
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen};
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
3fb1531681f9cbe49928f8e32357a692bf901c83Timo Sirainenstruct ldap_field {
3fb1531681f9cbe49928f8e32357a692bf901c83Timo Sirainen /* Dovecot field name. */
3fb1531681f9cbe49928f8e32357a692bf901c83Timo Sirainen const char *name;
3fb1531681f9cbe49928f8e32357a692bf901c83Timo Sirainen /* Field value template with %vars. NULL = same as LDAP value. */
3fb1531681f9cbe49928f8e32357a692bf901c83Timo Sirainen const char *value;
3fb1531681f9cbe49928f8e32357a692bf901c83Timo Sirainen /* LDAP attribute name, or "" if this is a static field. */
3fb1531681f9cbe49928f8e32357a692bf901c83Timo Sirainen const char *ldap_attr_name;
3fb1531681f9cbe49928f8e32357a692bf901c83Timo Sirainen
3fb1531681f9cbe49928f8e32357a692bf901c83Timo Sirainen /* LDAP value contains a DN, which is looked up and used for @name
3fb1531681f9cbe49928f8e32357a692bf901c83Timo Sirainen attributes. */
3fb1531681f9cbe49928f8e32357a692bf901c83Timo Sirainen bool value_is_dn;
626a206050bbe60b1f758c8918d09dad8accf225Timo Sirainen /* This attribute is used internally only via %{ldap_ptr},
626a206050bbe60b1f758c8918d09dad8accf225Timo Sirainen it shouldn't be returned in iteration. */
626a206050bbe60b1f758c8918d09dad8accf225Timo Sirainen bool skip;
3fb1531681f9cbe49928f8e32357a692bf901c83Timo Sirainen};
3fb1531681f9cbe49928f8e32357a692bf901c83Timo SirainenARRAY_DEFINE_TYPE(ldap_field, struct ldap_field);
3fb1531681f9cbe49928f8e32357a692bf901c83Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstruct ldap_request {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen enum ldap_request_type type;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* msgid for sent requests, -1 if not sent */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen int msgid;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* timestamp when request was created */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen time_t create_time;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
53e4a0d5cb048ea2bdf598ca56120b626b8615f5Martti Rannanjärvi bool failed:1;
53e4a0d5cb048ea2bdf598ca56120b626b8615f5Martti Rannanjärvi /* This is to prevent double logging the result */
53e4a0d5cb048ea2bdf598ca56120b626b8615f5Martti Rannanjärvi bool result_logged:1;
5acace56d99e0bef77b35e9b55113afde837680aTimo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen db_search_callback_t *callback;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct auth_request *auth_request;
3fb1531681f9cbe49928f8e32357a692bf901c83Timo Sirainen};
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
3fb1531681f9cbe49928f8e32357a692bf901c83Timo Sirainenstruct ldap_request_named_result {
3fb1531681f9cbe49928f8e32357a692bf901c83Timo Sirainen const struct ldap_field *field;
3fb1531681f9cbe49928f8e32357a692bf901c83Timo Sirainen const char *dn;
14b495a09db7aea6b68146fd6427229e75d2bb39Timo Sirainen struct db_ldap_result *result;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen};
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstruct ldap_request_search {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct ldap_request request;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen const char *base;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen const char *filter;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen char **attributes; /* points to pass_attr_names / user_attr_names */
3fb1531681f9cbe49928f8e32357a692bf901c83Timo Sirainen const ARRAY_TYPE(ldap_field) *attr_map;
3fb1531681f9cbe49928f8e32357a692bf901c83Timo Sirainen
14b495a09db7aea6b68146fd6427229e75d2bb39Timo Sirainen struct db_ldap_result *result;
3fb1531681f9cbe49928f8e32357a692bf901c83Timo Sirainen ARRAY(struct ldap_request_named_result) named_results;
3fb1531681f9cbe49928f8e32357a692bf901c83Timo Sirainen unsigned int name_idx;
f2f40b6ca4ce986d80ae0fe59efb542b3b837bfaTimo Sirainen
f2f40b6ca4ce986d80ae0fe59efb542b3b837bfaTimo Sirainen bool multi_entry;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen};
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstruct ldap_request_bind {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct ldap_request request;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen const char *dn;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen};
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenenum ldap_connection_state {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* Not connected */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen LDAP_CONN_STATE_DISCONNECTED,
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* Binding - either to default dn or doing auth bind */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen LDAP_CONN_STATE_BINDING,
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* Bound to auth dn */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen LDAP_CONN_STATE_BOUND_AUTH,
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* Bound to default dn */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen LDAP_CONN_STATE_BOUND_DEFAULT
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen};
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainenstruct ldap_connection {
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen struct ldap_connection *next;
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen pool_t pool;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen int refcount;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen char *config_path;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen struct ldap_settings set;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen LDAP *ld;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen enum ldap_connection_state conn_state;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen int default_bind_msgid;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen int fd;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen struct io *io;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct timeout *to;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* Request queue contains sent requests at tail (msgid != -1) and
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen queued requests at head (msgid == -1). */
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen struct aqueue *request_queue;
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen ARRAY(struct ldap_request *) request_array;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* Number of messages in queue with msgid != -1 */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen unsigned int pending_count;
e023e3c2677ab66d7a7445eae9caf3d739e199cbTimo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* Timestamp when we last received a reply */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen time_t last_reply_stamp;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen char **pass_attr_names, **user_attr_names, **iterate_attr_names;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen ARRAY_TYPE(ldap_field) pass_attr_map, user_attr_map, iterate_attr_map;
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen bool userdb_used;
e3c410263ee86079b575cb5084e773b2601ae576Timo Sirainen bool delayed_connect;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen};
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen/* Send/queue request */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenvoid db_ldap_request(struct ldap_connection *conn,
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct ldap_request *request);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainenvoid db_ldap_set_attrs(struct ldap_connection *conn, const char *attrlist,
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen char ***attr_names_r, ARRAY_TYPE(ldap_field) *attr_map,
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen const char *skip_attr) ATTR_NULL(5);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainenstruct ldap_connection *db_ldap_init(const char *config_path, bool userdb);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenvoid db_ldap_unref(struct ldap_connection **conn);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainenint db_ldap_connect(struct ldap_connection *conn);
99363aeac519d37553b7776b322e60b8a23cd2b9Timo Sirainenvoid db_ldap_connect_delayed(struct ldap_connection *conn);
08aea01ef9a9d20703e0fcf8618e6195c0037a44Timo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenvoid db_ldap_enable_input(struct ldap_connection *conn, bool enable);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainenconst char *ldap_escape(const char *str,
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen const struct auth_request *auth_request);
ebfcfd258acc89633c47d9c3b0b40a1a3f75cdcbTimo Sirainenconst char *ldap_get_error(struct ldap_connection *conn);
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainenstruct db_ldap_result_iterate_context *
3fb1531681f9cbe49928f8e32357a692bf901c83Timo Sirainendb_ldap_result_iterate_init(struct ldap_connection *conn,
b6df44e31bf9d54669b5903dfb5dd3fbbe896accTimo Sirainen struct ldap_request_search *ldap_request,
190ba2ebc899bd114e1e4ab9ee119be10f0cc0ecTimo Sirainen LDAPMessage *res, bool skip_null_values);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainenbool db_ldap_result_iterate_next(struct db_ldap_result_iterate_context *ctx,
3dadeec1ce7a5bf72fbd850658df1db3cedd4416Timo Sirainen const char **name_r,
3dadeec1ce7a5bf72fbd850658df1db3cedd4416Timo Sirainen const char *const **values_r);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainenvoid db_ldap_result_iterate_deinit(struct db_ldap_result_iterate_context **ctx);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen#endif