imap-proxy.c revision e3a838c80f54f024115fade93c6c87a0998f1fab
2e37d45867d081db150ab78dad303b9077aea24fTimo Sirainen/* Copyright (c) 2004-2009 Dovecot authors, see the included COPYING file */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen "NO ["IMAP_RESP_CODE_UNAVAILABLE"] "AUTH_TEMP_FAILED_MSG
b624773984e35dd894db8dff976c1a2114c70782Timo Sirainenstatic bool imap_banner_has_capability(const char *line, const char *capability)
b624773984e35dd894db8dff976c1a2114c70782Timo Sirainen unsigned int capability_len = strlen(capability);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen while (strncmp(line, capability, capability_len) != 0 ||
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen /* skip over the capability */
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic void proxy_write_id(struct imap_client *client, string_t *str)
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen "\"x-originating-ip\" \"%s\" "
788a0754cfd38dcfec1902844b085e4e84cfe7e6Timo Sirainen "\"x-originating-port\" \"%u\" "
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen "\"x-connected-ip\" \"%s\" "
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen "\"x-connected-port\" \"%u\")\r\n",
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainenstatic void proxy_free_password(struct imap_client *client)
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen safe_memset(client->proxy_password, 0, strlen(client->proxy_password));
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic void proxy_failed(struct imap_client *client, bool send_tagline)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen client_send_tagline(client, PROXY_FAILURE_MSG);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* call this last - it may destroy the client */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic void get_plain_auth(struct imap_client *client, string_t *dest)
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen base64_encode(str_data(str), str_len(str), dest);
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainenstatic int proxy_input_banner(struct imap_client *client,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen client_syslog_err(&client->common, t_strdup_printf(
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen "proxy: Remote returned invalid banner: %s",
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen if (imap_banner_has_capability(line + 5, "ID"))
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* logging in normally - use LOGIN command */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen imap_quote_append_string(str, client->proxy_user, FALSE);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen imap_quote_append_string(str, client->proxy_password, FALSE);
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen } else if (imap_banner_has_capability(line + 5, "SASL-IR")) {
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen /* master user login with SASL initial response support */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen /* master user login without SASL initial response */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen (void)o_stream_send(output, str_data(str), str_len(str));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainenstatic int proxy_input_line(struct imap_client *client,
33dd58ab84a020c4f061d2f6031eb6d4c168df1bTimo Sirainen /* this is a banner */
33dd58ab84a020c4f061d2f6031eb6d4c168df1bTimo Sirainen if (proxy_input_banner(client, output, line) < 0) {
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen /* AUTHENTICATE started. finish it. */
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen (void)o_stream_send(output, str_data(str), str_len(str));
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* Login successful. Send this line to client. */
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen str_printfa(str, "proxy(%s): started proxying to %s:%u",
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* remote username is different, log it */
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen login_proxy_detach(client->proxy, client->common.input,
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen str_printfa(str, "proxy(%s): Login failed to %s:%u",
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen /* remote username is different, log it */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen#define STR_NO_IMAP_RESP_CODE_AUTHFAILED "NO ["IMAP_RESP_CODE_AUTHFAILED"]"
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (strncmp(line, STR_NO_IMAP_RESP_CODE_AUTHFAILED,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen strlen(STR_NO_IMAP_RESP_CODE_AUTHFAILED)) == 0) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen /* the remote sent a generic "authentication failed"
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen error. replace it with our one, so that in case
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen the remote is sending a different error message
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen an attacker can't find out what users exist in
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen the system. */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen /* remote sent some other resp-code. forward it. */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen /* there was no [resp-code], so remote isn't Dovecot
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen v1.2+. we could either forward the line as-is and
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen leak information about what users exist in this
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen system, or we could hide other errors than password
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen failures. since other errors are pretty rare,
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen it's safer to just hide them. they're still
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen available in logs though. */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* probably some untagged reply */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenstatic void proxy_input(struct istream *input, struct ostream *output,
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen /* we're just freeing the proxy */
e2a700d0628e395d64cbcef4b5b4510816bf51c4Timo Sirainen /* we came here from client_destroy() */
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen /* failed for some reason, probably server disconnected */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen "proxy: Remote input buffer full");
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen "proxy: Remote disconnected");
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen while ((line = i_stream_next_line(input)) != NULL) {
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen if (proxy_input_line(client, output, line) != 0)
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainenint imap_proxy_new(struct imap_client *client, const char *host,
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen unsigned int port, const char *user, const char *master_user,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen client_syslog_err(&client->common, "proxy: password not given");
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen client_send_tagline(client, PROXY_FAILURE_MSG);
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen /* connection_queue_add() decided that we were the oldest
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen connection and killed us. */
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (login_proxy_is_ourself(&client->common, host, port, user)) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen client_syslog_err(&client->common, "Proxying loops to itself");
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen client_send_tagline(client, PROXY_FAILURE_MSG);
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen client->proxy = login_proxy_new(&client->common, host, port,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen client_send_tagline(client, PROXY_FAILURE_MSG);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen client->proxy_master_user = i_strdup(master_user);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen /* disable input until authentication is finished */