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 .Dt CATGIRL 1
.Os .Os
. .
@ -222,11 +222,9 @@ Authenticate as
with with
.Ar pass .Ar pass
using SASL PLAIN. using SASL PLAIN.
Since this requires the account password Leave
in plain text, .Ar pass
it is recommended to use CertFP instead. blank to prompt for the password.
See
.Sx Configuring CertFP .
. .
.It Fl c Ar path | Cm cert No = Ar path .It Fl c Ar path | Cm cert No = Ar path
Load the TLS client certificate from 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 .It Fl w Ar pass | Cm pass No = Ar pass
Log in with the server password Log in with the server password
.Ar pass . .Ar pass .
Leave
.Ar pass
blank to prompt for the password.
.El .El
. .
.Ss Configuring CertFP .Ss Configuring CertFP

24
chat.c
View File

@ -50,6 +50,8 @@
#include <capsicum_helpers.h> #include <capsicum_helpers.h>
#endif #endif
char *readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags);
#include "chat.h" #include "chat.h"
#ifndef OPENSSL_BIN #ifndef OPENSSL_BIN
@ -131,6 +133,12 @@ static void parseHash(char *str) {
if (*str) hashBound = strtoul(&str[1], NULL, 0); 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 volatile sig_atomic_t signals[NSIG];
static void signalHandler(int signal) { static void signalHandler(int signal) {
signals[signal] = 1; signals[signal] = 1;
@ -288,7 +296,7 @@ int main(int argc, char *argv[]) {
uiTime.enable = true; uiTime.enable = true;
if (optarg) uiTime.format = optarg; 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 'c': cert = optarg;
break; case 'e': sasl = true; break; case 'e': sasl = true;
break; case 'g': genCert(optarg); break; case 'g': genCert(optarg);
@ -337,6 +345,20 @@ int main(int argc, char *argv[]) {
user = hash; 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: // Modes defined in RFC 1459:
set(&network.chanTypes, "#&"); set(&network.chanTypes, "#&");
set(&network.prefixes, "@+"); set(&network.prefixes, "@+");

3
chat.h
View File

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

View File

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