pop3-proxy.c revision 67ac9e1493601933d3d4eb2d30893e0d84d2a5b5
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen/* Copyright (c) 2004-2017 Dovecot authors, see the included COPYING file */
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainenstatic const char *pop3_proxy_state_names[POP3_PROXY_STATE_COUNT] = {
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen "banner", "starttls", "xclient", "login1", "login2"
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainenstatic void proxy_free_password(struct client *client)
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen safe_memset(client->proxy_password, 0, strlen(client->proxy_password));
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainenstatic int proxy_send_login(struct pop3_client *client, struct ostream *output)
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen const unsigned char *sasl_output;
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen for(const char *const *ptr = client->common.auth_passdb_args;*ptr != NULL; ptr++) {
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen str_printfa(str, "XCLIENT ADDR=%s PORT=%u SESSION=%s TTL=%u",
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen base64_encode(str_data(fwd), str_len(fwd), str);
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen /* remote supports XCLIENT, send it */
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen o_stream_nsend(output, str_data(str), str_len(str));
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen /* send USER command */
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen o_stream_nsend(output, str_data(str), str_len(str));
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen i_assert(client->common.proxy_sasl_client == NULL);
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen sasl_set.authid = client->common.proxy_master_user != NULL ?
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen client->common.proxy_master_user : client->common.proxy_user;
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen sasl_set.password = client->common.proxy_password;
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen dsasl_client_new(client->common.proxy_mech, &sasl_set);
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen mech_name = dsasl_client_mech_get_name(client->common.proxy_mech);
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen if (dsasl_client_output(client->common.proxy_sasl_client,
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen client_log_err(&client->common, t_strdup_printf(
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen "proxy: SASL mechanism %s init failed: %s",
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen o_stream_nsend(output, str_data(str), str_len(str));
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen if (client->proxy_state != POP3_PROXY_XCLIENT)
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainenpop3_proxy_continue_sasl_auth(struct client *client, struct ostream *output,
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen const unsigned char *data;
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen if (base64_decode(line, strlen(line), NULL, str) < 0) {
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen client_log_err(client, "proxy: Server sent invalid base64 data in AUTH response");
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen ret = dsasl_client_input(client->proxy_sasl_client,
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen ret = dsasl_client_output(client->proxy_sasl_client,
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen "proxy: Server sent invalid authentication data: %s",
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen o_stream_nsend(output, str_data(str), str_len(str));
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainenint pop3_proxy_parse_line(struct client *client, const char *line)
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen struct pop3_client *pop3_client = (struct pop3_client *)client;
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen output = login_proxy_get_ostream(client->login_proxy);
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen /* this is a banner */
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen "proxy: Remote returned invalid banner: %s",
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen ssl_flags = login_proxy_get_ssl_flags(client->login_proxy);
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen if ((ssl_flags & PROXY_SSL_FLAG_STARTTLS) == 0) {
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen if (proxy_send_login(pop3_client, output) < 0) {
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen pop3_client->proxy_state = POP3_PROXY_STARTTLS;
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen "proxy: Remote STLS failed: %s",
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen if (login_proxy_starttls(client->login_proxy) < 0) {
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen /* i/ostreams changed. */
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen output = login_proxy_get_ostream(client->login_proxy);
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen if (proxy_send_login(pop3_client, output) < 0) {
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen "proxy: Remote XCLIENT failed: %s",
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen pop3_client->proxy_state = client->proxy_sasl_client == NULL ?
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen /* USER successful, send PASS */
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen /* continue SASL authentication */
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen if (pop3_proxy_continue_sasl_auth(client, output,
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen /* Login successful. Send this line to client. */
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen /* Login failed. Pass through the error message to client.
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen If the backend server isn't Dovecot, the error message may
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen be different from Dovecot's "user doesn't exist" error. This
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen would allow an attacker to find out what users exist in the
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen The optimal way to handle this would be to replace the
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen backend's "password failed" error message with Dovecot's
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen AUTH_FAILED_MSG, but this would require a new setting and
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen the sysadmin to actually bother setting it properly.
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen So for now we'll just forward the error message. This
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen shouldn't be a real problem since of course everyone will
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen be using only Dovecot as their backend :) */
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen client_send_reply(client, POP3_CMD_REPLY_ERROR,
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen client_send_raw(client, t_strconcat(line, "\r\n", NULL));
d646a63462a696824b1facd73e00732d4ac0f3dcTimo Sirainen struct pop3_client *pop3_client = (struct pop3_client *)client;
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainenvoid pop3_proxy_error(struct client *client, const char *text)
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen client_send_reply(client, POP3_CMD_REPLY_ERROR, text);
d646a63462a696824b1facd73e00732d4ac0f3dcTimo Sirainenconst char *pop3_proxy_get_state(struct client *client)
d646a63462a696824b1facd73e00732d4ac0f3dcTimo Sirainen struct pop3_client *pop3_client = (struct pop3_client *)client;