imap-proxy.c revision be71a9de88d1266597eb8c5e0b6f519d90e14397
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2004-2009 Dovecot authors, see the included COPYING file */
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainenstatic void proxy_write_id(struct imap_client *client, string_t *str)
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen "\"x-originating-ip\" \"%s\" "
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen "\"x-originating-port\" \"%u\" "
493123e38ca1f27b07ac30dcbc59663c5fcdcba2Timo Sirainen "\"x-connected-ip\" \"%s\" "
493123e38ca1f27b07ac30dcbc59663c5fcdcba2Timo Sirainen "\"x-connected-port\" \"%u\")\r\n",
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic void proxy_free_password(struct client *client)
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen safe_memset(client->proxy_password, 0, strlen(client->proxy_password));
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic void get_plain_auth(struct client *client, string_t *dest)
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen base64_encode(str_data(str), str_len(str), dest);
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainenstatic void proxy_write_login(struct imap_client *client, string_t *str)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (client->common.proxy_master_user == NULL) {
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen /* logging in normally - use LOGIN command */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen imap_quote_append_string(str, client->common.proxy_user, FALSE);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen imap_quote_append_string(str, client->common.proxy_password,
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen /* master user login with SASL initial response support */
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen /* master user login without SASL initial response */
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainenstatic int proxy_input_banner(struct imap_client *client,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen client_log_err(&client->common, t_strdup_printf(
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen "proxy: Remote returned invalid banner: %s",
53d564c421ca7292d7b1bd945f86894a34b75370Timo Sirainen if (strncmp(line + 5, "[CAPABILITY ", 12) == 0) {
3cb26db7f4756b71ba06c6e4950fa4f8ce7fad66Timo Sirainen capabilities = t_strsplit(t_strcut(line + 5 + 12, ']'), " ");
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen if (str_array_icase_find(capabilities, "SASL-IR"))
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen ssl_flags = login_proxy_get_ssl_flags(client->common.login_proxy);
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen if ((ssl_flags & PROXY_SSL_FLAG_STARTTLS) != 0) {
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen !str_array_icase_find(capabilities, "STARTTLS")) {
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen "proxy: Remote doesn't support STARTTLS");
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen (void)o_stream_send(output, str_data(str), str_len(str));
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainenclient_send_login_reply(struct imap_client *client, string_t *str,
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen capability = client->proxy_backend_capability;
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen tagged_capability = strncasecmp(line, "[CAPABILITY ", 12) == 0;
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen if (client->client_ignores_capability_resp_code && capability != NULL) {
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen /* client has used CAPABILITY command, so it didn't understand
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen the capabilities in the banner. send the backend's untagged
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen CAPABILITY reply and hope that the client understands it */
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen str_printfa(str, "* CAPABILITY %s\r\n", capability);
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen if (!client->client_ignores_capability_resp_code &&
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen str_printfa(str, "[CAPABILITY %s] ", capability);
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen /* we need to send the capability.
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen skip over this resp-code */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenint imap_proxy_parse_line(struct client *client, const char *line)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct imap_client *imap_client = (struct imap_client *)client;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen output = login_proxy_get_ostream(client->login_proxy);
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen /* this is a banner */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (proxy_input_banner(imap_client, output, line) < 0) {
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen /* AUTHENTICATE started. finish it. */
27d50b3aa143964143e4bef66c0bfe3c72aea233Timo Sirainen /* used literals with LOGIN command, just ignore. */
9c47edf0d1aa8afa6d05dde93e7aa5169059c94aTimo Sirainen imap_client->proxy_wait_auth_continue = FALSE;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen (void)o_stream_send(output, str_data(str), str_len(str));
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen /* STARTTLS failed */
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen "proxy: Remote STARTTLS failed: %s",
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen /* STARTTLS successful, begin TLS negotiation. */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (login_proxy_starttls(client->login_proxy) < 0) {
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen /* i/ostreams changed. */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen output = login_proxy_get_ostream(client->login_proxy);
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen (void)o_stream_send(output, str_data(str), str_len(str));
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen /* Login successful. Send this line to client. */
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen client_send_login_reply(imap_client, str, line + 5);
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen#define STR_NO_IMAP_RESP_CODE_AUTHFAILED "NO ["IMAP_RESP_CODE_AUTHFAILED"]"
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen if (strncmp(line, STR_NO_IMAP_RESP_CODE_AUTHFAILED,
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen strlen(STR_NO_IMAP_RESP_CODE_AUTHFAILED)) == 0) {
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen /* the remote sent a generic "authentication failed"
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen error. replace it with our one, so that in case
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen the remote is sending a different error message
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen an attacker can't find out what users exist in
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen the system. */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAILED,
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen /* remote sent some other resp-code. forward it. */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen imap_client->cmd_tag, " ", line, "\r\n", NULL));
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen /* there was no [resp-code], so remote isn't Dovecot
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen v1.2+. we could either forward the line as-is and
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen leak information about what users exist in this
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen system, or we could hide other errors than password
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen failures. since other errors are pretty rare,
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen it's safer to just hide them. they're still
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen available in logs though. */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAILED,
3cb26db7f4756b71ba06c6e4950fa4f8ce7fad66Timo Sirainen } else if (strncasecmp(line, "* CAPABILITY ", 13) == 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen i_free(imap_client->proxy_backend_capability);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen imap_client->proxy_backend_capability = i_strdup(line + 13);
31750e7fddc514c68c4eaf85b4f8c00000c281e0Timo Sirainen /* Reply to CAPABILITY command we sent, ignore it */
087eb3d719a5667631cc7ce9de6c372ddea19f4dTimo Sirainen /* Reply to ID command we sent, ignore it */
087eb3d719a5667631cc7ce9de6c372ddea19f4dTimo Sirainen /* untagged reply. just foward it. */
00fa8dcbc66f56daa737487c9dec7166c37de79eTimo Sirainen client_send_raw(client, t_strconcat(line, "\r\n", NULL));
087eb3d719a5667631cc7ce9de6c372ddea19f4dTimo Sirainen /* tagged reply, shouldn't happen. */
9c47edf0d1aa8afa6d05dde93e7aa5169059c94aTimo Sirainen "proxy: Unexpected input, ignoring: %s",
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct imap_client *imap_client = (struct imap_client *)client;