From 50b1e5987c6e2a8e0623b84995328c67bfdeff57 Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Sun, 20 Nov 2016 20:43:53 +0000 Subject: [PATCH] listener: use exit_client instead of free_client As well as leaking a connid and leaving the connection open, these calls to free_client() leave the client in the unknown_list causing check_unknowns_list() to crash when either ptr->data (ptr being the freed client_p->localClient->tnode) is NULL or when client_p->localClient is NULL. Flag the client as an IO error so that we don't try to send it any data (as this is not a normal plaintext connection). --- include/client.h | 1 - ircd/client.c | 2 +- ircd/listener.c | 83 +++++++++++++++++++++++++----------------------- 3 files changed, 45 insertions(+), 41 deletions(-) diff --git a/include/client.h b/include/client.h index 708bf69d..39f31e77 100644 --- a/include/client.h +++ b/include/client.h @@ -585,7 +585,6 @@ extern int is_remote_connect(struct Client *); extern void init_client(void); extern struct Client *make_client(struct Client *from); extern void free_pre_client(struct Client *client); -extern void free_client(struct Client *client); extern int exit_client(struct Client *, struct Client *, struct Client *, const char *); diff --git a/ircd/client.c b/ircd/client.c index 87f0b3b8..56872517 100644 --- a/ircd/client.c +++ b/ircd/client.c @@ -328,7 +328,7 @@ free_local_client(struct Client *client_p) client_p->localClient = NULL; } -void +static void free_client(struct Client *client_p) { s_assert(NULL != client_p); diff --git a/ircd/listener.c b/ircd/listener.c index ba4a1150..2e76c133 100644 --- a/ircd/listener.c +++ b/ircd/listener.c @@ -457,43 +457,7 @@ add_connection(struct Listener *listener, rb_fde_t *F, struct sockaddr *sai, str * the client has already been checked out in accept_connection */ new_client = make_client(NULL); - - if (listener->ssl) - { - rb_fde_t *xF[2]; - if(rb_socketpair(AF_UNIX, SOCK_STREAM, 0, &xF[0], &xF[1], "Incoming ssld Connection") == -1) - { - free_client(new_client); - return; - } - new_client->localClient->ssl_callback = accept_sslcallback; - defer = true; - new_client->localClient->ssl_ctl = start_ssld_accept(F, xF[1], connid_get(new_client)); /* this will close F for us */ - if(new_client->localClient->ssl_ctl == NULL) - { - free_client(new_client); - return; - } - F = xF[0]; - SetSSL(new_client); - } - - if (listener->wsock) - { - rb_fde_t *xF[2]; - if(rb_socketpair(AF_UNIX, SOCK_STREAM, 0, &xF[0], &xF[1], "Incoming wsockd Connection") == -1) - { - free_client(new_client); - return; - } - new_client->localClient->ws_ctl = start_wsockd_accept(F, xF[1], connid_get(new_client)); /* this will close F for us */ - if(new_client->localClient->ws_ctl == NULL) - { - free_client(new_client); - return; - } - F = xF[0]; - } + new_client->localClient->F = F; memcpy(&new_client->localClient->ip, sai, sizeof(struct rb_sockaddr_storage)); memcpy(&new_client->preClient->lip, lai, sizeof(struct rb_sockaddr_storage)); @@ -505,10 +469,51 @@ add_connection(struct Listener *listener, rb_fde_t *F, struct sockaddr *sai, str rb_inet_ntop_sock((struct sockaddr *)&new_client->localClient->ip, new_client->sockhost, sizeof(new_client->sockhost)); - rb_strlcpy(new_client->host, new_client->sockhost, sizeof(new_client->host)); - new_client->localClient->F = F; + if (listener->ssl) + { + rb_fde_t *xF[2]; + if(rb_socketpair(AF_UNIX, SOCK_STREAM, 0, &xF[0], &xF[1], "Incoming ssld Connection") == -1) + { + SetIOError(new_client); + exit_client(new_client, new_client, new_client, "Fatal Error"); + return; + } + new_client->localClient->ssl_callback = accept_sslcallback; + defer = true; + new_client->localClient->ssl_ctl = start_ssld_accept(F, xF[1], connid_get(new_client)); /* this will close F for us */ + if(new_client->localClient->ssl_ctl == NULL) + { + SetIOError(new_client); + exit_client(new_client, new_client, new_client, "Service Unavailable"); + return; + } + F = xF[0]; + new_client->localClient->F = F; + SetSSL(new_client); + } + + if (listener->wsock) + { + rb_fde_t *xF[2]; + if(rb_socketpair(AF_UNIX, SOCK_STREAM, 0, &xF[0], &xF[1], "Incoming wsockd Connection") == -1) + { + SetIOError(new_client); + exit_client(new_client, new_client, new_client, "Fatal Error"); + return; + } + new_client->localClient->ws_ctl = start_wsockd_accept(F, xF[1], connid_get(new_client)); /* this will close F for us */ + if(new_client->localClient->ws_ctl == NULL) + { + SetIOError(new_client); + exit_client(new_client, new_client, new_client, "Service Unavailable"); + return; + } + F = xF[0]; + new_client->localClient->F = F; + } + new_client->localClient->listener = listener; ++listener->ref_count;