X-Git-Url: https://jfr.im/git/irc/rqf/shadowircd.git/blobdiff_plain/9bf8f69cc6440d53f4a980b782b4d0229d1de020..d4eab91a9941a9c9eb20f5253115686de8e26af4:/ssld/ssld.c diff --git a/ssld/ssld.c b/ssld/ssld.c index ed44e99..a6c6b5f 100644 --- a/ssld/ssld.c +++ b/ssld/ssld.c @@ -171,6 +171,7 @@ static void conn_mod_write_sendq(rb_fde_t *, void *data); static void conn_plain_write_sendq(rb_fde_t *, void *data); static void mod_write_ctl(rb_fde_t *, void *data); static void conn_plain_read_cb(rb_fde_t *fd, void *data); +static void conn_plain_read_shutdown_cb(rb_fde_t *fd, void *data); static void mod_cmd_write_queue(mod_ctl_t * ctl, const void *data, size_t len); static const char *remote_closed = "Remote host closed the connection"; static int ssl_ok; @@ -262,16 +263,17 @@ close_conn(conn_t * conn, int wait_plain, const char *fmt, ...) rb_close(conn->mod_fd); SetDead(conn); + if(conn->id >= 0 && !IsZipSSL(conn)) + rb_dlinkDelete(&conn->node, connid_hash(conn->id)); + if(!wait_plain || fmt == NULL) { rb_close(conn->plain_fd); - - if(conn->id >= 0 && !IsZipSSL(conn)) - rb_dlinkDelete(&conn->node, connid_hash(conn->id)); rb_dlinkAdd(conn, &conn->node, &dead_list); return; } - rb_setselect(conn->plain_fd, RB_SELECT_WRITE | RB_SELECT_READ, NULL, NULL); + rb_setselect(conn->plain_fd, RB_SELECT_READ, conn_plain_read_shutdown_cb, conn); + rb_setselect(conn->plain_fd, RB_SELECT_WRITE, NULL, NULL); va_start(ap, fmt); rb_vsnprintf(reason, sizeof(reason), fmt, ap); va_end(ap); @@ -541,6 +543,34 @@ conn_plain_read_cb(rb_fde_t *fd, void *data) } } +static void +conn_plain_read_shutdown_cb(rb_fde_t *fd, void *data) +{ + conn_t *conn = data; + int length = 0; + + if(conn == NULL) + return; + + while(1) + { + length = rb_read(conn->plain_fd, inbuf, sizeof(inbuf)); + + if(length == 0 || (length < 0 && !rb_ignore_errno(errno))) + { + rb_close(conn->plain_fd); + rb_dlinkAdd(conn, &conn->node, &dead_list); + return; + } + + if(length < 0) + { + rb_setselect(conn->plain_fd, RB_SELECT_READ, conn_plain_read_shutdown_cb, conn); + return; + } + } +} + static void conn_mod_read_cb(rb_fde_t *fd, void *data) { @@ -649,8 +679,16 @@ static void ssl_process_accept_cb(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t len, void *data) { conn_t *conn = data; + char buf[5 + RB_SSL_CERTFP_LEN]; + if(status == RB_OK) { + if(rb_get_ssl_certfp(F, &buf[5])) + { + buf[0] = 'F'; + int32_to_buf(&buf[1], conn->id); + mod_cmd_write_queue(conn->ctl, buf, sizeof buf); + } conn_mod_read_cb(conn->mod_fd, conn); conn_plain_read_cb(conn->plain_fd, conn); return; @@ -678,6 +716,16 @@ ssl_process_connect_cb(rb_fde_t *F, int status, void *data) } +static void +cleanup_bad_message(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb) +{ + int i; + + /* XXX should log this somehow */ + for (i = 0; i < ctlb->nfds; i++) + rb_close(ctlb->F[i]); +} + static void ssl_process_accept(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb) { @@ -918,6 +966,12 @@ mod_process_cmd_recv(mod_ctl_t * ctl) { case 'A': { + if (ctl_buf->nfds != 2 || ctl_buf->buflen != 5) + { + cleanup_bad_message(ctl, ctl_buf); + break; + } + if(!ssl_ok) { send_nossl_support(ctl, ctl_buf); @@ -928,6 +982,12 @@ mod_process_cmd_recv(mod_ctl_t * ctl) } case 'C': { + if (ctl_buf->nfds != 2 || ctl_buf->buflen != 5) + { + cleanup_bad_message(ctl, ctl_buf); + break; + } + if(!ssl_ok) { send_nossl_support(ctl, ctl_buf); @@ -964,6 +1024,12 @@ mod_process_cmd_recv(mod_ctl_t * ctl) #ifdef HAVE_LIBZ case 'Z': { + if (ctl_buf->nfds != 2 || ctl_buf->buflen < 6) + { + cleanup_bad_message(ctl, ctl_buf); + break; + } + /* just zlib only */ zlib_process(ctl, ctl_buf); break; @@ -994,6 +1060,7 @@ mod_read_ctl(rb_fde_t *F, void *data) mod_ctl_buf_t *ctl_buf; mod_ctl_t *ctl = data; int retlen; + int i; do { @@ -1011,6 +1078,9 @@ mod_read_ctl(rb_fde_t *F, void *data) { ctl_buf->buflen = retlen; rb_dlinkAddTail(ctl_buf, &ctl_buf->node, &ctl->readq); + for (i = 0; i < MAXPASSFD && ctl_buf->F[i] != NULL; i++) + ; + ctl_buf->nfds = i; } } while(retlen > 0);