if (client->ssl_proxy != NULL)
ssl_proxy_free(&client->ssl_proxy);
client->v.destroy(client);
- client_unref(client);
+ client_unref(&client);
}
void client_destroy_success(struct client *client, const char *reason)
client->refcount++;
}
-bool client_unref(struct client *client)
+bool client_unref(struct client **_client)
{
+ struct client *client = *_client;
+
i_assert(client->refcount > 0);
if (--client->refcount > 0)
return TRUE;
+ *_client = NULL;
+
i_assert(client->destroyed);
+ i_assert(client->ssl_proxy == NULL);
+ i_assert(client->login_proxy == NULL);
if (client->input != NULL)
i_stream_unref(&client->input);
if (client->output != NULL)
o_stream_unref(&client->output);
- if (!client->proxying) {
- i_assert(client->ssl_proxy == NULL);
- master_service_client_connection_destroyed(master_service);
- }
-
i_free(client->virtual_user);
i_free(client->auth_mech_name);
pool_unref(&client->pool);
+
+ master_service_client_connection_destroyed(master_service);
return FALSE;
}
int fd_ssl;
client_ref(client);
- if (!client_unref(client) || client->destroyed)
+ if (!client_unref(&client) || client->destroyed)
return;
fd_ssl = ssl_proxy_new(client->fd, &client->ip,
"Disconnected: TLS initialization failed.");
return;
}
+ ssl_proxy_set_client(client->ssl_proxy, client);
client->starttls = TRUE;
- client->proxying = TRUE;
client->tls = TRUE;
client->secured = TRUE;
client_set_title(client);
struct login_proxy {
struct login_proxy *prev, *next;
- struct client *prelogin_client;
+ struct client *client;
int client_fd, server_fd;
struct io *client_io, *server_io;
struct istream *server_input;
struct ostream *client_output, *server_output;
- struct ip_addr ip;
- struct ssl_proxy *ssl_proxy;
+ struct ssl_proxy *ssl_server_proxy;
struct timeval created;
struct timeout *to;
proxy->user = i_strdup(client->virtual_user);
proxy->port = set->port;
proxy->ssl_flags = set->ssl_flags;
- proxy->prelogin_client = client;
+ proxy->client = client;
+ client_ref(client);
proxy->server_fd = fd;
proxy->server_io = io_add(fd, IO_WRITE, proxy_wait_connect, proxy);
proxy->callback = callback;
proxy->context = context;
- proxy->ip = client->ip;
proxy->client_fd = -1;
proxy->state_rec = rec;
void login_proxy_free(struct login_proxy **_proxy)
{
struct login_proxy *proxy = *_proxy;
+ struct client *client = proxy->client;
const char *ipstr;
*_proxy = NULL;
/* detached proxy */
DLLIST_REMOVE(&login_proxies, proxy);
- ipstr = net_ip2addr(&proxy->ip);
+ ipstr = net_ip2addr(&proxy->client->ip);
i_info("proxy(%s): disconnecting %s",
str_sanitize(proxy->user, 80),
ipstr != NULL ? ipstr : "");
proxy->callback(proxy->context);
}
- if (proxy->ssl_proxy != NULL)
- ssl_proxy_free(&proxy->ssl_proxy);
net_disconnect(proxy->server_fd);
+ if (proxy->ssl_server_proxy != NULL)
+ ssl_proxy_free(&proxy->ssl_server_proxy);
i_free(proxy->host);
i_free(proxy->user);
i_free(proxy);
- master_service_client_connection_destroyed(master_service);
+ client->login_proxy = NULL;
+ client_unref(&client);
}
bool login_proxy_is_ourself(const struct client *client, const char *host,
return proxy->ssl_flags;
}
-void login_proxy_detach(struct login_proxy *proxy, struct istream *client_input,
- struct ostream *client_output)
+void login_proxy_detach(struct login_proxy *proxy)
{
+ struct client *client = proxy->client;
const unsigned char *data;
size_t size;
i_assert(proxy->client_fd == -1);
i_assert(proxy->server_output != NULL);
- proxy->prelogin_client = NULL;
- proxy->client_fd = i_stream_get_fd(client_input);
- proxy->client_output = client_output;
+ proxy->client_fd = i_stream_get_fd(client->input);
+ proxy->client_output = client->output;
- o_stream_set_max_buffer_size(client_output, (size_t)-1);
- o_stream_set_flush_callback(client_output, proxy_client_output, proxy);
+ o_stream_set_max_buffer_size(client->output, (size_t)-1);
+ o_stream_set_flush_callback(client->output, proxy_client_output, proxy);
+ client->output = NULL;
/* send all pending client input to proxy and get rid of the stream */
- data = i_stream_get_data(client_input, &size);
+ data = i_stream_get_data(client->input, &size);
if (size != 0)
(void)o_stream_send(proxy->server_output, data, size);
- i_stream_unref(&client_input);
/* from now on, just do dummy proxying */
io_remove(&proxy->server_io);
proxy->context = NULL;
DLLIST_PREPEND(&login_proxies, proxy);
+
+ client->fd = -1;
+ client->login_proxy = NULL;
}
static int login_proxy_ssl_handshaked(void *context)
struct login_proxy *proxy = context;
if ((proxy->ssl_flags & PROXY_SSL_FLAG_ANY_CERT) != 0 ||
- ssl_proxy_has_valid_client_cert(proxy->ssl_proxy))
+ ssl_proxy_has_valid_client_cert(proxy->ssl_server_proxy))
return 0;
- if (!ssl_proxy_has_broken_client_cert(proxy->ssl_proxy)) {
- client_log_err(proxy->prelogin_client, t_strdup_printf(
+ if (!ssl_proxy_has_broken_client_cert(proxy->ssl_server_proxy)) {
+ client_log_err(proxy->client, t_strdup_printf(
"proxy: SSL certificate not received from %s:%u",
proxy->host, proxy->port));
} else {
- client_log_err(proxy->prelogin_client, t_strdup_printf(
+ client_log_err(proxy->client, t_strdup_printf(
"proxy: Received invalid SSL certificate from %s:%u",
proxy->host, proxy->port));
}
o_stream_destroy(&proxy->server_output);
io_remove(&proxy->server_io);
- fd = ssl_proxy_client_new(proxy->server_fd, &proxy->ip,
- proxy->prelogin_client->set,
+ fd = ssl_proxy_client_new(proxy->server_fd, &proxy->client->ip,
+ proxy->client->set,
login_proxy_ssl_handshaked, proxy,
- &proxy->ssl_proxy);
+ &proxy->ssl_server_proxy);
if (fd < 0) {
- client_log_err(proxy->prelogin_client, t_strdup_printf(
+ client_log_err(proxy->client, t_strdup_printf(
"proxy: SSL handshake failed to %s:%u",
proxy->host, proxy->port));
return -1;
}
+ ssl_proxy_set_client(proxy->ssl_server_proxy, proxy->client);
proxy->server_fd = fd;
proxy_plain_connected(proxy);
#include "llist.h"
#include "master-service.h"
#include "master-interface.h"
+#include "client-common.h"
#include "ssl-proxy.h"
#include <fcntl.h>
struct ssl_proxy *prev, *next;
SSL *ssl;
+ struct client *client;
struct ip_addr ip;
const struct login_settings *set;
unsigned int destroyed:1;
unsigned int cert_received:1;
unsigned int cert_broken:1;
- unsigned int client:1;
+ unsigned int client_proxy:1;
};
struct ssl_parameters {
{
int ret;
- if (proxy->client) {
+ if (proxy->client_proxy) {
ret = SSL_connect(proxy->ssl);
if (ret != 1) {
ssl_handle_error(proxy, ret, "SSL_connect()");
(*proxy_r)->handshake_callback = callback;
(*proxy_r)->handshake_context = context;
- (*proxy_r)->client = TRUE;
+ (*proxy_r)->client_proxy = TRUE;
ssl_step(*proxy_r);
return ret;
}
+void ssl_proxy_set_client(struct ssl_proxy *proxy, struct client *client)
+{
+ i_assert(proxy->client == NULL);
+
+ client_ref(client);
+ proxy->client = client;
+}
+
bool ssl_proxy_has_valid_client_cert(const struct ssl_proxy *proxy)
{
return proxy->cert_received && !proxy->cert_broken;
i_assert(proxy->refcount == 0);
SSL_free(proxy->ssl);
+
+ if (proxy->client != NULL)
+ client_unref(&proxy->client);
i_free(proxy);
}
(void)net_disconnect(proxy->fd_plain);
ssl_proxy_unref(proxy);
-
- master_service_client_connection_destroyed(master_service);
}
static RSA *ssl_gen_rsa_key(SSL *ssl ATTR_UNUSED,