imap-proxy.c revision 9c47edf0d1aa8afa6d05dde93e7aa5169059c94a
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2004-2009 Dovecot authors, see the included COPYING file */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic void proxy_write_id(struct imap_client *client, string_t *str)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi "\"x-originating-ip\" \"%s\" "
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi "\"x-originating-port\" \"%u\" "
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi "\"x-connected-ip\" \"%s\" "
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi "\"x-connected-port\" \"%u\")\r\n",
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic void proxy_free_password(struct client *client)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi safe_memset(client->proxy_password, 0, strlen(client->proxy_password));
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic void get_plain_auth(struct client *client, string_t *dest)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomiclient_send_capability_if_needed(struct imap_client *client, string_t *str,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (!client->client_ignores_capability_resp_code || capability == NULL)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* reset this so that we don't re-send the CAPABILITY in case server
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi sends it multiple times */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi client->client_ignores_capability_resp_code = FALSE;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* client has used CAPABILITY command, so it didn't understand the
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi capabilities in the banner. send the backend's untagged CAPABILITY
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi reply and hope that the client understands it */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi str_printfa(str, "* CAPABILITY %s\r\n", capability);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic void proxy_write_login(struct imap_client *client, string_t *str)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* logging in normally - use LOGIN command */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi imap_quote_append_string(str, client->common.proxy_user, FALSE);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi imap_quote_append_string(str, client->common.proxy_password,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* master user login with SASL initial response support */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* master user login without SASL initial response */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic int proxy_input_banner(struct imap_client *client,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi "proxy: Remote returned invalid banner: %s",
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi capabilities = t_strsplit(t_strcut(line + 5 + 12, ']'), " ");
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (str_array_icase_find(capabilities, "SASL-IR"))
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi ssl_flags = login_proxy_get_ssl_flags(client->common.login_proxy);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi !str_array_icase_find(capabilities, "STARTTLS")) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi "proxy: Remote doesn't support STARTTLS");
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi (void)o_stream_send(output, str_data(str), str_len(str));
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomiint imap_proxy_parse_line(struct client *client, const char *line)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct imap_client *imap_client = (struct imap_client *)client;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi output = login_proxy_get_ostream(client->login_proxy);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* this is a banner */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (proxy_input_banner(imap_client, output, line) < 0) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* AUTHENTICATE started. finish it. */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi "proxy: Unexpected input: %s",
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi (void)o_stream_send(output, str_data(str), str_len(str));
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* STARTTLS failed */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi "proxy: Remote STARTTLS failed: %s",
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* STARTTLS successful, begin TLS negotiation. */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (login_proxy_starttls(client->login_proxy) < 0) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* i/ostreams changed. */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi output = login_proxy_get_ostream(client->login_proxy);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi (void)o_stream_send(output, str_data(str), str_len(str));
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* Login successful. Send this line to client. */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi capability = imap_client->proxy_backend_capability;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi client_send_capability_if_needed(imap_client, str, capability);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi#define STR_NO_IMAP_RESP_CODE_AUTHFAILED "NO ["IMAP_RESP_CODE_AUTHFAILED"]"
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (strncmp(line, STR_NO_IMAP_RESP_CODE_AUTHFAILED,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* the remote sent a generic "authentication failed"
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi error. replace it with our one, so that in case
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi the remote is sending a different error message
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi an attacker can't find out what users exist in
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi the system. */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAILED,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* remote sent some other resp-code. forward it. */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* there was no [resp-code], so remote isn't Dovecot
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi v1.2+. we could either forward the line as-is and
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi leak information about what users exist in this
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi system, or we could hide other errors than password
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi failures. since other errors are pretty rare,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi it's safer to just hide them. they're still
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi available in logs though. */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAILED,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi } else if (strncasecmp(line, "* CAPABILITY ", 13) == 0) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi imap_client->proxy_backend_capability = i_strdup(line + 13);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* Reply to ID command we sent, ignore it */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* untagged reply. just foward it. */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi client_send_raw(client, t_strconcat(line, "\r\n", NULL));
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* tagged reply, shouldn't happen. */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi "proxy: Unexpected input, ignoring: %s",
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct imap_client *imap_client = (struct imap_client *)client;