about summary refs log tree commit diff
path: root/enroll.c
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2022-03-03 21:29:16 -0500
committerJune McEnroe <june@causal.agency>2022-03-03 21:29:16 -0500
commit776fc1cccb2e17799528b35864f64ab0ef7ebfd2 (patch)
treec94a200a4a5a5724d7a7b24f7cdecd189ec75563 /enroll.c
parentPrompt for account, nick, pronouns (diff)
downloadcatgirl-776fc1cccb2e17799528b35864f64ab0ef7ebfd2.tar.gz
catgirl-776fc1cccb2e17799528b35864f64ab0ef7ebfd2.zip
Prompt for account password
Diffstat (limited to 'enroll.c')
-rw-r--r--enroll.c94
1 files changed, 84 insertions, 10 deletions
diff --git a/enroll.c b/enroll.c
index ac97414..9776e80 100644
--- a/enroll.c
+++ b/enroll.c
@@ -122,6 +122,47 @@ static int yesno(bool *resp, bool def, const char *format, ...) {
 	}
 }
 
+static int password(char **resp, bool confirm, const char *format, ...)
+__attribute__((format(printf, 3, 4)));
+static int password(char **resp, bool confirm, const char *format, ...) {
+	va_list ap;
+	char desc[1024];
+	va_start(ap, format);
+	vsnprintf(desc, sizeof(desc), format, ap);
+	va_end(ap);
+
+	enum { Cap = 1024 };
+	char *buf1 = malloc(Cap);
+	if (!buf1) err(EX_OSERR, "malloc");
+
+	char *buf2 = NULL;
+	if (confirm) {
+		buf2 = malloc(Cap);
+		if (!buf2) errx(EX_OSERR, "malloc");
+	}
+
+	for (;;) {
+		*resp = readpassphrase(desc, buf1, Cap, 0);
+		if (!*resp) errx(EX_IOERR, "could not read passphrase");
+		if (!buf1[0]) {
+			*resp = NULL;
+			free(buf1);
+			free(buf2);
+			return -1;
+		}
+		if (!confirm) return 0;
+
+		*resp = readpassphrase("Confirm password: ", buf2, Cap, 0);
+		if (!*resp) errx(EX_IOERR, "could not read passphrase");
+		if (!strcmp(buf2, buf1)) {
+			explicit_bzero(buf1, Cap);
+			free(buf1);
+			return 0;
+		}
+		printf("Passwords do not match.\n");
+	}
+}
+
 static struct {
 	char *network;
 	char *config;
@@ -130,7 +171,10 @@ static struct {
 	struct addrinfo *addr;
 	struct tls_config *tls;
 	char *trust;
-	char *account;
+	struct {
+		char *name;
+		char *pass;
+	} account;
 	char *nick;
 	char *pronouns;
 } info;
@@ -426,24 +470,29 @@ fail:
 	return -1;
 }
 
-static int getAccount(void) {
+static int getAccountName(void) {
 	int pop = prompt(
-		&info.account, "",
+		&info.account.name, "",
 		"If you already have an account on %s, what is its name?\n"
 		"If you have a NickServ account already, enter the name of the\n"
 		"account. If you aren't sure, leave this blank.\n",
 		info.network
 	);
 	if (pop) return pop;
-	if (!info.account[0]) return 0;
+	if (!info.account.name[0]) return 0;
 
-	info.nick = strdup(info.account);
+	info.nick = strdup(info.account.name);
 	if (!info.nick) err(EX_OSERR, "strdup");
-
-	// TODO: Prompt for account password.
 	return 0;
 }
 
+static int getAccountPass(void) {
+	return password(
+		&info.account.pass, false,
+		"Password for %s on %s: ", info.account.name, info.network
+	);
+}
+
 static int getNick(void) {
 	return prompt(
 		&info.nick, getenv("USER"),
@@ -527,8 +576,8 @@ int main(int argc, char *argv[]) {
 				unset(&info.host);
 				unset(&info.port);
 			}
-		} else if (!info.account) {
-			pop = getAccount();
+		} else if (!info.account.name) {
+			pop = getAccountName();
 			if (pop) {
 				unset(&info.trust);
 				freeaddrinfo(info.addr);
@@ -536,9 +585,15 @@ int main(int argc, char *argv[]) {
 				unset(&info.host);
 				unset(&info.port);
 			}
+		} else if (info.account.name[0] && !info.account.pass) {
+			pop = getAccountPass();
+			if (pop) unset(&info.account.name);
 		} else if (!info.nick) {
 			pop = getNick();
-			if (pop) unset(&info.account);
+			if (pop) {
+				unset(&info.account.name);
+				unset(&info.account.pass);
+			}
 		} else if (!info.pronouns) {
 			pop = getPronouns();
 			if (pop) unset(&info.nick);
@@ -559,6 +614,25 @@ int main(int argc, char *argv[]) {
 	if (info.trust) {
 		fprintf(file, "trust = %s.pem\n", info.host);
 	}
+
+	// TODO: Check for CertFP instead.
+	bool saslPass;
+	pop = yesno(
+		&saslPass, true,
+		"Would you like to save your account password?\n"
+		"If yes, your account password will be written to the configuration\n"
+		"file and sent automatically using SASL when catgirl connects.\n"
+		"Otherwise, only your account name will be saved, and catgirl will\n"
+		"prompt you for the password every time.\n"
+	);
+	if (!pop && saslPass) {
+		fprintf(
+			file, "sasl-plain = %s:%s\n", info.account.name, info.account.pass
+		);
+	} else {
+		fprintf(file, "sasl-plain = %s:\n", info.account.name);
+	}
+
 	fprintf(file, "nick = %s\n", info.nick);
 	if (strlen(info.pronouns) > 1) {
 		fprintf(file, "real = %s [%s]\n", info.nick, info.pronouns);