From f3e736b6fbc163d725230c18d3f44b66963644c0 Mon Sep 17 00:00:00 2001 From: James Lu Date: Thu, 19 Mar 2015 16:21:49 -0700 Subject: [PATCH] Add an inspircd protocol module - still a WIP --- config.yml.example | 5 ++++ protocols/inspircd.py | 66 +++++++++++++++++++++++++++++++++++++++++++ pylink-main.py | 1 + 3 files changed, 72 insertions(+) create mode 100644 protocols/inspircd.py diff --git a/config.yml.example b/config.yml.example index 37b13c7..6963fe6 100644 --- a/config.yml.example +++ b/config.yml.example @@ -16,5 +16,10 @@ networks: port: 6667 recvpass: "abcdefg" sendpass: "gfedcba" + # Hostname we will use to connect to the remote server + hostname: "pylink.overdrive.pw" + # SID - required for InspIRCd and TS6 based servers. This must be three characters long. + # The first char must be a digit [0-9], and the remaining two chars may be letters [A-Z] or digits. + sid: "0AL" # Set protocol module (currently only a null stub is available, but this will change in the future) protocol: stub diff --git a/protocols/inspircd.py b/protocols/inspircd.py new file mode 100644 index 0000000..160b8a9 --- /dev/null +++ b/protocols/inspircd.py @@ -0,0 +1,66 @@ +import threading +import socket +import time +import re + +class AuthenticationError: + pass + +class InspircdHandler(threading.Thread): + + def __init__(self, name, serverdata): + threading.Thread.__init__(self) + self.name = name + self.authenticated = False + self.connected = False + self.serverdata = serverdata + ip = self.serverdata["ip"] + port = self.serverdata["port"] + self.sid = self.serverdata["sid"] + self.socket = socket.socket() + self.socket.connect((ip, port)) + print("[+] New thread started for %s:%s" % (ip, port)) + self.authenticate(serverdata) + self.listen() + + def send(self, data): + data = data.encode("utf-8") + b"\n" + print("-> {}".format(data.decode("utf-8").strip("\n"))) + self.socket.send(data) + + def authenticate(self, serverdata): + f = self.send + f('CAPAB START 1202') + f('CAPAB CAPABILITIES :NICKMAX=32 HALFOP=0 CHANMAX=65 MAXMODES=20 IDENTMAX=12 MAXQUIT=255 PROTOCOL=1203') + f('CAPAB END') + f('SERVER %s %s 0 %s :PyLink Service' % (self.serverdata["hostname"], + serverdata["sendpass"], self.sid)) + f(':%s BURST %s' % (self.sid, int(time.time()))) + # :751 UID 751AAAAAA 1220196319 Brain brainwave.brainbox.cc netadmin.chatspike.net brain 192.168.1.10 1220196324 +Siosw +ACKNOQcdfgklnoqtx :Craig Edwards + f(":{sid} UID {sid}AAAAAA {ts} PyLink {host} {host} pylink 127.0.0.1 {ts} +o + :PyLink Client".format(sid=self.sid, + ts=int(time.time()), host=self.serverdata["hostname"])) + f(':%s ENDBURST' % (self.sid)) + # :7NU PING 7NU 0AL + def handle_ping(self, data): + m = re.search('\:(\d[A-Z0-9]{1,2}) PING (\d[A-Z0-9]{1,2}) %s' % self.sid, data) + if m: + self.send(':%s PONG %s' % (self.sid, m.group(0))) + + def listen(self): + while True: + data = self.socket.recv(2048) + if not data: + print("Connection reset.") + break + try: + buf = data.decode("utf-8") + for line in buf.split("\n"): + print("<- {}".format(line)) + self.handle_ping(line) + except socket.error as e: + print("%s: Received socket error: '%s', aborting! =X=" % (self.name, e)) + break + +def connect(name, serverdata): + s = InspircdHandler(name, serverdata) + s.start() diff --git a/pylink-main.py b/pylink-main.py index 62c57bc..e5fc6a4 100755 --- a/pylink-main.py +++ b/pylink-main.py @@ -17,6 +17,7 @@ networkobjects = {} class irc: def __init__(self, network): + self.connected = False self.netname = network self.networkdata = conf['networks'][network] protoname = self.networkdata['protocol']