bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2004-2018 Dovecot authors, see the included COPYING file */
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen
46552a931924c2d743f045e95b08c3ce6beda91aTimo Sirainen#include "login-common.h"
3cb26db7f4756b71ba06c6e4950fa4f8ce7fad66Timo Sirainen#include "array.h"
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen#include "ioloop.h"
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen#include "istream.h"
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen#include "ostream.h"
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen#include "base64.h"
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen#include "str.h"
45155bb1250cf5a120278f349465aded513a100fTimo Sirainen#include "str-sanitize.h"
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen#include "safe-memset.h"
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen#include "dsasl-client.h"
0af9ef2e9bb71a426bba236e74ceec30be699fb7Timo Sirainen#include "imap-login-client.h"
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen#include "client-authenticate.h"
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen#include "imap-resp-code.h"
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen#include "imap-quote.h"
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen#include "imap-proxy.h"
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainenstatic const char *imap_proxy_sent_state_names[IMAP_PROXY_SENT_STATE_COUNT] = {
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen "id", "starttls", "capability",
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen "authenticate", "auth-continue", "login"
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen};
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainenstatic const char *imap_proxy_rcvd_state_names[IMAP_PROXY_RCVD_STATE_COUNT] = {
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen "none", "banner", "id", "starttls", "capability",
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen "auth-continue", "login"
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainen};
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainen
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainenstatic void proxy_write_id(struct imap_client *client, string_t *str)
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen{
9508ac436fff0e1dcea975855c139cd251deb703Timo Sirainen i_assert(client->common.proxy_ttl > 1);
ddbdc644a15f56f4b43596f1b8c0fc196c101445Timo Sirainen
a9523ec8f6c32ccdfe3a78d743a9cd749c3eb3aaAki Tuomi str_append(str, "I ID (");
a9523ec8f6c32ccdfe3a78d743a9cd749c3eb3aaAki Tuomi if (client->common.client_id != NULL &&
a9523ec8f6c32ccdfe3a78d743a9cd749c3eb3aaAki Tuomi str_len(client->common.client_id) > 0) {
a9523ec8f6c32ccdfe3a78d743a9cd749c3eb3aaAki Tuomi str_append_str(str, client->common.client_id);
a9523ec8f6c32ccdfe3a78d743a9cd749c3eb3aaAki Tuomi str_append_c(str, ' ');
a9523ec8f6c32ccdfe3a78d743a9cd749c3eb3aaAki Tuomi }
a9523ec8f6c32ccdfe3a78d743a9cd749c3eb3aaAki Tuomi str_printfa(str, "\"x-session-id\" \"%s\" "
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen "\"x-originating-ip\" \"%s\" "
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen "\"x-originating-port\" \"%u\" "
493123e38ca1f27b07ac30dcbc59663c5fcdcba2Timo Sirainen "\"x-connected-ip\" \"%s\" "
ddbdc644a15f56f4b43596f1b8c0fc196c101445Timo Sirainen "\"x-connected-port\" \"%u\" "
998eadc15aabe598cc9301fdb28c0fef5225b3f7Aki Tuomi "\"x-proxy-ttl\" \"%u\"",
b55f914c0ade77252cfd798ea8eb9a84bda56315Timo Sirainen client_get_session_id(&client->common),
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen net_ip2addr(&client->common.ip),
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen client->common.remote_port,
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen net_ip2addr(&client->common.local_ip),
ddbdc644a15f56f4b43596f1b8c0fc196c101445Timo Sirainen client->common.local_port,
ddbdc644a15f56f4b43596f1b8c0fc196c101445Timo Sirainen client->common.proxy_ttl - 1);
998eadc15aabe598cc9301fdb28c0fef5225b3f7Aki Tuomi
998eadc15aabe598cc9301fdb28c0fef5225b3f7Aki Tuomi /* append any forward_ variables to request */
998eadc15aabe598cc9301fdb28c0fef5225b3f7Aki Tuomi for(const char *const *ptr = client->common.auth_passdb_args; *ptr != NULL; ptr++) {
998eadc15aabe598cc9301fdb28c0fef5225b3f7Aki Tuomi if (strncasecmp(*ptr, "forward_", 8) == 0) {
998eadc15aabe598cc9301fdb28c0fef5225b3f7Aki Tuomi const char *key = t_strconcat("x-forward-",
998eadc15aabe598cc9301fdb28c0fef5225b3f7Aki Tuomi t_strcut((*ptr)+8, '='),
998eadc15aabe598cc9301fdb28c0fef5225b3f7Aki Tuomi NULL);
998eadc15aabe598cc9301fdb28c0fef5225b3f7Aki Tuomi const char *val = i_strchr_to_next(*ptr, '=');
998eadc15aabe598cc9301fdb28c0fef5225b3f7Aki Tuomi str_append_c(str, ' ');
998eadc15aabe598cc9301fdb28c0fef5225b3f7Aki Tuomi imap_append_string(str, key);
998eadc15aabe598cc9301fdb28c0fef5225b3f7Aki Tuomi str_append_c(str, ' ');
998eadc15aabe598cc9301fdb28c0fef5225b3f7Aki Tuomi imap_append_nstring(str, val);
998eadc15aabe598cc9301fdb28c0fef5225b3f7Aki Tuomi }
998eadc15aabe598cc9301fdb28c0fef5225b3f7Aki Tuomi }
998eadc15aabe598cc9301fdb28c0fef5225b3f7Aki Tuomi
998eadc15aabe598cc9301fdb28c0fef5225b3f7Aki Tuomi str_append(str, ")\r\n");
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen}
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic void proxy_free_password(struct client *client)
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen{
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen if (client->proxy_password == NULL)
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen return;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen safe_memset(client->proxy_password, 0, strlen(client->proxy_password));
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen i_free_and_null(client->proxy_password);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen}
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomistatic int proxy_write_starttls(struct imap_client *client, string_t *str)
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi{
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi enum login_proxy_ssl_flags ssl_flags = login_proxy_get_ssl_flags(client->common.login_proxy);
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi if ((ssl_flags & PROXY_SSL_FLAG_STARTTLS) != 0) {
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi if (client->proxy_backend_capability != NULL &&
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi !str_array_icase_find(t_strsplit(client->proxy_backend_capability, " "), "STARTTLS")) {
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi client_log_err(&client->common,
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi "proxy: Remote doesn't support STARTTLS");
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi return -1;
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi }
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi str_append(str, "S STARTTLS\r\n");
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen client->proxy_sent_state |= IMAP_PROXY_SENT_STATE_STARTTLS;
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi return 1;
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi }
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi return 0;
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi}
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainenstatic int proxy_write_login(struct imap_client *client, string_t *str)
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen{
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen struct dsasl_client_settings sasl_set;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen const unsigned char *output;
2c5c293940fd6c7e020e1d58dae77a9d01f9059bTimo Sirainen size_t len;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen const char *mech_name, *error;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
3bc9d91f987261e989aa653fd412b0e8095e4810Timo Sirainen /* Send CAPABILITY command if we don't know the capabilities yet.
3bc9d91f987261e989aa653fd412b0e8095e4810Timo Sirainen Also as kind of a Dovecot-backend workaround if the client insisted
3bc9d91f987261e989aa653fd412b0e8095e4810Timo Sirainen on sending CAPABILITY command (even though our banner already sent
3bc9d91f987261e989aa653fd412b0e8095e4810Timo Sirainen it), send the (unnecessary) CAPABILITY command to backend as well
3bc9d91f987261e989aa653fd412b0e8095e4810Timo Sirainen to avoid sending the CAPABILITY reply twice (untagged and OK resp
3bc9d91f987261e989aa653fd412b0e8095e4810Timo Sirainen code). */
41783dcf1bcd7118440c9c40a691a09fb98a9460Timo Sirainen if (!client->proxy_capability_request_sent &&
41783dcf1bcd7118440c9c40a691a09fb98a9460Timo Sirainen (client->proxy_backend_capability == NULL ||
41783dcf1bcd7118440c9c40a691a09fb98a9460Timo Sirainen client->client_ignores_capability_resp_code)) {
41783dcf1bcd7118440c9c40a691a09fb98a9460Timo Sirainen client->proxy_capability_request_sent = TRUE;
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen client->proxy_sent_state |= IMAP_PROXY_SENT_STATE_CAPABILITY;
5324117274df8564eeaebe369cb1eca76edb3165Timo Sirainen str_append(str, "C CAPABILITY\r\n");
ab281fc992907b6cf6c730f672dc3aa4c6685015Timo Sirainen if (client->common.proxy_nopipelining) {
ab281fc992907b6cf6c730f672dc3aa4c6685015Timo Sirainen /* authenticate only after receiving C OK reply. */
ab281fc992907b6cf6c730f672dc3aa4c6685015Timo Sirainen return 0;
ab281fc992907b6cf6c730f672dc3aa4c6685015Timo Sirainen }
ab281fc992907b6cf6c730f672dc3aa4c6685015Timo Sirainen }
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen if (client->common.proxy_mech == NULL) {
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen /* logging in normally - use LOGIN command */
52fe791133ad838c3aca3f1c88f96aab755950f8Timo Sirainen if (client->proxy_logindisabled &&
52fe791133ad838c3aca3f1c88f96aab755950f8Timo Sirainen login_proxy_get_ssl_flags(client->common.login_proxy) == 0) {
52fe791133ad838c3aca3f1c88f96aab755950f8Timo Sirainen client_log_err(&client->common,
52fe791133ad838c3aca3f1c88f96aab755950f8Timo Sirainen "proxy: Remote advertised LOGINDISABLED and SSL/TLS not enabled");
52fe791133ad838c3aca3f1c88f96aab755950f8Timo Sirainen return -1;
52fe791133ad838c3aca3f1c88f96aab755950f8Timo Sirainen }
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen str_append(str, "L LOGIN ");
686ad6d723004b807fd558f3ef9d1f88afa7e127Timo Sirainen imap_append_string(str, client->common.proxy_user);
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen str_append_c(str, ' ');
686ad6d723004b807fd558f3ef9d1f88afa7e127Timo Sirainen imap_append_string(str, client->common.proxy_password);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen str_append(str, "\r\n");
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen client->proxy_sent_state |= IMAP_PROXY_SENT_STATE_LOGIN;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen proxy_free_password(&client->common);
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_append(str, "L AUTHENTICATE ");
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen str_append(str, mech_name);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen if (client->proxy_sasl_ir) {
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen if (dsasl_client_output(client->common.proxy_sasl_client,
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen &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 str_append_c(str, ' ');
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen if (len == 0)
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen str_append_c(str, '=');
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen else
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen base64_encode(output, len, str);
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen }
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen str_append(str, "\r\n");
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen proxy_free_password(&client->common);
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen client->proxy_sent_state |= IMAP_PROXY_SENT_STATE_AUTHENTICATE;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen return 0;
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen}
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainenstatic int proxy_input_banner(struct imap_client *client,
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen struct ostream *output, const char *line)
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen{
3cb26db7f4756b71ba06c6e4950fa4f8ce7fad66Timo Sirainen const char *const *capabilities = NULL;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen string_t *str;
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi int ret;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen if (strncmp(line, "* OK ", 5) != 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen client_log_err(&client->common, t_strdup_printf(
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen "proxy: Remote returned invalid banner: %s",
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen str_sanitize(line, 160)));
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen return -1;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen }
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen str = t_str_new(128);
53d564c421ca7292d7b1bd945f86894a34b75370Timo Sirainen if (strncmp(line + 5, "[CAPABILITY ", 12) == 0) {
3cb26db7f4756b71ba06c6e4950fa4f8ce7fad66Timo Sirainen capabilities = t_strsplit(t_strcut(line + 5 + 12, ']'), " ");
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen if (str_array_icase_find(capabilities, "SASL-IR"))
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen client->proxy_sasl_ir = TRUE;
52fe791133ad838c3aca3f1c88f96aab755950f8Timo Sirainen if (str_array_icase_find(capabilities, "LOGINDISABLED"))
52fe791133ad838c3aca3f1c88f96aab755950f8Timo Sirainen client->proxy_logindisabled = TRUE;
5324117274df8564eeaebe369cb1eca76edb3165Timo Sirainen i_free(client->proxy_backend_capability);
5324117274df8564eeaebe369cb1eca76edb3165Timo Sirainen client->proxy_backend_capability =
5324117274df8564eeaebe369cb1eca76edb3165Timo Sirainen i_strdup(t_strcut(line + 5 + 12, ']'));
6d24551e169c0808695db35d7a228f1970a84c75Timo Sirainen if (str_array_icase_find(capabilities, "ID") &&
6d24551e169c0808695db35d7a228f1970a84c75Timo Sirainen !client->common.proxy_not_trusted) {
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen client->proxy_sent_state |= IMAP_PROXY_SENT_STATE_ID;
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi proxy_write_id(client, str);
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi if (client->common.proxy_nopipelining) {
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi /* write login or starttls after I OK */
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi o_stream_nsend(output, str_data(str), str_len(str));
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi return 0;
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi }
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi }
53d564c421ca7292d7b1bd945f86894a34b75370Timo Sirainen }
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi if ((ret = proxy_write_starttls(client, str)) < 0) {
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi return -1;
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi } else if (ret == 0) {
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen if (proxy_write_login(client, str) < 0)
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen return -1;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen }
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(output, str_data(str), str_len(str));
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen return 0;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen}
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainenstatic void
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainenclient_send_login_reply(struct imap_client *client, string_t *str,
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen const char *line)
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen{
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen const char *capability;
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen bool tagged_capability;
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen capability = client->proxy_backend_capability;
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen tagged_capability = strncasecmp(line, "[CAPABILITY ", 12) == 0;
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen if (tagged_capability)
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen capability = t_strcut(line + 12, ']');
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen if (client->client_ignores_capability_resp_code && capability != NULL) {
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen /* client has used CAPABILITY command, so it didn't understand
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen the capabilities in the banner. send the backend's untagged
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen CAPABILITY reply and hope that the client understands it */
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen str_printfa(str, "* CAPABILITY %s\r\n", capability);
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen }
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen str_append(str, client->cmd_tag);
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen str_append(str, " OK ");
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen if (!client->client_ignores_capability_resp_code &&
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen !tagged_capability && capability != NULL) {
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen str_printfa(str, "[CAPABILITY %s] ", capability);
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen if (*line == '[') {
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen /* we need to send the capability.
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen skip over this resp-code */
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen while (*line != ']' && *line != '\0')
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen line++;
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen if (*line == ' ') line++;
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen }
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen }
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen str_append(str, line);
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen str_append(str, "\r\n");
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen}
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenint imap_proxy_parse_line(struct client *client, const char *line)
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct imap_client *imap_client = (struct imap_client *)client;
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen struct ostream *output;
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo 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;
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen
feb665db52583259a1f42037c6e8a22852aa8889Timo Sirainen i_assert(!client->destroyed);
9bc0204ec8bda657ce2e96e6ae715e4034f1538bTimo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen output = login_proxy_get_ostream(client->login_proxy);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (!imap_client->proxy_seen_banner) {
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen /* this is a banner */
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen imap_client->proxy_rcvd_state = IMAP_PROXY_RCVD_STATE_BANNER;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen imap_client->proxy_seen_banner = TRUE;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (proxy_input_banner(imap_client, output, line) < 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen client_proxy_failed(client, TRUE);
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen return -1;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen }
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen return 0;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen } else if (*line == '+') {
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen /* AUTHENTICATE started. finish it. */
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen if (client->proxy_sasl_client == NULL) {
27d50b3aa143964143e4bef66c0bfe3c72aea233Timo Sirainen /* used literals with LOGIN command, just ignore. */
27d50b3aa143964143e4bef66c0bfe3c72aea233Timo Sirainen return 0;
9c47edf0d1aa8afa6d05dde93e7aa5169059c94aTimo Sirainen }
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen imap_client->proxy_sent_state &= ~IMAP_PROXY_SENT_STATE_AUTHENTICATE;
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen imap_client->proxy_rcvd_state = IMAP_PROXY_RCVD_STATE_AUTH_CONTINUE;
9c47edf0d1aa8afa6d05dde93e7aa5169059c94aTimo Sirainen
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen str = t_str_new(128);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen if (line[1] != ' ' ||
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen base64_decode(line+2, strlen(line+2), NULL, str) < 0) {
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen client_log_err(client,
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen "proxy: Server sent invalid base64 data in AUTHENTICATE response");
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen client_proxy_failed(client, TRUE);
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);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo 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 client_proxy_failed(client, TRUE);
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);
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen str_append(str, "\r\n");
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen imap_client->proxy_sent_state |= IMAP_PROXY_SENT_STATE_AUTH_CONTINUE;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(output, str_data(str), str_len(str));
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen return 0;
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen } else if (strncmp(line, "S ", 2) == 0) {
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen imap_client->proxy_sent_state &= ~IMAP_PROXY_SENT_STATE_STARTTLS;
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen imap_client->proxy_rcvd_state = IMAP_PROXY_RCVD_STATE_STARTTLS;
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen if (strncmp(line, "S OK ", 5) != 0) {
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen /* STARTTLS failed */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen client_log_err(client, t_strdup_printf(
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen "proxy: Remote STARTTLS failed: %s",
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen str_sanitize(line + 5, 160)));
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen client_proxy_failed(client, TRUE);
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen return -1;
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen }
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen /* STARTTLS successful, begin TLS negotiation. */
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);
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen str = t_str_new(128);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen if (proxy_write_login(imap_client, str) < 0) {
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen client_proxy_failed(client, TRUE);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen return -1;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen }
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(output, str_data(str), str_len(str));
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen return 1;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen } else if (strncmp(line, "L OK ", 5) == 0) {
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen /* Login successful. Send this line to client. */
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen imap_client->proxy_sent_state &= ~IMAP_PROXY_SENT_STATE_LOGIN;
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen imap_client->proxy_rcvd_state = IMAP_PROXY_RCVD_STATE_LOGIN;
8e50329e2c5e3a199674ae9f6d3dfcddab02487bTimo Sirainen str = t_str_new(128);
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen client_send_login_reply(imap_client, str, line + 5);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(client->output, str_data(str), str_len(str));
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen client_proxy_finish_destroy_client(client);
eb188b2a2d5395b2c6125f875ec053b04a10e5fbTimo Sirainen return 1;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen } else if (strncmp(line, "L ", 2) == 0) {
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen imap_client->proxy_sent_state &= ~IMAP_PROXY_SENT_STATE_LOGIN;
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen imap_client->proxy_rcvd_state = IMAP_PROXY_RCVD_STATE_LOGIN;
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen line += 2;
ac45ba9c603b67cc43fa7bceffdef0a19100720bTimo Sirainen if (client->set->auth_verbose) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen const char *log_line = line;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (strncasecmp(log_line, "NO ", 3) == 0)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen log_line += 3;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen client_proxy_log_failure(client, log_line);
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen }
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen#define STR_NO_IMAP_RESP_CODE_AUTHFAILED "NO ["IMAP_RESP_CODE_AUTHFAILED"]"
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen if (strncmp(line, STR_NO_IMAP_RESP_CODE_AUTHFAILED,
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen strlen(STR_NO_IMAP_RESP_CODE_AUTHFAILED)) == 0) {
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen /* the remote sent a generic "authentication failed"
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen error. replace it with our one, so that in case
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen the remote is sending a different error message
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen an attacker can't find out what users exist in
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen the system. */
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen client_send_reply_code(client, IMAP_CMD_REPLY_NO,
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen IMAP_RESP_CODE_AUTHFAILED,
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen AUTH_FAILED_MSG);
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen } else if (strncmp(line, "NO [", 4) == 0) {
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen /* remote sent some other resp-code. forward it. */
00fa8dcbc66f56daa737487c9dec7166c37de79eTimo Sirainen client_send_raw(client, t_strconcat(
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen imap_client->cmd_tag, " ", line, "\r\n", NULL));
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen } else {
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen /* there was no [resp-code], so remote isn't Dovecot
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen v1.2+. we could either forward the line as-is and
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen leak information about what users exist in this
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen system, or we could hide other errors than password
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen failures. since other errors are pretty rare,
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen it's safer to just hide them. they're still
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen available in logs though. */
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen client_send_reply_code(client, IMAP_CMD_REPLY_NO,
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen IMAP_RESP_CODE_AUTHFAILED,
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen AUTH_FAILED_MSG);
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen }
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen
80980955bb1bbcc1bd73623fe0912f334194ddd2Timo Sirainen client->proxy_auth_failed = TRUE;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen client_proxy_failed(client, FALSE);
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen return -1;
3cb26db7f4756b71ba06c6e4950fa4f8ce7fad66Timo Sirainen } else if (strncasecmp(line, "* CAPABILITY ", 13) == 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen i_free(imap_client->proxy_backend_capability);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen imap_client->proxy_backend_capability = i_strdup(line + 13);
3cb26db7f4756b71ba06c6e4950fa4f8ce7fad66Timo Sirainen return 0;
31750e7fddc514c68c4eaf85b4f8c00000c281e0Timo Sirainen } else if (strncmp(line, "C ", 2) == 0) {
737d994fb6bb0f3e87f7412e35874694013d2fc3Timo Sirainen /* Reply to CAPABILITY command we sent */
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen imap_client->proxy_sent_state &= ~IMAP_PROXY_SENT_STATE_CAPABILITY;
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen imap_client->proxy_rcvd_state = IMAP_PROXY_RCVD_STATE_CAPABILITY;
737d994fb6bb0f3e87f7412e35874694013d2fc3Timo Sirainen if (strncmp(line, "C OK ", 5) == 0 &&
737d994fb6bb0f3e87f7412e35874694013d2fc3Timo Sirainen client->proxy_password != NULL) {
737d994fb6bb0f3e87f7412e35874694013d2fc3Timo Sirainen /* pipelining was disabled, send the login now. */
737d994fb6bb0f3e87f7412e35874694013d2fc3Timo Sirainen str = t_str_new(128);
737d994fb6bb0f3e87f7412e35874694013d2fc3Timo Sirainen if (proxy_write_login(imap_client, str) < 0)
737d994fb6bb0f3e87f7412e35874694013d2fc3Timo Sirainen return -1;
737d994fb6bb0f3e87f7412e35874694013d2fc3Timo Sirainen o_stream_nsend(output, str_data(str), str_len(str));
737d994fb6bb0f3e87f7412e35874694013d2fc3Timo Sirainen return 1;
737d994fb6bb0f3e87f7412e35874694013d2fc3Timo Sirainen }
31750e7fddc514c68c4eaf85b4f8c00000c281e0Timo Sirainen return 0;
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi } else if (strncasecmp(line, "I ", 2) == 0) {
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi /* Reply to ID command we sent, ignore it unless
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi pipelining is disabled, in which case send
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi either STARTTLS or login */
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen imap_client->proxy_sent_state &= ~IMAP_PROXY_SENT_STATE_ID;
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen imap_client->proxy_rcvd_state = IMAP_PROXY_RCVD_STATE_ID;
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi
9a6fe618193d3029328a9b056d4435f135a64bfdAki Tuomi if (client->proxy_nopipelining) {
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi str = t_str_new(128);
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi if ((ret = proxy_write_starttls(imap_client, str)) < 0) {
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi return -1;
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi } else if (ret == 0) {
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi if (proxy_write_login(imap_client, str) < 0)
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi return -1;
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi }
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi o_stream_nsend(output, str_data(str), str_len(str));
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi return 1;
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi }
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi return 0;
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi } else if (strncasecmp(line, "* ID ", 5) == 0) {
abd4203d97d6db19550fc45d6b6806b2deadb625Aki Tuomi /* Reply to ID command we sent, ignore it */
087eb3d719a5667631cc7ce9de6c372ddea19f4dTimo Sirainen return 0;
087eb3d719a5667631cc7ce9de6c372ddea19f4dTimo Sirainen } else if (strncmp(line, "* ", 2) == 0) {
c24150b68efb24c12e95ec101f382d5c40cd15c9Aki Tuomi /* untagged reply. just forward it. */
00fa8dcbc66f56daa737487c9dec7166c37de79eTimo Sirainen client_send_raw(client, t_strconcat(line, "\r\n", NULL));
087eb3d719a5667631cc7ce9de6c372ddea19f4dTimo Sirainen return 0;
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen } else {
087eb3d719a5667631cc7ce9de6c372ddea19f4dTimo Sirainen /* tagged reply, shouldn't happen. */
9c47edf0d1aa8afa6d05dde93e7aa5169059c94aTimo Sirainen client_log_err(client, t_strdup_printf(
9c47edf0d1aa8afa6d05dde93e7aa5169059c94aTimo Sirainen "proxy: Unexpected input, ignoring: %s",
9c47edf0d1aa8afa6d05dde93e7aa5169059c94aTimo Sirainen str_sanitize(line, 160)));
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen return 0;
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen }
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen}
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenvoid imap_proxy_reset(struct client *client)
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct imap_client *imap_client = (struct imap_client *)client;
d7cd49f01fad7c87c5a0865ebf54a548275e9feeTimo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen imap_client->proxy_sasl_ir = FALSE;
52fe791133ad838c3aca3f1c88f96aab755950f8Timo Sirainen imap_client->proxy_logindisabled = FALSE;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen imap_client->proxy_seen_banner = FALSE;
c3ad163c5d78e6c6f9dbe90ab949506c038d3275Timo Sirainen imap_client->proxy_capability_request_sent = FALSE;
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen imap_client->proxy_sent_state = 0;
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen imap_client->proxy_rcvd_state = IMAP_PROXY_RCVD_STATE_NONE;
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen}
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainenvoid imap_proxy_error(struct client *client, const char *text)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen{
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen client_send_reply_code(client, IMAP_CMD_REPLY_NO,
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen IMAP_RESP_CODE_UNAVAILABLE, text);
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen}
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainenconst char *imap_proxy_get_state(struct client *client)
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen{
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen struct imap_client *imap_client = (struct imap_client *)client;
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen string_t *str = t_str_new(128);
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen for (unsigned int i = 0; i < IMAP_PROXY_SENT_STATE_COUNT; i++) {
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen if (str_len(str) > 0)
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen str_append_c(str, '+');
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen if ((imap_client->proxy_sent_state & (1 << i)) != 0)
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen str_append(str, imap_proxy_sent_state_names[i]);
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen }
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen str_append_c(str, '/');
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen str_append(str, imap_proxy_rcvd_state_names[imap_client->proxy_rcvd_state]);
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen return str_c(str);
b4bf60434dcfc23433fc09e1899bba4a8b20022eTimo Sirainen}