imap-proxy.c revision 31750e7fddc514c68c4eaf85b4f8c00000c281e0
7cb128dc4cae2a03a742f63ba7afee23c78e3af0Phil Carmody/* Copyright (c) 2004-2009 Dovecot authors, see the included COPYING file */
b321df9603081896b70ec44635af96d674a9839aTimo Sirainenstatic void proxy_write_id(struct imap_client *client, string_t *str)
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",
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainenstatic void proxy_free_password(struct client *client)
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen safe_memset(client->proxy_password, 0, strlen(client->proxy_password));
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainenstatic void get_plain_auth(struct client *client, string_t *dest)
31e7be5e1d41a77f08d26cef46aba1df24b3f1baTimo Sirainen base64_encode(str_data(str), str_len(str), dest);
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainenclient_send_capability_if_needed(struct imap_client *client, string_t *str,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (!client->client_ignores_capability_resp_code || capability == NULL)
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;
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);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainenstatic void proxy_write_login(struct imap_client *client, string_t *str)
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen if (client->client_ignores_capability_resp_code)
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen if (client->common.proxy_master_user == NULL) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen /* logging in normally - use LOGIN command */
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen imap_quote_append_string(str, client->common.proxy_user, FALSE);
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen imap_quote_append_string(str, client->common.proxy_password,
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen /* master user login with SASL initial response support */
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen /* master user login without SASL initial response */
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainenstatic int proxy_input_banner(struct imap_client *client,
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen client_log_err(&client->common, t_strdup_printf(
17e09bf093bf968f383a90c559399656dffafe73Timo Sirainen "proxy: Remote returned invalid banner: %s",
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (strncmp(line + 5, "[CAPABILITY ", 12) == 0) {
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen capabilities = t_strsplit(t_strcut(line + 5 + 12, ']'), " ");
1108376e39a19912e8394e64e19b1bc6f6691cf6Timo Sirainen if (str_array_icase_find(capabilities, "SASL-IR"))
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen ssl_flags = login_proxy_get_ssl_flags(client->common.login_proxy);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen if ((ssl_flags & PROXY_SSL_FLAG_STARTTLS) != 0) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen !str_array_icase_find(capabilities, "STARTTLS")) {
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen "proxy: Remote doesn't support STARTTLS");
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen (void)o_stream_send(output, str_data(str), str_len(str));
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainenint imap_proxy_parse_line(struct client *client, const char *line)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct imap_client *imap_client = (struct imap_client *)client;
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen output = login_proxy_get_ostream(client->login_proxy);
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen /* this is a banner */
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen if (proxy_input_banner(imap_client, output, line) < 0) {
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen /* AUTHENTICATE started. finish it. */
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen "proxy: Unexpected input: %s",
a7bee3930831a9261fa6180d02af29c484d862e9Timo Sirainen imap_client->proxy_wait_auth_continue = FALSE;
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen (void)o_stream_send(output, str_data(str), str_len(str));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* STARTTLS failed */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen "proxy: Remote STARTTLS failed: %s",
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* STARTTLS successful, begin TLS negotiation. */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (login_proxy_starttls(client->login_proxy) < 0) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* i/ostreams changed. */
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen output = login_proxy_get_ostream(client->login_proxy);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen (void)o_stream_send(output, str_data(str), str_len(str));
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)
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen client_send_capability_if_needed(imap_client, str, capability);
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 /* remote sent some other resp-code. forward it. */
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen imap_client->cmd_tag, " ", line, "\r\n", NULL));
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,
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);
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen /* Reply to CAPABILITY command we sent, ignore it */
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen /* Reply to ID command we sent, ignore it */
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen /* untagged reply. just foward it. */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen client_send_raw(client, t_strconcat(line, "\r\n", NULL));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* tagged reply, shouldn't happen. */
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen "proxy: Unexpected input, ignoring: %s",
e665999b757e60bfb98e5a84a78b05f061453140Timo Sirainen struct imap_client *imap_client = (struct imap_client *)client;