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).
This commit is contained in:
Simon Arlott 2016-11-20 20:43:53 +00:00
parent 4381284e72
commit 50b1e5987c
No known key found for this signature in database
GPG key ID: C8975F2043CA5D24
3 changed files with 45 additions and 41 deletions

View file

@ -585,7 +585,6 @@ extern int is_remote_connect(struct Client *);
extern void init_client(void); extern void init_client(void);
extern struct Client *make_client(struct Client *from); extern struct Client *make_client(struct Client *from);
extern void free_pre_client(struct Client *client); 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 *); extern int exit_client(struct Client *, struct Client *, struct Client *, const char *);

View file

@ -328,7 +328,7 @@ free_local_client(struct Client *client_p)
client_p->localClient = NULL; client_p->localClient = NULL;
} }
void static void
free_client(struct Client *client_p) free_client(struct Client *client_p)
{ {
s_assert(NULL != client_p); s_assert(NULL != client_p);

View file

@ -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 * the client has already been checked out in accept_connection
*/ */
new_client = make_client(NULL); new_client = make_client(NULL);
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)
{
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];
}
memcpy(&new_client->localClient->ip, sai, sizeof(struct rb_sockaddr_storage)); memcpy(&new_client->localClient->ip, sai, sizeof(struct rb_sockaddr_storage));
memcpy(&new_client->preClient->lip, lai, 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, rb_inet_ntop_sock((struct sockaddr *)&new_client->localClient->ip, new_client->sockhost,
sizeof(new_client->sockhost)); sizeof(new_client->sockhost));
rb_strlcpy(new_client->host, new_client->sockhost, sizeof(new_client->host)); rb_strlcpy(new_client->host, new_client->sockhost, sizeof(new_client->host));
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; 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; new_client->localClient->listener = listener;
++listener->ref_count; ++listener->ref_count;