diff options
author | Matt Arnold | 2025-02-20 20:08:19 -0500 |
---|---|---|
committer | Matt Arnold | 2025-02-20 20:08:19 -0500 |
commit | 5667670e4a28613bdc8689481d08eaf54e945f3e (patch) | |
tree | 11afa4505e9907884d36d9c4c4fa8615e0749fc6 | |
parent | 3b9cdc51408d15c5efebc006ccb1c075282a6a71 (diff) |
Add SASL auth
-rw-r--r-- | IRC.py | 60 |
1 files changed, 53 insertions, 7 deletions
diff --git a/IRC.py b/IRC.py index c26d18e..5f8d09e 100644 --- a/IRC.py +++ b/IRC.py @@ -4,6 +4,37 @@ import socket import sys import irctokens import time +import base64 + + +def create_sasl_plain_auth(username, password): + # per KICL this is the valid way to do it + auth_string = f"{username}\x00{username}\x00{password}" + auth_bytes = auth_string.encode("utf-8") + base64_auth = base64.b64encode(auth_bytes).decode("utf-8") + + return base64_auth + + +def decode_sasl_plain_auth(base64_auth): + """ + Decode a SASL PLAIN authentication string for verification. + + Args: + base64_auth (str): Base64 encoded SASL PLAIN authentication string + + Returns: + tuple: (authorization_identity, username, password) + """ + # Decode base64 + auth_bytes = base64.b64decode(base64_auth) + auth_string = auth_bytes.decode("utf-8") + + # Split on null bytes + parts = auth_string.split("\x00") + + # Return the three components + return tuple(parts) class IRCBadMessage(Exception): @@ -54,6 +85,7 @@ class IRCBot: if not self.connected: raise IRCError("Not Connected") encmsg = bytes(line.format() + LINEEND, "UTF-8") + printred(encmsg) expected = len(encmsg) if self.irc.send(encmsg) == expected: return str(encmsg) @@ -61,7 +93,7 @@ class IRCBot: raise IRCError("Unexpected Send Length") def on_welcome(self, *args, **kwargs): - authmsg = irctokens.build("NICKSERV", ["IDENTIFY", self.config["nickpass"]]) + authmsg = irctokens.build("NICKSERV", ["SET", "autoreplay-lines", "0"]) self.send_cmd(authmsg) joinmsg = irctokens.build("JOIN", [self.config["channel"]]) self.send_cmd(joinmsg) @@ -89,14 +121,28 @@ class IRCBot: print("Connecting to: " + server) self.irc.connect((self.config["hostname"], self.config["port"])) self.connected = True + # perform SASL + caps_msg = irctokens.build("CAP", ["REQ", "sasl"]) + printred(caps_msg) + self.send_cmd(caps_msg) # Perform user registration - password_msg = irctokens.build("PASS", [self.config["nickpass"]]).format() - print(password_msg) - - usermsg = irctokens.build("USER", [botnick, "0", "*", "frog"]).format() + cap = irctokens.build("CAP", ["LS", "302"]) + self.send_cmd(cap) + password_msg = irctokens.build("PASS", [self.config["nickpass"]]) + printred(password_msg) + token = create_sasl_plain_auth(botnick, botnickpass) + usermsg = irctokens.build("USER", [botnick, "0", "*", "frog"]) + auth = irctokens.build("AUTHENTICATE", ["PLAIN"]) + self.send_cmd(auth) + # auth_st2 = irctokens.build("AUTHENTICATE", ["+"]) + # self.send_cmd(auth_st2) + auth_st3 = irctokens.build("AUTHENTICATE", [token]) + self.send_cmd(auth_st3) + cmd = irctokens.build("CAP", ["END"]) + self.send_cmd(cmd) print(usermsg) - self.send_cmd(password_msg) + # s#elf.send_cmd(password_msg) nickmsg = irctokens.build("NICK", [botnick]).format() print(nickmsg) self.send_cmd(nickmsg) @@ -114,6 +160,6 @@ class IRCBot: raise IRCError(str(nwmsg.params[0])) if nwmsg.command == "PING": print("Sending pong") - self.irc.send(bytes("PONG " + LINEEND, "UTF-8")) + self.irc.send(bytes("PONG " + nwmsg.params[0] + LINEEND, "UTF-8")) return msg |