summaryrefslogtreecommitdiffstats
path: root/src/login-common/client-common.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/login-common/client-common.h')
-rw-r--r--src/login-common/client-common.h373
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