db-ldap.h revision 3fb1531681f9cbe49928f8e32357a692bf901c83
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen#ifndef DB_LDAP_H
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#define DB_LDAP_H
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen/* Functions like ldap_bind() have been deprecated in OpenLDAP 2.3
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen This define enables them until the code here can be refactored */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#define LDAP_DEPRECATED 1
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen/* Maximum number of pending requests before delaying new requests. */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#define DB_LDAP_MAX_PENDING_REQUESTS 8
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen/* If LDAP connection is down, fail requests after waiting for this long. */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#define DB_LDAP_REQUEST_DISCONNECT_TIMEOUT_SECS 4
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen/* If request is still in queue after this many seconds and other requests
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen have been replied, assume the request was lost and abort it. */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen#define DB_LDAP_REQUEST_LOST_TIMEOUT_SECS 60
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen/* If server disconnects us, don't reconnect if no requests have been sent
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen for this many seconds. */
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen#define DB_LDAP_IDLE_RECONNECT_SECS 60
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen#include <ldap.h>
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainenstruct auth_request;
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainenstruct ldap_connection;
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainenstruct ldap_request;
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainentypedef void db_search_callback_t(struct ldap_connection *conn,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct ldap_request *request,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen LDAPMessage *res);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstruct ldap_settings {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char *hosts;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char *uris;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char *dn;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char *dnpass;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen bool auth_bind;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char *auth_bind_userdn;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen bool tls;
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen bool sasl_bind;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen const char *sasl_mech;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen const char *sasl_realm;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen const char *sasl_authz_id;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen const char *tls_ca_cert_file;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen const char *tls_ca_cert_dir;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen const char *tls_cert_file;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen const char *tls_key_file;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen const char *tls_cipher_suite;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen const char *tls_require_cert;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen const char *deref;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen const char *scope;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen const char *base;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen unsigned int ldap_version;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen const char *ldaprc_path;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen const char *debug_level;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen const char *user_attrs;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen const char *user_filter;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen const char *pass_attrs;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen const char *pass_filter;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen const char *iterate_attrs;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen const char *iterate_filter;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen const char *default_pass_scheme;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen bool userdb_warning_disable; /* deprecated for now at least */
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* ... */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen int ldap_deref, ldap_scope;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen uid_t uid;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen gid_t gid;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen};
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainenenum ldap_request_type {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen LDAP_REQUEST_TYPE_SEARCH,
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen LDAP_REQUEST_TYPE_BIND
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen};
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen
3c493c276f599d9b9cd10764876d648003046954Timo Sirainenstruct ldap_field {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen /* Dovecot field name. */
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen const char *name;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen /* Field value template with %vars. NULL = same as LDAP value. */
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen const char *value;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen /* LDAP attribute name, or "" if this is a static field. */
b42697a5749b85659a24316d97f1c208d469e4e8Timo Sirainen const char *ldap_attr_name;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen /* LDAP value contains a DN, which is looked up and used for @name
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen attributes. */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen bool value_is_dn;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen};
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo SirainenARRAY_DEFINE_TYPE(ldap_field, struct ldap_field);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstruct ldap_request {
d22301419109ed4a38351715e6760011421dadecTimo Sirainen enum ldap_request_type type;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* msgid for sent requests, -1 if not sent */
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen int msgid;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen /* timestamp when request was created */
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen time_t create_time;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen db_search_callback_t *callback;
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen struct auth_request *auth_request;
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen};
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen
3c493c276f599d9b9cd10764876d648003046954Timo Sirainenstruct ldap_request_named_result {
9ffdc9d18870acef2e4dde99715d8528ff4b080dTimo Sirainen const struct ldap_field *field;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen const char *dn;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen LDAPMessage *result;
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen};
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstruct ldap_request_search {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen struct ldap_request request;
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen const char *base;
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen const char *filter;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen char **attributes; /* points to pass_attr_names / user_attr_names */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen const ARRAY_TYPE(ldap_field) *attr_map;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen LDAPMessage *result;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen ARRAY(struct ldap_request_named_result) named_results;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen unsigned int name_idx;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen};
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstruct ldap_request_bind {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct ldap_request request;
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen const char *dn;
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen};
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
1108376e39a19912e8394e64e19b1bc6f6691cf6Timo Sirainenenum ldap_connection_state {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen /* Not connected */
3e564425db51f3921ce4de11859777135fdedd15Timo Sirainen LDAP_CONN_STATE_DISCONNECTED,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* Binding - either to default dn or doing auth bind */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen LDAP_CONN_STATE_BINDING,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* Bound to auth dn */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen LDAP_CONN_STATE_BOUND_AUTH,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen /* Bound to default dn */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen LDAP_CONN_STATE_BOUND_DEFAULT
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen};
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainenstruct ldap_connection {
09c08fad8e7cc694a6c8d1711e67839acd3a2f04Timo Sirainen struct ldap_connection *next;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen
9ffdc9d18870acef2e4dde99715d8528ff4b080dTimo Sirainen pool_t pool;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen int refcount;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen char *config_path;
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen struct ldap_settings set;
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen
fbd918f47f591f8084fd52b207ef29515ddd11b9Timo Sirainen LDAP *ld;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen enum ldap_connection_state conn_state;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen int default_bind_msgid;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen int fd;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen struct io *io;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen struct timeout *to;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* Request queue contains sent requests at tail (msgid != -1) and
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen queued requests at head (msgid == -1). */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen struct aqueue *request_queue;
14ab4610b6038da6c5d0814fecabc6b74bc81a6bTimo Sirainen ARRAY(struct ldap_request *) request_array;
84ed9f8f3d0e5ed47607ef417618e49e4f865557Timo Sirainen /* Number of messages in queue with msgid != -1 */
84ed9f8f3d0e5ed47607ef417618e49e4f865557Timo Sirainen unsigned int pending_count;
e3796bfd2bc0fd5ba664893d346df9334a5b3af0Timo Sirainen
5afa8e2edf4f313cd56e5909f92f39c3b5b7b4d3Timo Sirainen /* Timestamp when we last received a reply */
408e5be344c9131fdebe771718a5bf49f88cc51cTimo Sirainen time_t last_reply_stamp;
370b60cfccff7c50586fc30f4f591499a55301a8Timo Sirainen
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen char **pass_attr_names, **user_attr_names, **iterate_attr_names;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen ARRAY_TYPE(ldap_field) pass_attr_map, user_attr_map, iterate_attr_map;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen bool userdb_used;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen};
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
de58be41126e5d68008d2ea706d62ccdc1f29337Timo Sirainen/* Send/queue request */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenvoid db_ldap_request(struct ldap_connection *conn,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen struct ldap_request *request);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenvoid db_ldap_set_attrs(struct ldap_connection *conn, const char *attrlist,
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen char ***attr_names_r, ARRAY_TYPE(ldap_field) *attr_map,
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen const char *skip_attr) ATTR_NULL(5);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstruct ldap_connection *db_ldap_init(const char *config_path, bool userdb);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenvoid db_ldap_unref(struct ldap_connection **conn);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenint db_ldap_connect(struct ldap_connection *conn);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenvoid db_ldap_enable_input(struct ldap_connection *conn, bool enable);
const char *ldap_escape(const char *str,
const struct auth_request *auth_request);
const char *ldap_get_error(struct ldap_connection *conn);
struct db_ldap_result_iterate_context *
db_ldap_result_iterate_init(struct ldap_connection *conn,
struct ldap_request_search *ldap_request);
bool db_ldap_result_iterate_next(struct db_ldap_result_iterate_context *ctx,
const char **name_r,
const char *const **values_r);
void db_ldap_result_iterate_deinit(struct db_ldap_result_iterate_context **ctx);
#endif