Prompt for empty server or SASL passwords

master
June McEnroe 2022-02-12 13:26:38 -05:00
parent 9c384de6db
commit 397b4ce6bd
4 changed files with 42 additions and 16 deletions

View File

@ -1,4 +1,4 @@
.Dd February 3, 2022
.Dd February 12, 2022
.Dt CATGIRL 1
.Os
.
@ -222,11 +222,9 @@ Authenticate as
with
.Ar pass
using SASL PLAIN.
Since this requires the account password
in plain text,
it is recommended to use CertFP instead.
See
.Sx Configuring CertFP .
Leave
.Ar pass
blank to prompt for the password.
.
.It Fl c Ar path | Cm cert No = Ar path
Load the TLS client certificate from
@ -375,6 +373,9 @@ if it is not a terminal.
.It Fl w Ar pass | Cm pass No = Ar pass
Log in with the server password
.Ar pass .
Leave
.Ar pass
blank to prompt for the password.
.El
.
.Ss Configuring CertFP

24
chat.c
View File

@ -50,6 +50,8 @@
#include <capsicum_helpers.h>
#endif
char *readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags);
#include "chat.h"
#ifndef OPENSSL_BIN
@ -131,6 +133,12 @@ static void parseHash(char *str) {
if (*str) hashBound = strtoul(&str[1], NULL, 0);
}
static void parsePlain(char *str) {
self.plainUser = strsep(&str, ":");
if (!str) errx(EX_USAGE, "SASL PLAIN missing colon");
self.plainPass = str;
}
static volatile sig_atomic_t signals[NSIG];
static void signalHandler(int signal) {
signals[signal] = 1;
@ -288,7 +296,7 @@ int main(int argc, char *argv[]) {
uiTime.enable = true;
if (optarg) uiTime.format = optarg;
}
break; case 'a': sasl = true; self.plain = optarg;
break; case 'a': sasl = true; parsePlain(optarg);
break; case 'c': cert = optarg;
break; case 'e': sasl = true;
break; case 'g': genCert(optarg);
@ -337,6 +345,20 @@ int main(int argc, char *argv[]) {
user = hash;
}
if (pass && !pass[0]) {
char *buf = malloc(512);
if (!buf) err(EX_OSERR, "malloc");
pass = readpassphrase("Server password: ", buf, 512, 0);
if (!pass) errx(EX_IOERR, "unable to read passphrase");
}
if (self.plainPass && !self.plainPass[0]) {
char *buf = malloc(512);
if (!buf) err(EX_OSERR, "malloc");
self.plainPass = readpassphrase("Account password: ", buf, 512, 0);
if (!self.plainPass) errx(EX_IOERR, "unable to read passphrase");
}
// Modes defined in RFC 1459:
set(&network.chanTypes, "#&");
set(&network.prefixes, "@+");

3
chat.h
View File

@ -193,7 +193,8 @@ extern struct Self {
bool restricted;
size_t pos;
enum Cap caps;
char *plain;
char *plainUser;
char *plainPass;
char *mode;
char *join;
char *nick;

View File

@ -164,7 +164,9 @@ static void handleCap(struct Message *msg) {
} else if (!strcmp(msg->params[1], "ACK")) {
self.caps |= caps;
if (caps & CapSASL) {
ircFormat("AUTHENTICATE %s\r\n", (self.plain ? "PLAIN" : "EXTERNAL"));
ircFormat(
"AUTHENTICATE %s\r\n", (self.plainUser ? "PLAIN" : "EXTERNAL")
);
}
if (!(self.caps & CapSASL)) ircFormat("CAP END\r\n");
} else if (!strcmp(msg->params[1], "NAK")) {
@ -203,18 +205,18 @@ static void base64(char *dst, const byte *src, size_t len) {
static void handleAuthenticate(struct Message *msg) {
(void)msg;
if (!self.plain) {
if (!self.plainUser) {
ircFormat("AUTHENTICATE +\r\n");
return;
}
byte buf[299] = {0};
size_t len = 1 + strlen(self.plain);
size_t userLen = strlen(self.plainUser);
size_t passLen = strlen(self.plainPass);
size_t len = 1 + userLen + 1 + passLen;
if (sizeof(buf) < len) errx(EX_USAGE, "SASL PLAIN is too long");
memcpy(&buf[1], self.plain, len - 1);
byte *sep = memchr(buf, ':', len);
if (!sep) errx(EX_USAGE, "SASL PLAIN missing colon");
*sep = 0;
memcpy(&buf[1], self.plainUser, userLen);
memcpy(&buf[1 + userLen + 1], self.plainPass, passLen);
char b64[BASE64_SIZE(sizeof(buf))];
base64(b64, buf, len);
@ -224,7 +226,7 @@ static void handleAuthenticate(struct Message *msg) {
explicit_bzero(b64, sizeof(b64));
explicit_bzero(buf, sizeof(buf));
explicit_bzero(self.plain, strlen(self.plain));
explicit_bzero(self.plainPass, strlen(self.plainPass));
}
static void handleReplyLoggedIn(struct Message *msg) {