client.c revision 00fa8dcbc66f56daa737487c9dec7166c37de79e
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek/* max. size of output buffer. if it gets full, the client is disconnected.
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek SASL authentication gives the largest output. */
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek/* maximum length for IMAP command line. */
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher/* Disconnect client when it sends too many bad commands */
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher/* When max. number of simultaneous connections is reached, few of the
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher oldest connections are disconnected. Since we have to go through all of the
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher clients, it's faster if we disconnect multiple clients. */
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher/* If we've been waiting auth server to respond for over this many milliseconds,
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher send a "waiting" message. */
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher#define AUTH_WAITING_TIMEOUT_MSECS (30*1000)
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek#if CLIENT_LOGIN_IDLE_TIMEOUT_MSECS < AUTH_REQUEST_TIMEOUT*1000
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher# error client idle timeout must be larger than authentication timeout
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher "Waiting for authentication process to respond.."
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher "Waiting for authentication master process to respond.."
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagherconst char *login_process_name = "imap-login";
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagherstatic void client_set_title(struct imap_client *client)
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher if (!client->common.set->verbose_proctitle ||
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher !client->common.set->login_process_per_connection)
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek process_title_set(t_strdup_printf(client->common.tls ?
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagherstatic void client_open_streams(struct imap_client *client, int fd)
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher i_stream_create_fd(fd, LOGIN_MAX_INBUF_SIZE, FALSE);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher client->output = o_stream_create_fd(fd, MAX_OUTBUF_SIZE, FALSE);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher client->parser = imap_parser_create(client->common.input,
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher/* Skip incoming data until newline is found,
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher returns TRUE if newline was found. */
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagherbool client_skip_line(struct imap_client *client)
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher const unsigned char *data;
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher data = i_stream_get_data(client->common.input, &data_size);
ea929f1b022fc2cb77dec89b0e12accef983ec85Jakub Hrozek for (i = 0; i < data_size; i++) {
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagherstatic const char *get_capability(struct imap_client *client)
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher auths = client_authenticate_get_capabilities(client);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher return t_strconcat(CAPABILITY_BANNER_STRING,
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher (ssl_initialized && !client->common.tls) ?
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher client->common.set->disable_plaintext_auth &&
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagherstatic int cmd_capability(struct imap_client *client)
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher /* Client is required to send CAPABILITY after STARTTLS, so the
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher capability resp-code workaround checks only pre-STARTTLS
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher CAPABILITY commands. */
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher client->client_ignores_capability_resp_code = TRUE;
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher "* CAPABILITY ", get_capability(client), "\r\n", NULL));
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher client_send_line(&client->common, CLIENT_CMD_REPLY_OK,
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher "Capability completed.");
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagherstatic void client_start_tls(struct imap_client *client)
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher if (!client_unref(client) || client->destroyed)
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher fd_ssl = ssl_proxy_new(client->common.fd, &client->common.ip,
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher client->common.set, &client->common.proxy);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher client_send_line(&client->common, CLIENT_CMD_REPLY_BYE,
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek "TLS initialization failed.");
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher "Disconnected: TLS initialization failed.");
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher /* CRLF is lost from buffer when streams are reopened. */
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher client->io = io_add(client->common.fd, IO_READ, client_input, client);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagherstatic int client_output_starttls(struct imap_client *client)
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher if ((ret = o_stream_flush(client->output)) < 0) {
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher o_stream_unset_flush_callback(client->output);
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagherstatic int cmd_starttls(struct imap_client *client)
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher client_send_line(&client->common, CLIENT_CMD_REPLY_BAD,
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher "TLS is already active.");
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher client_send_line(&client->common, CLIENT_CMD_REPLY_BAD,
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher "TLS support isn't enabled.");
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher /* remove input handler, SSL proxy gives us a new fd. we also have to
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher remove it in case we have to wait for buffer to be flushed */
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher client_send_line(&client->common, CLIENT_CMD_REPLY_OK,
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher "Begin TLS negotiation now.");
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher /* uncork the old fd */
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher if (o_stream_flush(client->output) <= 0) {
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher /* the buffer has to be flushed */
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher o_stream_set_flush_pending(client->output, TRUE);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher o_stream_set_flush_callback(client->output,
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagherclient_update_info(struct imap_client *client, const struct imap_arg *args)
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher if (strcasecmp(key, "x-originating-ip") == 0)
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher (void)net_addr2ip(value, &client->common.ip);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher else if (strcasecmp(key, "x-originating-port") == 0)
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher else if (strcasecmp(key, "x-connected-ip") == 0)
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek (void)net_addr2ip(value, &client->common.local_ip);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher else if (strcasecmp(key, "x-connected-port") == 0)
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagherstatic int cmd_id(struct imap_client *client, const struct imap_arg *args)
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher value = imap_id_args_get_log_reply(args, env);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher t_strdup_printf("* ID %s\r\n", imap_id_reply_generate(env)));
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher client_send_line(&client->common, CLIENT_CMD_REPLY_OK, "ID completed.");
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagherstatic int cmd_noop(struct imap_client *client)
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher client_send_line(&client->common, CLIENT_CMD_REPLY_OK,
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher "NOOP completed.");
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagherstatic int cmd_logout(struct imap_client *client)
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek client_send_line(&client->common, CLIENT_CMD_REPLY_BYE,
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher "Logging out");
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher client_send_line(&client->common, CLIENT_CMD_REPLY_OK,
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher "Logout completed.");
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagherstatic int cmd_enable(struct imap_client *client)
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher client_send_line(&client->common, CLIENT_CMD_REPLY_OK,
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher "ENABLE ignored in non-authenticated state.");
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagherstatic int client_command_execute(struct imap_client *client, const char *cmd,
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagherstatic bool client_handle_input(struct imap_client *client)
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher /* clear the previous command from memory. don't do this
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek immediately after handling command since we need the
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek cmd_tag to stay some time after authentication commands. */
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek /* remove \r\n */
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher client->cmd_tag = imap_parser_read_word(client->parser);
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher client->cmd_name = imap_parser_read_word(client->parser);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher switch (imap_parser_read_args(client->parser, 0, 0, &args)) {
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek msg = imap_parser_get_error(client->parser, &fatal);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher t_strconcat("Disconnected: ", msg, NULL));
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher client_send_line(&client->common, CLIENT_CMD_REPLY_BAD, msg);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher /* not enough data */
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher /* we read the entire line - skip over the CRLF */
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek ret = client_command_execute(client, client->cmd_name, args);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher if (++client->bad_counter >= CLIENT_MAX_BAD_COMMANDS) {
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher client_send_line(&client->common, CLIENT_CMD_REPLY_BYE,
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher "Too many invalid IMAP commands.");
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher "Disconnected: Too many invalid commands");
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher client_send_line(&client->common, CLIENT_CMD_REPLY_BAD,
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher "Error in IMAP command received by server.");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherbool client_read(struct imap_client *client)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher switch (i_stream_read(client->common.input)) {
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek /* buffer full */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher client_send_line(&client->common, CLIENT_CMD_REPLY_BYE,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Input buffer full, aborting");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher client_destroy(client, "Disconnected: Input buffer full");
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher /* disconnected */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* nothing new read */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* something was read */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher timeout_reset(client->to_idle_disconnect);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghervoid client_input(struct imap_client *client)
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher if (!auth_client_is_connected(auth_client)) {
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher /* we're not yet connected to auth process -
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek don't allow any commands */
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher client_send_line(&client->common, CLIENT_CMD_REPLY_STATUS,
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek struct imap_client *destroy_buf[CLIENT_DESTROY_OLDEST_COUNT];
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek unsigned int i, destroy_count;
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek /* find the oldest clients and put them to destroy-buffer */
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek destroy_count = max_connections > CLIENT_DESTROY_OLDEST_COUNT*2 ?
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek CLIENT_DESTROY_OLDEST_COUNT : I_MIN(max_connections/2, 1);
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek for (client = clients; client != NULL; client = client->next) {
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek struct imap_client *imap_client = (struct imap_client *)client;
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek for (i = 0; i < destroy_count; i++) {
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek destroy_buf[i]->created > imap_client->created) {
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek /* @UNSAFE */
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher /* then kill them */
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher for (i = 0; i < destroy_count; i++) {
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher "Disconnected: Connection queue full");
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagherstatic void client_send_greeting(struct imap_client *client)
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher str_printfa(greet, "[CAPABILITY %s] ", get_capability(client));
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek str_append(greet, client->common.set->login_greeting);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagherstatic void client_idle_disconnect_timeout(struct imap_client *client)
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek client_send_line(&client->common, CLIENT_CMD_REPLY_BAD,
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher "Disconnected for inactivity.");
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher client_destroy(client, "Disconnected: Inactivity");
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozekstatic void client_auth_waiting_timeout(struct imap_client *client)
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher client_send_line(&client->common, CLIENT_CMD_REPLY_STATUS,
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher AUTH_SERVER_WAITING_MSG : AUTH_MASTER_WAITING_MSG);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallaghervoid client_set_auth_waiting(struct imap_client *client)
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagherstruct client *client_create(int fd, bool ssl, pool_t pool,
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher if (clients_get_count() >= set->login_max_connections) {
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher /* reached max. users count, kill few of the
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher oldest connections */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* always use nonblocking I/O */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher client = p_new(pool, struct imap_client, 1);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher client->common.trusted = client_is_trusted(&client->common);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher client->common.secured = ssl || client->common.trusted ||
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher client->io = io_add(fd, IO_READ, client_input, client);
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher if (auth_client_is_connected(auth_client))
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher timeout_add(CLIENT_LOGIN_IDLE_TIMEOUT_MSECS,
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallaghervoid client_destroy(struct imap_client *client, const char *reason)
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher if (!client->login_success && reason != NULL) {
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher client_get_extra_disconnect_reason(&client->common),
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher i_assert(client->common.auth_request == NULL);
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher } else if (client->common.auth_request != NULL) {
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher timeout_remove(&client->to_authfail_delay);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher i_free_and_null(client->proxy_master_user);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher i_free_and_null(client->proxy_backend_capability);
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozekvoid client_destroy_success(struct imap_client *client, const char *reason)
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallaghervoid client_destroy_internal_failure(struct imap_client *client)
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek client_send_line(&client->common, CLIENT_CMD_REPLY_BYE,
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher "Internal login failure. "
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher "Refer to server log for more information.");
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher client_destroy(client, "Internal login failure");
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallaghervoid client_ref(struct imap_client *client)
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagherbool client_unref(struct imap_client *client)
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher master_service_client_connection_destroyed(master_service);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagherclient_send_raw_data(struct imap_client *client, const void *data, size_t size)
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek ret = o_stream_send(client->output, data, size);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher /* either disconnection or buffer full. in either case we want
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher this connection destroyed. however destroying it here might
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher break things if client is still tried to be accessed without
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek being referenced.. */
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallaghervoid client_send_raw(struct imap_client *client, const char *data)
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher client_send_raw_data(client, data, strlen(data));
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallaghervoid client_send_line(struct client *client, enum client_cmd_reply reply,
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher struct imap_client *imap_client = (struct imap_client *)client;
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek client_send_raw_data(imap_client, str_data(line),
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher for (client = clients; client != NULL; client = client->next) {
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek struct imap_client *imap_client = (struct imap_client *)client;
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher timeout_remove(&imap_client->to_auth_waiting);
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek for (client = clients; client != NULL; client = next) {
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek struct imap_client *imap_client = (struct imap_client *)client;
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek client_destroy(imap_client, "Disconnected: Shutting down");
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek /* Nothing to initialize for IMAP */