ssld: add a callback when the connection is opened

This allows us to wait until we have the fingerprint information before
continuing with a server connect process.
This commit is contained in:
Simon Arlott 2016-04-24 11:48:35 +01:00
parent fbbc6aeb00
commit 4fbb736202
No known key found for this signature in database
GPG key ID: C8975F2043CA5D24
5 changed files with 71 additions and 8 deletions

View file

@ -275,6 +275,8 @@ struct LocalUser
struct _ssl_ctl *ssl_ctl; /* which ssl daemon we're associate with */
struct _ssl_ctl *z_ctl; /* second ctl for ssl+zlib */
struct ws_ctl *ws_ctl; /* ctl for wsockd */
CNCB *ssl_callback; /* ssl connection is now open */
void *ssl_data; /* data for callback */
uint32_t localflags;
struct ZipStats *zipstats; /* zipstats */
uint16_t cork_count; /* used for corking/uncorking connections */

View file

@ -1166,6 +1166,8 @@ serv_connect_ssl_callback(rb_fde_t *F, int status, void *data)
}
client_p->localClient->F = xF[0];
client_p->localClient->ssl_callback = serv_connect_callback;
client_p->localClient->ssl_data = data;
client_p->localClient->ssl_ctl = start_ssld_connect(F, xF[1], connid_get(client_p));
if(!client_p->localClient->ssl_ctl)
@ -1174,7 +1176,6 @@ serv_connect_ssl_callback(rb_fde_t *F, int status, void *data)
return;
}
SetSSL(client_p);
serv_connect_callback(client_p->localClient->F, RB_OK, client_p);
}
/*
@ -1218,7 +1219,7 @@ serv_connect_callback(rb_fde_t *F, int status, void *data)
/* COMM_ERR_TIMEOUT wont have an errno associated with it,
* the others will.. --fl
*/
if(status == RB_ERR_TIMEOUT)
if(status == RB_ERR_TIMEOUT || status == RB_ERROR_SSL)
{
sendto_realops_snomask(SNO_GENERAL, is_remote_connect(client_p) ? L_NETWIDE : L_ALL,
"Error connecting to %s[%s]: %s",

View file

@ -387,6 +387,32 @@ ssl_process_zipstats(ssl_ctl_t * ctl, ssl_ctl_buf_t * ctl_buf)
zips->out_ratio = 0;
}
static void
ssl_process_open_fd(ssl_ctl_t * ctl, ssl_ctl_buf_t * ctl_buf)
{
struct Client *client_p;
uint32_t fd;
if(ctl_buf->buflen < 5)
return; /* bogus message..drop it.. XXX should warn here */
fd = buf_to_uint32(&ctl_buf->buf[1]);
client_p = find_cli_connid_hash(fd);
if(client_p == NULL || client_p->localClient == NULL)
return;
if(client_p->localClient->ssl_callback)
{
CNCB *hdl = client_p->localClient->ssl_callback;
void *data = client_p->localClient->ssl_data;
client_p->localClient->ssl_callback = NULL;
client_p->localClient->ssl_data = NULL;
hdl(client_p->localClient->F, RB_OK, data);
}
}
static void
ssl_process_dead_fd(ssl_ctl_t * ctl, ssl_ctl_buf_t * ctl_buf)
{
@ -400,8 +426,30 @@ ssl_process_dead_fd(ssl_ctl_t * ctl, ssl_ctl_buf_t * ctl_buf)
fd = buf_to_uint32(&ctl_buf->buf[1]);
rb_strlcpy(reason, &ctl_buf->buf[5], sizeof(reason));
client_p = find_cli_connid_hash(fd);
if(client_p == NULL)
if(client_p == NULL || client_p->localClient == NULL)
return;
if(IsAnyServer(client_p))
{
sendto_realops_snomask(SNO_GENERAL, is_remote_connect(client_p) && !IsServer(client_p) ? L_NETWIDE : L_ALL, "ssld error for %s: %s", client_p->name, reason);
ilog(L_SERVER, "ssld error for %s: %s", log_client_name(client_p, SHOW_IP), reason);
}
/* if there is still a pending callback, call it now */
if(client_p->localClient->ssl_callback)
{
CNCB *hdl = client_p->localClient->ssl_callback;
void *data = client_p->localClient->ssl_data;
client_p->localClient->ssl_callback = NULL;
client_p->localClient->ssl_data = NULL;
hdl(client_p->localClient->F, RB_ERROR_SSL, data);
/* the callback should have exited the client */
return;
}
if(IsAnyServer(client_p) || IsRegistered(client_p))
{
/* read any last moment ERROR, QUIT or the like -- jilles */
@ -410,11 +458,6 @@ ssl_process_dead_fd(ssl_ctl_t * ctl, ssl_ctl_buf_t * ctl_buf)
if (IsAnyDead(client_p))
return;
}
if(IsAnyServer(client_p))
{
sendto_realops_snomask(SNO_GENERAL, is_remote_connect(client_p) && !IsServer(client_p) ? L_NETWIDE : L_ALL, "ssld error for %s: %s", client_p->name, reason);
ilog(L_SERVER, "ssld error for %s: %s", log_client_name(client_p, SHOW_IP), reason);
}
exit_client(client_p, client_p, &me, reason);
}
@ -490,6 +533,9 @@ ssl_process_cmd_recv(ssl_ctl_t * ctl)
case 'N':
ircd_ssl_ok = false; /* ssld says it can't do ssl/tls */
break;
case 'O':
ssl_process_open_fd(ctl, ctl_buf);
break;
case 'D':
ssl_process_dead_fd(ctl, ctl_buf);
break;

View file

@ -95,6 +95,8 @@ mr_starttls(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sou
sendto_one_numeric(client_p, RPL_STARTTLS, form_str(RPL_STARTTLS));
send_queued(client_p);
/* TODO: set localClient->ssl_callback and handle success/failure */
ctl = start_ssld_accept(client_p->localClient->F, F[1], connid_get(client_p));
if (ctl != NULL)
{

View file

@ -699,6 +699,16 @@ ssl_send_certfp(conn_t *conn)
mod_cmd_write_queue(conn->ctl, buf, 9 + len);
}
static void
ssl_send_open(conn_t *conn)
{
uint8_t buf[5];
buf[0] = 'O';
uint32_to_buf(&buf[1], conn->id);
mod_cmd_write_queue(conn->ctl, buf, 5);
}
static void
ssl_process_accept_cb(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t len, void *data)
{
@ -708,6 +718,7 @@ ssl_process_accept_cb(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen
{
ssl_send_cipher(conn);
ssl_send_certfp(conn);
ssl_send_open(conn);
conn_mod_read_cb(conn->mod_fd, conn);
conn_plain_read_cb(conn->plain_fd, conn);
return;
@ -726,6 +737,7 @@ ssl_process_connect_cb(rb_fde_t *F, int status, void *data)
{
ssl_send_cipher(conn);
ssl_send_certfp(conn);
ssl_send_open(conn);
conn_mod_read_cb(conn->mod_fd, conn);
conn_plain_read_cb(conn->plain_fd, conn);
}