client.c revision 74ee5590487e89b25dffb58560ab1fea79fc21d9
2e37d45867d081db150ab78dad303b9077aea24fTimo Sirainen/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "common.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "buffer.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "ioloop.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "istream.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "ostream.h"
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen#include "process-title.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "safe-memset.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "str.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "strescape.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "imap-parser.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "imap-id.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "master-service.h"
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen#include "master-auth.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "client.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "client-authenticate.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "auth-client.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "ssl-proxy.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "imap-proxy.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include <stdlib.h>
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen/* max. size of output buffer. if it gets full, the client is disconnected.
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen SASL authentication gives the largest output. */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#define MAX_OUTBUF_SIZE 4096
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen/* maximum length for IMAP command line. */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#define MAX_IMAP_LINE 8192
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen/* Disconnect client when it sends too many bad commands */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#define CLIENT_MAX_BAD_COMMANDS 10
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen/* When max. number of simultaneous connections is reached, few of the
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen oldest connections are disconnected. Since we have to go through all of the
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen clients, it's faster if we disconnect multiple clients. */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#define CLIENT_DESTROY_OLDEST_COUNT 16
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen/* If we've been waiting auth server to respond for over this many milliseconds,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen send a "waiting" message. */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#define AUTH_WAITING_TIMEOUT_MSECS (30*1000)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#if CLIENT_LOGIN_IDLE_TIMEOUT_MSECS < AUTH_REQUEST_TIMEOUT*1000
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen# error client idle timeout must be larger than authentication timeout
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#endif
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#define AUTH_SERVER_WAITING_MSG \
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen "* OK Waiting for authentication process to respond.."
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#define AUTH_MASTER_WAITING_MSG \
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen "* OK Waiting for authentication master process to respond.."
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenconst char *login_protocol = "imap";
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenconst char *login_process_name = "imap-login";
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void client_set_title(struct imap_client *client)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen const char *addr;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (!client->common.set->verbose_proctitle ||
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen !client->common.set->login_process_per_connection)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen addr = net_ip2addr(&client->common.ip);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (addr == NULL)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen addr = "??";
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen process_title_set(t_strdup_printf(client->common.tls ?
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen "[%s TLS]" : "[%s]", addr));
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void client_open_streams(struct imap_client *client, int fd)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client->common.input =
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_stream_create_fd(fd, LOGIN_MAX_INBUF_SIZE, FALSE);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client->output = o_stream_create_fd(fd, MAX_OUTBUF_SIZE, FALSE);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client->parser = imap_parser_create(client->common.input,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client->output, MAX_IMAP_LINE);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen/* Skip incoming data until newline is found,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen returns TRUE if newline was found. */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenbool client_skip_line(struct imap_client *client)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen const unsigned char *data;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen size_t i, data_size;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen data = i_stream_get_data(client->common.input, &data_size);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen for (i = 0; i < data_size; i++) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (data[i] == '\n') {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_stream_skip(client->common.input, i+1);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return TRUE;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return FALSE;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic const char *get_capability(struct imap_client *client)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen const char *auths;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen auths = client_authenticate_get_capabilities(client);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return t_strconcat(CAPABILITY_BANNER_STRING,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen (ssl_initialized && !client->common.tls) ?
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen " STARTTLS" : "",
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client->common.set->disable_plaintext_auth &&
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen !client->common.secured ?
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen " LOGINDISABLED" : "", auths, NULL);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic int cmd_capability(struct imap_client *client)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* Client is required to send CAPABILITY after STARTTLS, so the
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen capability resp-code workaround checks only pre-STARTTLS
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen CAPABILITY commands. */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (!client->starttls)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client->client_ignores_capability_resp_code = TRUE;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client_send_line(client, t_strconcat(
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen "* CAPABILITY ", get_capability(client), NULL));
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client_send_tagline(client, "OK Capability completed.");
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return 1;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void client_start_tls(struct imap_client *client)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen int fd_ssl;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client_ref(client);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (!client_unref(client) || client->destroyed)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fd_ssl = ssl_proxy_new(client->common.fd, &client->common.ip,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client->common.set, &client->common.proxy);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (fd_ssl == -1) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client_send_line(client, "* BYE TLS initialization failed.");
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client_destroy(client,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen "Disconnected: TLS initialization failed.");
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client->starttls = TRUE;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client->common.proxying = TRUE;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client->common.tls = TRUE;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client->common.secured = TRUE;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client_set_title(client);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client->common.fd = fd_ssl;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_stream_unref(&client->common.input);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen o_stream_unref(&client->output);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen imap_parser_destroy(&client->parser);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* CRLF is lost from buffer when streams are reopened. */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client->skip_line = FALSE;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client_open_streams(client, fd_ssl);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client->io = io_add(client->common.fd, IO_READ, client_input, client);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic int client_output_starttls(struct imap_client *client)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen int ret;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if ((ret = o_stream_flush(client->output)) < 0) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client_destroy(client, "Disconnected");
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return 1;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (ret > 0) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen o_stream_unset_flush_callback(client->output);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen client_start_tls(client);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int cmd_starttls(struct imap_client *client)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (client->common.tls) {
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainen client_send_tagline(client, "BAD TLS is already active.");
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e8bdf1be00aec45d0c6dd72ad9c8be02a3dfc778Timo Sirainen if (!ssl_initialized) {
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen client_send_tagline(client, "BAD TLS support isn't enabled.");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
2abfef71398a61e5ed97c23a1ceb71461933ccb8Timo Sirainen /* remove input handler, SSL proxy gives us a new fd. we also have to
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen remove it in case we have to wait for buffer to be flushed */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (client->io != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen io_remove(&client->io);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client_send_tagline(client, "OK Begin TLS negotiation now.");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen /* uncork the old fd */
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen o_stream_uncork(client->output);
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen if (o_stream_flush(client->output) <= 0) {
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen /* the buffer has to be flushed */
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen o_stream_set_flush_pending(client->output, TRUE);
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen o_stream_set_flush_callback(client->output,
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen client_output_starttls, client);
cbf7138b49d32fce0645dc6523fbb42cc07cb2faTimo Sirainen } else {
cbf7138b49d32fce0645dc6523fbb42cc07cb2faTimo Sirainen client_start_tls(client);
b9b48aaaebf6f72dfab567cda073cde8a7b26598Timo Sirainen }
b9b48aaaebf6f72dfab567cda073cde8a7b26598Timo Sirainen return 1;
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen}
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenclient_update_info(struct imap_client *client, const struct imap_arg *args)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *key, *value;
e30b748edcef3cf3352478bf21fa8f785bdc773aTimo Sirainen
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen if (args->type != IMAP_ARG_LIST)
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen return;
d4dcb9c30dba354cff7af6d303ecef7698194c55Timo Sirainen args = IMAP_ARG_LIST_ARGS(args);
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen while (args->type == IMAP_ARG_STRING &&
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen args[1].type == IMAP_ARG_STRING) {
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen key = IMAP_ARG_STR_NONULL(&args[0]);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen value = IMAP_ARG_STR_NONULL(&args[1]);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (strcasecmp(key, "x-originating-ip") == 0)
9c7e765845357342923e16351181091028e5930fTimo Sirainen (void)net_addr2ip(value, &client->common.ip);
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen else if (strcasecmp(key, "x-originating-port") == 0)
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen client->common.remote_port = atoi(value);
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen else if (strcasecmp(key, "x-connected-ip") == 0)
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen (void)net_addr2ip(value, &client->common.local_ip);
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen else if (strcasecmp(key, "x-connected-port") == 0)
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen client->common.local_port = atoi(value);
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen args += 2;
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen }
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen}
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen
b00787191c3c31bebb939c3d00f1fcdb67356c69Timo Sirainenstatic int cmd_id(struct imap_client *client, const struct imap_arg *args)
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen{
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen const char *env, *value;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen if (!client->id_logged) {
d22301419109ed4a38351715e6760011421dadecTimo Sirainen client->id_logged = TRUE;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen if (client->common.trusted)
ee116df08d0fdab703483e18fe8076b2ef9fd9d7Timo Sirainen client_update_info(client, args);
ee116df08d0fdab703483e18fe8076b2ef9fd9d7Timo Sirainen
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen env = getenv("IMAP_ID_LOG");
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen value = imap_id_args_get_log_reply(args, env);
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen if (value != NULL) {
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen client_syslog(&client->common,
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen t_strdup_printf("ID sent: %s", value));
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen }
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e30b748edcef3cf3352478bf21fa8f785bdc773aTimo Sirainen env = getenv("IMAP_ID_SEND");
e30b748edcef3cf3352478bf21fa8f785bdc773aTimo Sirainen client_send_line(client, t_strdup_printf("* ID %s",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen imap_id_reply_generate(env)));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client_send_tagline(client, "OK ID completed.");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainenstatic int cmd_noop(struct imap_client *client)
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen{
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen client_send_tagline(client, "OK NOOP completed.");
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen return 1;
e30b748edcef3cf3352478bf21fa8f785bdc773aTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int cmd_logout(struct imap_client *client)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client_send_line(client, "* BYE Logging out");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client_send_tagline(client, "OK Logout completed.");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client_destroy(client, "Aborted login");
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen return 1;
ea9fd7f876643e985946a2563140359064819b8eTimo Sirainen}
ea9fd7f876643e985946a2563140359064819b8eTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int cmd_enable(struct imap_client *client)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen client_send_line(client, "* ENABLED");
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen client_send_tagline(client,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "OK ENABLE ignored in non-authenticated state.");
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen return 1;
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen}
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int client_command_execute(struct imap_client *client, const char *cmd,
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen const struct imap_arg *args)
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen{
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen cmd = t_str_ucase(cmd);
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen if (strcmp(cmd, "LOGIN") == 0)
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen return cmd_login(client, args);
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen if (strcmp(cmd, "AUTHENTICATE") == 0)
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen return cmd_authenticate(client, args);
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen if (strcmp(cmd, "CAPABILITY") == 0)
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen return cmd_capability(client);
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen if (strcmp(cmd, "STARTTLS") == 0)
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen return cmd_starttls(client);
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen if (strcmp(cmd, "ID") == 0)
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen return cmd_id(client, args);
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen if (strcmp(cmd, "NOOP") == 0)
cbf7138b49d32fce0645dc6523fbb42cc07cb2faTimo Sirainen return cmd_noop(client);
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen if (strcmp(cmd, "LOGOUT") == 0)
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen return cmd_logout(client);
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen if (strcmp(cmd, "ENABLE") == 0)
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen return cmd_enable(client);
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen return -1;
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen}
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainenstatic bool client_handle_input(struct imap_client *client)
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen{
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen const struct imap_arg *args;
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen const char *msg;
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen int ret;
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen bool fatal;
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen i_assert(!client->common.authenticating);
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen if (client->cmd_finished) {
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen /* clear the previous command from memory. don't do this
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen immediately after handling command since we need the
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen cmd_tag to stay some time after authentication commands. */
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen client->cmd_tag = NULL;
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen client->cmd_name = NULL;
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen imap_parser_reset(client->parser);
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen
538303a216166f3526c0ae9658c9978275cfa100Timo Sirainen /* remove \r\n */
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen if (client->skip_line) {
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen if (!client_skip_line(client))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen client->skip_line = FALSE;
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen }
a87e5f15283e057c7dc26dd9db7b616268c95ca7Timo Sirainen
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen client->cmd_finished = FALSE;
c93cd163f9c1d4b0ca29f49cbfdbf474caeef5bfTimo Sirainen }
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (client->cmd_tag == NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client->cmd_tag = imap_parser_read_word(client->parser);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (client->cmd_tag == NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE; /* need more data */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen if (client->cmd_name == NULL) {
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen client->cmd_name = imap_parser_read_word(client->parser);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen if (client->cmd_name == NULL)
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen return FALSE; /* need more data */
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen }
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen switch (imap_parser_read_args(client->parser, 0, 0, &args)) {
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen case -1:
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen /* error */
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen msg = imap_parser_get_error(client->parser, &fatal);
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen if (fatal) {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen client_send_line(client, t_strconcat("* BYE ",
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen msg, NULL));
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen client_destroy(client,
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen t_strconcat("Disconnected: ", msg, NULL));
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen return FALSE;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen }
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen client_send_tagline(client, t_strconcat("BAD ", msg, NULL));
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen client->cmd_finished = TRUE;
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainen client->skip_line = TRUE;
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen case -2:
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen /* not enough data */
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* we read the entire line - skip over the CRLF */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!client_skip_line(client))
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen i_unreached();
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen if (*client->cmd_tag == '\0')
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen ret = -1;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen else
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen ret = client_command_execute(client, client->cmd_name, args);
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen client->cmd_finished = TRUE;
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen if (ret < 0) {
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen if (*client->cmd_tag == '\0')
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen client->cmd_tag = "*";
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen if (++client->bad_counter >= CLIENT_MAX_BAD_COMMANDS) {
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen client_send_line(client,
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen "* BYE Too many invalid IMAP commands.");
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainen client_destroy(client,
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainen "Disconnected: Too many invalid commands");
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainen return FALSE;
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainen }
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainen client_send_tagline(client,
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainen "BAD Error in IMAP command received by server.");
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainen }
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen return ret != 0;
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen}
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainenbool client_read(struct imap_client *client)
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen{
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen switch (i_stream_read(client->common.input)) {
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen case -2:
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen /* buffer full */
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen client_send_line(client, "* BYE Input buffer full, aborting");
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen client_destroy(client, "Disconnected: Input buffer full");
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen return FALSE;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen case -1:
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen /* disconnected */
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen client_destroy(client, "Disconnected");
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen return FALSE;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen case 0:
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen /* nothing new read */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen default:
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen /* something was read */
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen timeout_reset(client->to_idle_disconnect);
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen return TRUE;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen }
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen}
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
b3bb775c6b735a7f6021dea799601fbfdb656e58Timo Sirainenvoid client_input(struct imap_client *client)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen{
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen if (!client_read(client))
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen return;
b3bb775c6b735a7f6021dea799601fbfdb656e58Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen client_ref(client);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
d77c309fccbc6a7594f8cb08fb01009fa613c568Timo Sirainen if (!auth_client_is_connected(auth_client)) {
d77c309fccbc6a7594f8cb08fb01009fa613c568Timo Sirainen /* we're not yet connected to auth process -
d77c309fccbc6a7594f8cb08fb01009fa613c568Timo Sirainen don't allow any commands */
d22301419109ed4a38351715e6760011421dadecTimo Sirainen client_send_line(client, AUTH_SERVER_WAITING_MSG);
4145cbac82bfc0c8bfeceeca0ef841700117930cTimo Sirainen if (client->to_auth_waiting != NULL)
ced118ac5caf6fe83d34339c2c65c63b2aa768acTimo Sirainen timeout_remove(&client->to_auth_waiting);
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo Sirainen
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo Sirainen client->input_blocked = TRUE;
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo Sirainen } else {
7bd6001d84ecc1792ddfd54fe8efa63c509d90b1Timo Sirainen o_stream_cork(client->output);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while (client_handle_input(client)) ;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen o_stream_uncork(client->output);
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
9a56220167d02bbcb66a81b7553f4eb4da939945Timo Sirainen client_unref(client);
9a56220167d02bbcb66a81b7553f4eb4da939945Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid client_destroy_oldest(void)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int max_connections =
8754bb7a1f24705ffa5434f9e10d57e0b3b88d6eTimo Sirainen global_login_settings->login_max_connections;
8754bb7a1f24705ffa5434f9e10d57e0b3b88d6eTimo Sirainen struct client *client;
8754bb7a1f24705ffa5434f9e10d57e0b3b88d6eTimo Sirainen struct imap_client *destroy_buf[CLIENT_DESTROY_OLDEST_COUNT];
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen unsigned int i, destroy_count;
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen /* find the oldest clients and put them to destroy-buffer */
b60baf6af900a610b2b2ddd24a46f8311acc3386Timo Sirainen memset(destroy_buf, 0, sizeof(destroy_buf));
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen destroy_count = max_connections > CLIENT_DESTROY_OLDEST_COUNT*2 ?
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen CLIENT_DESTROY_OLDEST_COUNT : I_MIN(max_connections/2, 1);
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen for (client = clients; client != NULL; client = client->next) {
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen struct imap_client *imap_client = (struct imap_client *)client;
b60baf6af900a610b2b2ddd24a46f8311acc3386Timo Sirainen
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen for (i = 0; i < destroy_count; i++) {
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen if (destroy_buf[i] == NULL ||
9a099a65160987349f441c82ab0e38f32b747adbTimo Sirainen destroy_buf[i]->created > imap_client->created) {
9a099a65160987349f441c82ab0e38f32b747adbTimo Sirainen /* @UNSAFE */
9a099a65160987349f441c82ab0e38f32b747adbTimo Sirainen memmove(destroy_buf+i+1, destroy_buf+i,
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen sizeof(destroy_buf) -
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (i+1) * sizeof(struct imap_client *));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen destroy_buf[i] = imap_client;
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
b60baf6af900a610b2b2ddd24a46f8311acc3386Timo Sirainen /* then kill them */
b60baf6af900a610b2b2ddd24a46f8311acc3386Timo Sirainen for (i = 0; i < destroy_count; i++) {
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen if (destroy_buf[i] == NULL)
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen break;
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client_destroy(destroy_buf[i],
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Disconnected: Connection queue full");
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen }
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen}
b60baf6af900a610b2b2ddd24a46f8311acc3386Timo Sirainen
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainenstatic void client_send_greeting(struct imap_client *client)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen string_t *greet;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen greet = t_str_new(128);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_append(greet, "* OK ");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_printfa(greet, "[CAPABILITY %s] ", get_capability(client));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_append(greet, client->common.set->login_greeting);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen client_send_line(client, str_c(greet));
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen client->greeting_sent = TRUE;
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen}
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void client_idle_disconnect_timeout(struct imap_client *client)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client_send_line(client, "* BYE Disconnected for inactivity.");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client_destroy(client, "Disconnected: Inactivity");
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainen}
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainen
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainenstatic void client_auth_waiting_timeout(struct imap_client *client)
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainen{
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainen client_send_line(client, client->common.master_tag == 0 ?
eae1d6e75713d3d658908ac39b719992e2f8a456Timo Sirainen AUTH_SERVER_WAITING_MSG : AUTH_MASTER_WAITING_MSG);
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainen timeout_remove(&client->to_auth_waiting);
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainen}
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo Sirainen
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo Sirainenvoid client_set_auth_waiting(struct imap_client *client)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen{
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo Sirainen i_assert(client->to_auth_waiting == NULL);
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo Sirainen client->to_auth_waiting =
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo Sirainen timeout_add(AUTH_WAITING_TIMEOUT_MSECS,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client_auth_waiting_timeout, client);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo Sirainenstruct client *client_create(int fd, bool ssl, pool_t pool,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct login_settings *set,
d77c309fccbc6a7594f8cb08fb01009fa613c568Timo Sirainen const struct ip_addr *local_ip,
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen const struct ip_addr *remote_ip)
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen{
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen struct imap_client *client;
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen i_assert(fd != -1);
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen if (clients_get_count() >= set->login_max_connections) {
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen /* reached max. users count, kill few of the
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen oldest connections */
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen client_destroy_oldest();
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen }
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen /* always use nonblocking I/O */
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen net_set_nonblock(fd, TRUE);
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen client = p_new(pool, struct imap_client, 1);
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen client->created = ioloop_time;
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen client->refcount = 1;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen client->common.pool = pool;
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen client->common.set = set;
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen client->common.local_ip = *local_ip;
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen client->common.ip = *remote_ip;
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen client->common.fd = fd;
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen client->common.tls = ssl;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen client->common.trusted = client_is_trusted(&client->common);
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen client->common.secured = ssl || client->common.trusted ||
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainen net_ip_compare(remote_ip, local_ip);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client_open_streams(client, fd);
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen client->io = io_add(fd, IO_READ, client_input, client);
a3d22d3cb0e5436128ca7287cedc921f1789b2c8Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen client_link(&client->common);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen if (auth_client_is_connected(auth_client))
d22301419109ed4a38351715e6760011421dadecTimo Sirainen client_send_greeting(client);
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen else
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen client_set_auth_waiting(client);
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen client_set_title(client);
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen client->to_idle_disconnect =
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen timeout_add(CLIENT_LOGIN_IDLE_TIMEOUT_MSECS,
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen client_idle_disconnect_timeout, client);
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen return &client->common;
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen}
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainenvoid client_destroy(struct imap_client *client, const char *reason)
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen{
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen if (client->destroyed)
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen return;
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen client->destroyed = TRUE;
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen if (!client->login_success && reason != NULL) {
a3d22d3cb0e5436128ca7287cedc921f1789b2c8Timo Sirainen reason = t_strconcat(reason, " ",
a3d22d3cb0e5436128ca7287cedc921f1789b2c8Timo Sirainen client_get_extra_disconnect_reason(&client->common),
7c449f545b10daa47027552f98d916a9805da662Timo Sirainen NULL);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen }
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen if (reason != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client_syslog(&client->common, reason);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen client_unlink(&client->common);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
7c449f545b10daa47027552f98d916a9805da662Timo Sirainen if (client->common.input != NULL)
7c449f545b10daa47027552f98d916a9805da662Timo Sirainen i_stream_close(client->common.input);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen if (client->output != NULL)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen o_stream_close(client->output);
ff4bb2dfb5714eeb0408d3bb862de1646351d097Timo Sirainen
b3bb775c6b735a7f6021dea799601fbfdb656e58Timo Sirainen if (client->common.master_tag != 0) {
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen i_assert(client->common.auth_request == NULL);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen i_assert(client->common.authenticating);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen master_auth_request_abort(master_service,
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen client->common.master_tag);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen } else if (client->common.auth_request != NULL) {
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen i_assert(client->common.authenticating);
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen sasl_server_auth_abort(&client->common);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen } else {
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen i_assert(!client->common.authenticating);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen }
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen if (client->io != NULL)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen io_remove(&client->io);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (client->to_idle_disconnect != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen timeout_remove(&client->to_idle_disconnect);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (client->to_auth_waiting != NULL)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen timeout_remove(&client->to_auth_waiting);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen if (client->to_authfail_delay != NULL)
fe813f74aaccb12f38e1bd9cd338c6a37fa646e5Timo Sirainen timeout_remove(&client->to_authfail_delay);
fe813f74aaccb12f38e1bd9cd338c6a37fa646e5Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen if (client->common.fd != -1) {
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen net_disconnect(client->common.fd);
60f9b96be55e63f0113e273dda8ba3b883c6f095Timo Sirainen client->common.fd = -1;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen }
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen if (client->proxy_password != NULL) {
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen safe_memset(client->proxy_password, 0,
fe813f74aaccb12f38e1bd9cd338c6a37fa646e5Timo Sirainen strlen(client->proxy_password));
fe813f74aaccb12f38e1bd9cd338c6a37fa646e5Timo Sirainen i_free(client->proxy_password);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen client->proxy_password = NULL;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen }
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen i_free_and_null(client->proxy_user);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free_and_null(client->proxy_master_user);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen i_free_and_null(client->proxy_backend_capability);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
bde6382cf65fba6165dc3603f5419e194d87f404Timo Sirainen if (client->proxy != NULL)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen login_proxy_free(&client->proxy);
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen if (client->common.proxy != NULL) {
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen ssl_proxy_free(client->common.proxy);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen client->common.proxy = NULL;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client_unref(client);
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen}
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainenvoid client_destroy_success(struct imap_client *client, const char *reason)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen{
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen client->login_success = TRUE;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen client_destroy(client, reason);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen}
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainenvoid client_destroy_internal_failure(struct imap_client *client)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen{
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen client_send_line(client, "* BYE Internal login failure. "
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen "Refer to server log for more information.");
60f9b96be55e63f0113e273dda8ba3b883c6f095Timo Sirainen client_destroy(client, "Internal login failure");
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid client_ref(struct imap_client *client)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client->refcount++;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
7895c4845da515b0aa9bb156674a1fca40803f44Timo Sirainen
7895c4845da515b0aa9bb156674a1fca40803f44Timo Sirainenbool client_unref(struct imap_client *client)
7895c4845da515b0aa9bb156674a1fca40803f44Timo Sirainen{
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen i_assert(client->refcount > 0);
7895c4845da515b0aa9bb156674a1fca40803f44Timo Sirainen if (--client->refcount > 0)
d22301419109ed4a38351715e6760011421dadecTimo Sirainen return TRUE;
7895c4845da515b0aa9bb156674a1fca40803f44Timo Sirainen
7895c4845da515b0aa9bb156674a1fca40803f44Timo Sirainen i_assert(client->destroyed);
7895c4845da515b0aa9bb156674a1fca40803f44Timo Sirainen
7895c4845da515b0aa9bb156674a1fca40803f44Timo Sirainen imap_parser_destroy(&client->parser);
7895c4845da515b0aa9bb156674a1fca40803f44Timo Sirainen
7895c4845da515b0aa9bb156674a1fca40803f44Timo Sirainen if (client->common.input != NULL)
7895c4845da515b0aa9bb156674a1fca40803f44Timo Sirainen i_stream_unref(&client->common.input);
7895c4845da515b0aa9bb156674a1fca40803f44Timo Sirainen if (client->output != NULL)
7895c4845da515b0aa9bb156674a1fca40803f44Timo Sirainen o_stream_unref(&client->output);
7895c4845da515b0aa9bb156674a1fca40803f44Timo Sirainen
7895c4845da515b0aa9bb156674a1fca40803f44Timo Sirainen if (!client->common.proxying) {
7895c4845da515b0aa9bb156674a1fca40803f44Timo Sirainen i_assert(client->common.proxy == NULL);
7895c4845da515b0aa9bb156674a1fca40803f44Timo Sirainen master_service_client_connection_destroyed(master_service);
7895c4845da515b0aa9bb156674a1fca40803f44Timo Sirainen }
7895c4845da515b0aa9bb156674a1fca40803f44Timo Sirainen
0ed9ccd0047f75df54a49bc117ca301eb398e447Timo Sirainen i_free(client->common.virtual_user);
0ed9ccd0047f75df54a49bc117ca301eb398e447Timo Sirainen i_free(client->common.auth_mech_name);
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen pool_unref(&client->common.pool);
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen return FALSE;
0ed9ccd0047f75df54a49bc117ca301eb398e447Timo Sirainen}
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainenvoid client_send_line(struct imap_client *client, const char *line)
0ed9ccd0047f75df54a49bc117ca301eb398e447Timo Sirainen{
0ed9ccd0047f75df54a49bc117ca301eb398e447Timo Sirainen struct const_iovec iov[2];
0ed9ccd0047f75df54a49bc117ca301eb398e447Timo Sirainen ssize_t ret;
0ed9ccd0047f75df54a49bc117ca301eb398e447Timo Sirainen
0ed9ccd0047f75df54a49bc117ca301eb398e447Timo Sirainen iov[0].iov_base = line;
0ed9ccd0047f75df54a49bc117ca301eb398e447Timo Sirainen iov[0].iov_len = strlen(line);
0ed9ccd0047f75df54a49bc117ca301eb398e447Timo Sirainen iov[1].iov_base = "\r\n";
0ed9ccd0047f75df54a49bc117ca301eb398e447Timo Sirainen iov[1].iov_len = 2;
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen ret = o_stream_sendv(client->output, iov, 2);
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainen if (ret < 0 || (size_t)ret != iov[0].iov_len + iov[1].iov_len) {
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainen /* either disconnection or buffer full. in either case we
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainen want this connection destroyed. however destroying it here
ced118ac5caf6fe83d34339c2c65c63b2aa768acTimo Sirainen might break things if client is still tried to be accessed
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainen without being referenced.. */
7c449f545b10daa47027552f98d916a9805da662Timo Sirainen i_stream_close(client->common.input);
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainen }
ced118ac5caf6fe83d34339c2c65c63b2aa768acTimo Sirainen}
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainen
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainenvoid client_send_tagline(struct imap_client *client, const char *line)
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainen{
0ed9ccd0047f75df54a49bc117ca301eb398e447Timo Sirainen client_send_line(client, t_strconcat(client->cmd_tag, " ", line, NULL));
0ed9ccd0047f75df54a49bc117ca301eb398e447Timo Sirainen}
4145cbac82bfc0c8bfeceeca0ef841700117930cTimo Sirainen
8d889b6d842e96ecbe7b6493920bbb6df8e0ed30Timo Sirainenvoid clients_notify_auth_connected(void)
0ed9ccd0047f75df54a49bc117ca301eb398e447Timo Sirainen{
8d889b6d842e96ecbe7b6493920bbb6df8e0ed30Timo Sirainen struct client *client;
0ed9ccd0047f75df54a49bc117ca301eb398e447Timo Sirainen
8d889b6d842e96ecbe7b6493920bbb6df8e0ed30Timo Sirainen for (client = clients; client != NULL; client = client->next) {
8d889b6d842e96ecbe7b6493920bbb6df8e0ed30Timo Sirainen struct imap_client *imap_client = (struct imap_client *)client;
0ed9ccd0047f75df54a49bc117ca301eb398e447Timo Sirainen
0ed9ccd0047f75df54a49bc117ca301eb398e447Timo Sirainen if (imap_client->to_auth_waiting != NULL)
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainen timeout_remove(&imap_client->to_auth_waiting);
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainen if (!imap_client->greeting_sent)
7d7f4648f72b8c70928e04514b0d93dad0ba6fd5Timo Sirainen client_send_greeting(imap_client);
7d7f4648f72b8c70928e04514b0d93dad0ba6fd5Timo Sirainen if (imap_client->input_blocked) {
7d7f4648f72b8c70928e04514b0d93dad0ba6fd5Timo Sirainen imap_client->input_blocked = FALSE;
4145cbac82bfc0c8bfeceeca0ef841700117930cTimo Sirainen client_input(imap_client);
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainen }
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainen }
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen}
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainenvoid clients_destroy_all(void)
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen{
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen struct client *client, *next;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainen for (client = clients; client != NULL; client = next) {
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainen struct imap_client *imap_client = (struct imap_client *)client;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
f7ad1162969feff6b08f0e640a928db1783daae9Timo Sirainen next = client->next;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client_destroy(imap_client, "Disconnected: Shutting down");
649823f9c7e42a424a8fadc427e12f3576c4f714Timo Sirainen }
f7ad1162969feff6b08f0e640a928db1783daae9Timo Sirainen}
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainenvoid clients_init(void)
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* Nothing to initialize for IMAP */
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainenvoid clients_deinit(void)
a38ef15060e45e5060bb24c403a580b9a57a818cTimo Sirainen{
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainen clients_destroy_all();
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainen}
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainen