[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC] certfp for rcirc
From: |
Omar Polo |
Subject: |
[RFC] certfp for rcirc |
Date: |
Wed, 11 Nov 2021 10:02:27 +0100 |
User-agent: |
mu4e 1.6.9; emacs 29.0.50 |
Hello,
I was told earlier today that is actually possible to log in to an irc
server using TLS client certificates. I like the idea and I wanted to
used it, but unfortunately, rcirc doesn't seem to support them.
I briefly tried circe, which has support for certfp, and while it's a
great irc client, I still like rcirc more (eheh) so here's a try at
adding the certfp login style to rcirc. It's still missing the
documentation bits, but as per the subject, I'd like to get a feedback
on the diff before proceding with the documentation.
Here's some documentation on how to use certfp:
https://libera.chat/guides/certfp
To use certfp you need to:
1. generate a certificate (e.g. with openssl(1))
2. the first time:
- connect using the certificate
- authenticate via the usual /msg nickserv identify ...
- associate the certificate with your account
/msg NickServ CERT ADD
3. from now on every time you connect with that cert, you're
automatically authenticated. No passwords needed.
With the following patch I can connect to libera with the following
configuration:
(setq rcirc-server-alist
'(("irc.libera.chat" :channels (...) :port 6697)))
(setq rcirc-authinfo
'(("libera"
certfp
"/home/op/.emacs.d/irc/key.pem"
"/home/op/.emacs.d/irc/cert.pem")))
Here's an excerpt from the *irc.libera.chat* server in a emacs -Q with
the above config and the custom rcirc.el loaded:
[...]
23:28 *** erbium.libera.chat 001 Welcome to the Libera.Chat Internet
Relay Chat Network op2
^^^
note how I'm already logged in
[...]
23:28 *** op2 MODE +Zi
23:28 -NickServ- This nickname is registered. Please choose a
different nickname, or identify via /msg NickServ
IDENTIFY op2 <password>
23:28 -NickServ- You have 30 seconds to identify to your nickname
before it is changed.
23:28 -NickServ- You are now identified for op2.
23:28 -NickServ- Last login from: ~op<redacted>
on Nov 10 22:27:31 2021 +0000.
23:29 /whois op2
[...]
23:29 *** 276 op2 has client certificate fingerprint
<redacted>
[...]
For some reason I don't know yet, the NickServ still says that I've got
30 seconds to identify myself, but in reality I'm already logged in. I
don't know basically anything about how the irc protocol works, so I'm
probably missing something incredibly obvious.
What do you think?
Cheers,
Omar Polo
diff --git a/lisp/net/rcirc.el b/lisp/net/rcirc.el
index 52d74a3394..070218ef0a 100644
--- a/lisp/net/rcirc.el
+++ b/lisp/net/rcirc.el
@@ -262,10 +262,12 @@ The ARGUMENTS for each METHOD symbol are:
`bitlbee': NICK PASSWORD
`quakenet': ACCOUNT PASSWORD
`sasl': NICK PASSWORD
+ `certfp': KEY CERT
Examples:
((\"Libera.Chat\" nickserv \"bob\" \"p455w0rd\")
(\"Libera.Chat\" chanserv \"bob\" \"#bobland\" \"passwd99\")
+ (\"Libera.Chat\" certfp \"/path/to/key.pem\" \"/path/to/cert.pem\")
(\"bitlbee\" bitlbee \"robert\" \"sekrit\")
(\"dal.net\" nickserv \"bob\" \"sekrit\" \"NickServ@services.dal.net\")
(\"quakenet.org\" quakenet \"bobby\" \"sekrit\")
@@ -291,7 +293,11 @@ Examples:
(list :tag "SASL"
(const sasl)
(string :tag "Nick")
- (string :tag "Password")))))
+ (string :tag "Password"))
+ (list :tag "CertFP"
+ (const certfp)
+ (string :tag "Key")
+ (string :tag "Certificate")))))
(defcustom rcirc-auto-authenticate-flag t
"Non-nil means automatically send authentication string to server.
@@ -547,6 +553,9 @@ If ARG is non-nil, instead prompt for connection
parameters."
(password (plist-get (cdr c) :password))
(encryption (plist-get (cdr c) :encryption))
(server-alias (plist-get (cdr c) :server-alias))
+ (client-cert (when (eq (rcirc-get-server-method (car c))
+ 'certfp)
+ (rcirc-get-server-cert (car c))))
contact)
(when-let (((not password))
(auth (auth-source-search :host server
@@ -563,7 +572,7 @@ If ARG is non-nil, instead prompt for connection
parameters."
(condition-case nil
(let ((process (rcirc-connect server port nick user-name
full-name channels
password encryption
- server-alias)))
+ client-cert server-alias)))
(when rcirc-display-server-buffer
(pop-to-buffer-same-window (process-buffer
process))))
(quit (message "Quit connecting to %s"
@@ -662,13 +671,22 @@ See `rcirc-connect' for more details on these variables.")
(when (string-match server-i server)
(throw 'pass (car args)))))))
+(defun rcirc-get-server-cert (server)
+ "Return a list of key and certificate for SERVER."
+ (catch 'pass
+ (dolist (i rcirc-authinfo)
+ (let ((server-i (car i))
+ (args (cddr i)))
+ (when (string-match server-i server)
+ (throw 'pass args))))))
+
;;;###autoload
(defun rcirc-connect (server &optional port nick user-name
full-name startup-channels password encryption
- server-alias)
+ certfp server-alias)
"Connect to SERVER.
The arguments PORT, NICK, USER-NAME, FULL-NAME, PASSWORD,
-ENCRYPTION, SERVER-ALIAS are interpreted as in
+ENCRYPTION, CERTFP, SERVER-ALIAS are interpreted as in
`rcirc-server-alist'. STARTUP-CHANNELS is a list of channels
that are joined after authentication."
(save-excursion
@@ -692,10 +710,16 @@ that are joined after authentication."
(delete-process process))
;; Set up process
- (setq process (open-network-stream
- (or server-alias server) nil server port-number
- :type (or encryption 'plain)
- :nowait t))
+ (setq process (if certfp
+ (open-network-stream
+ (or server-alias server) nil server port-number
+ :type 'tls
+ :nowait t
+ :client-certificate certfp)
+ (open-network-stream
+ (or server-alias server) nil server port-number
+ :type (or encryption 'plain)
+ :nowait t)))
(set-process-coding-system process 'raw-text 'raw-text)
(with-current-buffer (get-buffer-create (rcirc-generate-new-buffer-name
process nil))
(set-process-buffer process (current-buffer))
- [RFC] certfp for rcirc,
Omar Polo <=