X-Git-Url: https://jfr.im/git/solanum.git/blobdiff_plain/74ff144d33ab1d6728b4bd3c2a58062db6b7086e..4d12e65469c877f8028d5ac40a39457ec96b2f40:/ssld/ssld.c diff --git a/ssld/ssld.c b/ssld/ssld.c index 5acb930c..a4bb8a02 100644 --- a/ssld/ssld.c +++ b/ssld/ssld.c @@ -17,17 +17,11 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA - * - * $Id$ */ #include "stdinc.h" -#ifdef HAVE_LIBZ -#include -#endif - #define MAXPASSFD 4 #ifndef READBUF_SIZE #define READBUF_SIZE 16384 @@ -72,15 +66,6 @@ typedef struct _mod_ctl static mod_ctl_t *mod_ctl; - -#ifdef HAVE_LIBZ -typedef struct _zlib_stream -{ - z_stream instream; - z_stream outstream; -} zlib_stream_t; -#endif - typedef struct _conn { rb_dlink_node node; @@ -92,10 +77,10 @@ typedef struct _conn rb_fde_t *mod_fd; rb_fde_t *plain_fd; - unsigned long long mod_out; - unsigned long long mod_in; - unsigned long long plain_in; - unsigned long long plain_out; + uint64_t mod_out; + uint64_t mod_in; + uint64_t plain_in; + uint64_t plain_out; uint8_t flags; void *stream; } conn_t; @@ -122,15 +107,10 @@ typedef struct _conn #define SetDead(x) ((x)->flags |= FLAG_DEAD) #define SetSSLWWantsR(x) ((x)->flags |= FLAG_SSL_W_WANTS_R) #define SetSSLRWantsW(x) ((x)->flags |= FLAG_SSL_R_WANTS_W) -#define SetZipSSL(x) ((x)->flags |= FLAG_ZIPSSL) -#define ClearSSL(x) ((x)->flags &= ~FLAG_SSL) -#define ClearZip(x) ((x)->flags &= ~FLAG_ZIP) #define ClearCork(x) ((x)->flags &= ~FLAG_CORK) -#define ClearDead(x) ((x)->flags &= ~FLAG_DEAD) #define ClearSSLWWantsR(x) ((x)->flags &= ~FLAG_SSL_W_WANTS_R) #define ClearSSLRWantsW(x) ((x)->flags &= ~FLAG_SSL_R_WANTS_W) -#define ClearZipSSL(x) ((x)->flags &= ~FLAG_ZIPSSL) #define NO_WAIT 0x0 #define WAIT_PLAIN 0x1 @@ -153,28 +133,9 @@ 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; -static int certfp_method = RB_SSL_CERTFP_METH_SHA1; -#ifdef HAVE_LIBZ -static int zlib_ok = 1; -#else -static int zlib_ok = 0; -#endif - +static bool ssld_ssl_ok; +static int certfp_method = RB_SSL_CERTFP_METH_CERT_SHA1; -#ifdef HAVE_LIBZ -static void * -ssld_alloc(void *unused, size_t count, size_t size) -{ - return rb_malloc(count * size); -} - -static void -ssld_free(void *unused, void *ptr) -{ - rb_free(ptr); -} -#endif static conn_t * conn_find_by_id(uint32_t id) @@ -203,14 +164,6 @@ free_conn(conn_t * conn) { rb_free_rawbuffer(conn->modbuf_out); rb_free_rawbuffer(conn->plainbuf_out); -#ifdef HAVE_LIBZ - if(IsZip(conn)) - { - zlib_stream_t *stream = conn->stream; - inflateEnd(&stream->instream); - deflateEnd(&stream->outstream); - } -#endif rb_free(conn); } @@ -255,7 +208,7 @@ close_conn(conn_t * conn, int wait_plain, const char *fmt, ...) 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); + vsnprintf(reason, sizeof(reason), fmt, ap); va_end(ap); buf[0] = 'D'; @@ -385,82 +338,7 @@ mod_cmd_write_queue(mod_ctl_t * ctl, const void *data, size_t len) mod_write_ctl(ctl->F, ctl); } -#ifdef HAVE_LIBZ -static void -common_zlib_deflate(conn_t * conn, void *buf, size_t len) -{ - char outbuf[READBUF_SIZE]; - int ret, have; - z_stream *outstream = &((zlib_stream_t *) conn->stream)->outstream; - outstream->next_in = buf; - outstream->avail_in = len; - outstream->next_out = (Bytef *) outbuf; - outstream->avail_out = sizeof(outbuf); - - ret = deflate(outstream, Z_SYNC_FLUSH); - if(ret != Z_OK) - { - /* deflate error */ - close_conn(conn, WAIT_PLAIN, "Deflate failed: %s", zError(ret)); - return; - } - if(outstream->avail_out == 0) - { - /* avail_out empty */ - close_conn(conn, WAIT_PLAIN, "error compressing data, avail_out == 0"); - return; - } - if(outstream->avail_in != 0) - { - /* avail_in isn't empty... */ - close_conn(conn, WAIT_PLAIN, "error compressing data, avail_in != 0"); - return; - } - have = sizeof(outbuf) - outstream->avail_out; - conn_mod_write(conn, outbuf, have); -} - -static void -common_zlib_inflate(conn_t * conn, void *buf, size_t len) -{ - char outbuf[READBUF_SIZE]; - int ret, have = 0; - ((zlib_stream_t *) conn->stream)->instream.next_in = buf; - ((zlib_stream_t *) conn->stream)->instream.avail_in = len; - ((zlib_stream_t *) conn->stream)->instream.next_out = (Bytef *) outbuf; - ((zlib_stream_t *) conn->stream)->instream.avail_out = sizeof(outbuf); - - while(((zlib_stream_t *) conn->stream)->instream.avail_in) - { - ret = inflate(&((zlib_stream_t *) conn->stream)->instream, Z_NO_FLUSH); - if(ret != Z_OK) - { - if(!strncmp("ERROR ", buf, 6)) - { - close_conn(conn, WAIT_PLAIN, "Received uncompressed ERROR"); - return; - } - close_conn(conn, WAIT_PLAIN, "Inflate failed: %s", zError(ret)); - return; - } - have = sizeof(outbuf) - ((zlib_stream_t *) conn->stream)->instream.avail_out; - - if(((zlib_stream_t *) conn->stream)->instream.avail_in) - { - conn_plain_write(conn, outbuf, have); - have = 0; - ((zlib_stream_t *) conn->stream)->instream.next_out = (Bytef *) outbuf; - ((zlib_stream_t *) conn->stream)->instream.avail_out = sizeof(outbuf); - } - } - if(have == 0) - return; - - conn_plain_write(conn, outbuf, have); -} -#endif - -static int +static bool plain_check_cork(conn_t * conn) { if(rb_rawbuf_length(conn->modbuf_out) >= 4096) @@ -471,9 +349,9 @@ plain_check_cork(conn_t * conn) rb_setselect(conn->plain_fd, RB_SELECT_READ, NULL, NULL); /* try to write */ conn_mod_write_sendq(conn->mod_fd, conn); - return 1; + return true; } - return 0; + return false; } @@ -513,12 +391,7 @@ conn_plain_read_cb(rb_fde_t *fd, void *data) } conn->plain_in += length; -#ifdef HAVE_LIBZ - if(IsZip(conn)) - common_zlib_deflate(conn, inbuf, length); - else -#endif - conn_mod_write(conn, inbuf, length); + conn_mod_write(conn, inbuf, length); if(IsDead(conn)) return; if(plain_check_cork(conn)) @@ -560,7 +433,6 @@ conn_mod_read_cb(rb_fde_t *fd, void *data) { char inbuf[READBUF_SIZE]; conn_t *conn = data; - const char *err = remote_closed; int length; if(conn == NULL) return; @@ -590,6 +462,7 @@ conn_mod_read_cb(rb_fde_t *fd, void *data) return; } + const char *err; if(IsSSL(conn) && length == RB_RW_SSL_ERROR) err = rb_get_ssl_strerror(conn->mod_fd); else @@ -611,12 +484,7 @@ conn_mod_read_cb(rb_fde_t *fd, void *data) return; } conn->mod_in += length; -#ifdef HAVE_LIBZ - if(IsZip(conn)) - common_zlib_inflate(conn, inbuf, length); - else -#endif - conn_plain_write(conn, inbuf, length); + conn_plain_write(conn, inbuf, length); } } @@ -649,14 +517,12 @@ conn_plain_write_sendq(rb_fde_t *fd, void *data) static int maxconn(void) { -#if defined(RLIMIT_NOFILE) && defined(HAVE_SYS_RESOURCE_H) struct rlimit limit; if(!getrlimit(RLIMIT_NOFILE, &limit)) { return limit.rlim_cur; } -#endif /* RLIMIT_FD_MAX */ return MAXCONNECTIONS; } @@ -687,17 +553,28 @@ ssl_send_cipher(conn_t *conn) static void ssl_send_certfp(conn_t *conn) { - uint8_t buf[9 + RB_SSL_CERTFP_LEN]; + uint8_t buf[13 + RB_SSL_CERTFP_LEN]; - int len = rb_get_ssl_certfp(conn->mod_fd, &buf[9], certfp_method); + int len = rb_get_ssl_certfp(conn->mod_fd, &buf[13], certfp_method); if (!len) return; lrb_assert(len <= RB_SSL_CERTFP_LEN); buf[0] = 'F'; uint32_to_buf(&buf[1], conn->id); - uint32_to_buf(&buf[5], len); - mod_cmd_write_queue(conn->ctl, buf, 9 + len); + uint32_to_buf(&buf[5], certfp_method); + uint32_to_buf(&buf[9], len); + mod_cmd_write_queue(conn->ctl, buf, 13 + 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 @@ -707,10 +584,11 @@ ssl_process_accept_cb(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen if(status == RB_OK) { - conn_mod_read_cb(conn->mod_fd, conn); - conn_plain_read_cb(conn->plain_fd, conn); 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; } /* ircd doesn't care about the reason for this */ @@ -725,10 +603,11 @@ ssl_process_connect_cb(rb_fde_t *F, int status, void *data) if(status == RB_OK) { - conn_mod_read_cb(conn->mod_fd, conn); - conn_plain_read_cb(conn->plain_fd, conn); 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); } else if(status == RB_ERR_TIMEOUT) close_conn(conn, WAIT_PLAIN, "SSL handshake timed out"); @@ -762,11 +641,9 @@ ssl_process_accept(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb) SetSSL(conn); if(rb_get_type(conn->mod_fd) & RB_FD_UNKNOWN) - { - rb_set_type(conn->mod_fd, RB_FD_SOCKET); - } - if(rb_get_type(conn->mod_fd) == RB_FD_UNKNOWN) + + if(rb_get_type(conn->plain_fd) == RB_FD_UNKNOWN) rb_set_type(conn->plain_fd, RB_FD_SOCKET); rb_ssl_start_accepted(ctlb->F[0], ssl_process_accept_cb, conn, 10); @@ -792,7 +669,7 @@ ssl_process_connect(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb) if(rb_get_type(conn->mod_fd) == RB_FD_UNKNOWN) rb_set_type(conn->mod_fd, RB_FD_SOCKET); - if(rb_get_type(conn->mod_fd) == RB_FD_UNKNOWN) + if(rb_get_type(conn->plain_fd) == RB_FD_UNKNOWN) rb_set_type(conn->plain_fd, RB_FD_SOCKET); @@ -815,8 +692,11 @@ process_stats(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb) if(conn == NULL) return; - rb_snprintf(outstat, sizeof(outstat), "S %s %llu %llu %llu %llu", odata, - conn->plain_out, conn->mod_in, conn->plain_in, conn->mod_out); + snprintf(outstat, sizeof(outstat), "S %s %llu %llu %llu %llu", odata, + (unsigned long long)conn->plain_out, + (unsigned long long)conn->mod_in, + (unsigned long long)conn->plain_in, + (unsigned long long)conn->mod_out); conn->plain_out = 0; conn->plain_in = 0; conn->mod_in = 0; @@ -824,93 +704,11 @@ process_stats(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb) mod_cmd_write_queue(ctl, outstat, strlen(outstat) + 1); /* +1 is so we send the \0 as well */ } -static void -change_connid(mod_ctl_t *ctl, mod_ctl_buf_t *ctlb) -{ - uint32_t id = buf_to_uint32(&ctlb->buf[1]); - uint32_t newid = buf_to_uint32(&ctlb->buf[5]); - conn_t *conn = conn_find_by_id(id); - rb_dlinkDelete(&conn->node, connid_hash(conn->id)); - SetZipSSL(conn); - conn->id = newid; -} - -#ifdef HAVE_LIBZ -static void -zlib_process(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb) -{ - uint8_t level; - size_t recvqlen; - size_t hdr = (sizeof(uint8_t) * 2) + sizeof(uint32_t); - void *recvq_start; - z_stream *instream, *outstream; - conn_t *conn; - uint32_t id; - - conn = make_conn(ctl, ctlb->F[0], ctlb->F[1]); - if(rb_get_type(conn->mod_fd) == RB_FD_UNKNOWN) - rb_set_type(conn->mod_fd, RB_FD_SOCKET); - - if(rb_get_type(conn->plain_fd) == RB_FD_UNKNOWN) - rb_set_type(conn->plain_fd, RB_FD_SOCKET); - - id = buf_to_uint32(&ctlb->buf[1]); - conn_add_id_hash(conn, id); - - level = (uint8_t)ctlb->buf[5]; - - recvqlen = ctlb->buflen - hdr; - recvq_start = &ctlb->buf[6]; - - SetZip(conn); - conn->stream = rb_malloc(sizeof(zlib_stream_t)); - instream = &((zlib_stream_t *) conn->stream)->instream; - outstream = &((zlib_stream_t *) conn->stream)->outstream; - - instream->total_in = 0; - instream->total_out = 0; - instream->zalloc = (alloc_func) ssld_alloc; - instream->zfree = (free_func) ssld_free; - instream->data_type = Z_ASCII; - inflateInit(&((zlib_stream_t *) conn->stream)->instream); - - outstream->total_in = 0; - outstream->total_out = 0; - outstream->zalloc = (alloc_func) ssld_alloc; - outstream->zfree = (free_func) ssld_free; - outstream->data_type = Z_ASCII; - - if(level > 9) - level = (uint8_t) Z_DEFAULT_COMPRESSION; - - deflateInit(&((zlib_stream_t *) conn->stream)->outstream, level); - if(recvqlen > 0) - common_zlib_inflate(conn, recvq_start, recvqlen); - - conn_mod_read_cb(conn->mod_fd, conn); - conn_plain_read_cb(conn->plain_fd, conn); - return; - -} -#endif - -static void -init_prng(mod_ctl_t * ctl, mod_ctl_buf_t * ctl_buf) -{ - char *path; - prng_seed_t seed_type; - - seed_type = (prng_seed_t) ctl_buf->buf[1]; - path = (char *) &ctl_buf->buf[2]; - rb_init_prng(path, seed_type); -} - - static void ssl_new_keys(mod_ctl_t * ctl, mod_ctl_buf_t * ctl_buf) { char *buf; - char *cert, *key, *dhparam; + char *cert, *key, *dhparam, *cipher_list; buf = (char *) &ctl_buf->buf[2]; cert = buf; @@ -918,10 +716,16 @@ ssl_new_keys(mod_ctl_t * ctl, mod_ctl_buf_t * ctl_buf) key = buf; buf += strlen(key) + 1; dhparam = buf; + buf += strlen(dhparam) + 1; + cipher_list = buf; + if(strlen(key) == 0) + key = cert; if(strlen(dhparam) == 0) dhparam = NULL; + if(strlen(cipher_list) == 0) + cipher_list = NULL; - if(!rb_setup_ssl_server(cert, key, dhparam)) + if(!rb_setup_ssl_server(cert, key, dhparam, cipher_list)) { const char *invalid = "I"; mod_cmd_write_queue(ctl, invalid, strlen(invalid)); @@ -953,6 +757,14 @@ send_i_am_useless(mod_ctl_t * ctl) mod_cmd_write_queue(ctl, useless, strlen(useless)); } +static void +send_version(mod_ctl_t * ctl) +{ + char version[256] = { 'V', 0 }; + strncpy(&version[1], rb_lib_version(), sizeof(version) - 2); + mod_cmd_write_queue(ctl, version, strlen(version)); +} + static void send_nozlib_support(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb) { @@ -989,7 +801,7 @@ mod_process_cmd_recv(mod_ctl_t * ctl) break; } - if(!ssl_ok) + if(!ssld_ssl_ok) { send_nossl_support(ctl, ctl_buf); break; @@ -999,13 +811,13 @@ mod_process_cmd_recv(mod_ctl_t * ctl) } case 'C': { - if (ctl_buf->nfds != 2 || ctl_buf->buflen != 5) + if (ctl_buf->buflen != 5) { cleanup_bad_message(ctl, ctl_buf); break; } - if(!ssl_ok) + if(!ssld_ssl_ok) { send_nossl_support(ctl, ctl_buf); break; @@ -1015,7 +827,7 @@ mod_process_cmd_recv(mod_ctl_t * ctl) } case 'F': { - if (ctl_buf->nfds != 2 || ctl_buf->buflen != 5) + if (ctl_buf->buflen != 5) { cleanup_bad_message(ctl, ctl_buf); break; @@ -1025,7 +837,7 @@ mod_process_cmd_recv(mod_ctl_t * ctl) } case 'K': { - if(!ssl_ok) + if(!ssld_ssl_ok) { send_nossl_support(ctl, ctl_buf); break; @@ -1033,40 +845,16 @@ mod_process_cmd_recv(mod_ctl_t * ctl) ssl_new_keys(ctl, ctl_buf); break; } - case 'I': - init_prng(ctl, ctl_buf); - break; case 'S': { process_stats(ctl, ctl_buf); break; } - case 'Y': - { - change_connid(ctl, ctl_buf); - break; - } - -#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; - } -#else case 'Z': send_nozlib_support(ctl, ctl_buf); break; -#endif default: break; /* Log unknown commands */ @@ -1168,7 +956,7 @@ int main(int argc, char **argv) { const char *s_ctlfd, *s_pipe, *s_pid; - int ctlfd, pipefd, x, maxfd; + int ctlfd, pipefd, maxfd, x; maxfd = maxconn(); s_ctlfd = getenv("CTL_FD"); @@ -1178,23 +966,22 @@ main(int argc, char **argv) if(s_ctlfd == NULL || s_pipe == NULL || s_pid == NULL) { fprintf(stderr, - "This is ircd-ratbox ssld. You know you aren't supposed to run me directly?\n"); + "This is the solanum ssld for internal ircd use.\n"); fprintf(stderr, - "You get an Id tag for this: $Id$\n"); - fprintf(stderr, "Have a nice life\n"); + "You aren't supposed to run me directly. Exiting.\n"); exit(1); } ctlfd = atoi(s_ctlfd); pipefd = atoi(s_pipe); ppid = atoi(s_pid); - x = 0; -#ifndef _WIN32 - for(x = 0; x < maxfd; x++) + + for(x = 3; x < maxfd; x++) { - if(x != ctlfd && x != pipefd && x > 2) + if(x != ctlfd && x != pipefd) close(x); } + x = open("/dev/null", O_RDWR); if(x >= 0) @@ -1208,11 +995,12 @@ main(int argc, char **argv) if(x > 2) close(x); } -#endif + setup_signals(); rb_lib_init(NULL, NULL, NULL, 0, maxfd, 1024, 4096); rb_init_rawbuffers(1024); - ssl_ok = rb_supports_ssl(); + rb_init_prng(NULL, RB_PRNG_DEFAULT); + ssld_ssl_ok = rb_supports_ssl(); mod_ctl = rb_malloc(sizeof(mod_ctl_t)); mod_ctl->F = rb_open(ctlfd, RB_FD_SOCKET, "ircd control socket"); mod_ctl->F_pipe = rb_open(pipefd, RB_FD_PIPE, "ircd pipe"); @@ -1222,36 +1010,33 @@ main(int argc, char **argv) rb_event_add("check_handshake_flood", check_handshake_flood, NULL, 10); read_pipe_ctl(mod_ctl->F_pipe, NULL); mod_read_ctl(mod_ctl->F, mod_ctl); - if(!zlib_ok && !ssl_ok) + send_version(mod_ctl); + if(!ssld_ssl_ok) { /* this is really useless... */ send_i_am_useless(mod_ctl); /* sleep until the ircd kills us */ - rb_sleep(2 << 30, 0); + rb_sleep(1 << 30, 0); exit(1); } - if(!zlib_ok) - send_nozlib_support(mod_ctl, NULL); - if(!ssl_ok) + send_nozlib_support(mod_ctl, NULL); + if(!ssld_ssl_ok) send_nossl_support(mod_ctl, NULL); rb_lib_loop(0); return 0; } -#ifndef _WIN32 static void dummy_handler(int sig) { return; } -#endif static void setup_signals() { -#ifndef _WIN32 struct sigaction act; act.sa_flags = 0; @@ -1274,5 +1059,4 @@ setup_signals() act.sa_handler = dummy_handler; sigaction(SIGALRM, &act, 0); -#endif }