imap-proxy.c revision e95dba8921087afebb8a92c592af3b8ca22ae796
/* Copyright (c) 2004-2009 Dovecot authors, see the included COPYING file */
#include "common.h"
#include "array.h"
#include "ioloop.h"
#include "istream.h"
#include "ostream.h"
#include "base64.h"
#include "str.h"
#include "str-sanitize.h"
#include "safe-memset.h"
#include "client.h"
#include "client-authenticate.h"
#include "imap-resp-code.h"
#include "imap-quote.h"
#include "imap-proxy.h"
#include <stdlib.h>
#define PROXY_FAILURE_MSG \
static const char *const *
capabilities_strip_prelogin(const char *const *capabilities)
{
unsigned int count;
continue;
str = *capabilities;
}
(void)array_append_space(&new_caps_arr);
return array_idx(&new_caps_arr, 0);
}
{
"\"x-originating-ip\" \"%s\" "
"\"x-originating-port\" \"%u\" "
"\"x-connected-ip\" \"%s\" "
"\"x-connected-port\" \"%u\")\r\n",
}
{
return;
}
{
if (send_tagline)
/* call this last - it may destroy the client */
}
{
}
{
unsigned int i;
return FALSE;
}
return TRUE;
}
static void
const char *capability)
{
const char *const *backend_capabilities;
const char *const *proxy_capabilities;
return;
/* reset this so that we don't re-send the CAPABILITY in case server
sends it multiple times */
/* client has used CAPABILITY command, so it didn't understand the
capabilities in the banner. if backend server has different
capabilities than we advertised already, there's a problem.
to solve that we'll send the backend's untagged CAPABILITY reply
and hope that the client understands it */
return;
}
{
/* logging in normally - use LOGIN command */
} else if (client->proxy_sasl_ir) {
/* master user login with SASL initial response support */
} else {
/* master user login without SASL initial response */
}
}
{
const char *const *capabilities = NULL;
"proxy: Remote returned invalid banner: %s",
return -1;
}
}
if ((ssl_flags & PROXY_SSL_FLAG_STARTTLS) != 0) {
if (capabilities != NULL &&
"proxy: Remote doesn't support STARTTLS");
return -1;
}
} else {
}
return 0;
}
{
const char *capability;
if (!client->proxy_seen_banner) {
/* this is a banner */
return -1;
}
return 0;
} else if (*line == '+') {
/* AUTHENTICATE started. finish it. */
return 0;
/* STARTTLS failed */
"proxy: Remote STARTTLS failed: %s",
return -1;
}
/* STARTTLS successful, begin TLS negotiation. */
return -1;
}
return 1;
/* Login successful. Send this line to client. */
str_truncate(str, 0);
client->proxy_user) != 0) {
/* remote username is different, log it */
}
}
(void)client_skip_line(client);
return 1;
line += 2;
if (login_settings->verbose_auth) {
client->proxy_user) != 0) {
/* remote username is different, log it */
}
}
else
}
strlen(STR_NO_IMAP_RESP_CODE_AUTHFAILED)) == 0) {
/* the remote sent a generic "authentication failed"
error. replace it with our one, so that in case
the remote is sending a different error message
an attacker can't find out what users exist in
the system. */
/* remote sent some other resp-code. forward it. */
} else {
/* there was no [resp-code], so remote isn't Dovecot
v1.2+. we could either forward the line as-is and
leak information about what users exist in this
system, or we could hide other errors than password
failures. since other errors are pretty rare,
it's safer to just hide them. they're still
available in logs though. */
}
return -1;
return 0;
} else {
/* probably some untagged reply */
return 0;
}
}
{
const char *line;
/* we're just freeing the proxy */
return;
}
/* we came here from client_destroy() */
return;
}
/* failed for some reason, probably server disconnected */
return;
}
switch (i_stream_read(input)) {
case -2:
"proxy: Remote input buffer full");
return;
case -1:
"proxy: Remote disconnected");
return;
}
break;
}
}
{
return -1;
}
/* connection_queue_add() decided that we were the oldest
connection and killed us. */
return -1;
}
return -1;
}
return -1;
}
/* disable input until authentication is finished */
return 0;
}