[PATCH] Add /identify command to prevent leaking passwords

[PATCH] Add /identify command to prevent leaking passwords

From: Klemens Nanni
"identify mysecret" in the NickServ query goes to logs and debug output;
"/ns identify mysecret" does not go to logs but still appears in debug
output as raw IRC command.

Provide a safe "/identify mysecret" such that debug logs see everything
as usual except the actual password, just like PASS and AUTHENTICATE are
handled already.

This way it is possible to use catgirl and authenticate oneself without
passing sensitive passwords on the command line, in configuration files
or leaking them through logs or debug output at all.
---
 catgirl.1 | 2 ++
 command.c | 9 +++++++++
 2 files changed, 11 insertions(+)

diff --git a/catgirl.1 b/catgirl.1
index 1b74b6c..06053fc 100644
--- a/catgirl.1
+++ b/catgirl.1
@@ -434,6 +434,8 @@ can be typed
 Set or clear your away status.
 .It Ic /cs Ar command
 Send a command to ChanServ.
+.It Ic /identify Oo Ar nick Oc Ar password
+Identify against NickServ without logging the password.
 .It Ic /invite Ar nick
 Invite a user to the channel.
 .It Ic /join Op Ar channel Op Ar key
diff --git a/command.c b/command.c
index 73712a5..d5c3720 100644
--- a/command.c
+++ b/command.c
@@ -359,6 +359,14 @@ static void commandNS(uint id, char *params) {
 	ircFormat("NS %s\r\n", (params ?: "HELP"));
 }
 
+static void commandIdentify(uint id, char *params) {
+	(void)id;
+	ircFormat("NS IDENTIFY ");
+	ircSend(params, strlen(params));
+	ircFormat("\r\n");
+	explicit_bzero(params, strlen(params));
+}
+
 static void commandCS(uint id, char *params) {
 	(void)id;
 	ircFormat("CS %s\r\n", (params ?: "HELP"));
@@ -544,6 +552,7 @@ static const struct Handler {
 	{ "/exec", commandExec, Multiline | Restrict },
 	{ "/help", commandHelp, 0 }, // Restrict special case.
 	{ "/highlight", commandHighlight, 0 },
+	{ "/identify", commandIdentify, 0 },
 	{ "/ignore", commandIgnore, 0 },
 	{ "/invex", commandInvex, 0 },
 	{ "/invite", commandInvite, 0 },
-- 
2.32.0

Re: [PATCH] Add /identify command to prevent leaking passwords

From: Klemens Nanni
Sorry for the noise, here is the complete diff that doesn't segfault on
"/identify", i.e. usage without arguments.

-- >8 --

From d735d6643e8f7dc4c770b3da708eae4451dc3560 Mon Sep 17 00:00:00 2001
From: Klemens Nanni <klemens@posteo.de>
Date: Thu, 8 Jul 2021 14:18:08 +0200
Subject: [PATCH 2/2] Add /identify command to prevent leaking passwords

"identify mysecret" in the NickServ query goes to logs and debug output;
"/ns identify mysecret" does not go to logs but still appears in debug
output as raw IRC command.

Provide a safe "/identify mysecret" such that debug logs see everything
as usual except the actual password, just like PASS and AUTHENTICATE are
handled already.

This way it is possible to use catgirl and authenticate oneself without
passing sensitive passwords on the command line, in configuration files
or leaking them through logs or debug output at all.
---
 catgirl.1 |  2 ++
 command.c | 10 ++++++++++
 2 files changed, 12 insertions(+)

diff --git a/catgirl.1 b/catgirl.1
index 1b74b6c..06053fc 100644
--- a/catgirl.1
+++ b/catgirl.1
@@ -434,6 +434,8 @@ can be typed
 Set or clear your away status.
 .It Ic /cs Ar command
 Send a command to ChanServ.
+.It Ic /identify Oo Ar nick Oc Ar password
+Identify against NickServ without logging the password.
 .It Ic /invite Ar nick
 Invite a user to the channel.
 .It Ic /join Op Ar channel Op Ar key
diff --git a/command.c b/command.c
index 73712a5..4022bea 100644
--- a/command.c
+++ b/command.c
@@ -359,6 +359,15 @@ static void commandNS(uint id, char *params) {
 	ircFormat("NS %s\r\n", (params ?: "HELP"));
 }
 
+static void commandIdentify(uint id, char *params) {
+	(void)id;
+	if (!params) return;
+	ircFormat("NS IDENTIFY ");
+	ircSend(params, strlen(params));
+	ircFormat("\r\n");
+	explicit_bzero(params, strlen(params));
+}
+
 static void commandCS(uint id, char *params) {
 	(void)id;
 	ircFormat("CS %s\r\n", (params ?: "HELP"));
@@ -544,6 +553,7 @@ static const struct Handler {
 	{ "/exec", commandExec, Multiline | Restrict },
 	{ "/help", commandHelp, 0 }, // Restrict special case.
 	{ "/highlight", commandHighlight, 0 },
+	{ "/identify", commandIdentify, 0 },
 	{ "/ignore", commandIgnore, 0 },
 	{ "/invex", commandInvex, 0 },
 	{ "/invite", commandInvite, 0 },
-- 
2.32.0

Re: [PATCH] Add /identify command to prevent leaking passwords

From: june
> On Jul 8, 2021, at 08:32, Klemens Nanni <klemens@posteo.de> wrote:
> 
> Provide a safe "/identify mysecret" such that debug logs see everything
> as usual except the actual password, just like PASS and AUTHENTICATE are
> handled already.
> 
> This way it is possible to use catgirl and authenticate oneself without
> passing sensitive passwords on the command line, in configuration files
> or leaking them through logs or debug output at all.

The motivation for this makes sense to me, but I think there are
too many problems with late authentication through NickServ (compared
to SASL, CertFP or PASS-forwarded-to-services) to provide this
command. Namely, authentication should always happen before joining
channels. (I want to avoid any kind of generic “run these commands
after connect” function for the same reason). I think an ideal
implementation would provide a way to read a password for SASL PLAIN
(or PASS) from the terminal at runtime using readpassphrase(3).
Annoyingly, rpp is not available on GNU. I’m not sure what the
options should look like for that behaviour either.