db-ldap.h revision 53e4a0d5cb048ea2bdf598ca56120b626b8615f5
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen#ifndef DB_LDAP_H
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen#define DB_LDAP_H
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen/* Functions like ldap_bind() have been deprecated in OpenLDAP 2.3
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen This define enables them until the code here can be refactored */
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen#define LDAP_DEPRECATED 1
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen/* Maximum number of pending requests before delaying new requests. */
96e1ed172ae59cae6bc6e6ddd24d22a158e23dfeTimo Sirainen#define DB_LDAP_MAX_PENDING_REQUESTS 8
96e1ed172ae59cae6bc6e6ddd24d22a158e23dfeTimo Sirainen/* connect() timeout to LDAP */
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen#define DB_LDAP_CONNECT_TIMEOUT_SECS 5
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen/* If LDAP connection is down, fail requests after waiting for this long. */
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen#define DB_LDAP_REQUEST_DISCONNECT_TIMEOUT_SECS 4
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen/* If request is still in queue after this many seconds and other requests
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen have been replied, assume the request was lost and abort it. */
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen#define DB_LDAP_REQUEST_LOST_TIMEOUT_SECS 60
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen/* If server disconnects us, don't reconnect if no requests have been sent
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen for this many seconds. */
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen#define DB_LDAP_IDLE_RECONNECT_SECS 60
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen#include <ldap.h>
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainenstruct auth_request;
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainenstruct ldap_connection;
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainenstruct ldap_request;
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainentypedef void db_search_callback_t(struct ldap_connection *conn,
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen struct ldap_request *request,
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen LDAPMessage *res);
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainenstruct ldap_settings {
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen const char *hosts;
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen const char *uris;
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen const char *dn;
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen const char *dnpass;
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen bool auth_bind;
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen const char *auth_bind_userdn;
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen bool tls;
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen bool sasl_bind;
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen const char *sasl_mech;
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen const char *sasl_realm;
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen const char *sasl_authz_id;
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen const char *tls_ca_cert_file;
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen const char *tls_ca_cert_dir;
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen const char *tls_cert_file;
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen const char *tls_key_file;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen const char *tls_cipher_suite;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen const char *tls_require_cert;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen const char *deref;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen const char *scope;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen const char *base;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen unsigned int ldap_version;
96e1ed172ae59cae6bc6e6ddd24d22a158e23dfeTimo Sirainen
96e1ed172ae59cae6bc6e6ddd24d22a158e23dfeTimo Sirainen const char *ldaprc_path;
96e1ed172ae59cae6bc6e6ddd24d22a158e23dfeTimo Sirainen const char *debug_level;
96e1ed172ae59cae6bc6e6ddd24d22a158e23dfeTimo Sirainen
96e1ed172ae59cae6bc6e6ddd24d22a158e23dfeTimo Sirainen const char *user_attrs;
96e1ed172ae59cae6bc6e6ddd24d22a158e23dfeTimo Sirainen const char *user_filter;
96e1ed172ae59cae6bc6e6ddd24d22a158e23dfeTimo Sirainen const char *pass_attrs;
96e1ed172ae59cae6bc6e6ddd24d22a158e23dfeTimo Sirainen const char *pass_filter;
96e1ed172ae59cae6bc6e6ddd24d22a158e23dfeTimo Sirainen const char *iterate_attrs;
96e1ed172ae59cae6bc6e6ddd24d22a158e23dfeTimo Sirainen const char *iterate_filter;
96e1ed172ae59cae6bc6e6ddd24d22a158e23dfeTimo Sirainen
96e1ed172ae59cae6bc6e6ddd24d22a158e23dfeTimo Sirainen const char *default_pass_scheme;
96e1ed172ae59cae6bc6e6ddd24d22a158e23dfeTimo Sirainen bool userdb_warning_disable; /* deprecated for now at least */
96e1ed172ae59cae6bc6e6ddd24d22a158e23dfeTimo Sirainen bool blocking;
96e1ed172ae59cae6bc6e6ddd24d22a158e23dfeTimo Sirainen
96e1ed172ae59cae6bc6e6ddd24d22a158e23dfeTimo Sirainen /* ... */
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen int ldap_deref, ldap_scope, ldap_tls_require_cert_parsed;
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen uid_t uid;
baf3e87e186453fda13bd21f7cbcb2efc8492e8bTimo Sirainen gid_t gid;
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen};
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen
96e1ed172ae59cae6bc6e6ddd24d22a158e23dfeTimo Sirainenenum ldap_request_type {
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen LDAP_REQUEST_TYPE_SEARCH,
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen LDAP_REQUEST_TYPE_BIND
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen};
b2ff0468c298dd2f525fff5977f1f24fba3a9f3bTimo Sirainen
struct ldap_field {
/* Dovecot field name. */
const char *name;
/* Field value template with %vars. NULL = same as LDAP value. */
const char *value;
/* LDAP attribute name, or "" if this is a static field. */
const char *ldap_attr_name;
/* LDAP value contains a DN, which is looked up and used for @name
attributes. */
bool value_is_dn;
/* This attribute is used internally only via %{ldap_ptr},
it shouldn't be returned in iteration. */
bool skip;
};
ARRAY_DEFINE_TYPE(ldap_field, struct ldap_field);
struct ldap_request {
enum ldap_request_type type;
/* msgid for sent requests, -1 if not sent */
int msgid;
/* timestamp when request was created */
time_t create_time;
bool failed:1;
/* This is to prevent double logging the result */
bool result_logged:1;
db_search_callback_t *callback;
struct auth_request *auth_request;
};
struct ldap_request_named_result {
const struct ldap_field *field;
const char *dn;
struct db_ldap_result *result;
};
struct ldap_request_search {
struct ldap_request request;
const char *base;
const char *filter;
char **attributes; /* points to pass_attr_names / user_attr_names */
const ARRAY_TYPE(ldap_field) *attr_map;
struct db_ldap_result *result;
ARRAY(struct ldap_request_named_result) named_results;
unsigned int name_idx;
bool multi_entry;
};
struct ldap_request_bind {
struct ldap_request request;
const char *dn;
};
enum ldap_connection_state {
/* Not connected */
LDAP_CONN_STATE_DISCONNECTED,
/* Binding - either to default dn or doing auth bind */
LDAP_CONN_STATE_BINDING,
/* Bound to auth dn */
LDAP_CONN_STATE_BOUND_AUTH,
/* Bound to default dn */
LDAP_CONN_STATE_BOUND_DEFAULT
};
struct ldap_connection {
struct ldap_connection *next;
pool_t pool;
int refcount;
char *config_path;
struct ldap_settings set;
LDAP *ld;
enum ldap_connection_state conn_state;
int default_bind_msgid;
int fd;
struct io *io;
struct timeout *to;
/* Request queue contains sent requests at tail (msgid != -1) and
queued requests at head (msgid == -1). */
struct aqueue *request_queue;
ARRAY(struct ldap_request *) request_array;
/* Number of messages in queue with msgid != -1 */
unsigned int pending_count;
/* Timestamp when we last received a reply */
time_t last_reply_stamp;
char **pass_attr_names, **user_attr_names, **iterate_attr_names;
ARRAY_TYPE(ldap_field) pass_attr_map, user_attr_map, iterate_attr_map;
bool userdb_used;
bool delayed_connect;
};
/* Send/queue request */
void db_ldap_request(struct ldap_connection *conn,
struct ldap_request *request);
void db_ldap_set_attrs(struct ldap_connection *conn, const char *attrlist,
char ***attr_names_r, ARRAY_TYPE(ldap_field) *attr_map,
const char *skip_attr) ATTR_NULL(5);
struct ldap_connection *db_ldap_init(const char *config_path, bool userdb);
void db_ldap_unref(struct ldap_connection **conn);
int db_ldap_connect(struct ldap_connection *conn);
void db_ldap_connect_delayed(struct ldap_connection *conn);
void 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,
LDAPMessage *res, bool skip_null_values);
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