imap-proxy.c revision 31750e7fddc514c68c4eaf85b4f8c00000c281e0
7cb128dc4cae2a03a742f63ba7afee23c78e3af0Phil Carmody/* Copyright (c) 2004-2009 Dovecot authors, see the included COPYING file */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "common.h"
d5abbb932a0a598f002da39a8b3326643b1b5efcTimo Sirainen#include "array.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "ioloop.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "istream.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "ostream.h"
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen#include "base64.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "str.h"
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen#include "str-sanitize.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "safe-memset.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "client.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "client-authenticate.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "imap-resp-code.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "imap-quote.h"
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen#include "imap-proxy.h"
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen#include <stdlib.h>
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen
b321df9603081896b70ec44635af96d674a9839aTimo Sirainenstatic void proxy_write_id(struct imap_client *client, string_t *str)
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen str_printfa(str, "I ID ("
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen "\"x-originating-ip\" \"%s\" "
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen "\"x-originating-port\" \"%u\" "
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen "\"x-connected-ip\" \"%s\" "
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen "\"x-connected-port\" \"%u\")\r\n",
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen net_ip2addr(&client->common.ip),
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen client->common.remote_port,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen net_ip2addr(&client->common.local_ip),
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen client->common.local_port);
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen}
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainenstatic void proxy_free_password(struct client *client)
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen{
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen if (client->proxy_password == NULL)
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen return;
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen safe_memset(client->proxy_password, 0, strlen(client->proxy_password));
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen i_free_and_null(client->proxy_password);
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen}
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainenstatic void get_plain_auth(struct client *client, string_t *dest)
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen{
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen string_t *str;
b4f35fa953a95e4d06fdae54d394095073fcfea0Timo Sirainen
b4f35fa953a95e4d06fdae54d394095073fcfea0Timo Sirainen str = t_str_new(128);
b4f35fa953a95e4d06fdae54d394095073fcfea0Timo Sirainen str_append(str, client->proxy_user);
b4f35fa953a95e4d06fdae54d394095073fcfea0Timo Sirainen str_append_c(str, '\0');
b4f35fa953a95e4d06fdae54d394095073fcfea0Timo Sirainen str_append(str, client->proxy_master_user);
31e7be5e1d41a77f08d26cef46aba1df24b3f1baTimo Sirainen str_append_c(str, '\0');
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen str_append(str, client->proxy_password);
31e7be5e1d41a77f08d26cef46aba1df24b3f1baTimo Sirainen base64_encode(str_data(str), str_len(str), dest);
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen}
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainenstatic void
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainenclient_send_capability_if_needed(struct imap_client *client, string_t *str,
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen const char *capability)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (!client->client_ignores_capability_resp_code || capability == NULL)
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen return;
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen /* reset this so that we don't re-send the CAPABILITY in case server
a9c8c1f74e5d2911d3c15657727a30b649d3bbc4Timo Sirainen sends it multiple times */
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen client->client_ignores_capability_resp_code = FALSE;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen /* client has used CAPABILITY command, so it didn't understand the
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen capabilities in the banner. send the backend's untagged CAPABILITY
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen reply and hope that the client understands it */
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen str_printfa(str, "* CAPABILITY %s\r\n", capability);
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen}
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainenstatic void proxy_write_login(struct imap_client *client, string_t *str)
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen{
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen if (client->client_ignores_capability_resp_code)
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen str_append(str, "C CAPABILITY\r\n");
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen if (client->common.proxy_master_user == NULL) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen /* logging in normally - use LOGIN command */
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen str_append(str, "L LOGIN ");
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen imap_quote_append_string(str, client->common.proxy_user, FALSE);
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen str_append_c(str, ' ');
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen imap_quote_append_string(str, client->common.proxy_password,
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen FALSE);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen proxy_free_password(&client->common);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen } else if (client->proxy_sasl_ir) {
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen /* master user login with SASL initial response support */
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen str_append(str, "L AUTHENTICATE PLAIN ");
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen get_plain_auth(&client->common, str);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen proxy_free_password(&client->common);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen } else {
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen /* master user login without SASL initial response */
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen str_append(str, "L AUTHENTICATE PLAIN");
dc8ba4890b74bde400e0feef96114940129ab181Timo Sirainen client->proxy_wait_auth_continue = TRUE;
dc8ba4890b74bde400e0feef96114940129ab181Timo Sirainen }
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen str_append(str, "\r\n");
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen}
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainenstatic int proxy_input_banner(struct imap_client *client,
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen struct ostream *output, const char *line)
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen{
1e7252421b9c85b898fef7e75bd6422ef1f046e4Timo Sirainen enum login_proxy_ssl_flags ssl_flags;
31633d676642b83305b8d46da495d9bb4e2d1ff8Timo Sirainen const char *const *capabilities = NULL;
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen string_t *str;
5af8ea0a24c5930a8e310ebc4f33fba1d084217cTimo Sirainen
1e7252421b9c85b898fef7e75bd6422ef1f046e4Timo Sirainen if (strncmp(line, "* OK ", 5) != 0) {
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen client_log_err(&client->common, t_strdup_printf(
17e09bf093bf968f383a90c559399656dffafe73Timo Sirainen "proxy: Remote returned invalid banner: %s",
17e09bf093bf968f383a90c559399656dffafe73Timo Sirainen str_sanitize(line, 160)));
17e09bf093bf968f383a90c559399656dffafe73Timo Sirainen return -1;
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen str = t_str_new(128);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (strncmp(line + 5, "[CAPABILITY ", 12) == 0) {
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen capabilities = t_strsplit(t_strcut(line + 5 + 12, ']'), " ");
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen if (str_array_icase_find(capabilities, "ID"))
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen proxy_write_id(client, str);
1108376e39a19912e8394e64e19b1bc6f6691cf6Timo Sirainen if (str_array_icase_find(capabilities, "SASL-IR"))
a8e132559a7ebe54c8269d79ce29fa3338c76199Timo Sirainen client->proxy_sasl_ir = TRUE;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen }
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen ssl_flags = login_proxy_get_ssl_flags(client->common.login_proxy);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen if ((ssl_flags & PROXY_SSL_FLAG_STARTTLS) != 0) {
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen if (capabilities != NULL &&
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen !str_array_icase_find(capabilities, "STARTTLS")) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen client_log_err(&client->common,
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen "proxy: Remote doesn't support STARTTLS");
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen return -1;
1108376e39a19912e8394e64e19b1bc6f6691cf6Timo Sirainen }
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen str_append(str, "S STARTTLS\r\n");
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen } else {
1108376e39a19912e8394e64e19b1bc6f6691cf6Timo Sirainen proxy_write_login(client, str);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen }
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen (void)o_stream_send(output, str_data(str), str_len(str));
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen return 0;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen}
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainenint imap_proxy_parse_line(struct client *client, const char *line)
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen{
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct imap_client *imap_client = (struct imap_client *)client;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct ostream *output;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *capability;
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen string_t *str;
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen i_assert(!client->destroyed);
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen output = login_proxy_get_ostream(client->login_proxy);
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen if (!imap_client->proxy_seen_banner) {
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen /* this is a banner */
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen imap_client->proxy_seen_banner = TRUE;
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen if (proxy_input_banner(imap_client, output, line) < 0) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen client_proxy_failed(client, TRUE);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return -1;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen }
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen return 0;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen } else if (*line == '+') {
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen /* AUTHENTICATE started. finish it. */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (!imap_client->proxy_wait_auth_continue) {
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen client_log_err(client, t_strdup_printf(
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen "proxy: Unexpected input: %s",
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen str_sanitize(line, 160)));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen client_proxy_failed(client, TRUE);
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen return -1;
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen }
a7bee3930831a9261fa6180d02af29c484d862e9Timo Sirainen imap_client->proxy_wait_auth_continue = FALSE;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen str = t_str_new(128);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen get_plain_auth(client, str);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen str_append(str, "\r\n");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen proxy_free_password(client);
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen (void)o_stream_send(output, str_data(str), str_len(str));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen } else if (strncmp(line, "S ", 2) == 0) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (strncmp(line, "S OK ", 5) != 0) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* STARTTLS failed */
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen client_log_err(client, t_strdup_printf(
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen "proxy: Remote STARTTLS failed: %s",
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen str_sanitize(line + 5, 160)));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen client_proxy_failed(client, TRUE);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* STARTTLS successful, begin TLS negotiation. */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (login_proxy_starttls(client->login_proxy) < 0) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen client_proxy_failed(client, TRUE);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* i/ostreams changed. */
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen output = login_proxy_get_ostream(client->login_proxy);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen str = t_str_new(128);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen proxy_write_login(imap_client, str);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen (void)o_stream_send(output, str_data(str), str_len(str));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen } else if (strncmp(line, "L OK ", 5) == 0) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* Login successful. Send this line to client. */
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen capability = imap_client->proxy_backend_capability;
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen if (strncmp(line + 5, "[CAPABILITY ", 12) == 0)
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen capability = t_strcut(line + 5 + 12, ']');
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen str = t_str_new(128);
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen client_send_capability_if_needed(imap_client, str, capability);
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen str_append(str, imap_client->cmd_tag);
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen str_append(str, line + 1);
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen str_append(str, "\r\n");
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen (void)o_stream_send(client->output,
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen str_data(str), str_len(str));
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen (void)client_skip_line(imap_client);
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen client_proxy_finish_destroy_client(client);
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen return 1;
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen } else if (strncmp(line, "L ", 2) == 0) {
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen line += 2;
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen if (client->set->verbose_auth) {
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen const char *log_line = line;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen if (strncasecmp(log_line, "NO ", 3) == 0)
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen log_line += 3;
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen client_proxy_log_failure(client, log_line);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen#define STR_NO_IMAP_RESP_CODE_AUTHFAILED "NO ["IMAP_RESP_CODE_AUTHFAILED"]"
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (strncmp(line, STR_NO_IMAP_RESP_CODE_AUTHFAILED,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen strlen(STR_NO_IMAP_RESP_CODE_AUTHFAILED)) == 0) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen /* the remote sent a generic "authentication failed"
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen error. replace it with our one, so that in case
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen the remote is sending a different error message
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen an attacker can't find out what users exist in
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen the system. */
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAILED,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen AUTH_FAILED_MSG);
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen } else if (strncmp(line, "NO [", 4) == 0) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen /* remote sent some other resp-code. forward it. */
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen client_send_raw(client, t_strconcat(
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen imap_client->cmd_tag, " ", line, "\r\n", NULL));
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen } else {
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen /* there was no [resp-code], so remote isn't Dovecot
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen v1.2+. we could either forward the line as-is and
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen leak information about what users exist in this
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen system, or we could hide other errors than password
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen failures. since other errors are pretty rare,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen it's safer to just hide them. they're still
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen available in logs though. */
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAILED,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen AUTH_FAILED_MSG);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen client_proxy_failed(client, FALSE);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen return -1;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen } else if (strncasecmp(line, "* CAPABILITY ", 13) == 0) {
849969f639a00eab26791db3cb1b66430420c0cdTimo Sirainen i_free(imap_client->proxy_backend_capability);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen imap_client->proxy_backend_capability = i_strdup(line + 13);
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen return 0;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen } else if (strncmp(line, "C ", 2) == 0) {
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen /* Reply to CAPABILITY command we sent, ignore it */
849969f639a00eab26791db3cb1b66430420c0cdTimo Sirainen return 0;
e665999b757e60bfb98e5a84a78b05f061453140Timo Sirainen } else if (strncasecmp(line, "I ", 2) == 0 ||
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen strncasecmp(line, "* ID ", 5) == 0) {
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen /* Reply to ID command we sent, ignore it */
849969f639a00eab26791db3cb1b66430420c0cdTimo Sirainen return 0;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen } else if (strncmp(line, "* ", 2) == 0) {
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen /* untagged reply. just foward it. */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen client_send_raw(client, t_strconcat(line, "\r\n", NULL));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 0;
f3d506e525a720f214020ca0f989a1966b30edaeTimo Sirainen } else {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* tagged reply, shouldn't happen. */
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen client_log_err(client, t_strdup_printf(
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen "proxy: Unexpected input, ignoring: %s",
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen str_sanitize(line, 160)));
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return 0;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen }
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen}
f8a86fdfb0048f9c87bf223373b35416ceb5856bTimo Sirainen
b321df9603081896b70ec44635af96d674a9839aTimo Sirainenvoid imap_proxy_reset(struct client *client)
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen{
e665999b757e60bfb98e5a84a78b05f061453140Timo Sirainen struct imap_client *imap_client = (struct imap_client *)client;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen imap_client->proxy_sasl_ir = FALSE;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen imap_client->proxy_seen_banner = FALSE;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen imap_client->proxy_wait_auth_continue = FALSE;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen}
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen