client.c revision 2cfe9983ce7a6280636ee12beccc2e865111967b
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (C) 2002 Timo Sirainen */
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen/* max. length of input command line (spec says 512), or max reply length in
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen SASL authentication */
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen/* max. size of output buffer. if it gets full, the client is disconnected.
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen SASL authentication gives the largest output. */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen/* Disconnect client after idling this many seconds */
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen/* Disconnect client when it sends too many bad commands */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen/* When max. number of simultaneous connections is reached, few of the
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen oldest connections are disconnected. Since we have to go through the whole
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen client hash, it's faster if we disconnect multiple clients. */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#if CLIENT_LOGIN_IDLE_TIMEOUT >= AUTH_REQUEST_TIMEOUT
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen# error client idle timeout must be smaller than authentication timeout
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenstatic void client_set_title(struct pop3_client *client)
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen if (!verbose_proctitle || !process_per_connection)
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen process_title_set(t_strdup_printf(client->common.tls ?
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainenstatic void client_open_streams(struct pop3_client *client, int fd)
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen client->input = i_stream_create_file(fd, default_pool,
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen client->output = o_stream_create_file(fd, default_pool,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic void client_start_tls(struct pop3_client *client)
214b18002f289c15b4e48fef537a79db312c9d0fTimo Sirainen fd_ssl = ssl_proxy_new(client->common.fd, &client->common.ip,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen client_send_line(client, "-ERR TLS initialization failed.");
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen "Disconnected: TLS initialization failed.");
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen client->io = io_add(client->common.fd, IO_READ, client_input, client);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic int client_output_starttls(struct pop3_client *client)
53cd46dd843c22f21f7e6efcc52a3e0f76cd1e52Timo Sirainen if ((ret = o_stream_flush(client->output)) < 0) {
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen o_stream_unset_flush_callback(client->output);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenstatic bool cmd_stls(struct pop3_client *client)
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen client_send_line(client, "-ERR TLS is already active.");
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen client_send_line(client, "-ERR TLS support isn't enabled.");
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* remove input handler, SSL proxy gives us a new fd. we also have to
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen remove it in case we have to wait for buffer to be flushed */
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen client_send_line(client, "+OK Begin TLS negotiation now.");
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen /* uncork the old fd */
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen /* the buffer has to be flushed */
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen o_stream_set_flush_pending(client->output, TRUE);
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainenstatic bool cmd_quit(struct pop3_client *client)
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainenstatic bool client_command_execute(struct pop3_client *client, const char *cmd,
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen client_send_line(client, "-ERR Unknown command.");
53cd46dd843c22f21f7e6efcc52a3e0f76cd1e52Timo Sirainen /* buffer full */
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen client_send_line(client, "-ERR Input line too long, aborting");
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen client_destroy(client, "Disconnected: Input buffer full");
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen /* disconnected */
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen /* something was read */
989cafb9d84d8c98d6441fc1ab45b4c37762a98aTimo Sirainen (line = i_stream_next_line(client->input)) != NULL) {
989cafb9d84d8c98d6441fc1ab45b4c37762a98aTimo Sirainen else if (++client->bad_counter > CLIENT_MAX_BAD_COMMANDS) {
989cafb9d84d8c98d6441fc1ab45b4c37762a98aTimo Sirainen client_send_line(client, "-ERR Too many bad commands.");
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "Disconnected: Too many bad commands");
40fdb94d4db3d81e39f0f6655269ea7f6c268f32Timo Sirainen struct pop3_client *destroy_buf[CLIENT_DESTROY_OLDEST_COUNT];
40fdb94d4db3d81e39f0f6655269ea7f6c268f32Timo Sirainen unsigned int i, destroy_count;
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen /* find the oldest clients and put them to destroy-buffer */
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen destroy_count = max_connections > CLIENT_DESTROY_OLDEST_COUNT*2 ?
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen CLIENT_DESTROY_OLDEST_COUNT : I_MIN(max_connections/2, 1);
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen for (i = 0; i < destroy_count; i++) {
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen /* @UNSAFE */
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen /* then kill them */
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen for (i = 0; i < destroy_count; i++) {
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen "Disconnected: Connection queue full");
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainenstatic char *get_apop_challenge(struct pop3_client *client)
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen struct auth_connect_id *id = &client->auth_id;
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen if (!auth_client_reserve_connection(auth_client, "APOP", id))
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen buf = buffer_create_static_hard(pool_datastack_create(),
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen (unsigned long)ioloop_time,
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)