unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* [RFC] certfp for rcirc
@ 2021-11-11  9:02 Omar Polo
  2021-11-14 18:25 ` Philip Kaludercic
  0 siblings, 1 reply; 8+ messages in thread
From: Omar Polo @ 2021-11-11  9:02 UTC (permalink / raw)
  To: Emacs developers

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))



^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2021-11-21 18:01 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-11  9:02 [RFC] certfp for rcirc Omar Polo
2021-11-14 18:25 ` Philip Kaludercic
2021-11-14 18:36   ` Omar Polo
2021-11-15 18:02   ` Omar Polo
2021-11-15 21:49     ` Omar Polo
2021-11-16  7:42       ` Lars Ingebrigtsen
2021-11-17 20:23       ` Philip Kaludercic
2021-11-21 18:01       ` Philip Kaludercic

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).