bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2004-2018 Dovecot authors, see the included COPYING file */
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen
46552a931924c2d743f045e95b08c3ce6beda91aTimo Sirainen#include "login-common.h"
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen#include "ioloop.h"
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen#include "istream.h"
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen#include "ostream.h"
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen#include "base64.h"
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen#include "safe-memset.h"
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen#include "str.h"
45155bb1250cf5a120278f349465aded513a100fTimo Sirainen#include "str-sanitize.h"
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi#include "strescape.h"
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen#include "dsasl-client.h"
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen#include "client.h"
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen#include "pop3-proxy.h"
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen
d77f679dac93f2416d6b04299b1a8154941036ddTimo Sirainenstatic const char *pop3_proxy_state_names[POP3_PROXY_STATE_COUNT] = {
d77f679dac93f2416d6b04299b1a8154941036ddTimo Sirainen "banner", "starttls", "xclient", "login1", "login2"
d77f679dac93f2416d6b04299b1a8154941036ddTimo Sirainen};
d77f679dac93f2416d6b04299b1a8154941036ddTimo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic void proxy_free_password(struct client *client)
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen{
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen if (client->proxy_password == NULL)
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen return;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen safe_memset(client->proxy_password, 0, strlen(client->proxy_password));
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen i_free_and_null(client->proxy_password);
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen}
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainenstatic int proxy_send_login(struct pop3_client *client, struct ostream *output)
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen{
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen struct dsasl_client_settings sasl_set;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen const unsigned char *sasl_output;
2c5c293940fd6c7e020e1d58dae77a9d01f9059bTimo Sirainen size_t len;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen const char *mech_name, *error;
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi string_t *str = t_str_new(128);
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen
9508ac436fff0e1dcea975855c139cd251deb703Timo Sirainen i_assert(client->common.proxy_ttl > 1);
6d24551e169c0808695db35d7a228f1970a84c75Timo Sirainen if (client->proxy_xclient &&
6d24551e169c0808695db35d7a228f1970a84c75Timo Sirainen !client->common.proxy_not_trusted) {
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi string_t *fwd = t_str_new(128);
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi for(const char *const *ptr = client->common.auth_passdb_args;*ptr != NULL; ptr++) {
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi if (strncasecmp(*ptr, "forward_", 8) == 0) {
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi if (str_len(fwd) > 0)
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi str_append_c(fwd, '\t');
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi str_append_tabescaped(fwd, (*ptr)+8);
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi }
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi }
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi str_printfa(str, "XCLIENT ADDR=%s PORT=%u SESSION=%s TTL=%u",
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi net_ip2addr(&client->common.ip),
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi client->common.remote_port,
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi client_get_session_id(&client->common),
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi client->common.proxy_ttl - 1);
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi if (str_len(fwd) > 0) {
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi str_append(str, " FORWARD=");
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi base64_encode(str_data(fwd), str_len(fwd), str);
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi }
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi str_append(str, "\r\n");
01cd9d4a8050a1dbf1da2c830f9755a45d6d004aTimo Sirainen /* remote supports XCLIENT, send it */
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi o_stream_nsend(output, str_data(str), str_len(str));
339726ad7f9f8b787ced3cd12042d0c29938de3dTimo Sirainen client->proxy_state = POP3_PROXY_XCLIENT;
ab45534d66792946b5794ab99a843d2f2b1d556fTimo Sirainen } else {
339726ad7f9f8b787ced3cd12042d0c29938de3dTimo Sirainen client->proxy_state = POP3_PROXY_LOGIN1;
01cd9d4a8050a1dbf1da2c830f9755a45d6d004aTimo Sirainen }
01cd9d4a8050a1dbf1da2c830f9755a45d6d004aTimo Sirainen
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi str_truncate(str, 0);
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen if (client->common.proxy_mech == NULL) {
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen /* send USER command */
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen str_append(str, "USER ");
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen str_append(str, client->common.proxy_user);
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen str_append(str, "\r\n");
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen o_stream_nsend(output, str_data(str), str_len(str));
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen return 0;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen }
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen i_assert(client->common.proxy_sasl_client == NULL);
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&sasl_set);
26681e71837ebbb3eb92455ec4e3cadefa710f82Timo Sirainen sasl_set.authid = client->common.proxy_master_user != NULL ?
26681e71837ebbb3eb92455ec4e3cadefa710f82Timo Sirainen client->common.proxy_master_user : client->common.proxy_user;
26681e71837ebbb3eb92455ec4e3cadefa710f82Timo Sirainen sasl_set.authzid = client->common.proxy_user;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen sasl_set.password = client->common.proxy_password;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen client->common.proxy_sasl_client =
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen dsasl_client_new(client->common.proxy_mech, &sasl_set);
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen mech_name = dsasl_client_mech_get_name(client->common.proxy_mech);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen str_printfa(str, "AUTH %s ", mech_name);
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen if (dsasl_client_output(client->common.proxy_sasl_client,
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen &sasl_output, &len, &error) < 0) {
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen client_log_err(&client->common, t_strdup_printf(
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen "proxy: SASL mechanism %s init failed: %s",
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen mech_name, error));
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen return -1;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen }
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen if (len == 0)
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen str_append_c(str, '=');
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen else
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen base64_encode(sasl_output, len, str);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen str_append(str, "\r\n");
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen o_stream_nsend(output, str_data(str), str_len(str));
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen proxy_free_password(&client->common);
339726ad7f9f8b787ced3cd12042d0c29938de3dTimo Sirainen if (client->proxy_state != POP3_PROXY_XCLIENT)
339726ad7f9f8b787ced3cd12042d0c29938de3dTimo Sirainen client->proxy_state = POP3_PROXY_LOGIN2;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen return 0;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen}
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainenstatic int
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainenpop3_proxy_continue_sasl_auth(struct client *client, struct ostream *output,
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen const char *line)
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen{
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen string_t *str;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen const unsigned char *data;
2c5c293940fd6c7e020e1d58dae77a9d01f9059bTimo Sirainen size_t data_len;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen const char *error;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen int ret;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen str = t_str_new(128);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen if (base64_decode(line, strlen(line), NULL, str) < 0) {
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen client_log_err(client, "proxy: Server sent invalid base64 data in AUTH response");
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen return -1;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen }
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen ret = dsasl_client_input(client->proxy_sasl_client,
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen str_data(str), str_len(str), &error);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen if (ret == 0) {
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen ret = dsasl_client_output(client->proxy_sasl_client,
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen &data, &data_len, &error);
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen }
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen if (ret < 0) {
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen client_log_err(client, t_strdup_printf(
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen "proxy: Server sent invalid authentication data: %s",
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen error));
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen return -1;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen }
d229d26d263a57a77eec8fe7cba24fbfd9509966Timo Sirainen i_assert(ret == 0);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen str_truncate(str, 0);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen base64_encode(data, data_len, str);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen str_append(str, "\r\n");
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(output, str_data(str), str_len(str));
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen return 0;
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen}
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenint pop3_proxy_parse_line(struct client *client, const char *line)
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct pop3_client *pop3_client = (struct pop3_client *)client;
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen struct ostream *output;
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen enum login_proxy_ssl_flags ssl_flags;
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen
d7cd49f01fad7c87c5a0865ebf54a548275e9feeTimo Sirainen i_assert(!client->destroyed);
d7cd49f01fad7c87c5a0865ebf54a548275e9feeTimo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen output = login_proxy_get_ostream(client->login_proxy);
339726ad7f9f8b787ced3cd12042d0c29938de3dTimo Sirainen switch (pop3_client->proxy_state) {
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen case POP3_PROXY_BANNER:
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen /* this is a banner */
b8cd2f2f99351605725b7260f5da89cff76d0a3aTimo Sirainen if (strncmp(line, "+OK", 3) != 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen client_log_err(client, t_strdup_printf(
45155bb1250cf5a120278f349465aded513a100fTimo Sirainen "proxy: Remote returned invalid banner: %s",
45155bb1250cf5a120278f349465aded513a100fTimo Sirainen str_sanitize(line, 160)));
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen client_proxy_failed(client, TRUE);
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen return -1;
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen }
01cd9d4a8050a1dbf1da2c830f9755a45d6d004aTimo Sirainen pop3_client->proxy_xclient =
01cd9d4a8050a1dbf1da2c830f9755a45d6d004aTimo Sirainen strncmp(line+3, " [XCLIENT]", 10) == 0;
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen ssl_flags = login_proxy_get_ssl_flags(client->login_proxy);
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen if ((ssl_flags & PROXY_SSL_FLAG_STARTTLS) == 0) {
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen if (proxy_send_login(pop3_client, output) < 0) {
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen client_proxy_failed(client, TRUE);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen return -1;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen }
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen } else {
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(output, "STLS\r\n");
339726ad7f9f8b787ced3cd12042d0c29938de3dTimo Sirainen pop3_client->proxy_state = POP3_PROXY_STARTTLS;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen }
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen return 0;
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen case POP3_PROXY_STARTTLS:
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen if (strncmp(line, "+OK", 3) != 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen client_log_err(client, t_strdup_printf(
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen "proxy: Remote STLS failed: %s",
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen str_sanitize(line, 160)));
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen client_proxy_failed(client, TRUE);
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen return -1;
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (login_proxy_starttls(client->login_proxy) < 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen client_proxy_failed(client, TRUE);
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen return -1;
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen }
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen /* i/ostreams changed. */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen output = login_proxy_get_ostream(client->login_proxy);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen if (proxy_send_login(pop3_client, output) < 0) {
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen client_proxy_failed(client, TRUE);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen return -1;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen }
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen return 1;
ab45534d66792946b5794ab99a843d2f2b1d556fTimo Sirainen case POP3_PROXY_XCLIENT:
ab45534d66792946b5794ab99a843d2f2b1d556fTimo Sirainen if (strncmp(line, "+OK", 3) != 0) {
ab45534d66792946b5794ab99a843d2f2b1d556fTimo Sirainen client_log_err(client, t_strdup_printf(
ab45534d66792946b5794ab99a843d2f2b1d556fTimo Sirainen "proxy: Remote XCLIENT failed: %s",
ab45534d66792946b5794ab99a843d2f2b1d556fTimo Sirainen str_sanitize(line, 160)));
ab45534d66792946b5794ab99a843d2f2b1d556fTimo Sirainen client_proxy_failed(client, TRUE);
ab45534d66792946b5794ab99a843d2f2b1d556fTimo Sirainen return -1;
ab45534d66792946b5794ab99a843d2f2b1d556fTimo Sirainen }
339726ad7f9f8b787ced3cd12042d0c29938de3dTimo Sirainen pop3_client->proxy_state = client->proxy_sasl_client == NULL ?
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen POP3_PROXY_LOGIN1 : POP3_PROXY_LOGIN2;
ac84cb764c3a6f4b4b9ded2510d425fb5744dfe8Timo Sirainen return 0;
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen case POP3_PROXY_LOGIN1:
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen i_assert(client->proxy_sasl_client == NULL);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen if (strncmp(line, "+OK", 3) != 0)
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen break;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen /* USER successful, send PASS */
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen o_stream_nsend_str(output, t_strdup_printf(
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen "PASS %s\r\n", client->proxy_password));
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen proxy_free_password(client);
339726ad7f9f8b787ced3cd12042d0c29938de3dTimo Sirainen pop3_client->proxy_state = POP3_PROXY_LOGIN2;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen return 0;
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen case POP3_PROXY_LOGIN2:
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen if (strncmp(line, "+ ", 2) == 0 &&
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen client->proxy_sasl_client != NULL) {
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen /* continue SASL authentication */
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen if (pop3_proxy_continue_sasl_auth(client, output,
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen line+2) < 0) {
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen client_proxy_failed(client, TRUE);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen return -1;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen }
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen return 0;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen }
b8422738d3c891c7c93294b027a5cfe7d520e378Timo Sirainen if (strncmp(line, "+OK", 3) != 0)
b8422738d3c891c7c93294b027a5cfe7d520e378Timo Sirainen break;
b8422738d3c891c7c93294b027a5cfe7d520e378Timo Sirainen
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen /* Login successful. Send this line to client. */
8e50329e2c5e3a199674ae9f6d3dfcddab02487bTimo Sirainen line = t_strconcat(line, "\r\n", NULL);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend_str(client->output, line);
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen client_proxy_finish_destroy_client(client);
f8a78c816b4dbfda42f13d8ee152e0cdb28c6a4aTimo Sirainen return 1;
d77f679dac93f2416d6b04299b1a8154941036ddTimo Sirainen case POP3_PROXY_STATE_COUNT:
d77f679dac93f2416d6b04299b1a8154941036ddTimo Sirainen i_unreached();
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen }
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen /* Login failed. Pass through the error message to client.
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen If the backend server isn't Dovecot, the error message may
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen be different from Dovecot's "user doesn't exist" error. This
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen would allow an attacker to find out what users exist in the
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen system.
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen The optimal way to handle this would be to replace the
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen backend's "password failed" error message with Dovecot's
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen AUTH_FAILED_MSG, but this would require a new setting and
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen the sysadmin to actually bother setting it properly.
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen So for now we'll just forward the error message. This
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen shouldn't be a real problem since of course everyone will
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen be using only Dovecot as their backend :) */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (strncmp(line, "-ERR ", 5) != 0) {
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen client_send_reply(client, POP3_CMD_REPLY_ERROR,
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen AUTH_FAILED_MSG);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen } else {
00fa8dcbc66f56daa737487c9dec7166c37de79eTimo Sirainen client_send_raw(client, t_strconcat(line, "\r\n", NULL));
00fa8dcbc66f56daa737487c9dec7166c37de79eTimo Sirainen }
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen
ac45ba9c603b67cc43fa7bceffdef0a19100720bTimo Sirainen if (client->set->auth_verbose) {
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen if (strncmp(line, "-ERR ", 5) == 0)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen line += 5;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen client_proxy_log_failure(client, line);
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen }
80980955bb1bbcc1bd73623fe0912f334194ddd2Timo Sirainen client->proxy_auth_failed = TRUE;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen client_proxy_failed(client, FALSE);
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen return -1;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen}
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenvoid pop3_proxy_reset(struct client *client)
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen{
339726ad7f9f8b787ced3cd12042d0c29938de3dTimo Sirainen struct pop3_client *pop3_client = (struct pop3_client *)client;
339726ad7f9f8b787ced3cd12042d0c29938de3dTimo Sirainen
339726ad7f9f8b787ced3cd12042d0c29938de3dTimo Sirainen pop3_client->proxy_state = POP3_PROXY_BANNER;
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen}
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainenvoid pop3_proxy_error(struct client *client, const char *text)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen{
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen client_send_reply(client, POP3_CMD_REPLY_ERROR, text);
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen}
d77f679dac93f2416d6b04299b1a8154941036ddTimo Sirainen
d77f679dac93f2416d6b04299b1a8154941036ddTimo Sirainenconst char *pop3_proxy_get_state(struct client *client)
d77f679dac93f2416d6b04299b1a8154941036ddTimo Sirainen{
339726ad7f9f8b787ced3cd12042d0c29938de3dTimo Sirainen struct pop3_client *pop3_client = (struct pop3_client *)client;
339726ad7f9f8b787ced3cd12042d0c29938de3dTimo Sirainen
339726ad7f9f8b787ced3cd12042d0c29938de3dTimo Sirainen return pop3_proxy_state_names[pop3_client->proxy_state];
d77f679dac93f2416d6b04299b1a8154941036ddTimo Sirainen}