pop3-proxy.c revision 26681e71837ebbb3eb92455ec4e3cadefa710f82
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter/* Copyright (c) 2004-2013 Dovecot authors, see the included COPYING file */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstatic void proxy_free_password(struct client *client)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter safe_memset(client->proxy_password, 0, strlen(client->proxy_password));
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstatic int proxy_send_login(struct pop3_client *client, struct ostream *output)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter const unsigned char *sasl_output;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter unsigned int len;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter /* remote supports XCLIENT, send it */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter "XCLIENT ADDR=%s PORT=%u SESSION=%s TTL=%u\r\n",
1a94716209e40a9ccaedc7e70f9de961d1cced48Lukas Slebodnik client->common.proxy_state = POP3_PROXY_XCLIENT;
1a94716209e40a9ccaedc7e70f9de961d1cced48Lukas Slebodnik client->common.proxy_state = POP3_PROXY_LOGIN1;
1a94716209e40a9ccaedc7e70f9de961d1cced48Lukas Slebodnik /* send USER command */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter o_stream_nsend(output, str_data(str), str_len(str));
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter i_assert(client->common.proxy_sasl_client == NULL);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter sasl_set.authid = client->common.proxy_master_user != NULL ?
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter client->common.proxy_master_user : client->common.proxy_user;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter sasl_set.password = client->common.proxy_password;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter sasl_client_new(client->common.proxy_mech, &sasl_set);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter mech_name = sasl_client_mech_get_name(client->common.proxy_mech);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (sasl_client_output(client->common.proxy_sasl_client,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter client_log_err(&client->common, t_strdup_printf(
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter "proxy: SASL mechanism %s init failed: %s",
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter o_stream_nsend(output, str_data(str), str_len(str));
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (client->common.proxy_state != POP3_PROXY_XCLIENT)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterpop3_proxy_continue_sasl_auth(struct client *client, struct ostream *output,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter const char *line)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter const unsigned char *data;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter unsigned int data_len;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter const char *error;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (base64_decode(line, strlen(line), NULL, str) < 0) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter client_log_err(client, "proxy: Server sent invalid base64 data in AUTH response");
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ret = sasl_client_input(client->proxy_sasl_client,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ret = sasl_client_output(client->proxy_sasl_client,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter "proxy: Server sent invalid authentication data: %s",
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter o_stream_nsend(output, str_data(str), str_len(str));
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterint pop3_proxy_parse_line(struct client *client, const char *line)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter struct pop3_client *pop3_client = (struct pop3_client *)client;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter output = login_proxy_get_ostream(client->login_proxy);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter /* this is a banner */
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter "proxy: Remote returned invalid banner: %s",
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter ssl_flags = login_proxy_get_ssl_flags(client->login_proxy);
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter if ((ssl_flags & PROXY_SSL_FLAG_STARTTLS) == 0) {
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter if (proxy_send_login(pop3_client, output) < 0) {
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter "proxy: Remote STLS failed: %s",
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter if (login_proxy_starttls(client->login_proxy) < 0) {
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter /* i/ostreams changed. */
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter output = login_proxy_get_ostream(client->login_proxy);
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter if (proxy_send_login(pop3_client, output) < 0) {
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter "proxy: Remote XCLIENT failed: %s",
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter client->proxy_state = client->proxy_sasl_client == NULL ?
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter /* USER successful, send PASS */
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter /* continue SASL authentication */
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter if (pop3_proxy_continue_sasl_auth(client, output,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter /* Login successful. Send this line to client. */
1203e462650f035b0df2304075d60b9a99e36715Stef Walter /* Login failed. Pass through the error message to client.
1203e462650f035b0df2304075d60b9a99e36715Stef Walter If the backend server isn't Dovecot, the error message may
1203e462650f035b0df2304075d60b9a99e36715Stef Walter be different from Dovecot's "user doesn't exist" error. This
1203e462650f035b0df2304075d60b9a99e36715Stef Walter would allow an attacker to find out what users exist in the
1203e462650f035b0df2304075d60b9a99e36715Stef Walter The optimal way to handle this would be to replace the
1203e462650f035b0df2304075d60b9a99e36715Stef Walter backend's "password failed" error message with Dovecot's
1203e462650f035b0df2304075d60b9a99e36715Stef Walter AUTH_FAILED_MSG, but this would require a new setting and
1203e462650f035b0df2304075d60b9a99e36715Stef Walter the sysadmin to actually bother setting it properly.
1203e462650f035b0df2304075d60b9a99e36715Stef Walter So for now we'll just forward the error message. This
1203e462650f035b0df2304075d60b9a99e36715Stef Walter shouldn't be a real problem since of course everyone will
1203e462650f035b0df2304075d60b9a99e36715Stef Walter be using only Dovecot as their backend :) */
1203e462650f035b0df2304075d60b9a99e36715Stef Walter client_send_raw(client, t_strconcat(line, "\r\n", NULL));
1203e462650f035b0df2304075d60b9a99e36715Stef Waltervoid pop3_proxy_error(struct client *client, const char *text)