From 81e2668d2d20025c38f780b9238e722f5d4e0317 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Mon, 12 Dec 2022 23:58:03 -0800 Subject: [PATCH 5/5] Add escape hatch for picky servers in erc-sasl * lisp/erc/erc-sasl.el (erc-sasl--send-cap-ls): Add internal switch to toggle feigning better support for IRCv3 capability negotiation by sending an opening "CAP LS" and holding off on the "CAP REQ" until after "USER". (erc--register-connection): Possibly send a "CAP LS" before anything. Also, don't attempt to send `erc-session-username' when it holds an SASL username because the latter may contain protocol-defying characters. * test/lisp/erc/resources/base/local-modules/fourth.eld: change user parameter of "USER" command to reflect nick when `erc-sasl-user' is set to `:user'. (Bug#59976.) --- lisp/erc/erc-sasl.el | 33 +++++++++++++++---- .../resources/base/local-modules/fourth.eld | 2 +- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/lisp/erc/erc-sasl.el b/lisp/erc/erc-sasl.el index 5b2c93988a..9486250529 100644 --- a/lisp/erc/erc-sasl.el +++ b/lisp/erc/erc-sasl.el @@ -414,17 +414,38 @@ erc-sasl--destroy " ")) (erc-sasl--destroy proc)) +;; The rationale for not enabling this by default is twofold: +;; +;; - It more strongly implies that ERC supports client capability +;; negotiation, which is therefore more disingenuous. +;; +;; - We'd still be "faking it" by firing and forgetting, and more +;; balls in the air makes things less predictable. + +(defvar erc-sasl--send-cap-ls nil + "Whether to send an opening \"CAP LS\" command. +This is an escape hatch for picky servers expecting this command. +If you need this, please let us know via \\[erc-bug], so we can +offer a user option instead.") + (cl-defmethod erc--register-connection (&context (erc-sasl-mode (eql t))) - "Send speculative/pipelined CAP and AUTHENTICATE and hope for the best." + "Send speculative CAP and pipelined AUTHENTICATE and hope for the best." (if-let* ((c (erc-sasl--state-client erc-sasl--state)) (m (sasl-mechanism-name (sasl-client-mechanism c)))) (progn - (erc-server-send "CAP REQ :sasl") - (if (and erc-session-password - (eq :password (alist-get 'password erc-sasl--options))) - (let (erc-session-password) - (erc-login)) + (erc-server-send (if erc-sasl--send-cap-ls "CAP LS" "CAP REQ :sasl")) + (let ((erc-session-password + (and erc-session-password + (not (eq :password (alist-get 'password erc-sasl--options))) + erc-session-password)) + (erc-session-username + ;; The username may contain a colon or a space + (if (eq :user (alist-get 'user erc-sasl--options)) + (erc-current-nick) + erc-session-username))) (erc-login)) + (when erc-sasl--send-cap-ls + (erc-server-send "CAP REQ :sasl")) (erc-server-send (format "AUTHENTICATE %s" m))) (erc-sasl--destroy erc-server-process))) diff --git a/test/lisp/erc/resources/base/local-modules/fourth.eld b/test/lisp/erc/resources/base/local-modules/fourth.eld index fd6d62b6cc..4ac5dcbd38 100644 --- a/test/lisp/erc/resources/base/local-modules/fourth.eld +++ b/test/lisp/erc/resources/base/local-modules/fourth.eld @@ -1,7 +1,7 @@ ;; -*- mode: lisp-data; -*- ((cap 10 "CAP REQ :sasl")) ((nick 10 "NICK tester`")) -((user 10 "USER tester 0 * :tester")) +((user 10 "USER tester` 0 * :tester")) ((authenticate 10 "AUTHENTICATE PLAIN") (0.0 ":irc.foonet.org CAP * ACK sasl") -- 2.38.1