tAdd support for Gopher over TLS. - sacc - [fork] customized build of sacc, the… | |
git clone git://src.adamsgaard.dk/sacc | |
Log | |
Files | |
Refs | |
LICENSE | |
--- | |
commit 23ed5ec549dc587313402809caf19f0c5ed80282 | |
parent 1f92f24f9061cd4e4ecdc72cc86fbda5cd382724 | |
Author: parazyd <[email protected]> | |
Date: Tue, 6 Apr 2021 13:24:32 +0200 | |
Add support for Gopher over TLS. | |
This implementation uses libtls and acts on gophers:// URIs. | |
Signed-off-by: Anders Damsgaard <[email protected]> | |
Diffstat: | |
M config.mk | 4 ++++ | |
M sacc.c | 72 ++++++++++++++++++++++++++---… | |
A tls.h | 15 +++++++++++++++ | |
3 files changed, 81 insertions(+), 10 deletions(-) | |
--- | |
diff --git a/config.mk b/config.mk | |
t@@ -12,3 +12,7 @@ LIBS=-lcurses | |
# Define NEED_ASPRINTF and/or NEED_STRCASESTR in your cflags if your system do… | |
# not provide asprintf() or strcasestr(), respectively. | |
#CFLAGS = -DNEED_ASPRINTF -DNEED_STRCASESTR | |
+ | |
+# Define USE_TLS if you want Gopher over TLS support as gophers:// URIs | |
+#CFLAGS = -DUSE_TLS | |
+#LIBS = -lcurses -ltls | |
diff --git a/sacc.c b/sacc.c | |
t@@ -19,6 +19,7 @@ | |
#include <sys/wait.h> | |
#include "common.h" | |
+#include "tls.h" | |
#include "config.h" | |
t@@ -27,6 +28,8 @@ static Item *mainentry; | |
static int devnullfd; | |
static int parent = 1; | |
static int interactive; | |
+static int dotls = 0; | |
+static struct tls *tlsctx = NULL; | |
static void (*diag)(char *fmt, ...); | |
t@@ -54,6 +57,40 @@ die(const char *fmt, ...) | |
exit(1); | |
} | |
+static ssize_t | |
+read_wrap(int s, void *buf, size_t bs) | |
+{ | |
+ if (tlsctx) { | |
+ ssize_t r = TLS_WANT_POLLIN; | |
+ while (r == TLS_WANT_POLLIN || r == TLS_WANT_POLLOUT) | |
+ r = tls_read(tlsctx, buf, bs); | |
+ return r; | |
+ } | |
+ return read(s, buf, bs); | |
+} | |
+ | |
+static ssize_t | |
+write_wrap(int fd, const void *buf, size_t nbyte) | |
+{ | |
+ if (tlsctx) { | |
+ ssize_t r = TLS_WANT_POLLIN; | |
+ while (r == TLS_WANT_POLLIN || r == TLS_WANT_POLLOUT) | |
+ r = tls_write(tlsctx, buf, nbyte); | |
+ return r; | |
+ } | |
+ return write(fd, buf, nbyte); | |
+} | |
+ | |
+static int | |
+close_wrap(int fd) | |
+{ | |
+ if (tlsctx) { | |
+ tls_close(tlsctx); | |
+ tls_reset(tlsctx); | |
+ } | |
+ return close(fd); | |
+} | |
+ | |
#ifdef NEED_ASPRINTF | |
int | |
asprintf(char **s, const char *fmt, ...) | |
t@@ -435,18 +472,20 @@ getrawitem(int sock) | |
buf = raw + (bn-1) * BUFSIZ; | |
bs = BUFSIZ; | |
} | |
- } while ((n = read(sock, buf, bs)) > 0); | |
+ } while ((n = read_wrap(sock, buf, bs)) > 0); | |
*buf = '\0'; | |
if (n < 0) { | |
- diag("Can't read socket: %s", strerror(errno)); | |
+ diag("Can't read socket: %s", | |
+ tlsctx ? tls_error(tlsctx) : strerror(errno)); | |
clear(&raw); | |
} | |
return raw; | |
} | |
+ | |
static int | |
sendselector(int sock, const char *selector) | |
{ | |
t@@ -458,14 +497,15 @@ sendselector(int sock, const char *selector) | |
msg = p = xmalloc(ln); | |
snprintf(msg, ln--, "%s\r\n", selector); | |
- while ((n = write(sock, p, ln)) > 0) { | |
+ while ((n = write_wrap(sock, p, ln)) > 0) { | |
ln -= n; | |
p += n; | |
} | |
free(msg); | |
if (n == -1) | |
- diag("Can't send message: %s", strerror(errno)); | |
+ diag("Can't send message: %s", | |
+ tlsctx ? tls_error(tlsctx) : strerror(errno)); | |
return n; | |
} | |
t@@ -480,7 +520,7 @@ connectto(const char *host, const char *port) | |
.ai_protocol = IPPROTO_TCP, | |
}; | |
struct addrinfo *addrs, *addr; | |
- int r, sock = -1; | |
+ int r, t = 0, sock = -1; | |
sigemptyset(&set); | |
sigaddset(&set, SIGWINCH); | |
t@@ -497,9 +537,13 @@ connectto(const char *host, const char *port) | |
addr->ai_protocol)) < 0) | |
continue; | |
if ((r = connect(sock, addr->ai_addr, addr->ai_addrlen)) < 0) { | |
- close(sock); | |
+ close_wrap(sock); | |
continue; | |
} | |
+ if (dotls) { | |
+ tlsctx = tls_client(); | |
+ t = tls_connect_socket(tlsctx, sock, host); | |
+ } | |
break; | |
} | |
t@@ -514,6 +558,10 @@ connectto(const char *host, const char *port) | |
host, port, strerror(errno)); | |
goto err; | |
} | |
+ if (t < 0) { | |
+ diag("Can't init TLS : %s", tls_error(tlsctx)); | |
+ goto err; | |
+ } | |
sigprocmask(SIG_SETMASK, &oset, NULL); | |
return sock; | |
t@@ -542,7 +590,7 @@ download(Item *item, int dest) | |
} | |
w = 0; | |
- while ((r = read(src, buf, BUFSIZ)) > 0) { | |
+ while ((r = read_wrap(src, buf, BUFSIZ)) > 0) { | |
while ((w = write(dest, buf, r)) > 0) | |
r -= w; | |
} | |
t@@ -553,7 +601,7 @@ download(Item *item, int dest) | |
errno = 0; | |
} | |
- close(src); | |
+ close_wrap(src); | |
return (r == 0 && w == 0); | |
} | |
t@@ -615,7 +663,7 @@ fetchitem(Item *item) | |
sendselector(sock, item->selector) < 0) | |
return 0; | |
raw = getrawitem(sock); | |
- close(sock); | |
+ close_wrap(sock); | |
if (raw == NULL || !*raw) { | |
diag("Empty response from server"); | |
t@@ -898,7 +946,11 @@ moldentry(char *url) | |
int parsed, ipv6; | |
if (p = strstr(url, "://")) { | |
- if (strncmp(url, "gopher", p - url)) | |
+ if (!strncmp(url, "gopher", p - url)) | |
+ dotls = 0; | |
+ else if (!strncmp(url, "gophers", p - url)) | |
+ dotls = 1; | |
+ else | |
die("Protocol not supported: %.*s", p - url, url); | |
host = p + 3; | |
} | |
diff --git a/tls.h b/tls.h | |
t@@ -0,0 +1,15 @@ | |
+/* See LICENSE file for copyright and license details. */ | |
+#ifndef USE_TLS | |
+ | |
+#define TLS_WANT_POLLIN 0 | |
+#define TLS_WANT_POLLOUT 0 | |
+#define tls_read(a,b,c) 0 | |
+#define tls_write(a,b,c) 0 | |
+#define tls_close(a) 0 | |
+#define tls_reset(a) 0 | |
+#define tls_error(a) 0 | |
+#define tls_client() 0 | |
+#define tls_connect_socket(a,b,c) 0 | |
+#else | |
+#include <tls.h> | |
+#endif |