From 551f22a901e297959cc303acd1d03645bda6ca16 Mon Sep 17 00:00:00 2001 From: dzwdz Date: Thu, 24 Mar 2022 20:47:38 +0000 Subject: [PATCH] Allow plaintext connections with -P --- README.7 | 7 +++--- catgirl.1 | 5 +++- chat.c | 7 ++++-- chat.h | 2 +- irc.c | 68 ++++++++++++++++++++++++++++++++++++++----------------- 5 files changed, 60 insertions(+), 29 deletions(-) diff --git a/README.7 b/README.7 index 32ee50f..63bfe4e 100644 --- a/README.7 +++ b/README.7 @@ -56,6 +56,9 @@ the option enables tight sandboxing. Sandboxing is always used on .Ox . +.It +Plaintext support: +It's usually less secure than TLS, but who cares. .El . .Ss Non-features @@ -95,10 +98,6 @@ Protocol coverage: IRCv3 extensions are implemented only where they contribute to the intended user experience. -.It -Cleartext IRC: -TLS is now ubiquitous -and certificates are easy to obtain. .El . .Sh INSTALLING diff --git a/catgirl.1 b/catgirl.1 index 2031d94..a1dfe1f 100644 --- a/catgirl.1 +++ b/catgirl.1 @@ -8,7 +8,7 @@ . .Sh SYNOPSIS .Nm -.Op Fl KRelqv +.Op Fl KPRelqv .Op Fl C Ar copy .Op Fl H Ar hash .Op Fl I Ar highlight @@ -188,6 +188,9 @@ The default is the first available of .Xr open 1 , .Xr xdg-open 1 . . +.It Fl P | Cm plaintext +Don't use TLS for the server connection. +. .It Fl R | Cm restrict Disable the .Ic /copy , diff --git a/chat.c b/chat.c index b74fdc0..2a2efb3 100644 --- a/chat.c +++ b/chat.c @@ -226,6 +226,7 @@ int main(int argc, char *argv[]) { setlocale(LC_CTYPE, ""); bool insecure = false; + bool useTLS = true; bool printCert = false; const char *bind = NULL; const char *host = NULL; @@ -249,6 +250,7 @@ int main(int argc, char *argv[]) { { .val = 'K', .name = "kiosk", no_argument }, { .val = 'N', .name = "notify", required_argument }, { .val = 'O', .name = "open", required_argument }, + { .val = 'P', .name = "plaintext", no_argument }, { .val = 'R', .name = "restrict", no_argument }, { .val = 'S', .name = "bind", required_argument }, { .val = 'T', .name = "timestamp", optional_argument }, @@ -290,6 +292,7 @@ int main(int argc, char *argv[]) { break; case 'K': self.kiosk = true; break; case 'N': utilPush(&uiNotifyUtil, optarg); break; case 'O': utilPush(&urlOpenUtil, optarg); + break; case 'P': useTLS = false; break; case 'R': self.restricted = true; break; case 'S': bind = optarg; break; case 'T': { @@ -326,7 +329,7 @@ int main(int argc, char *argv[]) { int error = pledge("stdio inet dns", NULL); if (error) err(EX_OSERR, "pledge"); #endif - ircConfig(true, NULL, NULL, NULL); + ircConfig(useTLS, true, NULL, NULL, NULL); ircConnect(bind, host, port); ircPrintCert(); ircClose(); @@ -373,7 +376,7 @@ int main(int argc, char *argv[]) { inputCompleteAdd(); - ircConfig(insecure, trust, cert, priv); + ircConfig(useTLS, insecure, trust, cert, priv); uiInit(); sig_t cursesWinch = signal(SIGWINCH, signalHandler); diff --git a/chat.h b/chat.h index 1c46f00..7f80d63 100644 --- a/chat.h +++ b/chat.h @@ -235,7 +235,7 @@ struct Message { }; void ircConfig( - bool insecure, const char *trust, const char *cert, const char *priv + bool useTLS, bool insecure, const char *trust, const char *cert, const char *priv ); int ircConnect(const char *bind, const char *host, const char *port); void ircHandshake(void); diff --git a/irc.c b/irc.c index 20e9f91..b06fb10 100644 --- a/irc.c +++ b/irc.c @@ -46,13 +46,16 @@ static struct tls *client; static struct tls_config *config; +static int sock = -1; void ircConfig( - bool insecure, const char *trust, const char *cert, const char *priv + bool useTLS, bool insecure, const char *trust, const char *cert, const char *priv ) { int error = 0; char buf[PATH_MAX]; + if (!useTLS) return; + config = tls_config_new(); if (!config) errx(EX_SOFTWARE, "tls_config_new"); @@ -107,10 +110,7 @@ void ircConfig( } int ircConnect(const char *bindHost, const char *host, const char *port) { - assert(client); - int error; - int sock = -1; struct addrinfo *head; struct addrinfo hints = { .ai_family = AF_UNSPEC, @@ -159,14 +159,18 @@ int ircConnect(const char *bindHost, const char *host, const char *port) { freeaddrinfo(head); fcntl(sock, F_SETFD, FD_CLOEXEC); - error = tls_connect_socket(client, sock, host); - if (error) errx(EX_PROTOCOL, "tls_connect: %s", tls_error(client)); + if (client) { + error = tls_connect_socket(client, sock, host); + if (error) errx(EX_PROTOCOL, "tls_connect: %s", tls_error(client)); + } return sock; } void ircHandshake(void) { int error; + if (!config) return; + do { error = tls_handshake(client); } while (error == TLS_WANT_POLLIN || error == TLS_WANT_POLLOUT); @@ -177,6 +181,8 @@ void ircHandshake(void) { void ircPrintCert(void) { size_t len; + if (!config) return; + ircHandshake(); const byte *pem = tls_peer_cert_chain_pem(client, &len); printf("subject= %s\n", tls_peer_cert_subject(client)); @@ -198,13 +204,22 @@ static void debug(const char *pre, const char *line) { } void ircSend(const char *ptr, size_t len) { - assert(client); - while (len) { - ssize_t ret = tls_write(client, ptr, len); - if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) continue; - if (ret < 0) errx(EX_IOERR, "tls_write: %s", tls_error(client)); - ptr += ret; - len -= ret; + if (client) { + while (len) { + ssize_t ret = tls_write(client, ptr, len); + if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) continue; + if (ret < 0) errx(EX_IOERR, "tls_write: %s", tls_error(client)); + ptr += ret; + len -= ret; + } + } else { + assert(sock != -1); + while (len) { + ssize_t ret = write(sock, ptr, len); + if (ret < 0) errx(EX_IOERR, "write: %s", "TODO how the fuck does errno work again"); + ptr += ret; + len -= ret; + } } } @@ -284,12 +299,19 @@ void ircRecv(void) { static char buf[MessageCap]; static size_t len = 0; - assert(client); - ssize_t ret = tls_read(client, &buf[len], sizeof(buf) - len); - if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) return; - if (ret < 0) errx(EX_IOERR, "tls_read: %s", tls_error(client)); - if (!ret) errx(EX_PROTOCOL, "server closed connection"); - len += ret; + if (client) { + ssize_t ret = tls_read(client, &buf[len], sizeof(buf) - len); + if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) return; + if (ret < 0) errx(EX_IOERR, "tls_read: %s", tls_error(client)); + if (!ret) errx(EX_PROTOCOL, "server closed connection"); + len += ret; + } else { + assert(sock != 1); + ssize_t ret = read(sock, &buf[len], sizeof(buf) - len); + if (ret < 0) errx(EX_IOERR, "read: %s", "TODO here too"); + if (!ret) errx(EX_PROTOCOL, "server closed connection"); + len += ret; + } char *crlf; char *line = buf; @@ -308,6 +330,10 @@ void ircRecv(void) { } void ircClose(void) { - tls_close(client); - tls_free(client); + if (client) { + tls_close(client); + tls_free(client); + } else { + close(sock); + } }