bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2004-2018 Dovecot authors, see the included COPYING file */
d77f679dac93f2416d6b04299b1a8154941036ddTimo Sirainenstatic const char *pop3_proxy_state_names[POP3_PROXY_STATE_COUNT] = {
d77f679dac93f2416d6b04299b1a8154941036ddTimo Sirainen "banner", "starttls", "xclient", "login1", "login2"
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic void proxy_free_password(struct client *client)
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen safe_memset(client->proxy_password, 0, strlen(client->proxy_password));
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainenstatic int proxy_send_login(struct pop3_client *client, struct ostream *output)
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi for(const char *const *ptr = client->common.auth_passdb_args;*ptr != NULL; ptr++) {
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi str_printfa(str, "XCLIENT ADDR=%s PORT=%u SESSION=%s TTL=%u",
01cd9d4a8050a1dbf1da2c830f9755a45d6d004aTimo Sirainen /* remote supports XCLIENT, send it */
67ac9e1493601933d3d4eb2d30893e0d84d2a5b5Aki Tuomi o_stream_nsend(output, str_data(str), str_len(str));
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen /* send USER command */
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen o_stream_nsend(output, str_data(str), str_len(str));
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen i_assert(client->common.proxy_sasl_client == NULL);
26681e71837ebbb3eb92455ec4e3cadefa710f82Timo Sirainen sasl_set.authid = client->common.proxy_master_user != NULL ?
26681e71837ebbb3eb92455ec4e3cadefa710f82Timo Sirainen client->common.proxy_master_user : client->common.proxy_user;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen sasl_set.password = client->common.proxy_password;
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen dsasl_client_new(client->common.proxy_mech, &sasl_set);
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen mech_name = dsasl_client_mech_get_name(client->common.proxy_mech);
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen if (dsasl_client_output(client->common.proxy_sasl_client,
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen client_log_err(&client->common, t_strdup_printf(
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen "proxy: SASL mechanism %s init failed: %s",
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen o_stream_nsend(output, str_data(str), str_len(str));
339726ad7f9f8b787ced3cd12042d0c29938de3dTimo Sirainen if (client->proxy_state != POP3_PROXY_XCLIENT)
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainenpop3_proxy_continue_sasl_auth(struct client *client, struct ostream *output,
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");
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen ret = dsasl_client_input(client->proxy_sasl_client,
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen ret = dsasl_client_output(client->proxy_sasl_client,
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen "proxy: Server sent invalid authentication data: %s",
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(output, str_data(str), str_len(str));
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenint pop3_proxy_parse_line(struct client *client, const char *line)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct pop3_client *pop3_client = (struct pop3_client *)client;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen output = login_proxy_get_ostream(client->login_proxy);
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen /* this is a banner */
45155bb1250cf5a120278f349465aded513a100fTimo Sirainen "proxy: Remote returned invalid banner: %s",
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) {
339726ad7f9f8b787ced3cd12042d0c29938de3dTimo Sirainen pop3_client->proxy_state = POP3_PROXY_STARTTLS;
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen "proxy: Remote STLS failed: %s",
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (login_proxy_starttls(client->login_proxy) < 0) {
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) {
ab45534d66792946b5794ab99a843d2f2b1d556fTimo Sirainen "proxy: Remote XCLIENT failed: %s",
339726ad7f9f8b787ced3cd12042d0c29938de3dTimo Sirainen pop3_client->proxy_state = client->proxy_sasl_client == NULL ?
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen /* USER successful, send PASS */
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen /* continue SASL authentication */
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen if (pop3_proxy_continue_sasl_auth(client, output,
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen /* Login successful. Send this line to client. */
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen /* Login failed. Pass through the error message to client.
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 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 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 :) */
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen client_send_reply(client, POP3_CMD_REPLY_ERROR,
00fa8dcbc66f56daa737487c9dec7166c37de79eTimo Sirainen client_send_raw(client, t_strconcat(line, "\r\n", NULL));
339726ad7f9f8b787ced3cd12042d0c29938de3dTimo Sirainen struct pop3_client *pop3_client = (struct pop3_client *)client;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainenvoid pop3_proxy_error(struct client *client, const char *text)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen client_send_reply(client, POP3_CMD_REPLY_ERROR, text);
d77f679dac93f2416d6b04299b1a8154941036ddTimo Sirainenconst char *pop3_proxy_get_state(struct client *client)
339726ad7f9f8b787ced3cd12042d0c29938de3dTimo Sirainen struct pop3_client *pop3_client = (struct pop3_client *)client;