client.c revision e59faf65ce864fe95dc00f5d52b8323cdbd0608a
7cb128dc4cae2a03a742f63ba7afee23c78e3af0Phil Carmody/* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "login-common.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "base64.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "buffer.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "ioloop.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "istream.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "ostream.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "randgen.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "hostpid.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "safe-memset.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "str.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "strescape.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "master-service.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "client.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "client-authenticate.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "auth-client.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "ssl-proxy.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "pop3-proxy.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "pop3-login-settings.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen/* Disconnect client when it sends too many bad commands */
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#define CLIENT_MAX_BAD_COMMANDS 10
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainenconst char *login_protocol = "pop3";
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainenconst char *login_process_name = "pop3-login";
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainenunsigned int login_default_port = 110;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainenvoid login_process_preinit(void)
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen{
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen}
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainenstatic bool cmd_stls(struct pop3_client *client)
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen{
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen client_cmd_starttls(&client->common);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen return TRUE;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen}
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainenstatic bool cmd_quit(struct pop3_client *client)
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen{
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen client_send_line(&client->common, CLIENT_CMD_REPLY_OK, "Logging out");
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen client_destroy(&client->common, "Aborted login");
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen return TRUE;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen}
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainenstatic bool client_command_execute(struct pop3_client *client, const char *cmd,
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen const char *args)
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen{
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen cmd = t_str_ucase(cmd);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen if (strcmp(cmd, "CAPA") == 0)
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen return cmd_capa(client, args);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen if (strcmp(cmd, "USER") == 0)
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen return cmd_user(client, args);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen if (strcmp(cmd, "PASS") == 0)
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen return cmd_pass(client, args);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen if (strcmp(cmd, "AUTH") == 0)
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen return cmd_auth(client, args);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen if (strcmp(cmd, "APOP") == 0)
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen return cmd_apop(client, args);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen if (strcmp(cmd, "STLS") == 0)
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen return cmd_stls(client);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen if (strcmp(cmd, "QUIT") == 0)
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen return cmd_quit(client);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen client_send_line(&client->common, CLIENT_CMD_REPLY_BAD,
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen "Unknown command.");
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen return FALSE;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen}
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainenstatic void pop3_client_input(struct client *client)
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen{
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen struct pop3_client *pop3_client = (struct pop3_client *)client;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen char *line, *args;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen i_assert(!client->authenticating);
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen if (!client_read(client))
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen return;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen client_ref(client);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen o_stream_cork(client->output);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen /* if a command starts an authentication, stop processing further
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen commands until the authentication is finished. */
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen while (!client->output->closed && !client->authenticating &&
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen auth_client_is_connected(auth_client) &&
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen (line = i_stream_next_line(client->input)) != NULL) {
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen args = strchr(line, ' ');
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen if (args != NULL)
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen *args++ = '\0';
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen if (client_command_execute(pop3_client, line,
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen args != NULL ? args : ""))
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen client->bad_counter = 0;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen else if (++client->bad_counter > CLIENT_MAX_BAD_COMMANDS) {
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen client_send_line(client, CLIENT_CMD_REPLY_BYE,
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen "Too many invalid bad commands.");
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen client_destroy(client,
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen "Disconnected: Too many bad commands");
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen }
5f237cf1915127fe143ac4c1d3cb4d1139f3b97dTimo Sirainen }
5f237cf1915127fe143ac4c1d3cb4d1139f3b97dTimo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen if (auth_client != NULL && !auth_client_is_connected(auth_client))
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen client->input_blocked = TRUE;
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen if (client_unref(&client))
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen o_stream_uncork(client->output);
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen}
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainenstatic struct client *pop3_client_alloc(pool_t pool)
5f237cf1915127fe143ac4c1d3cb4d1139f3b97dTimo Sirainen{
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen struct pop3_client *pop3_client;
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen pop3_client = p_new(pool, struct pop3_client, 1);
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen return &pop3_client->common;
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen}
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainenstatic void pop3_client_create(struct client *client ATTR_UNUSED,
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen void **other_sets ATTR_UNUSED)
5f237cf1915127fe143ac4c1d3cb4d1139f3b97dTimo Sirainen{
5f237cf1915127fe143ac4c1d3cb4d1139f3b97dTimo Sirainen}
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainenstatic void pop3_client_destroy(struct client *client)
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen{
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen struct pop3_client *pop3_client = (struct pop3_client *)client;
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen i_free_and_null(pop3_client->last_user);
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen i_free_and_null(pop3_client->apop_challenge);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen}
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainenstatic char *get_apop_challenge(struct pop3_client *client)
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen{
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen unsigned char buffer[16];
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen unsigned char buffer_base64[MAX_BASE64_ENCODED_SIZE(sizeof(buffer)) + 1];
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen buffer_t buf;
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen auth_client_get_connect_id(auth_client, &client->apop_server_pid,
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen &client->apop_connect_uid);
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen random_fill(buffer, sizeof(buffer));
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen buffer_create_data(&buf, buffer_base64, sizeof(buffer_base64));
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen base64_encode(buffer, sizeof(buffer), &buf);
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen buffer_append_c(&buf, '\0');
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen return i_strdup_printf("<%x.%x.%lx.%s@%s>",
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen client->apop_server_pid,
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen client->apop_connect_uid,
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen (unsigned long)ioloop_time,
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen (const char *)buf.data, my_hostname);
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen}
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainenstatic void pop3_client_send_greeting(struct client *client)
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen{
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen struct pop3_client *pop3_client = (struct pop3_client *)client;
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen client->io = io_add(client->fd, IO_READ, client_input, client);
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen pop3_client->apop_challenge = get_apop_challenge(pop3_client);
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen if (pop3_client->apop_challenge == NULL) {
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen client_send_line(client, CLIENT_CMD_REPLY_OK,
f148466c7b648669b99bf20c651ae7fc81d28659Timo Sirainen client->set->login_greeting);
f148466c7b648669b99bf20c651ae7fc81d28659Timo Sirainen } else {
f148466c7b648669b99bf20c651ae7fc81d28659Timo Sirainen client_send_line(client, CLIENT_CMD_REPLY_OK,
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen t_strconcat(client->set->login_greeting, " ",
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen pop3_client->apop_challenge, NULL));
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen }
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen client->greeting_sent = TRUE;
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen}
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainenstatic void pop3_client_starttls(struct client *client ATTR_UNUSED)
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen{
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen}
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainenstatic void
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainenpop3_client_send_line(struct client *client, enum client_cmd_reply reply,
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen const char *text)
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen{
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen const char *prefix = "-ERR";
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen switch (reply) {
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen case CLIENT_CMD_REPLY_OK:
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen prefix = "+OK";
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen break;
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen case CLIENT_CMD_REPLY_AUTH_FAIL_TEMP:
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen prefix = "-ERR [IN-USE]";
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen break;
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen case CLIENT_CMD_REPLY_AUTH_FAILED:
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen case CLIENT_CMD_REPLY_AUTHZ_FAILED:
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen case CLIENT_CMD_REPLY_AUTH_FAIL_REASON:
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen case CLIENT_CMD_REPLY_AUTH_FAIL_NOSSL:
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen case CLIENT_CMD_REPLY_BAD:
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen case CLIENT_CMD_REPLY_BYE:
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen break;
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen case CLIENT_CMD_REPLY_STATUS:
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen case CLIENT_CMD_REPLY_STATUS_BAD:
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen /* can't send status notifications */
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen return;
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen }
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen T_BEGIN {
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen string_t *line = t_str_new(256);
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen str_append(line, prefix);
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen str_append_c(line, ' ');
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen str_append(line, text);
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen str_append(line, "\r\n");
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen client_send_raw_data(client, str_data(line),
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen str_len(line));
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen } T_END;
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen}
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainenstatic void pop3_login_die(void)
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen{
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen /* do nothing. pop3 connections typically die pretty quick anyway. */
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen}
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainenvoid clients_init(void)
a4392e9d312e3b5973fe5dbaee7028197a700ff0Timo Sirainen{
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen login_set_roots = pop3_login_setting_roots;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen /* override the default login_die() */
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen master_service_set_die_callback(master_service, pop3_login_die);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen}
void clients_deinit(void)
{
clients_destroy_all();
}
struct client_vfuncs client_vfuncs = {
pop3_client_alloc,
pop3_client_create,
pop3_client_destroy,
pop3_client_send_greeting,
pop3_client_starttls,
pop3_client_input,
pop3_client_send_line,
pop3_client_auth_handle_reply,
NULL,
NULL,
pop3_proxy_reset,
pop3_proxy_parse_line
};