From 0d5f3f8761ec2535a90425212e96fcf1228c3dab Mon Sep 17 00:00:00 2001 From: Russ Garrett Date: Sun, 23 May 2021 17:25:20 +0100 Subject: [PATCH] Don't send CAP END before SASL auth is complete This is "RECOMMENDED" in the SASL-3.1 spec, and I've found the previous behaviour to be intermittent in practice. --- asyncirc/protocol.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/asyncirc/protocol.py b/asyncirc/protocol.py index 067f435..7fbc7d4 100644 --- a/asyncirc/protocol.py +++ b/asyncirc/protocol.py @@ -63,8 +63,13 @@ async def _internal_cap_handler(conn: 'IrcProtocol', message: 'Message'): if enabled: handlers = filter(None, conn.cap_handlers[cap.name]) await asyncio.gather(*[func(conn, cap) for func in handlers]) + if all(val[1] is not None for val in conn.server.caps.values()): - conn.send("CAP END") + # If SASL is enabled, SASL negotiation should be complete before sending CAP END, + # so this is done in the SASL handler. + if conn.sasl_mech == SASLMechanism.NONE: + conn.send("CAP END") + elif message.parameters[1] == 'LIST': if conn.logger: conn.logger.info("Current Capabilities: %s", caplist) @@ -117,6 +122,11 @@ async def _do_sasl(conn: 'IrcProtocol', cap): # TODO log SASL response await conn.wait_for('902', '903', '904', '905', '906', '907', '908', timeout=30) + # Send CAP END here, because it shouldn't be sent before SASL auth is complete + # NOTE: there is a (probably unlikely) race condition here, if CAP negotiation is + # incomplete by this point. + conn.send("CAP END") + async def _isupport_handler(conn: 'IrcProtocol', message: 'Message'): tokens = message.parameters[1:-1] # Remove the nick and trailing ':are supported by this server' message