client.c revision 00fa8dcbc66f56daa737487c9dec7166c37de79e
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen/* max. size of output buffer. if it gets full, the client is disconnected.
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen SASL authentication gives the largest output. */
c8b5a21a139992e66b4ad02adb69eaf929b3d024Timo Sirainen/* Disconnect client when it sends too many bad commands */
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen/* When max. number of simultaneous connections is reached, few of the
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen oldest connections are disconnected. Since we have to go through all of the
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen clients, it's faster if we disconnect multiple clients. */
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen#if CLIENT_LOGIN_IDLE_TIMEOUT_MSECS < AUTH_REQUEST_TIMEOUT*1000
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen# error client idle timeout must be larger than authentication timeout
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainenstatic void client_set_title(struct pop3_client *client)
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen !client->common.set->login_process_per_connection)
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen process_title_set(t_strdup_printf(client->common.tls ?
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainenstatic void client_open_streams(struct pop3_client *client, int fd)
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen i_stream_create_fd(fd, LOGIN_MAX_INBUF_SIZE, FALSE);
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen client->output = o_stream_create_fd(fd, MAX_OUTBUF_SIZE, FALSE);
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainenstatic void client_start_tls(struct pop3_client *client)
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen if (!client_unref(client) || client->destroyed)
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen fd_ssl = ssl_proxy_new(client->common.fd, &client->common.ip,
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen client_send_line(&client->common, CLIENT_CMD_REPLY_BYE,
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen "TLS initialization failed.");
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen "Disconnected: TLS initialization failed.");
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen client->io = io_add(client->common.fd, IO_READ, client_input, client);
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainenstatic int client_output_starttls(struct pop3_client *client)
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen if ((ret = o_stream_flush(client->output)) < 0) {
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen o_stream_unset_flush_callback(client->output);
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainenstatic bool cmd_stls(struct pop3_client *client)
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen client_send_line(&client->common, CLIENT_CMD_REPLY_BAD,
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen "TLS is already active.");
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen client_send_line(&client->common, CLIENT_CMD_REPLY_BAD,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen "TLS support isn't enabled.");
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen /* remove input handler, SSL proxy gives us a new fd. we also have to
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen remove it in case we have to wait for buffer to be flushed */
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen client_send_line(&client->common, CLIENT_CMD_REPLY_OK,
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen "Begin TLS negotiation now.");
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen /* uncork the old fd */
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen /* the buffer has to be flushed */
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen o_stream_set_flush_pending(client->output, TRUE);
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainenstatic bool cmd_quit(struct pop3_client *client)
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen client_send_line(&client->common, CLIENT_CMD_REPLY_OK, "Logging out");
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainenstatic bool client_command_execute(struct pop3_client *client, const char *cmd,
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen client_send_line(&client->common, CLIENT_CMD_REPLY_BAD,
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen "Unknown command.");
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen switch (i_stream_read(client->common.input)) {
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen /* buffer full */
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen client_send_line(&client->common, CLIENT_CMD_REPLY_BYE,
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen "Input buffer full, aborting");
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen client_destroy(client, "Disconnected: Input buffer full");
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen /* disconnected */
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen /* nothing new read */
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen /* something was read */
void client_destroy_oldest(void)
unsigned int max_connections =
unsigned int i, destroy_count;
for (i = 0; i < destroy_count; i++) {
sizeof(destroy_buf) -
for (i = 0; i < destroy_count; i++) {
return NULL;
(unsigned long)ioloop_time,
NULL);
return TRUE;
return FALSE;
const char *text)
switch (reply) {
case CLIENT_CMD_REPLY_OK:
case CLIENT_CMD_REPLY_BAD:
case CLIENT_CMD_REPLY_BYE:
case CLIENT_CMD_REPLY_STATUS:
T_BEGIN {
} T_END;
void clients_notify_auth_connected(void)
void clients_destroy_all(void)
void clients_init(void)
void clients_deinit(void)