client.c revision feb665db52583259a1f42037c6e8a22852aa8889
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch/* Copyright (C) 2002 Timo Sirainen */
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch/* max. length of input command line (spec says 512), or max reply length in
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch SASL authentication */
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch/* max. size of output buffer. if it gets full, the client is disconnected.
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch SASL authentication gives the largest output. */
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch/* Disconnect client after idling this many seconds */
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch/* Disconnect client when it sends too many bad commands */
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch/* When max. number of simultaneous connections is reached, few of the
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch oldest connections are disconnected. Since we have to go through the whole
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch client hash, it's faster if we disconnect multiple clients. */
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch#if CLIENT_LOGIN_IDLE_TIMEOUT >= AUTH_REQUEST_TIMEOUT
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch# error client idle timeout must be smaller than authentication timeout
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Boschstatic void client_set_title(struct pop3_client *client)
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch if (!verbose_proctitle || !process_per_connection)
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch process_title_set(t_strdup_printf(client->common.tls ?
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Boschstatic void client_open_streams(struct pop3_client *client, int fd)
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch client->input = i_stream_create_file(fd, default_pool,
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch client->output = o_stream_create_file(fd, default_pool,
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Boschstatic void client_start_tls(struct pop3_client *client)
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch fd_ssl = ssl_proxy_new(client->common.fd, &client->common.ip,
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch client_send_line(client, "-ERR TLS initialization failed.");
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch "Disconnected: TLS initialization failed.");
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch client->io = io_add(client->common.fd, IO_READ, client_input, client);
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Boschstatic int client_output_starttls(void *context)
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch if ((ret = o_stream_flush(client->output)) < 0) {
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch o_stream_set_flush_callback(client->output, NULL, NULL);
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Boschstatic bool cmd_stls(struct pop3_client *client)
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch client_send_line(client, "-ERR TLS is already active.");
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch client_send_line(client, "-ERR TLS support isn't enabled.");
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch /* remove input handler, SSL proxy gives us a new fd. we also have to
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch remove it in case we have to wait for buffer to be flushed */
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch client_send_line(client, "+OK Begin TLS negotiation now.");
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch /* uncork the old fd */
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch /* the buffer has to be flushed */
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch o_stream_set_flush_pending(client->output, TRUE);
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Boschstatic bool cmd_quit(struct pop3_client *client)
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Boschstatic bool client_command_execute(struct pop3_client *client, const char *cmd,
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch client_send_line(client, "-ERR Unknown command.");
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch /* buffer full */
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch client_send_line(client, "-ERR Input line too long, aborting");
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch client_destroy(client, "Disconnected: Input buffer full");
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch /* disconnected */
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch /* something was read */
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch (line = i_stream_next_line(client->input)) != NULL) {
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch if (client_command_execute(client, line, args))
1bd20e2a575473f3d05499f05f1d72da59b34fd6Stephan Bosch else if (++client->bad_counter > CLIENT_MAX_BAD_COMMANDS) {
void client_destroy_oldest(void)
unsigned int i, destroy_count;
for (i = 0; i < destroy_count; i++) {
sizeof(destroy_buf) -
for (i = 0; i < destroy_count; i++) {
char *ret;
return NULL;
t_push();
(unsigned long)ioloop_time,
t_pop();
return ret;
main_ref();
main_unref();
return TRUE;
return FALSE;
unsigned int clients_get_count(void)
void clients_notify_auth_connected(void)
void clients_destroy_all(void)
void clients_init(void)
void clients_deinit(void)