imap-proxy.c revision 6e8ad595d0603295f57bef576da8a3a00b55c5e2
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (c) 2004-2008 Dovecot authors, see the included COPYING file */
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainenstatic bool imap_banner_has_capability(const char *line, const char *capability)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int capability_len = strlen(capability);
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen while (strncmp(line, capability, capability_len) != 0 ||
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen /* skip over the capability */
367c05967091a2cbfce59b7f274f55b1a0f9e8c9Timo Sirainenstatic void proxy_write_id(struct imap_client *client, string_t *str)
26a8b7deb3a5b6f26f9c4d71538e1248f680e4beTimo Sirainen "\"x-originating-ip\" \"%s\" "
26a8b7deb3a5b6f26f9c4d71538e1248f680e4beTimo Sirainen "\"x-originating-port\" \"%u\" "
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen "\"x-connected-ip\" \"%s\" "
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "\"x-connected-port\" \"%u\")\r\n",
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenstatic int proxy_input_line(struct imap_client *client,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen /* this is a banner */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen client_syslog(&client->common, t_strdup_printf(
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainen "proxy: Remote returned invalid banner: %s",
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (imap_banner_has_capability(line + 5, "ID"))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* send LOGIN command */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen imap_quote_append_string(str, client->proxy_user, FALSE);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen imap_quote_append_string(str, client->proxy_password, FALSE);
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen (void)o_stream_send(output, str_data(str), str_len(str));
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* Login successful. Send this line to client. */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen str_printfa(str, "proxy(%s): started proxying to %s:%u",
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen /* remote username is different, log it */
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen login_proxy_detach(client->proxy, client->common.input,
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen /* If the backend server isn't Dovecot, the error message may
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen be different from Dovecot's "user doesn't exist" error. This
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen would allow an attacker to find out what users exist in the
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen The optimal way to handle this would be to replace the
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen backend's "password failed" error message with Dovecot's
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen AUTH_FAILED_MSG, but this would require a new setting and
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen the sysadmin to actually bother setting it properly.
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen So for now we'll just forward the error message. This
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen shouldn't be a real problem since of course everyone will
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen be using only Dovecot as their backend :) */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen str_printfa(str, "proxy(%s): Login failed to %s:%u",
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen /* remote username is different, log it */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen /* allow client input again */
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen client->io = io_add(client->common.fd, IO_READ,
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen /* probably some untagged reply */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainenstatic void proxy_input(struct istream *input, struct ostream *output,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen /* remote authentication failed, we're just
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen freeing the proxy */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen /* we came here from client_destroy() */
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen /* failed for some reason, probably server disconnected */
367c05967091a2cbfce59b7f274f55b1a0f9e8c9Timo Sirainen client_send_line(client, "* BYE Temporary login failure.");
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen /* buffer full */
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen "proxy: Remote input buffer full");
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen /* disconnected */
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen client_destroy_success(client, "Proxy: Remote disconnected");
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen while ((line = i_stream_next_line(input)) != NULL) {
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen if (proxy_input_line(client, output, line) < 0)
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainenint imap_proxy_new(struct imap_client *client, const char *host,
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen unsigned int port, const char *user, const char *password)
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen client_syslog(&client->common, "proxy: password not given");
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* connection_queue_add() decided that we were the oldest
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen connection and killed us. */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen client->proxy = login_proxy_new(&client->common, host, port,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen /* disable input until authentication is finished */