| Add tls support to geomyidae. - geomyidae - A small C-based gopherd. | |
| git clone git://bitreich.org/geomyidae/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfri… | |
| Log | |
| Files | |
| Refs | |
| Tags | |
| README | |
| LICENSE | |
| --- | |
| commit 07240d76fd8e1d0a67c49bf7e123bb508613e691 | |
| parent 4500d3596d7b166ad1e832adeefc6be3da685b09 | |
| Author: Christoph Lohmann <[email protected]> | |
| Date: Sun, 7 Jun 2020 18:49:28 +0200 | |
| Add tls support to geomyidae. | |
| Diffstat: | |
| M Makefile | 2 +- | |
| M handlr.c | 11 +++++++---- | |
| M main.c | 168 ++++++++++++++++++++++++++---… | |
| 3 files changed, 149 insertions(+), 32 deletions(-) | |
| --- | |
| diff --git a/Makefile b/Makefile | |
| @@ -11,7 +11,7 @@ MANDIR = ${PREFIX}/share/man/man8 | |
| CFLAGS = -O2 -Wall | |
| GEOM_CFLAGS = -D_DEFAULT_SOURCE -I. -I/usr/include ${CFLAGS} | |
| -GEOM_LDFLAGS = -L/usr/lib -L. ${LDFLAGS} | |
| +GEOM_LDFLAGS = -L/usr/lib -L. -ltls ${LDFLAGS} | |
| SRC = main.c ind.c handlr.c | |
| OBJ = ${SRC:.c=.o} | |
| diff --git a/handlr.c b/handlr.c | |
| @@ -16,6 +16,8 @@ | |
| #include <sys/stat.h> | |
| #include <dirent.h> | |
| #include <sys/wait.h> | |
| +#include <errno.h> | |
| + | |
| #include "ind.h" | |
| #include "arg.h" | |
| @@ -205,11 +207,11 @@ handledcgi(int sock, char *file, char *port, char *base, … | |
| if (args == NULL) | |
| args = ""; | |
| - dup2(sock, 0); | |
| - dup2(sock, 2); | |
| + while (dup2(sock, 0) < 0 && errno == EINTR); | |
| + while (dup2(sock, 2) < 0 && errno == EINTR); | |
| switch (fork()) { | |
| case 0: | |
| - dup2(outpipe[1], 1); | |
| + while(dup2(outpipe[1], 1) < 0 && errno == EINTR); | |
| close(outpipe[0]); | |
| if (path != NULL) { | |
| if (chdir(path) < 0) | |
| @@ -223,11 +225,12 @@ handledcgi(int sock, char *file, char *port, char *base, … | |
| perror("execl"); | |
| _exit(1); | |
| } | |
| + break; | |
| case -1: | |
| perror("fork"); | |
| break; | |
| default: | |
| - dup2(sock, 1); | |
| + while(dup2(sock, 1) < 0 && errno == EINTR); | |
| close(outpipe[1]); | |
| if (!(fp = fdopen(outpipe[0], "r"))) { | |
| diff --git a/main.c b/main.c | |
| @@ -25,6 +25,7 @@ | |
| #include <arpa/inet.h> | |
| #include <sys/select.h> | |
| #include <sys/time.h> | |
| +#include <tls.h> | |
| #include "ind.h" | |
| #include "handlr.h" | |
| @@ -116,34 +117,22 @@ logentry(char *host, char *port, char *qry, char *status) | |
| } | |
| void | |
| -handlerequest(int sock, char *base, char *ohost, char *port, char *clienth, | |
| - char *clientp, int nocgi) | |
| +handlerequest(int sock, char *req, int rlen, char *base, char *ohost, | |
| + char *port, char *clienth, char *clientp, int nocgi) | |
| { | |
| struct stat dir; | |
| char recvc[1025], recvb[1025], path[1025], *args = NULL, *sear, *c; | |
| - int len = 0, fd, i, retl, maxrecv; | |
| + int len = 0, fd, i, maxrecv; | |
| filetype *type; | |
| memset(&dir, 0, sizeof(dir)); | |
| memset(recvb, 0, sizeof(recvb)); | |
| memset(recvc, 0, sizeof(recvc)); | |
| - maxrecv = sizeof(recvb); | |
| - /* | |
| - * Force at least one byte per packet. Limit, so the server | |
| - * cannot be put into DoS via zero-length packets. | |
| - */ | |
| - do { | |
| - retl = recv(sock, recvb+len, sizeof(recvb)-1-len, 0); | |
| - if (retl <= 0) { | |
| - if (retl < 0) | |
| - perror("recv"); | |
| - break; | |
| - } | |
| - len += retl; | |
| - } while (recvb[len-1] != '\n' && --maxrecv > 0); | |
| - if (len <= 0) | |
| + maxrecv = sizeof(recvb) - 1; | |
| + if (rlen > maxrecv || rlen < 0) | |
| return; | |
| + memcpy(recvb, req, rlen); | |
| c = strchr(recvb, '\r'); | |
| if (c) | |
| @@ -174,7 +163,7 @@ handlerequest(int sock, char *base, char *ohost, char *port… | |
| } | |
| } | |
| - memmove(recvc, recvb, len+1); | |
| + memmove(recvc, recvb, rlen+1); | |
| if (!strncmp(recvb, "URL:", 4)) { | |
| len = snprintf(path, sizeof(path), htredir, | |
| @@ -409,6 +398,7 @@ void | |
| usage(void) | |
| { | |
| dprintf(2, "usage: %s [-46cden] [-l logfile] " | |
| + "[-t keyfile certfile] " | |
| "[-v loglvl] [-b base] [-p port] [-o sport] " | |
| "[-u user] [-g group] [-h host] [-i interface ...]\n", | |
| argv0); | |
| @@ -423,13 +413,18 @@ main(int argc, char *argv[]) | |
| socklen_t cltlen; | |
| int sock, dofork = 1, inetf = AF_UNSPEC, usechroot = 0, | |
| nocgi = 0, errno_save, nbindips = 0, i, j, | |
| - nlfdret, *lfdret, listfd, maxlfd; | |
| + nlfdret, *lfdret, listfd, maxlfd, dotls = 0, istls = 0, | |
| + shuflen, wlen, shufpos, tlspipe[2], maxrecv, retl, | |
| + rlen = 0; | |
| fd_set rfd; | |
| char *port, *base, clienth[NI_MAXHOST], clientp[NI_MAXSERV], | |
| *user = NULL, *group = NULL, **bindips = NULL, | |
| - *ohost = NULL, *sport = NULL, *p; | |
| + *ohost = NULL, *sport = NULL, *p, *certfile = NULL, | |
| + *keyfile = NULL, shufbuf[1025], byte0, recvb[1025]; | |
| struct passwd *us = NULL; | |
| struct group *gr = NULL; | |
| + struct tls_config *tlsconfig = NULL; | |
| + struct tls *tlsctx = NULL, *tlsclientctx; | |
| base = stdbase; | |
| port = stdport; | |
| @@ -483,6 +478,11 @@ main(int argc, char *argv[]) | |
| case 'n': | |
| revlookup = 0; | |
| break; | |
| + case 't': | |
| + dotls = 1; | |
| + keyfile = EARGF(usage()); | |
| + certfile = EARGF(usage()); | |
| + break; | |
| default: | |
| usage(); | |
| } ARGEND; | |
| @@ -493,6 +493,33 @@ main(int argc, char *argv[]) | |
| if (argc != 0) | |
| usage(); | |
| + if (dotls) { | |
| + if (tls_init() < 0) { | |
| + perror("tls_init"); | |
| + return 1; | |
| + } | |
| + if ((tlsconfig = tls_config_new()) == NULL) { | |
| + perror("tls_config_new"); | |
| + return 1; | |
| + } | |
| + if ((tlsctx = tls_server()) == NULL) { | |
| + perror("tls_server"); | |
| + return 1; | |
| + } | |
| + if (tls_config_set_key_file(tlsconfig, keyfile) < 0) { | |
| + perror("tls_config_set_key_file"); | |
| + return 1; | |
| + } | |
| + if (tls_config_set_cert_file(tlsconfig, certfile) < 0) { | |
| + perror("tls_config_set_cert_file"); | |
| + return 1; | |
| + } | |
| + if (tls_configure(tlsctx, tlsconfig) < 0) { | |
| + perror("tls_configure"); | |
| + return 1; | |
| + } | |
| + } | |
| + | |
| if (ohost == NULL) { | |
| /* Do not use HOST_NAME_MAX, it is not defined on NetBSD. */ | |
| ohost = xcalloc(1, 256+1); | |
| @@ -716,16 +743,97 @@ main(int argc, char *argv[]) | |
| } | |
| #endif /* __OpenBSD__ */ | |
| - handlerequest(sock, base, ohost, sport, clienth, | |
| - clientp, nocgi); | |
| + if (recv(sock, &byte0, 1, MSG_PEEK) < 1) | |
| + return 1; | |
| + | |
| + /* | |
| + * First byte is 0x16 == 22, which is the TLS | |
| + * Handshake first byte. | |
| + */ | |
| + istls = 0; | |
| + if (byte0 == 0x16 && dotls) { | |
| + istls = 1; | |
| + if (tls_accept_socket(tlsctx, &tlsclientctx, s… | |
| + return 1; | |
| + if (tls_handshake(tlsclientctx) < 0) | |
| + return 1; | |
| + } | |
| - waitforpendingbytes(sock); | |
| + maxrecv = sizeof(recvb) - 1; | |
| + do { | |
| + if (istls) { | |
| + retl = tls_read(tlsclientctx, | |
| + recvb+rlen, sizeof(recvb)-1-rl… | |
| + } else { | |
| + retl = read(sock, recvb+rlen, | |
| + sizeof(recvb)-1-rlen); | |
| + } | |
| + if (retl <= 0) { | |
| + if (retl < 0) | |
| + perror("recv"); | |
| + break; | |
| + } | |
| + rlen += retl; | |
| + } while (recvb[rlen-1] != '\n' | |
| + && --maxrecv > 0); | |
| + if (rlen <= 0) | |
| + return 1; | |
| - shutdown(sock, SHUT_RDWR); | |
| + if (istls) { | |
| + if (pipe(tlspipe) < 0) { | |
| + perror("tls_pipe"); | |
| + return 1; | |
| + } | |
| + | |
| + switch(fork()) { | |
| + case 0: | |
| + sock = tlspipe[1]; | |
| + close(tlspipe[0]); | |
| + break; | |
| + case -1: | |
| + perror("fork"); | |
| + return 1; | |
| + default: | |
| + close(tlspipe[1]); | |
| + do { | |
| + shuflen = read(tlspipe[0], shu… | |
| + if (shuflen == EINTR) | |
| + continue; | |
| + for (shufpos = 0; shufpos < sh… | |
| + wlen = tls_write(tlscl… | |
| + if (wlen < 0) { | |
| + printf("tls_wr… | |
| + return 1; | |
| + } | |
| + } | |
| + } while(shuflen > 0); | |
| + | |
| + tls_close(tlsclientctx); | |
| + tls_free(tlsclientctx); | |
| + close(tlspipe[0]); | |
| + | |
| + waitforpendingbytes(sock); | |
| + shutdown(sock, SHUT_RDWR); | |
| + close(sock); | |
| + return 0; | |
| + } | |
| + } | |
| + | |
| + handlerequest(sock, recvb, rlen, base, | |
| + ohost, sport, clienth, | |
| + clientp, nocgi); | |
| + | |
| + if (!istls) { | |
| + waitforpendingbytes(sock); | |
| + shutdown(sock, SHUT_RDWR); | |
| + close(sock); | |
| + } | |
| close(sock); | |
| - if (loglvl & CONN) | |
| - logentry(clienth, clientp, "-", "disconnected"… | |
| + if (loglvl & CONN) { | |
| + logentry(clienth, clientp, "-", | |
| + "disconnected"); | |
| + } | |
| return 0; | |
| default: | |
| @@ -746,6 +854,12 @@ main(int argc, char *argv[]) | |
| } | |
| free(listfds); | |
| + if (dotls) { | |
| + tls_close(tlsctx); | |
| + tls_free(tlsctx); | |
| + tls_config_free(tlsconfig); | |
| + } | |
| + | |
| return 0; | |
| } | |