imap-proxy.c revision 6e8ad595d0603295f57bef576da8a3a00b55c5e2
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (c) 2004-2008 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "common.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "ioloop.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "istream.h"
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen#include "ostream.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "str.h"
89b548af722113acb5d63dfffb44423cb60f91e4Timo Sirainen#include "str-sanitize.h"
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen#include "safe-memset.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "client.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "imap-quote.h"
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen#include "imap-proxy.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainenstatic bool imap_banner_has_capability(const char *line, const char *capability)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int capability_len = strlen(capability);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (strncmp(line, "[CAPABILITY ", 12) != 0)
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen return FALSE;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen line += 12;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen while (strncmp(line, capability, capability_len) != 0 ||
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen (line[capability_len] != ' ' &&
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen line[capability_len] != '\0')) {
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen /* skip over the capability */
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen while (*line != ' ') {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (*line == '\0')
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen line++;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen line++;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen
367c05967091a2cbfce59b7f274f55b1a0f9e8c9Timo Sirainenstatic void proxy_write_id(struct imap_client *client, string_t *str)
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen{
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen str_printfa(str, "I ID ("
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",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen net_ip2addr(&client->common.ip),
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen client->common.remote_port,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen net_ip2addr(&client->common.local_ip),
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen client->common.local_port);
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen}
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenstatic int proxy_input_line(struct imap_client *client,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen struct ostream *output, const char *line)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen string_t *str;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(!client->destroyed);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!client->proxy_login_sent) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen /* this is a banner */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (strncmp(line, "* OK ", 5) != 0) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen client_syslog(&client->common, t_strdup_printf(
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainen "proxy: Remote returned invalid banner: %s",
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen str_sanitize(line, 160)));
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen client_destroy_internal_failure(client);
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen return -1;
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen }
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen str = t_str_new(128);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (imap_banner_has_capability(line + 5, "ID"))
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainen proxy_write_id(client, str);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* send LOGIN command */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_append(str, "P LOGIN ");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen imap_quote_append_string(str, client->proxy_user, FALSE);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_append_c(str, ' ');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen imap_quote_append_string(str, client->proxy_password, FALSE);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_append(str, "\r\n");
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen (void)o_stream_send(output, str_data(str), str_len(str));
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen safe_memset(client->proxy_password, 0,
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen strlen(client->proxy_password));
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen i_free(client->proxy_password);
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen client->proxy_password = NULL;
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen client->proxy_login_sent = TRUE;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen return 0;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen } else if (strncmp(line, "P OK ", 5) == 0) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* Login successful. Send this line to client. */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen str = t_str_new(128);
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen str_append(str, client->cmd_tag);
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen str_append(str, line + 1);
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen str_append(str, "\r\n");
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen (void)o_stream_send(client->output,
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen str_data(str), str_len(str));
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen str_truncate(str, 0);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen str_printfa(str, "proxy(%s): started proxying to %s:%u",
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen client->common.virtual_user,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen login_proxy_get_host(client->proxy),
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen login_proxy_get_port(client->proxy));
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen if (strcmp(client->common.virtual_user,
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen client->proxy_user) != 0) {
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen /* remote username is different, log it */
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen str_append_c(str, '/');
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen str_append(str, client->proxy_user);
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen }
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen (void)client_skip_line(client);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen login_proxy_detach(client->proxy, client->common.input,
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen client->output);
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen client->proxy = NULL;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen client->common.input = NULL;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen client->output = NULL;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen client->common.fd = -1;
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen client_destroy_success(client, str_c(str));
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen return -1;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen } else if (strncmp(line, "P ", 2) == 0) {
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
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainen system.
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
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
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 :) */
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen client_send_tagline(client, line + 2);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen if (verbose_auth) {
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen str = t_str_new(128);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen str_printfa(str, "proxy(%s): Login failed to %s:%u",
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen client->common.virtual_user,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen login_proxy_get_host(client->proxy),
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen login_proxy_get_port(client->proxy));
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (strcmp(client->common.virtual_user,
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen client->proxy_user) != 0) {
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen /* remote username is different, log it */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen str_append_c(str, '/');
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen str_append(str, client->proxy_user);
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen }
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen str_append(str, ": ");
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen if (strncasecmp(line + 2, "NO ", 3) == 0)
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen str_append(str, line + 2 + 3);
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen else
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen str_append(str, line + 2);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen i_info("%s", str_c(str));
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen /* allow client input again */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen i_assert(client->io == NULL);
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen client->io = io_add(client->common.fd, IO_READ,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen client_input, client);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen login_proxy_free(client->proxy);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen client->proxy = NULL;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen i_free(client->proxy_user);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen client->proxy_user = NULL;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen return -1;
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen } else {
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen /* probably some untagged reply */
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen return 0;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen }
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen}
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainenstatic void proxy_input(struct istream *input, struct ostream *output,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen struct imap_client *client)
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen{
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen const char *line;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if (input == NULL) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if (client->io != NULL) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen /* remote authentication failed, we're just
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen freeing the proxy */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen return;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if (client->destroyed) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen /* we came here from client_destroy() */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen return;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen }
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen /* failed for some reason, probably server disconnected */
367c05967091a2cbfce59b7f274f55b1a0f9e8c9Timo Sirainen client_send_line(client, "* BYE Temporary login failure.");
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen client_destroy_success(client, NULL);
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen return;
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen }
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen i_assert(!client->destroyed);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen switch (i_stream_read(input)) {
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen case -2:
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen /* buffer full */
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen client_syslog(&client->common,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen "proxy: Remote input buffer full");
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen client_destroy_internal_failure(client);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen case -1:
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen /* disconnected */
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen client_destroy_success(client, "Proxy: Remote disconnected");
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen return;
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen }
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen while ((line = i_stream_next_line(input)) != NULL) {
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen if (proxy_input_line(client, output, line) < 0)
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen break;
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen}
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainenint imap_proxy_new(struct imap_client *client, const char *host,
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen unsigned int port, const char *user, const char *password)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen{
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen i_assert(user != NULL);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen i_assert(!client->destroyed);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (password == NULL) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen client_syslog(&client->common, "proxy: password not given");
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return -1;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen i_assert(client->refcount > 1);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen connection_queue_add(1);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (client->destroyed) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* connection_queue_add() decided that we were the oldest
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen connection and killed us. */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return -1;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen client->proxy = login_proxy_new(&client->common, host, port,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen proxy_input, client);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (client->proxy == NULL)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return -1;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen client->proxy_login_sent = FALSE;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen client->proxy_user = i_strdup(user);
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen client->proxy_password = i_strdup(password);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen /* disable input until authentication is finished */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (client->io != NULL)
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen io_remove(&client->io);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return 0;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen}
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen