#ifndef DB_LDAP_H #define DB_LDAP_H /* Functions like ldap_bind() have been deprecated in OpenLDAP 2.3 This define enables them until the code here can be refactored */ #define LDAP_DEPRECATED 1 /* Maximum number of pending requests before delaying new requests. */ #define DB_LDAP_MAX_PENDING_REQUESTS 8 /* connect() timeout to LDAP */ #define DB_LDAP_CONNECT_TIMEOUT_SECS 5 /* If LDAP connection is down, fail requests after waiting for this long. */ #define DB_LDAP_REQUEST_DISCONNECT_TIMEOUT_SECS 4 /* If request is still in queue after this many seconds and other requests have been replied, assume the request was lost and abort it. */ #define DB_LDAP_REQUEST_LOST_TIMEOUT_SECS 60 /* If server disconnects us, don't reconnect if no requests have been sent for this many seconds. */ #define DB_LDAP_IDLE_RECONNECT_SECS 60 #include struct auth_request; struct ldap_connection; struct ldap_request; typedef void db_search_callback_t(struct ldap_connection *conn, struct ldap_request *request, LDAPMessage *res); struct ldap_settings { const char *hosts; const char *uris; const char *dn; const char *dnpass; bool auth_bind; const char *auth_bind_userdn; bool tls; bool sasl_bind; const char *sasl_mech; const char *sasl_realm; const char *sasl_authz_id; const char *tls_ca_cert_file; const char *tls_ca_cert_dir; const char *tls_cert_file; const char *tls_key_file; const char *tls_cipher_suite; const char *tls_require_cert; const char *deref; const char *scope; const char *base; unsigned int ldap_version; const char *ldaprc_path; const char *debug_level; const char *user_attrs; const char *user_filter; const char *pass_attrs; const char *pass_filter; const char *iterate_attrs; const char *iterate_filter; const char *default_pass_scheme; bool userdb_warning_disable; /* deprecated for now at least */ bool blocking; /* ... */ int ldap_deref, ldap_scope, ldap_tls_require_cert_parsed; uid_t uid; gid_t gid; }; enum ldap_request_type { LDAP_REQUEST_TYPE_SEARCH, LDAP_REQUEST_TYPE_BIND }; 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; /* Number of times this request has been sent to LDAP server. This increases when LDAP gets disconnected and reconnect send the request again. */ unsigned int send_count; 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; struct event *event; 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