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.
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

View File

@ -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 ,

7
chat.c
View File

@ -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);

2
chat.h
View File

@ -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);

68
irc.c
View File

@ -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);
}
}