Allow plaintext connections with -P

master
dzwdz 2022-03-24 20:47:38 +00:00
parent 714b4bc76a
commit 551f22a901
5 changed files with 60 additions and 29 deletions

View File

@ -56,6 +56,9 @@ the
option enables tight sandboxing. option enables tight sandboxing.
Sandboxing is always used on Sandboxing is always used on
.Ox . .Ox .
.It
Plaintext support:
It's usually less secure than TLS, but who cares.
.El .El
. .
.Ss Non-features .Ss Non-features
@ -95,10 +98,6 @@ Protocol coverage:
IRCv3 extensions are implemented only IRCv3 extensions are implemented only
where they contribute to where they contribute to
the intended user experience. the intended user experience.
.It
Cleartext IRC:
TLS is now ubiquitous
and certificates are easy to obtain.
.El .El
. .
.Sh INSTALLING .Sh INSTALLING

View File

@ -8,7 +8,7 @@
. .
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm .Nm
.Op Fl KRelqv .Op Fl KPRelqv
.Op Fl C Ar copy .Op Fl C Ar copy
.Op Fl H Ar hash .Op Fl H Ar hash
.Op Fl I Ar highlight .Op Fl I Ar highlight
@ -188,6 +188,9 @@ The default is the first available of
.Xr open 1 , .Xr open 1 ,
.Xr xdg-open 1 . .Xr xdg-open 1 .
. .
.It Fl P | Cm plaintext
Don't use TLS for the server connection.
.
.It Fl R | Cm restrict .It Fl R | Cm restrict
Disable the Disable the
.Ic /copy , .Ic /copy ,

7
chat.c
View File

@ -226,6 +226,7 @@ int main(int argc, char *argv[]) {
setlocale(LC_CTYPE, ""); setlocale(LC_CTYPE, "");
bool insecure = false; bool insecure = false;
bool useTLS = true;
bool printCert = false; bool printCert = false;
const char *bind = NULL; const char *bind = NULL;
const char *host = NULL; const char *host = NULL;
@ -249,6 +250,7 @@ int main(int argc, char *argv[]) {
{ .val = 'K', .name = "kiosk", no_argument }, { .val = 'K', .name = "kiosk", no_argument },
{ .val = 'N', .name = "notify", required_argument }, { .val = 'N', .name = "notify", required_argument },
{ .val = 'O', .name = "open", required_argument }, { .val = 'O', .name = "open", required_argument },
{ .val = 'P', .name = "plaintext", no_argument },
{ .val = 'R', .name = "restrict", no_argument }, { .val = 'R', .name = "restrict", no_argument },
{ .val = 'S', .name = "bind", required_argument }, { .val = 'S', .name = "bind", required_argument },
{ .val = 'T', .name = "timestamp", optional_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 'K': self.kiosk = true;
break; case 'N': utilPush(&uiNotifyUtil, optarg); break; case 'N': utilPush(&uiNotifyUtil, optarg);
break; case 'O': utilPush(&urlOpenUtil, optarg); break; case 'O': utilPush(&urlOpenUtil, optarg);
break; case 'P': useTLS = false;
break; case 'R': self.restricted = true; break; case 'R': self.restricted = true;
break; case 'S': bind = optarg; break; case 'S': bind = optarg;
break; case 'T': { break; case 'T': {
@ -326,7 +329,7 @@ int main(int argc, char *argv[]) {
int error = pledge("stdio inet dns", NULL); int error = pledge("stdio inet dns", NULL);
if (error) err(EX_OSERR, "pledge"); if (error) err(EX_OSERR, "pledge");
#endif #endif
ircConfig(true, NULL, NULL, NULL); ircConfig(useTLS, true, NULL, NULL, NULL);
ircConnect(bind, host, port); ircConnect(bind, host, port);
ircPrintCert(); ircPrintCert();
ircClose(); ircClose();
@ -373,7 +376,7 @@ int main(int argc, char *argv[]) {
inputCompleteAdd(); inputCompleteAdd();
ircConfig(insecure, trust, cert, priv); ircConfig(useTLS, insecure, trust, cert, priv);
uiInit(); uiInit();
sig_t cursesWinch = signal(SIGWINCH, signalHandler); sig_t cursesWinch = signal(SIGWINCH, signalHandler);

2
chat.h
View File

@ -235,7 +235,7 @@ struct Message {
}; };
void ircConfig( 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); int ircConnect(const char *bind, const char *host, const char *port);
void ircHandshake(void); void ircHandshake(void);

68
irc.c
View File

@ -46,13 +46,16 @@
static struct tls *client; static struct tls *client;
static struct tls_config *config; static struct tls_config *config;
static int sock = -1;
void ircConfig( 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; int error = 0;
char buf[PATH_MAX]; char buf[PATH_MAX];
if (!useTLS) return;
config = tls_config_new(); config = tls_config_new();
if (!config) errx(EX_SOFTWARE, "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) { int ircConnect(const char *bindHost, const char *host, const char *port) {
assert(client);
int error; int error;
int sock = -1;
struct addrinfo *head; struct addrinfo *head;
struct addrinfo hints = { struct addrinfo hints = {
.ai_family = AF_UNSPEC, .ai_family = AF_UNSPEC,
@ -159,14 +159,18 @@ int ircConnect(const char *bindHost, const char *host, const char *port) {
freeaddrinfo(head); freeaddrinfo(head);
fcntl(sock, F_SETFD, FD_CLOEXEC); fcntl(sock, F_SETFD, FD_CLOEXEC);
error = tls_connect_socket(client, sock, host); if (client) {
if (error) errx(EX_PROTOCOL, "tls_connect: %s", tls_error(client)); error = tls_connect_socket(client, sock, host);
if (error) errx(EX_PROTOCOL, "tls_connect: %s", tls_error(client));
}
return sock; return sock;
} }
void ircHandshake(void) { void ircHandshake(void) {
int error; int error;
if (!config) return;
do { do {
error = tls_handshake(client); error = tls_handshake(client);
} while (error == TLS_WANT_POLLIN || error == TLS_WANT_POLLOUT); } while (error == TLS_WANT_POLLIN || error == TLS_WANT_POLLOUT);
@ -177,6 +181,8 @@ void ircHandshake(void) {
void ircPrintCert(void) { void ircPrintCert(void) {
size_t len; size_t len;
if (!config) return;
ircHandshake(); ircHandshake();
const byte *pem = tls_peer_cert_chain_pem(client, &len); const byte *pem = tls_peer_cert_chain_pem(client, &len);
printf("subject= %s\n", tls_peer_cert_subject(client)); 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) { void ircSend(const char *ptr, size_t len) {
assert(client); if (client) {
while (len) { while (len) {
ssize_t ret = tls_write(client, ptr, len); ssize_t ret = tls_write(client, ptr, len);
if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) continue; if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) continue;
if (ret < 0) errx(EX_IOERR, "tls_write: %s", tls_error(client)); if (ret < 0) errx(EX_IOERR, "tls_write: %s", tls_error(client));
ptr += ret; ptr += ret;
len -= 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 char buf[MessageCap];
static size_t len = 0; static size_t len = 0;
assert(client); if (client) {
ssize_t ret = tls_read(client, &buf[len], sizeof(buf) - len); ssize_t ret = tls_read(client, &buf[len], sizeof(buf) - len);
if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) return; if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) return;
if (ret < 0) errx(EX_IOERR, "tls_read: %s", tls_error(client)); if (ret < 0) errx(EX_IOERR, "tls_read: %s", tls_error(client));
if (!ret) errx(EX_PROTOCOL, "server closed connection"); if (!ret) errx(EX_PROTOCOL, "server closed connection");
len += ret; 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 *crlf;
char *line = buf; char *line = buf;
@ -308,6 +330,10 @@ void ircRecv(void) {
} }
void ircClose(void) { void ircClose(void) {
tls_close(client); if (client) {
tls_free(client); tls_close(client);
tls_free(client);
} else {
close(sock);
}
} }