client.c revision ccef83820a01bb37ad48653a05a9c5aa6560826a
183bea41fa640dc8117f3eb45ff935cd81377a84Timo Sirainen/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "common.h"
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen#include "buffer.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "ioloop.h"
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen#include "istream.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "ostream.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "process-title.h"
abf015c9682f0f723db87a7c97bc284ef814818fTimo Sirainen#include "safe-memset.h"
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen#include "str.h"
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen#include "strescape.h"
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen#include "imap-parser.h"
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen#include "imap-id.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "client.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "client-authenticate.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "auth-client.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "ssl-proxy.h"
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen#include "imap-proxy.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include <stdlib.h>
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen/* max. size of output buffer. if it gets full, the client is disconnected.
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen SASL authentication gives the largest output. */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define MAX_OUTBUF_SIZE 4096
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen/* maximum length for IMAP command line. */
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen#define MAX_IMAP_LINE 8192
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen/* Disconnect client after idling this many milliseconds */
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen#define CLIENT_LOGIN_IDLE_TIMEOUT_MSECS (3*60*1000)
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen/* Disconnect client when it sends too many bad commands */
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen#define CLIENT_MAX_BAD_COMMANDS 10
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen/* When max. number of simultaneous connections is reached, few of the
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen oldest connections are disconnected. Since we have to go through all of the
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen clients, it's faster if we disconnect multiple clients. */
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen#define CLIENT_DESTROY_OLDEST_COUNT 16
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen/* If we've been waiting auth server to respond for over this many milliseconds,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen send a "waiting" message. */
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen#define AUTH_WAITING_TIMEOUT_MSECS (30*1000)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
fa2433aebcf3fccfa30ca9eed9b1a9166cf92ee2Timo Sirainen#if CLIENT_LOGIN_IDLE_TIMEOUT_MSECS >= AUTH_REQUEST_TIMEOUT*1000
fa2433aebcf3fccfa30ca9eed9b1a9166cf92ee2Timo Sirainen# error client idle timeout must be smaller than authentication timeout
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen#endif
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define AUTH_WAITING_MSG \
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen "* OK Waiting for authentication process to respond.."
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainenconst char *login_protocol = "IMAP";
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenconst char *capability_string = CAPABILITY_STRING;
12797080b552a3c1727b73b61cc7427bec0c7472Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void client_set_title(struct imap_client *client)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen const char *addr;
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen if (!verbose_proctitle || !process_per_connection)
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen return;
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen addr = net_ip2addr(&client->common.ip);
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen if (addr == NULL)
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen addr = "??";
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen process_title_set(t_strdup_printf(client->common.tls ?
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen "[%s TLS]" : "[%s]", addr));
38f227941bcf673e0e523c1ac7267bca9cbcd2c4Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenstatic void client_open_streams(struct imap_client *client, int fd)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen{
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen client->common.input =
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen i_stream_create_fd(fd, LOGIN_MAX_INBUF_SIZE, FALSE);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen client->output = o_stream_create_fd(fd, MAX_OUTBUF_SIZE, FALSE);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen client->parser = imap_parser_create(client->common.input,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen client->output, MAX_IMAP_LINE);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen}
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen/* Skip incoming data until newline is found,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen returns TRUE if newline was found. */
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenbool client_skip_line(struct imap_client *client)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen{
2eb2cf8eeb763bd5ca9b6848dce32f0303e88ec1Timo Sirainen const unsigned char *data;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen size_t i, data_size;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen data = i_stream_get_data(client->common.input, &data_size);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen for (i = 0; i < data_size; i++) {
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if (data[i] == '\n') {
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen i_stream_skip(client->common.input, i+1);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen return TRUE;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen }
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen }
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen return FALSE;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen}
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic const char *get_capability(struct imap_client *client, bool full)
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char *auths;
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen auths = client_authenticate_get_capabilities(client->common.secured);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return t_strconcat(full ? capability_string : CAPABILITY_BANNER_STRING,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen (ssl_initialized && !client->common.tls) ?
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen " STARTTLS" : "",
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen disable_plaintext_auth && !client->common.secured ?
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen " LOGINDISABLED" : "", auths, NULL);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen}
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenstatic int cmd_capability(struct imap_client *client)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen{
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen client_send_line(client, t_strconcat(
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen "* CAPABILITY ", get_capability(client, TRUE), NULL));
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen client_send_tagline(client, "OK Capability completed.");
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen return 1;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen}
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenstatic void client_start_tls(struct imap_client *client)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen{
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen int fd_ssl;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen client_ref(client);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen connection_queue_add(1);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if (!client_unref(client) || client->destroyed)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen return;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen fd_ssl = ssl_proxy_new(client->common.fd, &client->common.ip,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen &client->common.proxy);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if (fd_ssl == -1) {
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen client_send_line(client, "* BYE TLS initialization failed.");
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen client_destroy(client,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen "Disconnected: TLS initialization failed.");
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen return;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen }
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen client->common.tls = TRUE;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen client->common.secured = TRUE;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen client_set_title(client);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen client->common.fd = fd_ssl;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen i_stream_unref(&client->common.input);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen o_stream_unref(&client->output);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen imap_parser_destroy(&client->parser);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* CRLF is lost from buffer when streams are reopened. */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client->skip_line = FALSE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_open_streams(client, fd_ssl);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client->io = io_add(client->common.fd, IO_READ, client_input, client);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic int client_output_starttls(struct imap_client *client)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen int ret;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if ((ret = o_stream_flush(client->output)) < 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_destroy(client, "Disconnected");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return 1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (ret > 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen o_stream_unset_flush_callback(client->output);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_start_tls(client);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return 1;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen}
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic int cmd_starttls(struct imap_client *client)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (client->common.tls) {
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen client_send_tagline(client, "BAD TLS is already active.");
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen return 1;
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (!ssl_initialized) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_send_tagline(client, "BAD TLS support isn't enabled.");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return 1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* remove input handler, SSL proxy gives us a new fd. we also have to
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen remove it in case we have to wait for buffer to be flushed */
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen if (client->io != NULL)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen io_remove(&client->io);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen client_send_tagline(client, "OK Begin TLS negotiation now.");
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen /* uncork the old fd */
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen o_stream_uncork(client->output);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen if (o_stream_flush(client->output) <= 0) {
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen /* the buffer has to be flushed */
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen o_stream_set_flush_pending(client->output, TRUE);
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen o_stream_set_flush_callback(client->output,
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen client_output_starttls, client);
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen } else {
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen client_start_tls(client);
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen }
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen return 1;
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen}
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainenclient_update_info(struct imap_client *client, const struct imap_arg *args)
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char *key, *value;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen if (args->type != IMAP_ARG_LIST)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen args = IMAP_ARG_LIST_ARGS(args);
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen while (args->type == IMAP_ARG_STRING &&
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen args[1].type == IMAP_ARG_STRING) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen key = IMAP_ARG_STR_NONULL(&args[0]);
d7ec773d995888b09c4d8c88a4b0b134a2002361Timo Sirainen value = IMAP_ARG_STR_NONULL(&args[1]);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (strcasecmp(key, "x-originating-ip") == 0)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen (void)net_addr2ip(value, &client->common.ip);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen else if (strcasecmp(key, "x-originating-port") == 0)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen client->common.remote_port = atoi(value);
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen else if (strcasecmp(key, "x-connected-ip") == 0)
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen (void)net_addr2ip(value, &client->common.local_ip);
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen else if (strcasecmp(key, "x-connected-port") == 0)
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen client->common.local_port = atoi(value);
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen args += 2;
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen }
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen}
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainenstatic int cmd_id(struct imap_client *client, const struct imap_arg *args)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen{
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen const char *env, *value;
18c209a06941ef583b08b173dadfbe4571995bf9Timo Sirainen
18c209a06941ef583b08b173dadfbe4571995bf9Timo Sirainen if (!client->id_logged) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client->id_logged = TRUE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (client->common.trusted)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_update_info(client, args);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen env = getenv("IMAP_ID_LOG");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen value = imap_id_args_get_log_reply(args, env);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (value != NULL) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_syslog(&client->common,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen t_strdup_printf("ID sent: %s", value));
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen }
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen }
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen env = getenv("IMAP_ID_SEND");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_send_line(client, t_strdup_printf("* ID %s",
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen imap_id_reply_generate(env)));
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen client_send_tagline(client, "OK ID completed.");
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen return 1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainenstatic int cmd_noop(struct imap_client *client)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen{
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen client_send_tagline(client, "OK NOOP completed.");
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen return 1;
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen}
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainenstatic int cmd_logout(struct imap_client *client)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen client_send_line(client, "* BYE Logging out");
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen client_send_tagline(client, "OK Logout completed.");
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen client_destroy(client, "Aborted login");
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen return 1;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen}
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainenstatic int cmd_enable(struct imap_client *client)
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen{
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen client_send_line(client, "* ENABLED");
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen client_send_tagline(client,
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen "OK ENABLE ignored in non-authenticated state.");
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen return 1;
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen}
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic int client_command_execute(struct imap_client *client, const char *cmd,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const struct imap_arg *args)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen cmd = t_str_ucase(cmd);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (strcmp(cmd, "LOGIN") == 0)
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen return cmd_login(client, args);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (strcmp(cmd, "AUTHENTICATE") == 0)
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen return cmd_authenticate(client, args);
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen if (strcmp(cmd, "CAPABILITY") == 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return cmd_capability(client);
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen if (strcmp(cmd, "STARTTLS") == 0)
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen return cmd_starttls(client);
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen if (strcmp(cmd, "ID") == 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return cmd_id(client, args);
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen if (strcmp(cmd, "NOOP") == 0)
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen return cmd_noop(client);
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen if (strcmp(cmd, "LOGOUT") == 0)
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen return cmd_logout(client);
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen if (strcmp(cmd, "ENABLE") == 0)
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen return cmd_enable(client);
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return -1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic bool client_handle_input(struct imap_client *client)
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const struct imap_arg *args;
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen const char *msg;
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen int ret;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen bool fatal;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen i_assert(!client->common.authenticating);
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (client->cmd_finished) {
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen /* clear the previous command from memory. don't do this
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen immediately after handling command since we need the
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen cmd_tag to stay some time after authentication commands. */
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen client->cmd_tag = NULL;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen client->cmd_name = NULL;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen imap_parser_reset(client->parser);
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* remove \r\n */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (client->skip_line) {
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen if (!client_skip_line(client))
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen return FALSE;
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen client->skip_line = FALSE;
f38485358ffc04c3466b917770575e29deef24c3Timo Sirainen }
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen client->cmd_finished = FALSE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (client->cmd_tag == NULL) {
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen client->cmd_tag = imap_parser_read_word(client->parser);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (client->cmd_tag == NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return FALSE; /* need more data */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
1503ac7619d97193d6690292b5f9523552c5d6ceTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (client->cmd_name == NULL) {
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen client->cmd_name = imap_parser_read_word(client->parser);
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen if (client->cmd_name == NULL)
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen return FALSE; /* need more data */
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen }
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen switch (imap_parser_read_args(client->parser, 0, 0, &args)) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen case -1:
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* error */
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen msg = imap_parser_get_error(client->parser, &fatal);
216cd45a5f47c9bd46fe67c1b3bd6b1a42f6e39cTimo Sirainen if (fatal) {
216cd45a5f47c9bd46fe67c1b3bd6b1a42f6e39cTimo Sirainen client_send_line(client, t_strconcat("* BYE ",
216cd45a5f47c9bd46fe67c1b3bd6b1a42f6e39cTimo Sirainen msg, NULL));
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen client_destroy(client,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen t_strconcat("Disconnected: ", msg, NULL));
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen return FALSE;
7f472e15b5f19a3536634863950c80a88079da23Timo Sirainen }
7f472e15b5f19a3536634863950c80a88079da23Timo Sirainen
0139fcb57a88f6ed27a1bb4a1bd537b04fd2b5d6Timo Sirainen client_send_tagline(client, t_strconcat("BAD ", msg, NULL));
0139fcb57a88f6ed27a1bb4a1bd537b04fd2b5d6Timo Sirainen client->cmd_finished = TRUE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client->skip_line = TRUE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return TRUE;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen case -2:
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen /* not enough data */
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen return FALSE;
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen }
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen /* we read the entire line - skip over the CRLF */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (!client_skip_line(client))
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_unreached();
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen if (*client->cmd_tag == '\0')
216cd45a5f47c9bd46fe67c1b3bd6b1a42f6e39cTimo Sirainen ret = -1;
216cd45a5f47c9bd46fe67c1b3bd6b1a42f6e39cTimo Sirainen else
216cd45a5f47c9bd46fe67c1b3bd6b1a42f6e39cTimo Sirainen ret = client_command_execute(client, client->cmd_name, args);
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client->cmd_finished = TRUE;
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen if (ret < 0) {
7f472e15b5f19a3536634863950c80a88079da23Timo Sirainen if (*client->cmd_tag == '\0')
7f472e15b5f19a3536634863950c80a88079da23Timo Sirainen client->cmd_tag = "*";
0139fcb57a88f6ed27a1bb4a1bd537b04fd2b5d6Timo Sirainen if (++client->bad_counter >= CLIENT_MAX_BAD_COMMANDS) {
0139fcb57a88f6ed27a1bb4a1bd537b04fd2b5d6Timo Sirainen client_send_line(client,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen "* BYE Too many invalid IMAP commands.");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_destroy(client,
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen "Disconnected: Too many invalid commands");
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen return FALSE;
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen }
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen client_send_tagline(client,
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen "BAD Error in IMAP command received by server.");
9aceb071780a949f4e8bf41d3cf80735d9ac7fdfTimo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
1503ac7619d97193d6690292b5f9523552c5d6ceTimo Sirainen return ret != 0;
1503ac7619d97193d6690292b5f9523552c5d6ceTimo Sirainen}
1503ac7619d97193d6690292b5f9523552c5d6ceTimo Sirainen
1503ac7619d97193d6690292b5f9523552c5d6ceTimo Sirainenbool client_read(struct imap_client *client)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen switch (i_stream_read(client->common.input)) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen case -2:
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* buffer full */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_send_line(client, "* BYE Input buffer full, aborting");
f38485358ffc04c3466b917770575e29deef24c3Timo Sirainen client_destroy(client, "Disconnected: Input buffer full");
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen return FALSE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen case -1:
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen /* disconnected */
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen client_destroy(client, "Disconnected");
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen return FALSE;
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen default:
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen /* something was read */
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen return TRUE;
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen }
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen}
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainenvoid client_input(struct imap_client *client)
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen{
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen timeout_reset(client->to_idle_disconnect);
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen if (!client_read(client))
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen return;
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen client_ref(client);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen if (!auth_client_is_connected(auth_client)) {
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen /* we're not yet connected to auth process -
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen don't allow any commands */
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen client_send_line(client, AUTH_WAITING_MSG);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (client->to_auth_waiting != NULL)
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen timeout_remove(&client->to_auth_waiting);
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen client->input_blocked = TRUE;
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen } else {
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen o_stream_cork(client->output);
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen while (client_handle_input(client)) ;
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen o_stream_uncork(client->output);
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen }
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_unref(client);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid client_destroy_oldest(void)
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen{
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen struct client *client;
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen struct imap_client *destroy_buf[CLIENT_DESTROY_OLDEST_COUNT];
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen unsigned int i, destroy_count;
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen /* find the oldest clients and put them to destroy-buffer */
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen memset(destroy_buf, 0, sizeof(destroy_buf));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen destroy_count = max_connections > CLIENT_DESTROY_OLDEST_COUNT*2 ?
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen CLIENT_DESTROY_OLDEST_COUNT : I_MIN(max_connections/2, 1);
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen for (client = clients; client != NULL; client = client->next) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct imap_client *imap_client = (struct imap_client *)client;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen for (i = 0; i < destroy_count; i++) {
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (destroy_buf[i] == NULL ||
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen destroy_buf[i]->created > imap_client->created) {
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen /* @UNSAFE */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen memmove(destroy_buf+i+1, destroy_buf+i,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen sizeof(destroy_buf) -
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen (i+1) * sizeof(struct imap_client *));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen destroy_buf[i] = imap_client;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen break;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen }
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen }
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen }
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen /* then kill them */
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen for (i = 0; i < destroy_count; i++) {
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen if (destroy_buf[i] == NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen break;
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk client_destroy(destroy_buf[i],
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen "Disconnected: Connection queue full");
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen }
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen}
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainenstatic void client_send_greeting(struct imap_client *client)
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen{
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen string_t *greet;
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen
02a6291366caff79793db35d479e2a062bec2af4Timo Sirainen greet = t_str_new(128);
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen str_append(greet, "* OK ");
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen str_printfa(greet, "[CAPABILITY %s] ", get_capability(client, FALSE));
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen str_append(greet, greeting);
573085b4b25b0bbae8d27969df2c91702eefa23eTimo Sirainen
0ee3fdb5e94ae6f34cb873ca3c9858342621e55fTimo Sirainen client_send_line(client, str_c(greet));
0ee3fdb5e94ae6f34cb873ca3c9858342621e55fTimo Sirainen client->greeting_sent = TRUE;
0ee3fdb5e94ae6f34cb873ca3c9858342621e55fTimo Sirainen}
0ee3fdb5e94ae6f34cb873ca3c9858342621e55fTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void client_idle_disconnect_timeout(struct imap_client *client)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk client_send_line(client, "* BYE Disconnected for inactivity.");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_destroy(client, "Disconnected: Inactivity");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
1b04762685272a53643ac2179939537a44c7c044Timo Sirainenstatic void client_auth_waiting_timeout(struct imap_client *client)
1b04762685272a53643ac2179939537a44c7c044Timo Sirainen{
1b04762685272a53643ac2179939537a44c7c044Timo Sirainen client_send_line(client, AUTH_WAITING_MSG);
1b04762685272a53643ac2179939537a44c7c044Timo Sirainen timeout_remove(&client->to_auth_waiting);
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen}
303e375b7e76278f4ec541f49af0476d3e4ee710Timo Sirainen
303e375b7e76278f4ec541f49af0476d3e4ee710Timo Sirainenvoid client_set_auth_waiting(struct imap_client *client)
303e375b7e76278f4ec541f49af0476d3e4ee710Timo Sirainen{
303e375b7e76278f4ec541f49af0476d3e4ee710Timo Sirainen i_assert(client->to_auth_waiting == NULL);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client->to_auth_waiting =
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen timeout_add(AUTH_WAITING_TIMEOUT_MSECS,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_auth_waiting_timeout, client);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainenstruct client *client_create(int fd, bool ssl, const struct ip_addr *local_ip,
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen const struct ip_addr *ip)
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen{
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen struct imap_client *client;
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen i_assert(fd != -1);
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen connection_queue_add(1);
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen /* always use nonblocking I/O */
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen net_set_nonblock(fd, TRUE);
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen client = i_new(struct imap_client, 1);
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen client->created = ioloop_time;
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen client->refcount = 1;
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen client->common.local_ip = *local_ip;
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen client->common.ip = *ip;
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen client->common.fd = fd;
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen client->common.tls = ssl;
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen client->common.trusted = client_is_trusted(&client->common);
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen client->common.secured = ssl || client->common.trusted ||
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen net_ip_compare(ip, local_ip);
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen client_open_streams(client, fd);
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen client->io = io_add(fd, IO_READ, client_input, client);
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen client_link(&client->common);
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen main_ref();
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen if (auth_client_is_connected(auth_client))
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen client_send_greeting(client);
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen else
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen client_set_auth_waiting(client);
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen client_set_title(client);
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen client->to_idle_disconnect =
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen timeout_add(CLIENT_LOGIN_IDLE_TIMEOUT_MSECS,
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen client_idle_disconnect_timeout, client);
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen return &client->common;
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen}
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainenvoid client_destroy(struct imap_client *client, const char *reason)
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen{
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen if (client->destroyed)
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen return;
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen client->destroyed = TRUE;
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen
12797080b552a3c1727b73b61cc7427bec0c7472Timo Sirainen if (!client->login_success && reason != NULL) {
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen reason = t_strconcat(reason, " ",
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen client_get_extra_disconnect_reason(&client->common),
12797080b552a3c1727b73b61cc7427bec0c7472Timo Sirainen NULL);
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen }
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen if (reason != NULL)
97333cbaa7893be8bac7b5741e328ebfff0aeab0Timo Sirainen client_syslog(&client->common, reason);
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen client_unlink(&client->common);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
12797080b552a3c1727b73b61cc7427bec0c7472Timo Sirainen if (client->common.input != NULL)
12797080b552a3c1727b73b61cc7427bec0c7472Timo Sirainen i_stream_close(client->common.input);
97333cbaa7893be8bac7b5741e328ebfff0aeab0Timo Sirainen if (client->output != NULL)
97333cbaa7893be8bac7b5741e328ebfff0aeab0Timo Sirainen o_stream_close(client->output);
97333cbaa7893be8bac7b5741e328ebfff0aeab0Timo Sirainen
97333cbaa7893be8bac7b5741e328ebfff0aeab0Timo Sirainen if (client->common.master_tag != 0)
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen master_request_abort(&client->common);
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen if (client->common.auth_request != NULL) {
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen i_assert(client->common.authenticating);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen sasl_server_auth_client_error(&client->common, NULL);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen } else {
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen i_assert(!client->common.authenticating);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen }
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen if (client->io != NULL)
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen io_remove(&client->io);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen if (client->to_idle_disconnect != NULL)
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen timeout_remove(&client->to_idle_disconnect);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen if (client->to_auth_waiting != NULL)
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen timeout_remove(&client->to_auth_waiting);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen if (client->common.fd != -1) {
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen net_disconnect(client->common.fd);
0992011130e9d0a498ca860ddbe4028398a530c5Timo Sirainen client->common.fd = -1;
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen }
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen if (client->proxy_password != NULL) {
0992011130e9d0a498ca860ddbe4028398a530c5Timo Sirainen safe_memset(client->proxy_password, 0,
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen strlen(client->proxy_password));
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen i_free(client->proxy_password);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen client->proxy_password = NULL;
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen }
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen i_free_and_null(client->proxy_user);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen i_free_and_null(client->proxy_master_user);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen if (client->proxy != NULL) {
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen login_proxy_free(client->proxy);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen client->proxy = NULL;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen }
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (client->common.proxy != NULL) {
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen ssl_proxy_free(client->common.proxy);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen client->common.proxy = NULL;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen client_unref(client);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen main_listen_start();
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen main_unref();
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen}
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainenvoid client_destroy_success(struct imap_client *client, const char *reason)
f934b271c69c7b3e5e3bca23ff9b3ab6187262c2Timo Sirainen{
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen client->login_success = TRUE;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen client_destroy(client, reason);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen}
f38485358ffc04c3466b917770575e29deef24c3Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainenvoid client_destroy_internal_failure(struct imap_client *client)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen{
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen client_send_line(client, "* BYE Internal login failure. "
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen "Refer to server log for more information.");
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen client_destroy(client, "Internal login failure");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenvoid client_ref(struct imap_client *client)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen{
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen client->refcount++;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen}
878a83a906e1be6354b563ead096955a22ad5fbeTimo Sirainen
878a83a906e1be6354b563ead096955a22ad5fbeTimo Sirainenbool client_unref(struct imap_client *client)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen{
b879ed8dd4b5850987e6b89a92f794d87c6be7d7Timo Sirainen i_assert(client->refcount > 0);
b879ed8dd4b5850987e6b89a92f794d87c6be7d7Timo Sirainen if (--client->refcount > 0)
b879ed8dd4b5850987e6b89a92f794d87c6be7d7Timo Sirainen return TRUE;
b879ed8dd4b5850987e6b89a92f794d87c6be7d7Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_assert(client->destroyed);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen imap_parser_destroy(&client->parser);
705f6fbad395e6f014838e797b7dbcaceafd2f1dTimo Sirainen
12797080b552a3c1727b73b61cc7427bec0c7472Timo Sirainen if (client->common.input != NULL)
12797080b552a3c1727b73b61cc7427bec0c7472Timo Sirainen i_stream_unref(&client->common.input);
97333cbaa7893be8bac7b5741e328ebfff0aeab0Timo Sirainen if (client->output != NULL)
97333cbaa7893be8bac7b5741e328ebfff0aeab0Timo Sirainen o_stream_unref(&client->output);
97333cbaa7893be8bac7b5741e328ebfff0aeab0Timo Sirainen
97333cbaa7893be8bac7b5741e328ebfff0aeab0Timo Sirainen i_free(client->common.virtual_user);
8f5b34c22e4c3bfb35ca13c4744867eb5ddbd3d6Timo Sirainen i_free(client->common.auth_mech_name);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_free(client);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return FALSE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenvoid client_send_line(struct imap_client *client, const char *line)
2eb0402a28bd0422e0170160808c67d6c7274689Timo Sirainen{
97180ea9c26c4de0807daaad21e03c80643b09fdTimo Sirainen struct const_iovec iov[2];
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen ssize_t ret;
2eb0402a28bd0422e0170160808c67d6c7274689Timo Sirainen
2eb0402a28bd0422e0170160808c67d6c7274689Timo Sirainen iov[0].iov_base = line;
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen iov[0].iov_len = strlen(line);
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen iov[1].iov_base = "\r\n";
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen iov[1].iov_len = 2;
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen ret = o_stream_sendv(client->output, iov, 2);
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen if (ret < 0 || (size_t)ret != iov[0].iov_len + iov[1].iov_len) {
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen /* either disconnection or buffer full. in either case we
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen want this connection destroyed. however destroying it here
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen might break things if client is still tried to be accessed
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen without being referenced.. */
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen i_stream_close(client->common.input);
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen }
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen}
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainenvoid client_send_tagline(struct imap_client *client, const char *line)
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen{
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen client_send_line(client, t_strconcat(client->cmd_tag, " ", line, NULL));
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen}
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainenvoid clients_notify_auth_connected(void)
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct client *client;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen for (client = clients; client != NULL; client = client->next) {
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen struct imap_client *imap_client = (struct imap_client *)client;
dbe06905918a415a34c5621b9fdf45be0b9c8e64Timo Sirainen
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen if (imap_client->to_auth_waiting != NULL)
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen timeout_remove(&imap_client->to_auth_waiting);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (!imap_client->greeting_sent)
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen client_send_greeting(imap_client);
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen if (imap_client->input_blocked) {
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen imap_client->input_blocked = FALSE;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen client_input(imap_client);
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen }
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen }
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen}
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen
762e17079d29d9f1838114ff5fec9ceaba8eb6a8Timo Sirainenvoid clients_destroy_all(void)
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen{
50349cd047ca9e7c100cbeb70acfe26672649959Timo Sirainen struct client *client;
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen for (client = clients; client != NULL; client = client->next) {
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen struct imap_client *imap_client = (struct imap_client *)client;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen client_destroy(imap_client, "Disconnected: Shutting down");
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen }
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen}
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenvoid clients_init(void)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen{
674f541b16689c0ed090dac32db94463c5af3977Timo Sirainen /* Nothing to initialize for IMAP */
674f541b16689c0ed090dac32db94463c5af3977Timo Sirainen}
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
674f541b16689c0ed090dac32db94463c5af3977Timo Sirainenvoid clients_deinit(void)
faca2afa3576c50caf28e0f009555325d2a49e0bTimo Sirainen{
faca2afa3576c50caf28e0f009555325d2a49e0bTimo Sirainen clients_destroy_all();
faca2afa3576c50caf28e0f009555325d2a49e0bTimo Sirainen}
faca2afa3576c50caf28e0f009555325d2a49e0bTimo Sirainen