Fix capability negotiation to be more sane (and IRCv3.2-compliant)

This commit is contained in:
nyuszika7h 2015-06-15 20:20:28 +02:00
parent 1a506907c9
commit 452c1b1ede
2 changed files with 46 additions and 21 deletions

View File

@ -186,19 +186,15 @@ class IRCClient(object):
if not self.blocking:
self.socket.setblocking(0)
self.cap("LS", "302")
if not self.sasl_auth:
self.send("PASS {0}:{1}".format(self.authname if self.authname else self.nickname,
self.password if self.password else "NOPASS"))
else:
self.cap("LS")
self.nick(self.nickname)
self.user(self.ident, self.real_name)
if self.sasl_auth:
self.cap("REQ", "multi-prefix")
self.cap("REQ", "sasl")
if self.connect_cb:
try:
self.connect_cb(self)

View File

@ -143,23 +143,52 @@ def connect_callback(cli):
hook("unavailresource")(mustrelease)
hook("nicknameinuse")(mustregain)
if botconfig.SASL_AUTHENTICATION:
request_caps = {"account-notify", "extended-join", "multi-prefix"}
if botconfig.SASL_AUTHENTICATION:
request_caps.add("sasl")
supported_caps = set()
@hook("cap")
def on_cap(cli, svr, mynick, cmd, caps, star=None):
if cmd == "LS":
if caps == "*":
# Multi-line LS
supported_caps.update(star.split())
else:
supported_caps.update(caps.split())
print(supported_caps)
if botconfig.SASL_AUTHENTICATION and "sasl" not in supported_caps:
alog("Server does not support SASL authentication")
cli.quit()
common_caps = request_caps & supported_caps
if common_caps:
cli.cap("REQ", ":{0}".format(" ".join(common_caps)))
elif cmd == "ACK":
if "sasl" in caps:
cli.send("AUTHENTICATE PLAIN")
else:
cli.cap("END")
elif cmd == "NAK":
# This isn't supposed to happen. The server claimed to support a
# capability but now claims otherwise.
alog("Server refused capabilities: {0}".format(" ".join(caps)))
if botconfig.SASL_AUTHENTICATION:
@hook("authenticate")
def auth_plus(cli, something, plus):
if plus == "+":
nick_b = bytes(botconfig.USERNAME if botconfig.USERNAME else botconfig.NICK, "utf-8")
pass_b = bytes(botconfig.PASS, "utf-8")
secrt_msg = b'\0'.join((nick_b, nick_b, pass_b))
cli.send("AUTHENTICATE " + base64.b64encode(secrt_msg).decode("utf-8"))
@hook("cap")
def on_cap(cli, svr, mynick, ack, cap):
if ack.upper() == "ACK" and "sasl" in cap:
cli.send("AUTHENTICATE PLAIN")
elif ack.upper() == "NAK" and "sasl" in cap:
cli.quit()
alog("Server does not support SASL authentication")
account = (botconfig.USERNAME or botconfig.NICK).encode("utf-8")
password = botconfig.PASS.encode("utf-8")
auth_token = base64.b64encode(b"\0".join((account, account, password))).decode("utf-8")
cli.send("AUTHENTICATE " + auth_token)
@hook("903")
def on_successful_auth(cli, blah, blahh, blahhh):
@ -170,9 +199,9 @@ def connect_callback(cli):
@hook("906")
@hook("907")
def on_failure_auth(cli, *etc):
alog("Authentication failed. Did you fill the account name "
"in botconfig.USERNAME if it's different from the bot nick?")
cli.quit()
alog("Authentication failed. Did you fill the account name "+
"in botconfig.USERNAME if it's different from the bot nick?")