diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 17:36:47 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 17:36:47 +0000 |
commit | 0441d265f2bb9da249c7abf333f0f771fadb4ab5 (patch) | |
tree | 3f3789daa2f6db22da6e55e92bee0062a7d613fe /src/login-common/client-common.h | |
parent | Initial commit. (diff) | |
download | dovecot-0441d265f2bb9da249c7abf333f0f771fadb4ab5.tar.xz dovecot-0441d265f2bb9da249c7abf333f0f771fadb4ab5.zip |
Adding upstream version 1:2.3.21+dfsg1.upstream/1%2.3.21+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | src/login-common/client-common.h | 373 |
1 files changed, 373 insertions, 0 deletions
diff --git a/src/login-common/client-common.h b/src/login-common/client-common.h new file mode 100644 index 0000000..a21dea1 --- /dev/null +++ b/src/login-common/client-common.h @@ -0,0 +1,373 @@ +#ifndef CLIENT_COMMON_H +#define CLIENT_COMMON_H + +struct module; + +#include "net.h" +#include "login-proxy.h" +#include "sasl-server.h" +#include "master-login.h" /* for LOGIN_MAX_SESSION_ID_LEN */ + +#define LOGIN_MAX_SESSION_ID_LEN 64 +#define LOGIN_MAX_MASTER_PREFIX_LEN 128 +#define LOGIN_MAX_CLIENT_ID_LEN 256 + +/* max. size of input buffer. this means: + + IMAP: Max. length of command's all parameters. SASL-IR is read into + a separate larger buffer. + POP3: Max. length of a command line (spec says 512 would be enough) +*/ +#define LOGIN_MAX_INBUF_SIZE \ + (MASTER_AUTH_MAX_DATA_SIZE - LOGIN_MAX_MASTER_PREFIX_LEN - \ + LOGIN_MAX_SESSION_ID_LEN) +/* max. size of output buffer. if it gets full, the client is disconnected. + SASL authentication gives the largest output. */ +#define LOGIN_MAX_OUTBUF_SIZE 4096 + +/* Max. length of SASL authentication buffer. */ +#define LOGIN_MAX_AUTH_BUF_SIZE 8192 + +/* Disconnect client after this many milliseconds if it hasn't managed + to log in yet. */ +#define CLIENT_LOGIN_TIMEOUT_MSECS (MASTER_LOGIN_TIMEOUT_SECS*1000) + +#define AUTH_SERVER_WAITING_MSG \ + "Waiting for authentication process to respond.." +#define AUTH_MASTER_WAITING_MSG \ + "Waiting for authentication master process to respond.." + +/* Client logged out without having successfully authenticated. */ +#define CLIENT_UNAUTHENTICATED_LOGOUT_MSG \ + "Aborted login by logging out" + +struct master_service_connection; + +enum client_disconnect_reason { + CLIENT_DISCONNECT_TIMEOUT, + CLIENT_DISCONNECT_SYSTEM_SHUTDOWN, + CLIENT_DISCONNECT_RESOURCE_CONSTRAINT, + CLIENT_DISCONNECT_INTERNAL_ERROR +}; + +enum client_auth_fail_code { + CLIENT_AUTH_FAIL_CODE_NONE = 0, + CLIENT_AUTH_FAIL_CODE_AUTHZFAILED, + CLIENT_AUTH_FAIL_CODE_TEMPFAIL, + CLIENT_AUTH_FAIL_CODE_USER_DISABLED, + CLIENT_AUTH_FAIL_CODE_PASS_EXPIRED, + CLIENT_AUTH_FAIL_CODE_INVALID_BASE64, + CLIENT_AUTH_FAIL_CODE_LOGIN_DISABLED, + CLIENT_AUTH_FAIL_CODE_MECH_INVALID, + CLIENT_AUTH_FAIL_CODE_MECH_SSL_REQUIRED, + CLIENT_AUTH_FAIL_CODE_ANONYMOUS_DENIED, +}; + +enum client_auth_result { + CLIENT_AUTH_RESULT_SUCCESS, + CLIENT_AUTH_RESULT_REFERRAL_SUCCESS, + CLIENT_AUTH_RESULT_REFERRAL_NOLOGIN, + CLIENT_AUTH_RESULT_ABORTED, + CLIENT_AUTH_RESULT_AUTHFAILED, + CLIENT_AUTH_RESULT_AUTHFAILED_REASON, + CLIENT_AUTH_RESULT_AUTHZFAILED, + CLIENT_AUTH_RESULT_TEMPFAIL, + CLIENT_AUTH_RESULT_PASS_EXPIRED, + CLIENT_AUTH_RESULT_SSL_REQUIRED, + CLIENT_AUTH_RESULT_INVALID_BASE64, + CLIENT_AUTH_RESULT_LOGIN_DISABLED, + CLIENT_AUTH_RESULT_MECH_INVALID, + CLIENT_AUTH_RESULT_MECH_SSL_REQUIRED, + CLIENT_AUTH_RESULT_ANONYMOUS_DENIED +}; + +enum client_list_type { + CLIENT_LIST_TYPE_NONE = 0, + /* clients (disconnected=FALSE, fd_proxying=FALSE, destroyed=FALSE) */ + CLIENT_LIST_TYPE_ACTIVE, + /* destroyed_clients (destroyed=TRUE, fd_proxying=FALSE). Either the + client will soon be freed or it's only referenced via + "login_proxies". */ + CLIENT_LIST_TYPE_DESTROYED, + /* client_fd_proxies (fd_proxying=TRUE) */ + CLIENT_LIST_TYPE_FD_PROXY, +}; + +struct client_auth_reply { + const char *master_user, *reason; + enum client_auth_fail_code fail_code; + + /* for proxying */ + const char *host, *hostip, *source_ip; + const char *destuser, *password, *proxy_mech; + in_port_t port; + unsigned int proxy_timeout_msecs; + unsigned int proxy_refresh_secs; + unsigned int proxy_host_immediate_failure_after_secs; + enum login_proxy_ssl_flags ssl_flags; + + /* all the key=value fields returned by passdb */ + const char *const *all_fields; + + bool proxy:1; + bool proxy_noauth:1; + bool proxy_nopipelining:1; + bool proxy_not_trusted:1; + bool nologin:1; +}; + +struct client_vfuncs { + struct client *(*alloc)(pool_t pool); + void (*create)(struct client *client, void **other_sets); + void (*destroy)(struct client *client); + void (*notify_auth_ready)(struct client *client); + void (*notify_disconnect)(struct client *client, + enum client_disconnect_reason reason, + const char *text); + void (*notify_status)(struct client *client, + bool bad, const char *text); + void (*notify_starttls)(struct client *client, + bool success, const char *text); + void (*starttls)(struct client *client); + void (*input)(struct client *client); + bool (*sasl_filter_mech)(struct client *client, + struct auth_mech_desc *mech); + bool (*sasl_check_login)(struct client *client); + void (*auth_send_challenge)(struct client *client, const char *data); + void (*auth_parse_response)(struct client *client); + void (*auth_result)(struct client *client, + enum client_auth_result result, + const struct client_auth_reply *reply, + const char *text); + void (*proxy_reset)(struct client *client); + int (*proxy_parse_line)(struct client *client, const char *line); + void (*proxy_failed)(struct client *client, + enum login_proxy_failure_type type, + const char *reason, bool reconnecting); + const char *(*proxy_get_state)(struct client *client); + void (*send_raw_data)(struct client *client, + const void *data, size_t size); + bool (*input_next_cmd)(struct client *client); + void (*free)(struct client *client); +}; + +struct client { + struct client *prev, *next; + /* Specifies which linked list the client is in */ + enum client_list_type list_type; + + pool_t pool; + /* this pool gets free'd once proxying starts */ + pool_t preproxy_pool; + struct client_vfuncs v; + struct client_vfuncs *vlast; + + struct timeval created; + int refcount; + struct event *event; + + struct ip_addr local_ip; + struct ip_addr ip; + struct ip_addr real_remote_ip, real_local_ip; + in_port_t local_port, remote_port; + in_port_t real_local_port, real_remote_port; + struct ssl_iostream *ssl_iostream; + const struct login_settings *set; + const struct master_service_ssl_settings *ssl_set; + const struct master_service_ssl_server_settings *ssl_server_set; + const char *session_id, *listener_name, *postlogin_socket_path; + const char *local_name; + const char *client_cert_common_name; + + string_t *client_id; + string_t *forward_fields; + + int fd; + struct istream *input; + struct ostream *output; + struct io *io; + struct iostream_proxy *iostream_fd_proxy; + struct timeout *to_auth_waiting; + struct timeout *to_disconnect; + + unsigned char *master_data_prefix; + unsigned int master_data_prefix_len; + + struct login_proxy *login_proxy; + char *proxy_user, *proxy_master_user, *proxy_password; + const struct dsasl_client_mech *proxy_mech; + struct dsasl_client *proxy_sasl_client; + unsigned int proxy_ttl; + + char *auth_mech_name; + enum sasl_server_auth_flags auth_flags; + struct auth_client_request *auth_request; + string_t *auth_response; + time_t auth_first_started, auth_finished; + const char *sasl_final_resp; + const char *sasl_final_delayed_resp; + enum sasl_server_reply delayed_final_reply; + const char *const *final_args; + const char *const *auth_passdb_args; + struct anvil_query *anvil_query; + struct anvil_request *anvil_request; + + unsigned int master_auth_id; + unsigned int master_tag; + sasl_server_callback_t *sasl_callback; + + unsigned int bad_counter; + unsigned int auth_attempts, auth_successes; + enum client_auth_fail_code last_auth_fail; + pid_t mail_pid; + + /* Module-specific contexts. */ + ARRAY(union login_client_module_context *) module_contexts; + + char *virtual_user, *virtual_user_orig, *virtual_auth_user; + /* passdb user_* fields are set here after a successful auth. + This is a NULL-terminated array where fields are in the same order + as in global_alt_usernames. If some field doesn't exist, it's "". + Can also be NULL if there are no user_* fields. */ + const char **alt_usernames; + /* director_username_hash cached, if non-zero */ + unsigned int director_username_hash_cache; + + bool create_finished:1; + bool disconnected:1; + bool destroyed:1; + bool input_blocked:1; + bool login_success:1; + bool no_extra_disconnect_reason:1; + bool starttls:1; + bool tls:1; + bool proxied_ssl:1; + bool secured:1; + bool ssl_secured:1; + bool trusted:1; + bool ssl_servername_settings_read:1; + bool banner_sent:1; + bool authenticating:1; + bool auth_client_continue_pending:1; + bool auth_try_aborted:1; + bool auth_initializing:1; + bool auth_process_comm_fail:1; + bool auth_anonymous:1; + bool proxy_auth_failed:1; + bool proxy_noauth:1; + bool proxy_nopipelining:1; + bool proxy_not_trusted:1; + bool auth_waiting:1; + bool notified_auth_ready:1; + bool notified_disconnect:1; + bool fd_proxying:1; + bool final_response:1; + /* ... */ +}; + +union login_client_module_context { + struct client_vfuncs super; + struct login_module_register *reg; +}; + +struct login_client_hooks { + void (*client_allocated)(struct client *client); +}; + +extern struct client *clients; + +typedef void login_client_allocated_func_t(struct client *client); + +void login_client_hooks_add(struct module *module, + const struct login_client_hooks *hooks); +void login_client_hooks_remove(const struct login_client_hooks *hooks); + +struct client * +client_alloc(int fd, pool_t pool, + const struct master_service_connection *conn, + const struct login_settings *set, + const struct master_service_ssl_settings *ssl_set, + const struct master_service_ssl_server_settings *ssl_server_set); +void client_init(struct client *client, void **other_sets); +void client_disconnect(struct client *client, const char *reason, + bool add_disconnected_prefix); +void client_destroy(struct client *client, const char *reason); +void client_destroy_iostream_error(struct client *client); +/* Destroy the client after a successful login. Either the client fd was + sent to the post-login process, or the connection will be proxied. */ +void client_destroy_success(struct client *client, const char *reason); + +void client_ref(struct client *client); +bool client_unref(struct client **client) ATTR_NOWARN_UNUSED_RESULT; + +int client_init_ssl(struct client *client); +void client_cmd_starttls(struct client *client); + +int client_get_plaintext_fd(struct client *client, int *fd_r, bool *close_fd_r); + +unsigned int clients_get_count(void) ATTR_PURE; +unsigned int clients_get_fd_proxies_count(void); +struct client *clients_get_first_fd_proxy(void); + +void client_add_forward_field(struct client *client, const char *key, + const char *value); +void client_set_title(struct client *client); +const char *client_get_extra_disconnect_reason(struct client *client); + +void client_auth_respond(struct client *client, const char *response); +void client_auth_abort(struct client *client); +bool client_is_tls_enabled(struct client *client); +void client_auth_fail(struct client *client, const char *text); +const char *client_get_session_id(struct client *client); + +bool client_read(struct client *client); + +void client_input(struct client *client); + +static inline bool +client_does_custom_io(struct client *client) +{ + return (client->v.input == NULL); +} + +void client_notify_auth_ready(struct client *client); +void client_notify_status(struct client *client, bool bad, const char *text); +void client_notify_disconnect(struct client *client, + enum client_disconnect_reason reason, + const char *text); + +void client_send_raw_data(struct client *client, const void *data, size_t size); +void client_send_raw(struct client *client, const char *data); +void client_common_send_raw_data(struct client *client, + const void *data, size_t size); +void client_common_default_free(struct client *client); +void client_common_proxy_failed(struct client *client, + enum login_proxy_failure_type type, + const char *reason, bool reconnecting); + +void client_set_auth_waiting(struct client *client); +void client_auth_send_challenge(struct client *client, const char *data); +void client_auth_parse_response(struct client *client); +int client_auth_begin(struct client *client, const char *mech_name, + const char *init_resp); +int client_auth_begin_private(struct client *client, const char *mech_name, + const char *init_resp); +int client_auth_begin_implicit(struct client *client, const char *mech_name, + const char *init_resp); +bool client_check_plaintext_auth(struct client *client, bool pass_sent); +int client_auth_read_line(struct client *client); + +void client_proxy_finish_destroy_client(struct client *client); +void client_proxy_log_failure(struct client *client, const char *line); +const char *client_proxy_get_state(struct client *client); + +void clients_notify_auth_connected(void); +bool client_destroy_oldest(bool kill, struct timeval *created_r); +void clients_destroy_all(void); +void clients_destroy_all_reason(const char *reason); + +void client_destroy_fd_proxies(void); +void client_common_init(void); +void client_common_deinit(void); + +#endif |