]> jfr.im git - solanum.git/commitdiff
ssld: add a callback when the connection is opened
authorSimon Arlott <sa.me.uk>
Sun, 24 Apr 2016 10:48:35 +0000 (11:48 +0100)
committerSimon Arlott <sa.me.uk>
Sun, 24 Apr 2016 10:48:35 +0000 (11:48 +0100)
This allows us to wait until we have the fingerprint information before
continuing with a server connect process.

include/client.h
ircd/s_serv.c
ircd/sslproc.c
modules/m_starttls.c
ssld/ssld.c

index cfc55ceeee97ee5b3f14cfafc59988254a344f3d..a23f444bfff1cb5ec1f4590d416997c26a8229b6 100644 (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 */
index 6335c5767a66249c34c39e4d142741c435102bce..ac1737dd16276162b339a5353e441e9980053333 100644 (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",
index 5472fbb0aa714f59374b7e21d2a6e28473218708..5abd92b1729c36e4b8238d2b3effd59918ccfef2 100644 (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;
index 62b7feb60e145f1642d34b9173e84b68fefb68b1..b70d03bd30b2e9df00584e9437996e6f56b1d4b7 100644 (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)
        {
index cb74d2de82ab1195a714c9ba76b74b439c4269cc..a8243a2dd7643484b3053a97ea576566f30c679f 100644 (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);
        }