submission-proxy.c revision 2cbbe9b4829adb184c83dbf780316f4144559054
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (c) 2017 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
659fe5d24825b160cae512538088020d97a60239Timo Sirainen#include "login-common.h"
659fe5d24825b160cae512538088020d97a60239Timo Sirainen#include "ioloop.h"
659fe5d24825b160cae512538088020d97a60239Timo Sirainen#include "istream.h"
659fe5d24825b160cae512538088020d97a60239Timo Sirainen#include "ostream.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "base64.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "safe-memset.h"
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen#include "str.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "str-sanitize.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "strescape.h"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#include "dsasl-client.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "client.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "submission-login-settings.h"
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen#include "submission-proxy.h"
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen#include <ctype.h>
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainenstatic const char *submission_proxy_state_names[SUBMISSION_PROXY_STATE_COUNT] = {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "banner", "ehlo", "starttls", "tls-ehlo", "xclient", "authenticate"
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainen};
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainenstatic void proxy_free_password(struct client *client)
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen{
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen if (client->proxy_password == NULL)
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen return;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen safe_memset(client->proxy_password, 0, strlen(client->proxy_password));
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen i_free_and_null(client->proxy_password);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen}
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenstatic void
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainenproxy_send_xclient(struct submission_client *client, struct ostream *output)
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen{
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen const char *const *arg;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen string_t *str, *fwd;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if ((client->proxy_capability & SMTP_CAPABILITY_XCLIENT) == 0 ||
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen client->common.proxy_not_trusted)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen return;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen /* remote supports XCLIENT, send it */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen fwd = t_str_new(128);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen for(arg = client->common.auth_passdb_args; *arg != NULL; arg++) {
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen if (strncasecmp(*arg, "forward_", 8) == 0) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (str_len(fwd) > 0)
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen str_append_c(fwd, '\t');
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen str_append_tabescaped(fwd, (*arg)+8);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen }
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen }
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen str = t_str_new(128);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen str_append(str, "XCLIENT ");
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (str_array_icase_find(client->proxy_xclient, "ADDR")) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen str_append(str, "ADDR=");
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen str_append(str, net_ip2addr(&client->common.ip));
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen }
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (str_array_icase_find(client->proxy_xclient, "PORT"))
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen str_printfa(str, "PORT=%u", client->common.remote_port);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (str_array_icase_find(client->proxy_xclient, "SESSION")) {
e8acc691a14a6d0884c5ca9aa4d8507f1e082040Timo Sirainen str_append(str, "SESSION=");
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainen str_append(str, client_get_session_id(&client->common));
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainen }
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainen if (str_array_icase_find(client->proxy_xclient, "TTL"))
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainen str_printfa(str, "TTL=%u", client->common.proxy_ttl - 1);
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainen if (str_array_icase_find(client->proxy_xclient, "FORWARD") &&
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainen str_len(fwd) > 0) {
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainen str_append(str, " FORWARD=");
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainen base64_encode(str_data(fwd), str_len(fwd), str);
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainen }
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainen str_append(str, "\r\n");
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainen o_stream_nsend(output, str_data(str), str_len(str));
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainen client->proxy_state = SUBMISSION_PROXY_XCLIENT;
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainen}
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainen
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainenstatic int
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainenproxy_send_login(struct submission_client *client, struct ostream *output)
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainen{
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainen struct dsasl_client_settings sasl_set;
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainen const unsigned char *sasl_output;
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainen size_t len;
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainen const char *mech_name, *error;
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainen string_t *str;
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainen
e8acc691a14a6d0884c5ca9aa4d8507f1e082040Timo Sirainen if ((client->proxy_capability & SMTP_CAPABILITY_AUTH) == 0) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen /* Prevent sending credentials to a server that has login disabled;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i.e., due to the lack of TLS */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client_log_err(&client->common, "proxy: "
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Server has disabled authentication (TLS required?)");
48136ae5a0eb49daa44e343553f3688a500307e2Timo Sirainen return -1;
48136ae5a0eb49daa44e343553f3688a500307e2Timo Sirainen }
48136ae5a0eb49daa44e343553f3688a500307e2Timo Sirainen
48136ae5a0eb49daa44e343553f3688a500307e2Timo Sirainen i_assert(client->common.proxy_ttl > 1);
48136ae5a0eb49daa44e343553f3688a500307e2Timo Sirainen proxy_send_xclient(client, output);
48136ae5a0eb49daa44e343553f3688a500307e2Timo Sirainen
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen str = t_str_new(128);
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen if (client->common.proxy_mech == NULL)
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen client->common.proxy_mech = &dsasl_client_mech_plain;
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen i_assert(client->common.proxy_sasl_client == NULL);
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen i_zero(&sasl_set);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen sasl_set.authid = client->common.proxy_master_user != NULL ?
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen client->common.proxy_master_user : client->common.proxy_user;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen sasl_set.authzid = client->common.proxy_user;
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen sasl_set.password = client->common.proxy_password;
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen client->common.proxy_sasl_client =
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen dsasl_client_new(client->common.proxy_mech, &sasl_set);
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen mech_name = dsasl_client_mech_get_name(client->common.proxy_mech);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen str_printfa(str, "AUTH %s ", mech_name);
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen if (dsasl_client_output(client->common.proxy_sasl_client,
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen &sasl_output, &len, &error) < 0) {
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen client_log_err(&client->common, t_strdup_printf(
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen "proxy: SASL mechanism %s init failed: %s",
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen mech_name, error));
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen return -1;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen }
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen if (len == 0)
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen str_append_c(str, '=');
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen else
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen base64_encode(sasl_output, len, str);
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen str_append(str, "\r\n");
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen o_stream_nsend(output, str_data(str), str_len(str));
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen proxy_free_password(&client->common);
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen if (client->proxy_state != SUBMISSION_PROXY_XCLIENT)
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen client->proxy_state = SUBMISSION_PROXY_AUTHENTICATE;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen return 0;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen}
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainenstatic int
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainensubmission_proxy_continue_sasl_auth(struct client *client, struct ostream *output,
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen const char *line)
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen{
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen string_t *str;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen const unsigned char *data;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen size_t data_len;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen const char *error;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen int ret;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen str = t_str_new(128);
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen if (base64_decode(line, strlen(line), NULL, str) < 0) {
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen client_log_err(client,
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen "proxy: Server sent invalid base64 data in AUTH response");
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen return -1;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen }
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen ret = dsasl_client_input(client->proxy_sasl_client,
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen str_data(str), str_len(str), &error);
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen if (ret == 0) {
a4962562bb77afe1d058124762b7ecea5028a528Timo Sirainen ret = dsasl_client_output(client->proxy_sasl_client,
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen &data, &data_len, &error);
2d79e603e20a32bdae4c2b516ead5c5c9169545aTimo Sirainen }
a4962562bb77afe1d058124762b7ecea5028a528Timo Sirainen if (ret < 0) {
2d79e603e20a32bdae4c2b516ead5c5c9169545aTimo Sirainen client_log_err(client, t_strdup_printf(
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen "proxy: Server sent invalid authentication data: %s",
a4962562bb77afe1d058124762b7ecea5028a528Timo Sirainen error));
a4962562bb77afe1d058124762b7ecea5028a528Timo Sirainen return -1;
a4962562bb77afe1d058124762b7ecea5028a528Timo Sirainen }
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen i_assert(ret == 0);
a4962562bb77afe1d058124762b7ecea5028a528Timo Sirainen
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen str_truncate(str, 0);
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen base64_encode(data, data_len, str);
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen str_append(str, "\r\n");
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen o_stream_nsend(output, str_data(str), str_len(str));
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen return 0;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen}
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainenstatic const char *
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainenstrip_enhanced_code(const char *text, const char **enh_code_r)
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen{
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen const char *p = text;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen unsigned int digits;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen *enh_code_r = NULL;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen if (*p != '2' && *p != '4' && *p != '5')
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen return text;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen p++;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen if (*p != '.')
659fe5d24825b160cae512538088020d97a60239Timo Sirainen return text;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen p++;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen
659fe5d24825b160cae512538088020d97a60239Timo Sirainen digits = 0;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen while (i_isdigit(*p) && digits < 3) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen p++;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen digits++;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen }
659fe5d24825b160cae512538088020d97a60239Timo Sirainen if (*p != '.')
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen return text;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen p++;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen digits = 0;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen while (i_isdigit(*p) && digits < 3) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen p++;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen digits++;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen }
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen if (*p != ' ')
a6745c1336427f5641715baee3d2369d3e91ebe0Timo Sirainen return text;
a6745c1336427f5641715baee3d2369d3e91ebe0Timo Sirainen *enh_code_r = t_strdup_until(text, p);
a6745c1336427f5641715baee3d2369d3e91ebe0Timo Sirainen p++;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return p;
a6745c1336427f5641715baee3d2369d3e91ebe0Timo Sirainen}
9d8d1efcc1274ef4d8413c3687549b297d81da10Timo Sirainen
a6745c1336427f5641715baee3d2369d3e91ebe0Timo Sirainenstatic void
a6745c1336427f5641715baee3d2369d3e91ebe0Timo Sirainensubmission_proxy_success_reply_sent(struct smtp_server_cmd_ctx *cmd)
a6745c1336427f5641715baee3d2369d3e91ebe0Timo Sirainen{
a6745c1336427f5641715baee3d2369d3e91ebe0Timo Sirainen struct submission_client *subm_client =
a6745c1336427f5641715baee3d2369d3e91ebe0Timo Sirainen (struct submission_client *)cmd->context;
a6745c1336427f5641715baee3d2369d3e91ebe0Timo Sirainen
a6745c1336427f5641715baee3d2369d3e91ebe0Timo Sirainen client_proxy_finish_destroy_client(&subm_client->common);
a6745c1336427f5641715baee3d2369d3e91ebe0Timo Sirainen}
a6745c1336427f5641715baee3d2369d3e91ebe0Timo Sirainen
a6745c1336427f5641715baee3d2369d3e91ebe0Timo Sirainenint submission_proxy_parse_line(struct client *client, const char *line)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen{
a6745c1336427f5641715baee3d2369d3e91ebe0Timo Sirainen struct submission_client *subm_client =
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen (struct submission_client *)client;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen struct smtp_server_cmd_ctx *cmd = subm_client->pending_auth;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen struct smtp_server_command *command = cmd->cmd;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen struct ostream *output;
e6f0cbdb1eb604f21a65cd45072febe678187054Timo Sirainen enum login_proxy_ssl_flags ssl_flags;
e6f0cbdb1eb604f21a65cd45072febe678187054Timo Sirainen bool last_line = FALSE, invalid_line = FALSE;
e6f0cbdb1eb604f21a65cd45072febe678187054Timo Sirainen const char *text = NULL, *enh_code = NULL;
e6f0cbdb1eb604f21a65cd45072febe678187054Timo Sirainen unsigned int status = 0;
e6f0cbdb1eb604f21a65cd45072febe678187054Timo Sirainen
e6f0cbdb1eb604f21a65cd45072febe678187054Timo Sirainen i_assert(!client->destroyed);
e6f0cbdb1eb604f21a65cd45072febe678187054Timo Sirainen i_assert(cmd != NULL);
e6f0cbdb1eb604f21a65cd45072febe678187054Timo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen if ((line[3] != ' ' && line[3] != '-') ||
e6f0cbdb1eb604f21a65cd45072febe678187054Timo Sirainen str_parse_uint(line, &status, &text) < 0 ||
e6f0cbdb1eb604f21a65cd45072febe678187054Timo Sirainen status < 200 || status >= 560) {
e6f0cbdb1eb604f21a65cd45072febe678187054Timo Sirainen invalid_line = TRUE;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen }
e6f0cbdb1eb604f21a65cd45072febe678187054Timo Sirainen if (subm_client->proxy_reply_status != 0 &&
e6f0cbdb1eb604f21a65cd45072febe678187054Timo Sirainen subm_client->proxy_reply_status != status) {
e6f0cbdb1eb604f21a65cd45072febe678187054Timo Sirainen client_log_err(client, t_strdup_printf(
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen "proxy: Remote returned inconsistent SMTP reply: %s "
e6f0cbdb1eb604f21a65cd45072febe678187054Timo Sirainen "(status != %u)", str_sanitize(line, 160),
e6f0cbdb1eb604f21a65cd45072febe678187054Timo Sirainen subm_client->proxy_reply_status));
e6f0cbdb1eb604f21a65cd45072febe678187054Timo Sirainen client_proxy_failed(client, TRUE);
e6f0cbdb1eb604f21a65cd45072febe678187054Timo Sirainen return -1;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen }
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (line[3] == ' ') {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen last_line = TRUE;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen subm_client->proxy_reply_status = 0;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen } else {
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen subm_client->proxy_reply_status = status;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen }
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen text++;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen if ((subm_client->proxy_capability &
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen SMTP_CAPABILITY_ENHANCEDSTATUSCODES) != 0)
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen text = strip_enhanced_code(text, &enh_code);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen output = login_proxy_get_ostream(client->login_proxy);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen switch (subm_client->proxy_state) {
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen case SUBMISSION_PROXY_BANNER:
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen /* this is a banner */
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen if (invalid_line || status != 220) {
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen client_log_err(client, t_strdup_printf(
e6f0cbdb1eb604f21a65cd45072febe678187054Timo Sirainen "proxy: Remote returned invalid banner: %s",
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen str_sanitize(line, 160)));
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen client_proxy_failed(client, TRUE);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen return -1;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen }
659fe5d24825b160cae512538088020d97a60239Timo Sirainen if (!last_line)
659fe5d24825b160cae512538088020d97a60239Timo Sirainen return 0;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen subm_client->proxy_state = SUBMISSION_PROXY_EHLO;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen o_stream_nsend_str(output, t_strdup_printf("EHLO %s\r\n",
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen subm_client->set->hostname));
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen return 0;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen case SUBMISSION_PROXY_EHLO:
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen case SUBMISSION_PROXY_TLS_EHLO:
406393bc328f056c49df0804f894ac2070aa5846Timo Sirainen if (invalid_line || (status / 100) != 2) {
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen client_log_err(client, t_strdup_printf(
406393bc328f056c49df0804f894ac2070aa5846Timo Sirainen "proxy: Remote returned invalid EHLO line: %s",
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen str_sanitize(line, 160)));
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen client_proxy_failed(client, TRUE);
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen return -1;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen }
985fa802913c96ce6f2e25bbc788ee39c416a7e0Timo Sirainen
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen if (strncasecmp(text, "XCLIENT ", 8) == 0) {
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen subm_client->proxy_capability |=
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen SMTP_CAPABILITY_XCLIENT;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen i_free_and_null(subm_client->proxy_xclient);
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen subm_client->proxy_xclient = p_strarray_dup(
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen default_pool, t_strsplit_spaces(text + 8, " "));
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen } else if (strncasecmp(text, "STARTTLS", 9) == 0) {
985fa802913c96ce6f2e25bbc788ee39c416a7e0Timo Sirainen subm_client->proxy_capability |=
985fa802913c96ce6f2e25bbc788ee39c416a7e0Timo Sirainen SMTP_CAPABILITY_STARTTLS;
985fa802913c96ce6f2e25bbc788ee39c416a7e0Timo Sirainen } else if (strncasecmp(text, "AUTH", 4) == 0 &&
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen text[4] == ' ' && text[5] != '\0') {
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen subm_client->proxy_capability |=
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen SMTP_CAPABILITY_AUTH;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen } else if (strcasecmp(text, "ENHANCEDSTATUSCODES") == 0) {
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen subm_client->proxy_capability |=
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen SMTP_CAPABILITY_ENHANCEDSTATUSCODES;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen }
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen if (!last_line)
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen return 0;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen if (subm_client->proxy_state == SUBMISSION_PROXY_TLS_EHLO) {
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen if (proxy_send_login(subm_client, output) < 0) {
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen client_proxy_failed(client, TRUE);
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen return -1;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen }
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen return 0;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen }
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen ssl_flags = login_proxy_get_ssl_flags(client->login_proxy);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen if ((ssl_flags & PROXY_SSL_FLAG_STARTTLS) == 0) {
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen if (proxy_send_login(subm_client, output) < 0) {
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen client_proxy_failed(client, TRUE);
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen return -1;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen }
3d3bde73024116f6d739eaf9f3638f267e97bd66Timo Sirainen } else {
3d3bde73024116f6d739eaf9f3638f267e97bd66Timo Sirainen if ((subm_client->proxy_capability &
3d3bde73024116f6d739eaf9f3638f267e97bd66Timo Sirainen SMTP_CAPABILITY_STARTTLS) == 0) {
3d3bde73024116f6d739eaf9f3638f267e97bd66Timo Sirainen client_log_err(client,
3d3bde73024116f6d739eaf9f3638f267e97bd66Timo Sirainen "proxy: Remote doesn't support STARTTLS");
3d3bde73024116f6d739eaf9f3638f267e97bd66Timo Sirainen return -1;
3d3bde73024116f6d739eaf9f3638f267e97bd66Timo Sirainen }
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen o_stream_nsend_str(output, "STARTTLS\r\n");
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen subm_client->proxy_state = SUBMISSION_PROXY_STARTTLS;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen }
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen return 0;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen case SUBMISSION_PROXY_STARTTLS:
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen if (invalid_line || status != 220) {
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen client_log_err(client, t_strdup_printf(
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen "proxy: Remote STARTTLS failed: %s",
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen str_sanitize(line, 160)));
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen client_proxy_failed(client, TRUE);
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen return -1;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen }
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen if (!last_line)
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen return 0;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen if (login_proxy_starttls(client->login_proxy) < 0) {
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen client_proxy_failed(client, TRUE);
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen return -1;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen }
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen /* i/ostreams changed. */
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen output = login_proxy_get_ostream(client->login_proxy);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen subm_client->proxy_capability = 0;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen i_free_and_null(subm_client->proxy_xclient);
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen subm_client->proxy_state = SUBMISSION_PROXY_TLS_EHLO;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen o_stream_nsend_str(output, t_strdup_printf("EHLO %s\r\n",
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen subm_client->set->hostname));
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen return 0;
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen case SUBMISSION_PROXY_XCLIENT:
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen if (invalid_line || (status / 100) != 2) {
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen client_log_err(client, t_strdup_printf(
5ada3f57a970f226eb29956d30f66afc3537200dTimo Sirainen "proxy: Remote XCLIENT failed: %s",
985fa802913c96ce6f2e25bbc788ee39c416a7e0Timo Sirainen str_sanitize(line, 160)));
985fa802913c96ce6f2e25bbc788ee39c416a7e0Timo Sirainen client_proxy_failed(client, TRUE);
406393bc328f056c49df0804f894ac2070aa5846Timo Sirainen return -1;
406393bc328f056c49df0804f894ac2070aa5846Timo Sirainen }
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen if (!last_line)
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen return 0;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen subm_client->proxy_state = SUBMISSION_PROXY_AUTHENTICATE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen case SUBMISSION_PROXY_AUTHENTICATE:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (invalid_line)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen break;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (status == 334 && client->proxy_sasl_client != NULL) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen /* continue SASL authentication */
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (submission_proxy_continue_sasl_auth(client, output,
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen text) < 0) {
985fa802913c96ce6f2e25bbc788ee39c416a7e0Timo Sirainen client_proxy_failed(client, TRUE);
406393bc328f056c49df0804f894ac2070aa5846Timo Sirainen return -1;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen }
659fe5d24825b160cae512538088020d97a60239Timo Sirainen return 0;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen }
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
659fe5d24825b160cae512538088020d97a60239Timo Sirainen if (subm_client->proxy_reply == NULL) {
659fe5d24825b160cae512538088020d97a60239Timo Sirainen subm_client->proxy_reply =
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen smtp_server_reply_create(command, status, enh_code);
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen smtp_server_reply_add_text(subm_client->proxy_reply, text);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!last_line)
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((status / 100) != 2)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen break;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen smtp_server_connection_input_lock(cmd->conn);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen cmd->context = subm_client;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen cmd->hook_destroy = submission_proxy_success_reply_sent;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen subm_client->pending_auth = NULL;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen /* Login successful. Send this reply to client. */
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen smtp_server_reply_submit(subm_client->proxy_reply);
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen return 1;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen case SUBMISSION_PROXY_STATE_COUNT:
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen i_unreached();
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen }
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen /* Login failed. Pass through the error message to client.
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen If the backend server isn't Dovecot, the error message may
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen be different from Dovecot's "user doesn't exist" error. This
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen would allow an attacker to find out what users exist in the
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen system.
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen The optimal way to handle this would be to replace the
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen backend's "password failed" error message with Dovecot's
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen AUTH_FAILED_MSG, but this would require a new setting and
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen the sysadmin to actually bother setting it properly.
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen So for now we'll just forward the error message. This
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen shouldn't be a real problem since of course everyone will
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen be using only Dovecot as their backend :) */
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen if ((status / 100) == 2) {
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen submission_proxy_error(client, AUTH_FAILED_MSG);
b44a50ea4123f21dfc8e1b6c602f690fd9721b67Timo Sirainen } else {
b44a50ea4123f21dfc8e1b6c602f690fd9721b67Timo Sirainen i_assert(subm_client->proxy_reply != NULL);
b44a50ea4123f21dfc8e1b6c602f690fd9721b67Timo Sirainen smtp_server_reply_submit(subm_client->proxy_reply);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen subm_client->pending_auth = NULL;
b44a50ea4123f21dfc8e1b6c602f690fd9721b67Timo Sirainen }
b44a50ea4123f21dfc8e1b6c602f690fd9721b67Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (client->set->auth_verbose) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client_proxy_log_failure(client, text);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client->proxy_auth_failed = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client_proxy_failed(client, FALSE);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen return -1;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen}
73e7998716853b5b7621c06aea0022dccda70ad1Timo Sirainen
73e7998716853b5b7621c06aea0022dccda70ad1Timo Sirainenvoid submission_proxy_reset(struct client *client)
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen{
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen struct submission_client *subm_client =
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (struct submission_client *)client;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen subm_client->proxy_state = SUBMISSION_PROXY_BANNER;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen subm_client->proxy_capability = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free_and_null(subm_client->proxy_xclient);
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen subm_client->proxy_reply_status = 0;
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen subm_client->proxy_reply = NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
053843989f13d9013b265fb401a4bde7e0e6568eTimo Sirainen
406393bc328f056c49df0804f894ac2070aa5846Timo Sirainenvoid submission_proxy_error(struct client *client, const char *text)
406393bc328f056c49df0804f894ac2070aa5846Timo Sirainen{
406393bc328f056c49df0804f894ac2070aa5846Timo Sirainen struct submission_client *subm_client =
406393bc328f056c49df0804f894ac2070aa5846Timo Sirainen (struct submission_client *)client;
406393bc328f056c49df0804f894ac2070aa5846Timo Sirainen
406393bc328f056c49df0804f894ac2070aa5846Timo Sirainen struct smtp_server_cmd_ctx *cmd = subm_client->pending_auth;
406393bc328f056c49df0804f894ac2070aa5846Timo Sirainen if (cmd != NULL) {
406393bc328f056c49df0804f894ac2070aa5846Timo Sirainen subm_client->pending_auth = NULL;
406393bc328f056c49df0804f894ac2070aa5846Timo Sirainen smtp_server_reply(cmd, 535, "5.7.8", "%s", text);
406393bc328f056c49df0804f894ac2070aa5846Timo Sirainen }
406393bc328f056c49df0804f894ac2070aa5846Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenconst char *submission_proxy_get_state(struct client *client)
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen{
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen struct submission_client *subm_client =
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen (struct submission_client *)client;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen i_assert(subm_client->proxy_state < SUBMISSION_PROXY_STATE_COUNT);
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen return submission_proxy_state_names[subm_client->proxy_state];
9aba3468134d4f5130c1d36c53b8664be4ef30d7Timo Sirainen}
9aba3468134d4f5130c1d36c53b8664be4ef30d7Timo Sirainen