Skip to content

Commit e9a880a

Browse files
committed
Add sasl support
1 parent a2e6b24 commit e9a880a

1 file changed

Lines changed: 67 additions & 0 deletions

File tree

plugins/sasl.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import asyncio
2+
import base64
3+
import logging
4+
5+
from cloudbot import hook
6+
7+
logger = logging.getLogger("cloudbot")
8+
9+
10+
@hook.on_cap_available("sasl")
11+
def sasl_available():
12+
pass
13+
14+
15+
@asyncio.coroutine
16+
@hook.on_cap_ack("sasl")
17+
def sasl_ack(conn):
18+
sasl_auth = conn.config.get('sasl')
19+
if sasl_auth:
20+
sasl_mech = sasl_auth.get("mechanism", "PLAIN").upper()
21+
auth_fut = conn.loop.create_future()
22+
conn.memory["sasl_auth_future"] = auth_fut
23+
conn.cmd("AUTHENTICATE", sasl_mech)
24+
cmd, arg = yield from auth_fut
25+
if cmd == "908":
26+
logger.warning("[%s|sasl] SASL mechanism not supported", conn.name)
27+
elif cmd == "AUTHENTICATE" and arg[0] == '+':
28+
num_fut = conn.loop.create_future()
29+
conn.memory["sasl_numeric_future"] = num_fut
30+
if sasl_mech == "PLAIN":
31+
auth_str = "{nick}\0{user}\0{passwd}".format(
32+
nick=conn.nick, user=sasl_auth["user"], passwd=sasl_auth["pass"]
33+
).encode()
34+
conn.cmd("AUTHENTICATE", base64.b64encode(auth_str).decode())
35+
else:
36+
conn.cmd("AUTHENTICATE", '+')
37+
numeric = yield from num_fut
38+
if numeric == "902":
39+
logger.warning("[%s|sasl] SASL nick locked", conn.name)
40+
elif numeric == "903":
41+
logger.info("[%s|sasl] SASL auth successful", conn.name)
42+
elif numeric == "904":
43+
logger.warning("[%s|sasl] SASL auth failed", conn.name)
44+
elif numeric == "905":
45+
logger.warning("[%s|sasl] SASL auth too long", conn.name)
46+
elif numeric == "906":
47+
logger.warning("[%s|sasl] SASL auth aborted", conn.name)
48+
elif numeric == "907":
49+
logger.warning(
50+
"[%s|sasl] SASL auth already completed", conn.name
51+
)
52+
53+
54+
@asyncio.coroutine
55+
@hook.irc_raw(["AUTHENTICATE", "908"])
56+
def auth(irc_command, conn, irc_paramlist):
57+
future = conn.memory.get("sasl_auth_future")
58+
if future and not future.done():
59+
future.set_result((irc_command, irc_paramlist))
60+
61+
62+
@asyncio.coroutine
63+
@hook.irc_raw(["902", "903", "904", "905", "906", "907"])
64+
def sasl_numerics(irc_command, conn):
65+
future = conn.memory.get("sasl_numeric_future")
66+
if future and not future.done():
67+
future.set_result(irc_command)

0 commit comments

Comments
 (0)