home · contact · privacy
Fix broken SASL negotation, add 900 handler.
authorChristian Heller <c.heller@plomlompom.de>
Mon, 18 Aug 2025 18:36:50 +0000 (20:36 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Mon, 18 Aug 2025 18:36:50 +0000 (20:36 +0200)
ircplom/client.py

index 16e935a9baa9871f001918997f37fc89f1880942..98111abc8bd1d1231366cdcaff0ca03630bacce3 100644 (file)
@@ -26,6 +26,9 @@ _NUMERICS_TO_CONFIRM_NICKNAME = (
     372,
     (375, 376),
     396,
+    900,
+    903,
+    904
 )
 _NUMERICS_TO_IGNORE = (
     (1, 4),      # nothing in this login info we're interested in
@@ -381,8 +384,10 @@ class SharedClientDbFields(IrcConnSetup):
     connection_state: str
     client_host: str
     nickname: str
+    sasl_account: str
     sasl_auth_state: str
     user_modes: str
+    username: str = ''
 
 
 class _ClientDb(_Db, SharedClientDbFields):
@@ -440,6 +445,7 @@ class Client(ABC, ClientQueueMixin):
         self.client_id = conn_setup.hostname
         super().__init__(client_id=self.client_id, **kwargs)
         self._db = _ClientDb(on_update=self._on_update)
+        self._db.username = getuser()
         self._caps = _CapsManager(self.send, self._db.caps)
         for k in conn_setup.__annotations__:
             setattr(self._db, k, getattr(conn_setup, k))
@@ -474,8 +480,8 @@ class Client(ABC, ClientQueueMixin):
         assert self.conn is not None
         self._db.connection_state = 'connected'
         self._caps.start_negotation()
-        self.send(IrcMessage(verb='USER',
-                             params=(getuser(), '0', '*', self._db.realname)))
+        self.send(IrcMessage(verb='USER', params=(self._db.username, '0', '*',
+                                                  self._db.realname)))
         self.send(IrcMessage(verb='NICK', params=(self._db.nick_wanted,)))
 
     @abstractmethod
@@ -549,12 +555,17 @@ class Client(ABC, ClientQueueMixin):
         elif msg.match('433', 3):  # ERR_NICKNAMEINUSE
             self._log('nickname already in use, trying increment', alert=True)
             self.set_nick(self._db.nick_incremented)
-        elif msg.match('903', 2) or msg.match('904', 2):  # RPL_SUCESS, or …
+        elif msg.match('900', 4):  # RPL_LOGGEDIN
+            nick, remainder = msg.params[1].split('!', maxsplit=1)
+            assert nick == self._db.nickname
+            self._db.username, self._db.client_host = remainder.split('@')
+            self._db.sasl_account = msg.params[2]
+        elif msg.match('903', 2) or msg.match('904', 2):  # RPL_SASLSUCCESS, …
             self._db.sasl_auth_state = 'WIN' if msg.verb == '903' else 'FAIL'
-            self._caps.end_negotiation()                  # … ERR_SASLFAIL
+            self._caps.end_negotiation()                  # … or ERR_SASLFAIL
         elif msg.match('AUTHENTICATE') and msg.params[0] == '+':
-            auth = b64encode((self._db.nickname + '\0'
-                              + self._db.nickname + '\0'
+            auth = b64encode((self._db.nick_wanted + '\0'
+                              + self._db.nick_wanted + '\0'
                               + self._db.password
                               ).encode('utf-8')).decode('utf-8')
             self.send(IrcMessage('AUTHENTICATE', (auth,)))