login-proxy.c revision 5f5870385cff47efd2f58e7892f251cf13761528
/* Copyright (c) 2004-2012 Dovecot authors, see the included COPYING file */
#include "login-common.h"
#include "ioloop.h"
#include "istream.h"
#include "ostream.h"
#include "llist.h"
#include "md5.h"
#include "str-sanitize.h"
#include "time-util.h"
#include "master-service.h"
#include "ipc-server.h"
#include "dns-lookup.h"
#include "client-common.h"
#include "ssl-proxy.h"
#include "login-proxy-state.h"
#include "login-proxy.h"
#define MAX_PROXY_INPUT_SIZE 4096
#define OUTBUF_THRESHOLD 1024
#define LOGIN_PROXY_DIE_IDLE_SECS 2
#define LOGIN_PROXY_DNS_WARN_MSECS 500
#define LOGIN_PROXY_IPC_PATH "ipc-proxy"
#define LOGIN_PROXY_IPC_NAME "proxy"
#define KILLED_BY_ADMIN_REASON "Killed by admin"
struct login_proxy {
struct istream *server_input;
struct ssl_proxy *ssl_server_proxy;
struct login_proxy_record *state_rec;
char *host;
unsigned int port;
unsigned int connect_timeout_msecs;
unsigned int notify_refresh_secs;
unsigned int destroying:1;
unsigned int disconnecting:1;
};
static struct login_proxy_state *proxy_state;
static struct ipc_server *login_proxy_ipc_server;
static void
{
const char *reason;
}
{
unsigned char buf[OUTBUF_THRESHOLD];
/* client's output buffer is already quite full.
don't send more until we're below threshold. */
return;
}
if (ret < 0)
"client");
}
}
{
unsigned char buf[OUTBUF_THRESHOLD];
/* proxy's output buffer is already quite full.
don't send more until we're below threshold. */
return;
}
if (ret < 0)
"server");
}
}
{
"server");
return 1;
}
/* there's again space in proxy's output buffer, so we can
read more from client. */
}
return 1;
}
{
"client");
return 1;
}
/* there's again space in client's output buffer, so we can
read more from proxy. */
}
return 1;
}
{
}
{
FALSE);
}
{
/* there was a successful connection done since we started
connecting. perhaps this is just a temporary one-off
failure. */
} else {
}
}
{
int err;
if (err != 0) {
i_error("proxy(%s): connect(%s, %u) failed: %s",
return;
}
if (login_proxy_starttls(proxy) < 0) {
return;
}
} else {
}
}
{
i_error("proxy(%s): connect(%s, %u) timed out",
}
{
struct login_proxy_record *rec;
rec->num_waiting_connections != 0) {
/* the server is down. fail immediately */
i_error("proxy(%s): Host %s:%u is down",
return -1;
}
i_error("proxy(%s): connect(%s, %u) failed: %m",
return -1;
}
if (proxy->connect_timeout_msecs != 0) {
}
return 0;
}
struct login_proxy *proxy)
{
i_error("proxy(%s): DNS lookup of %s failed: %s",
} else {
i_warning("proxy(%s): DNS lookup for %s took %u.%03u s",
}
(void)login_proxy_connect(proxy);
}
}
const struct login_proxy_settings *set,
{
struct login_proxy *proxy;
struct dns_lookup_settings dns_lookup_set;
return -1;
}
login_proxy_dns_done, proxy) < 0)
return -1;
} else {
if (login_proxy_connect(proxy) < 0)
return -1;
}
return 0;
}
static void
{
const char *ipstr;
if (proxy->destroying)
return;
/* detached proxy */
i_info("proxy(%s): disconnecting %s%s",
} else {
}
}
{
}
{
return FALSE;
return FALSE;
return FALSE;
}
{
}
{
return proxy->server_output;
}
{
}
{
}
{
}
{
}
{
const unsigned char *data;
/* send all pending client input to proxy and get rid of the stream */
if (size != 0)
/* from now on, just do dummy proxying */
if (proxy->notify_refresh_secs != 0) {
}
if (login_proxy_ipc_server == NULL) {
}
}
static int login_proxy_ssl_handshaked(void *context)
{
return 0;
"proxy: Received invalid SSL certificate from %s:%u",
"proxy: SSL certificate not received from %s:%u",
"proxy: hostname doesn't match SSL certificate at %s:%u",
} else {
return 0;
}
return -1;
}
{
int fd;
if (fd < 0) {
"proxy: SSL handshake failed to %s:%u",
return -1;
}
return 0;
}
{
}
void login_proxy_kill_idle(void)
{
unsigned int stop_msecs;
else {
}
}
}
static void
{
unsigned int count = 0;
return;
}
count++;
}
}
count++;
}
}
}
static unsigned int director_username_hash(const char *username)
{
/* NOTE: If you modify this, modify also
user_directory_get_username_hash() in director/user-director.c */
unsigned char md5[MD5_RESULTLEN];
unsigned int i, hash = 0;
for (i = 0; i < sizeof(hash); i++)
return hash;
}
static void
{
return;
}
count++;
}
}
count++;
}
}
}
static void
struct login_proxy *proxy)
{
T_BEGIN {
const char *reply;
} T_END;
}
static void
{
struct login_proxy *proxy;
}
{
args++;
else
}
void login_proxy_init(const char *proxy_notify_pipe_path)
{
}
void login_proxy_deinit(void)
{
struct login_proxy *proxy;
while (login_proxies != NULL) {
}
if (login_proxy_ipc_server != NULL)
}