Implement the backend for automatically provisioning relays
This commit is contained in:
parent
6046329a83
commit
4efea3f535
|
@ -10,5 +10,6 @@ conf/masterbuf.json
|
||||||
conf/monitor.json
|
conf/monitor.json
|
||||||
conf/alias.json
|
conf/alias.json
|
||||||
conf/relay.json
|
conf/relay.json
|
||||||
|
conf/network.json
|
||||||
conf/dist.sh
|
conf/dist.sh
|
||||||
env/
|
env/
|
||||||
|
|
|
@ -7,15 +7,17 @@ class Alias:
|
||||||
|
|
||||||
def alias(self, addr, authed, data, obj, spl, success, failure, info, incUsage, length):
|
def alias(self, addr, authed, data, obj, spl, success, failure, info, incUsage, length):
|
||||||
if authed:
|
if authed:
|
||||||
if length == 6:
|
if length == 8:
|
||||||
if spl[1] == "add":
|
if spl[1] == "add":
|
||||||
if spl[2] in main.alias.keys():
|
if spl[2] in main.alias.keys():
|
||||||
failure("Alias already exists: %s" % spl[2])
|
failure("Alias already exists: %s" % spl[2])
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
main.alias[spl[2]] = {"nick": spl[3],
|
main.alias[spl[2]] = {"nick": spl[3],
|
||||||
"ident": spl[4],
|
"altnick": spl[4],
|
||||||
"realname": spl[5]}
|
"ident": spl[5],
|
||||||
|
"realname": spl[6],
|
||||||
|
"password": spl[7]}
|
||||||
success("Successfully created alias: %s" % spl[2])
|
success("Successfully created alias: %s" % spl[2])
|
||||||
main.saveConf("alias")
|
main.saveConf("alias")
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,80 +0,0 @@
|
||||||
import main
|
|
||||||
|
|
||||||
class Default:
|
|
||||||
def __init__(self, register):
|
|
||||||
register("default", self.default)
|
|
||||||
|
|
||||||
def default(self, addr, authed, data, obj, spl, success, failure, info, incUsage, length):
|
|
||||||
if authed:
|
|
||||||
toUnset = False
|
|
||||||
if length == 1:
|
|
||||||
optionMap = ["Viewing defaults"]
|
|
||||||
for i in main.config["Default"].keys():
|
|
||||||
optionMap.append("%s: %s" % (i, main.config["Default"][i]))
|
|
||||||
info("\n".join(optionMap))
|
|
||||||
return
|
|
||||||
elif length == 2:
|
|
||||||
if not spl[1] in main.config["Default"].keys():
|
|
||||||
failure("No such key: %s" % spl[1])
|
|
||||||
return
|
|
||||||
info("%s: %s" % (spl[1], main.config["Default"][spl[1]]))
|
|
||||||
return
|
|
||||||
elif length == 3:
|
|
||||||
if not spl[1] in main.config["Default"].keys():
|
|
||||||
failure("No such key: %s" % spl[1])
|
|
||||||
return
|
|
||||||
|
|
||||||
if spl[2].lower() in ["none", "nil"]:
|
|
||||||
spl[2] = None
|
|
||||||
toUnset = True
|
|
||||||
|
|
||||||
if spl[1] in ["port", "timeout", "maxdelay"]:
|
|
||||||
try:
|
|
||||||
spl[2] = int(spl[2])
|
|
||||||
except:
|
|
||||||
failure("Value must be an integer, not %s" % spl[2])
|
|
||||||
return
|
|
||||||
|
|
||||||
if spl[2] in ["initialdelay", "factor", "jitter"]:
|
|
||||||
try:
|
|
||||||
spl[3] = float(spl[3])
|
|
||||||
except:
|
|
||||||
failure("Value must be a floating point integer, not %s" % spl[3])
|
|
||||||
return
|
|
||||||
|
|
||||||
if spl[1] == "protocol":
|
|
||||||
if not toUnset:
|
|
||||||
if not spl[2] in ["ssl", "plain"]:
|
|
||||||
failure("Protocol must be ssl or plain, not %s" % spl[2])
|
|
||||||
return
|
|
||||||
|
|
||||||
if spl[2] == main.config["Default"][spl[1]]:
|
|
||||||
failure("Value already exists: %s" % spl[2])
|
|
||||||
return
|
|
||||||
|
|
||||||
if spl[1] == "authtype":
|
|
||||||
if not toUnset:
|
|
||||||
if not spl[2] in ["sp", "ns"]:
|
|
||||||
failure("Authtype must be sp or ns, not %s" % spl[2])
|
|
||||||
return
|
|
||||||
if spl[1] == "enabled":
|
|
||||||
failure("Use the ConnectOnCreate main.config parameter to set this")
|
|
||||||
return
|
|
||||||
if spl[1] == "autojoin":
|
|
||||||
if not toUnset:
|
|
||||||
spl[2] = spl[2].split(",")
|
|
||||||
else:
|
|
||||||
spl[2] = []
|
|
||||||
|
|
||||||
main.config["Default"][spl[1]] = spl[2]
|
|
||||||
main.saveConf("config")
|
|
||||||
if toUnset:
|
|
||||||
success("Successfully unset key %s" % spl[1])
|
|
||||||
else:
|
|
||||||
success("Successfully set key %s to %s" % (spl[1], spl[2]))
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
incUsage("default")
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
incUsage(None)
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
import main
|
||||||
|
from yaml import dump
|
||||||
|
|
||||||
|
class Network:
|
||||||
|
def __init__(self, register):
|
||||||
|
register("network", self.network)
|
||||||
|
|
||||||
|
def network(self, addr, authed, data, obj, spl, success, failure, info, incUsage, length):
|
||||||
|
if authed:
|
||||||
|
if length == 7:
|
||||||
|
if spl[1] == "add":
|
||||||
|
if spl[2] in main.network.keys():
|
||||||
|
failure("Network already exists: %s" % spl[2])
|
||||||
|
return
|
||||||
|
if not spl[4].isdigit():
|
||||||
|
failure("Port must be an integer, not %s" % spl[4])
|
||||||
|
return
|
||||||
|
if not spl[5].lower() in ["ssl", "plain"]:
|
||||||
|
failure("Security must be ssl or plain, not %s" % spl[5])
|
||||||
|
return
|
||||||
|
if not spl[6].lower() in ["sasl", "ns", "none"]:
|
||||||
|
failure("Auth must be sasl, ns or none, not %s" % spl[5])
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
main.network[spl[2]] = {"host": spl[3],
|
||||||
|
"port": spl[4],
|
||||||
|
"security": spl[5].lower(),
|
||||||
|
"auth": spl[6].lower()}
|
||||||
|
success("Successfully created network: %s" % spl[2])
|
||||||
|
main.saveConf("network")
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
incUsage("network")
|
||||||
|
return
|
||||||
|
|
||||||
|
elif length == 3:
|
||||||
|
if spl[1] == "del":
|
||||||
|
if spl[2] in main.network.keys():
|
||||||
|
del main.network[spl[2]]
|
||||||
|
success("Successfully removed network: %s" % spl[2])
|
||||||
|
main.saveConf("network")
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
failure("No such network: %s" % spl[2])
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
incUsage("network")
|
||||||
|
return
|
||||||
|
elif length == 2:
|
||||||
|
if spl[1] == "list":
|
||||||
|
info(dump(main.network))
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
incUsage("network")
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
incUsage("network")
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
incUsage(None)
|
|
@ -0,0 +1,59 @@
|
||||||
|
import main
|
||||||
|
from modules import provision
|
||||||
|
|
||||||
|
class Provision:
|
||||||
|
def __init__(self, register):
|
||||||
|
register("provision", self.provision)
|
||||||
|
|
||||||
|
def provision(self, addr, authed, data, obj, spl, success, failure, info, incUsage, length):
|
||||||
|
if authed:
|
||||||
|
if length == 4 or length == 3:
|
||||||
|
if not spl[1] in main.relay.keys():
|
||||||
|
failure("No such relay: %s" % spl[1])
|
||||||
|
return
|
||||||
|
if not spl[2] in main.alias.keys():
|
||||||
|
failure("No such alias: %s" % spl[2])
|
||||||
|
return
|
||||||
|
if length == 4: # provision for relay, alias and network
|
||||||
|
if not spl[3] in main.network.keys():
|
||||||
|
failure("No such network: %s" % spl[3])
|
||||||
|
return
|
||||||
|
|
||||||
|
if "users" in main.relay[spl[1]]:
|
||||||
|
if not spl[2] in main.relay[spl[1]]["users"]:
|
||||||
|
failure("Relay %s not provisioned for alias %s" % (spl[1], spl[2]))
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
failure("Relay %s not provisioned for alias %s" % (spl[1], spl[2]))
|
||||||
|
return
|
||||||
|
|
||||||
|
rtrn = provision.provisionRelayForNetwork(spl[1], spl[2], spl[3])
|
||||||
|
if rtrn == "PROVISIONED":
|
||||||
|
failure("Relay %s already provisioned for network %s" % (spl[1], spl[3]))
|
||||||
|
return
|
||||||
|
elif rtrn == "DUPLICATE":
|
||||||
|
failure("Instance with relay %s and alias %s already exists for network %s" % (spl[1], spl[2], spl[3]))
|
||||||
|
elif rtrn:
|
||||||
|
success("Started provisioning network %s on relay %s for alias %s" % (spl[3], spl[1], spl[2]))
|
||||||
|
info("Instance name is %s" % rtrn)
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
failure("Failure while provisioning relay %s" % spl[1])
|
||||||
|
return
|
||||||
|
if length == 3: # provision for relay and alias only
|
||||||
|
rtrn = provision.provisionRelayForAlias(spl[1], spl[2])
|
||||||
|
if rtrn == "PROVISIONED":
|
||||||
|
failure("Relay %s already provisioned for alias %s" % (spl[1], spl[2]))
|
||||||
|
return
|
||||||
|
elif rtrn:
|
||||||
|
success("Started provisioning relay %s for alias %s" % (spl[1], spl[2]))
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
failure("Failure while provisioning relay %s" % spl[1])
|
||||||
|
return
|
||||||
|
|
||||||
|
else:
|
||||||
|
incUsage("provision")
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
incUsage(None)
|
|
@ -12,10 +12,10 @@ class Relay:
|
||||||
if spl[2] in main.relay.keys():
|
if spl[2] in main.relay.keys():
|
||||||
failure("Relay already exists: %s" % spl[2])
|
failure("Relay already exists: %s" % spl[2])
|
||||||
return
|
return
|
||||||
|
if not spl[4].isdigit():
|
||||||
|
failure("Port must be an integer, not %s" % spl[4])
|
||||||
|
return
|
||||||
else:
|
else:
|
||||||
if not spl[4].isdigit():
|
|
||||||
failure("Port must be an integer, not %s" % spl[4])
|
|
||||||
return
|
|
||||||
main.relay[spl[2]] = {"host": spl[3],
|
main.relay[spl[2]] = {"host": spl[3],
|
||||||
"port": spl[4],
|
"port": spl[4],
|
||||||
"user": spl[5],
|
"user": spl[5],
|
||||||
|
|
|
@ -2,13 +2,14 @@
|
||||||
"Listener": {
|
"Listener": {
|
||||||
"Port": 13867,
|
"Port": 13867,
|
||||||
"Address": "127.0.0.1",
|
"Address": "127.0.0.1",
|
||||||
"UseSSL": true,
|
"UseSSL": true
|
||||||
"Key": "key.pem",
|
|
||||||
"Certificate": "cert.pem"
|
|
||||||
},
|
},
|
||||||
|
"Key": "key.pem",
|
||||||
|
"Certificate": "cert.pem",
|
||||||
"RedisSocket": "/tmp/redis.sock",
|
"RedisSocket": "/tmp/redis.sock",
|
||||||
"UsePassword": true,
|
"UsePassword": true,
|
||||||
"ConnectOnCreate": false,
|
"ConnectOnCreate": false,
|
||||||
|
"RelayPassword": "s",
|
||||||
"Notifications": {
|
"Notifications": {
|
||||||
"Highlight": true,
|
"Highlight": true,
|
||||||
"Connection": true,
|
"Connection": true,
|
||||||
|
@ -29,32 +30,13 @@
|
||||||
},
|
},
|
||||||
"Delays": {
|
"Delays": {
|
||||||
"WhoLoop": 600,
|
"WhoLoop": 600,
|
||||||
"WhoRange": 1800
|
"WhoRange": 1800,
|
||||||
|
"Timeout": 30,
|
||||||
|
"MaxDelay": 360,
|
||||||
|
"InitialDelay": 1.0,
|
||||||
|
"Factor": 2.718281828459045,
|
||||||
|
"Jitter": 0.11962656472
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Default": {
|
|
||||||
"host": null,
|
|
||||||
"port": null,
|
|
||||||
"protocol": "ssl",
|
|
||||||
"bind": null,
|
|
||||||
"timeout": 30,
|
|
||||||
"maxdelay": 360,
|
|
||||||
"initialdelay": 1.0,
|
|
||||||
"factor": 2.7182818284590451,
|
|
||||||
"jitter": 0.11962656472,
|
|
||||||
"nickname": null,
|
|
||||||
"username": null,
|
|
||||||
"realname": null,
|
|
||||||
"userinfo": null,
|
|
||||||
"finger": null,
|
|
||||||
"version": null,
|
|
||||||
"source": null,
|
|
||||||
"autojoin": [],
|
|
||||||
"authtype": null,
|
|
||||||
"password": null,
|
|
||||||
"authentity": "NickServ",
|
|
||||||
"key": "key.pem",
|
|
||||||
"certificate": "cert.pem"
|
|
||||||
},
|
|
||||||
"Master": [null, null]
|
"Master": [null, null]
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
{}
|
|
@ -1,10 +1,8 @@
|
||||||
{
|
{
|
||||||
"pass": "pass <password>",
|
"pass": "pass <password>",
|
||||||
"logout": "logout",
|
"logout": "logout",
|
||||||
"add": "add <name> [<address>] [<port>] [<ssl|plain>] [<nickname>]",
|
|
||||||
"del": "del <name>",
|
"del": "del <name>",
|
||||||
"mod": "mod <name> [<key>] [<value>]",
|
"mod": "mod <name> [<key>] [<value>]",
|
||||||
"default": "default [<key>] [<value>]",
|
|
||||||
"get": "get <name> <variable>",
|
"get": "get <name> <variable>",
|
||||||
"key": "key <master|list|add|del|except|unexcept|listexcept|monitor> [<name>] [<target>] [<key...>] [<on|off>]",
|
"key": "key <master|list|add|del|except|unexcept|listexcept|monitor> [<name>] [<target>] [<key...>] [<on|off>]",
|
||||||
"who": "who <query>",
|
"who": "who <query>",
|
||||||
|
@ -22,6 +20,8 @@
|
||||||
"mon": "mon -h",
|
"mon": "mon -h",
|
||||||
"chans": "chans <nick> [<nick> ...]",
|
"chans": "chans <nick> [<nick> ...]",
|
||||||
"users": "users <channel> [<channel> ...]",
|
"users": "users <channel> [<channel> ...]",
|
||||||
"alias": "alias <add|del|list> [<alias> <nickname> <ident> <realname>]",
|
"alias": "alias <add|del|list> [<alias> <nickname> <altnick> <ident> <realname> <password>]",
|
||||||
"relay": "relay <add|del|list> [<relay> <host> <port> <user> <password>"
|
"relay": "relay <add|del|list> [<relay> <host> <port> <user> <password>]",
|
||||||
|
"network": "network <add|del|list> [<name> <address> <port> <ssl|plain> <sasl|ns|none>]",
|
||||||
|
"provision": "provision <relay> <alias> [<network>]"
|
||||||
}
|
}
|
||||||
|
|
115
core/bot.py
115
core/bot.py
|
@ -1,7 +1,8 @@
|
||||||
from twisted.internet.protocol import ReconnectingClientFactory
|
from twisted.internet.protocol import ReconnectingClientFactory
|
||||||
from twisted.words.protocols.irc import IRCClient
|
from twisted.words.protocols.irc import IRCClient
|
||||||
from twisted.internet.defer import Deferred
|
from twisted.internet.defer import Deferred
|
||||||
from twisted.internet.task import LoopingCall
|
from twisted.internet.task import LoopingCall, deferLater
|
||||||
|
from twisted.internet import reactor
|
||||||
|
|
||||||
from string import digits
|
from string import digits
|
||||||
from random import randint
|
from random import randint
|
||||||
|
@ -15,6 +16,76 @@ import main
|
||||||
from utils.logging.log import *
|
from utils.logging.log import *
|
||||||
from utils.logging.send import *
|
from utils.logging.send import *
|
||||||
|
|
||||||
|
from twisted.internet.ssl import DefaultOpenSSLContextFactory
|
||||||
|
|
||||||
|
def deliverRelayCommands(relay, relayCommands, user=None, stage2=None):
|
||||||
|
keyFN = main.certPath+main.config["Key"]
|
||||||
|
certFN = main.certPath+main.config["Certificate"]
|
||||||
|
contextFactory = DefaultOpenSSLContextFactory(keyFN.encode("utf-8", "replace"),
|
||||||
|
certFN.encode("utf-8", "replace"))
|
||||||
|
bot = IRCBotFactory(None, relay, relayCommands, user, stage2)
|
||||||
|
rct = reactor.connectSSL(main.relay[relay]["host"],
|
||||||
|
int(main.relay[relay]["port"]),
|
||||||
|
bot, contextFactory)
|
||||||
|
|
||||||
|
class IRCRelay(IRCClient):
|
||||||
|
def __init__(self, relay, relayCommands, user, stage2):
|
||||||
|
self.connected = False
|
||||||
|
self.buffer = ""
|
||||||
|
if user == None:
|
||||||
|
self.user = main.relay[relay]["user"]
|
||||||
|
else:
|
||||||
|
self.user = user
|
||||||
|
password = main.relay[relay]["password"]
|
||||||
|
self.nickname = self.user
|
||||||
|
self.realname = self.user
|
||||||
|
self.username = self.user
|
||||||
|
self.password = self.user+":"+password
|
||||||
|
|
||||||
|
self.relayCommands = relayCommands
|
||||||
|
self.relay = relay
|
||||||
|
self.stage2 = stage2
|
||||||
|
|
||||||
|
def parsen(self, user):
|
||||||
|
step = user.split("!")
|
||||||
|
nick = step[0]
|
||||||
|
if len(step) == 2:
|
||||||
|
step2 = step[1].split("@")
|
||||||
|
ident, host = step2
|
||||||
|
else:
|
||||||
|
ident = nick
|
||||||
|
host = nick
|
||||||
|
|
||||||
|
return [nick, ident, host]
|
||||||
|
|
||||||
|
def privmsg(self, user, channel, msg):
|
||||||
|
nick, ident, host = self.parsen(user)
|
||||||
|
if nick[0] == main.config["Tweaks"]["ZNC"]["Prefix"]:
|
||||||
|
nick = nick[1:]
|
||||||
|
if nick in self.relayCommands.keys():
|
||||||
|
sendAll("[%s] %s -> %s" % (self.relay, nick, msg))
|
||||||
|
|
||||||
|
def irc_ERR_PASSWDMISMATCH(self, prefix, params):
|
||||||
|
log("%s: relay password mismatch" % self.relay)
|
||||||
|
sendAll("%s: relay password mismatch" % self.relay)
|
||||||
|
|
||||||
|
def signedOn(self):
|
||||||
|
self.connected = True
|
||||||
|
log("signed on as a relay: %s" % self.relay)
|
||||||
|
if main.config["Notifications"]["Connection"]:
|
||||||
|
keyword.sendMaster("SIGNON: %s" % self.relay)
|
||||||
|
for i in self.relayCommands.keys():
|
||||||
|
for x in self.relayCommands[i]:
|
||||||
|
self.msg(main.config["Tweaks"]["ZNC"]["Prefix"]+i, x)
|
||||||
|
if not self.stage2 == None: # [["user", {"sasl": ["message1", "message2"]}], []]
|
||||||
|
if not len(self.stage2) == 0:
|
||||||
|
user = self.stage2[0].pop(0)
|
||||||
|
commands = self.stage2[0].pop(0)
|
||||||
|
del self.stage2[0]
|
||||||
|
deliverRelayCommands(self.relay, commands, user, self.stage2)
|
||||||
|
deferLater(reactor, 1, self.transport.loseConnection)
|
||||||
|
return
|
||||||
|
|
||||||
class IRCBot(IRCClient):
|
class IRCBot(IRCClient):
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self.connected = False
|
self.connected = False
|
||||||
|
@ -380,33 +451,46 @@ class IRCBot(IRCClient):
|
||||||
monitor.event(self.net, channel, {"type": "mode", "exact": user, "nick": nick, "ident": ident, "host": host, "modes": m, "modeargs": a})
|
monitor.event(self.net, channel, {"type": "mode", "exact": user, "nick": nick, "ident": ident, "host": host, "modes": m, "modeargs": a})
|
||||||
|
|
||||||
class IRCBotFactory(ReconnectingClientFactory):
|
class IRCBotFactory(ReconnectingClientFactory):
|
||||||
def __init__(self, name):
|
def __init__(self, name, relay=None, relayCommands=None, user=None, stage2=None):
|
||||||
self.instance = main.pool[name]
|
if not name == None:
|
||||||
self.name = name
|
self.name = name
|
||||||
self.net = "".join([x for x in self.name if not x in digits])
|
self.instance = main.pool[name]
|
||||||
|
self.net = "".join([x for x in self.name if not x in digits])
|
||||||
|
else:
|
||||||
|
self.name = "Relay to "+relay
|
||||||
self.client = None
|
self.client = None
|
||||||
self.maxDelay = self.instance["maxdelay"]
|
self.maxDelay = main.config["Tweaks"]["Delays"]["MaxDelay"]
|
||||||
self.initialDelay = self.instance["initialdelay"]
|
self.initialDelay = main.config["Tweaks"]["Delays"]["InitialDelay"]
|
||||||
self.factor = self.instance["factor"]
|
self.factor = main.config["Tweaks"]["Delays"]["Factor"]
|
||||||
self.jitter = self.instance["jitter"]
|
self.jitter = main.config["Tweaks"]["Delays"]["Jitter"]
|
||||||
|
|
||||||
|
self.relay, self.relayCommands, self.user, self.stage2 = relay, relayCommands, user, stage2
|
||||||
|
|
||||||
def buildProtocol(self, addr):
|
def buildProtocol(self, addr):
|
||||||
entry = IRCBot(self.name)
|
|
||||||
main.IRCPool[self.name] = entry
|
if self.relay == None:
|
||||||
|
entry = IRCBot(self.name)
|
||||||
|
main.IRCPool[self.name] = entry
|
||||||
|
else:
|
||||||
|
entry = IRCRelay(self.relay, self.relayCommands, self.user, self.stage2)
|
||||||
|
|
||||||
self.client = entry
|
self.client = entry
|
||||||
return entry
|
return entry
|
||||||
|
|
||||||
def clientConnectionLost(self, connector, reason):
|
def clientConnectionLost(self, connector, reason):
|
||||||
userinfo.delNetwork(self.net, self.client.channels)
|
if not self.relay:
|
||||||
|
userinfo.delNetwork(self.net, self.client.channels)
|
||||||
if not self.client == None:
|
if not self.client == None:
|
||||||
self.client.connected = False
|
self.client.connected = False
|
||||||
self.client.channels = []
|
self.client.channels = []
|
||||||
error = reason.getErrorMessage()
|
error = reason.getErrorMessage()
|
||||||
log("%s: connection lost: %s" % (self.name, error))
|
log("%s: connection lost: %s" % (self.name, error))
|
||||||
sendAll("%s: connection lost: %s" % (self.name, error))
|
if not self.relay:
|
||||||
|
sendAll("%s: connection lost: %s" % (self.name, error))
|
||||||
if main.config["Notifications"]["Connection"]:
|
if main.config["Notifications"]["Connection"]:
|
||||||
keyword.sendMaster("CONNLOST %s: %s" % (self.name, error))
|
keyword.sendMaster("CONNLOST %s: %s" % (self.name, error))
|
||||||
self.retry(connector)
|
if not self.relay:
|
||||||
|
self.retry(connector)
|
||||||
#ReconnectingClientFactory.clientConnectionLost(self, connector, reason)
|
#ReconnectingClientFactory.clientConnectionLost(self, connector, reason)
|
||||||
|
|
||||||
def clientConnectionFailed(self, connector, reason):
|
def clientConnectionFailed(self, connector, reason):
|
||||||
|
@ -418,6 +502,7 @@ class IRCBotFactory(ReconnectingClientFactory):
|
||||||
sendAll("%s: connection failed: %s" % (self.name, error))
|
sendAll("%s: connection failed: %s" % (self.name, error))
|
||||||
if main.config["Notifications"]["Connection"]:
|
if main.config["Notifications"]["Connection"]:
|
||||||
keyword.sendMaster("CONNFAIL %s: %s" % (self.name, error))
|
keyword.sendMaster("CONNFAIL %s: %s" % (self.name, error))
|
||||||
self.retry(connector)
|
if not self.relay:
|
||||||
|
self.retry(connector)
|
||||||
#ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)
|
#ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)
|
||||||
|
|
||||||
|
|
|
@ -1,35 +1,27 @@
|
||||||
from twisted.internet import reactor
|
from twisted.internet import reactor
|
||||||
from twisted.internet.ssl import DefaultOpenSSLContextFactory
|
|
||||||
|
|
||||||
from core.bot import IRCBot, IRCBotFactory
|
from core.bot import IRCBot, IRCBotFactory
|
||||||
import main
|
import main
|
||||||
from utils.logging.log import *
|
from utils.logging.log import *
|
||||||
|
|
||||||
def addBot(name):
|
def addBot(name):
|
||||||
instance = main.pool[name]
|
instance = main.pool[name]
|
||||||
log("Started bot %s to %s:%s protocol %s nickname %s" % (name, instance["host"], instance["port"], instance["protocol"], instance["nickname"]))
|
log("Started bot %s to %s:%s protocol %s nickname %s" % (name,
|
||||||
if instance["protocol"] == "plain":
|
instance["host"],
|
||||||
|
instance["port"],
|
||||||
|
instance["protocol"],
|
||||||
|
instance["nickname"]))
|
||||||
|
|
||||||
|
|
||||||
|
if instance["protocol"] == "ssl":
|
||||||
|
keyFN = main.certPath+main.config["Key"]
|
||||||
|
certFN = main.certPath+main.config["Certificate"]
|
||||||
|
contextFactory = DefaultOpenSSLContextFactory(keyFN.encode("utf-8", "replace"),
|
||||||
|
certFN.encode("utf-8", "replace"))
|
||||||
if instance["bind"] == None:
|
if instance["bind"] == None:
|
||||||
bot = IRCBotFactory(name)
|
bot = IRCBotFactory(name)
|
||||||
rct = reactor.connectTCP(instance["host"], instance["port"], bot, timeout=int(instance["timeout"]))
|
rct = reactor.connectSSL(instance["host"],
|
||||||
|
int(instance["port"]),
|
||||||
main.ReactorPool[name] = rct
|
bot, contextFactory)
|
||||||
main.FactoryPool[name] = bot
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
bot = IRCBotFactory(name)
|
|
||||||
rct = reactor.connectTCP(instance["host"], instance["port"], bot, timeout=int(instance["timeout"]), bindAddress=instance["bind"])
|
|
||||||
|
|
||||||
main.ReactorPool[name] = rct
|
|
||||||
main.FactoryPool[name] = bot
|
|
||||||
return
|
|
||||||
elif instance["protocol"] == "ssl":
|
|
||||||
keyFN = main.certPath+instance["key"]
|
|
||||||
certFN = main.certPath+instance["certificate"]
|
|
||||||
contextFactory = DefaultOpenSSLContextFactory(keyFN.encode("utf-8", "replace"), certFN.encode("utf-8", "replace"))
|
|
||||||
if instance["bind"] == None:
|
|
||||||
bot = IRCBotFactory(name)
|
|
||||||
rct = reactor.connectSSL(instance["host"], int(instance["port"]), bot, contextFactory)
|
|
||||||
|
|
||||||
main.ReactorPool[name] = rct
|
main.ReactorPool[name] = rct
|
||||||
main.FactoryPool[name] = bot
|
main.FactoryPool[name] = bot
|
||||||
|
@ -37,7 +29,10 @@ def addBot(name):
|
||||||
else:
|
else:
|
||||||
|
|
||||||
bot = IRCBotFactory(name)
|
bot = IRCBotFactory(name)
|
||||||
rct = reactor.connectSSL(instance["host"], int(instance["port"]), bot, contextFactory, bindAddress=instance["bind"])
|
rct = reactor.connectSSL(instance["host"],
|
||||||
|
int(instance["port"]),
|
||||||
|
bot, contextFactory,
|
||||||
|
bindAddress=instance["bind"])
|
||||||
|
|
||||||
main.ReactorPool[name] = rct
|
main.ReactorPool[name] = rct
|
||||||
main.FactoryPool[name] = bot
|
main.FactoryPool[name] = bot
|
||||||
|
|
3
main.py
3
main.py
|
@ -10,13 +10,14 @@ certPath = "cert/"
|
||||||
filemap = {
|
filemap = {
|
||||||
"config": ["config.json", "configuration"],
|
"config": ["config.json", "configuration"],
|
||||||
"keyconf": ["keyword.json", "keyword lists"],
|
"keyconf": ["keyword.json", "keyword lists"],
|
||||||
"pool": ["pool.json", "pool"],
|
"pool": ["pool.json", "network, alias and relay mappings"],
|
||||||
"help": ["help.json", "command help"],
|
"help": ["help.json", "command help"],
|
||||||
"counters": ["counters.json", "counters file"],
|
"counters": ["counters.json", "counters file"],
|
||||||
"masterbuf": ["masterbuf.json", "master buffer"],
|
"masterbuf": ["masterbuf.json", "master buffer"],
|
||||||
"monitor": ["monitor.json", "monitoring database"],
|
"monitor": ["monitor.json", "monitoring database"],
|
||||||
"alias": ["alias.json", "alias details"],
|
"alias": ["alias.json", "alias details"],
|
||||||
"relay": ["relay.json", "relay list"],
|
"relay": ["relay.json", "relay list"],
|
||||||
|
"network": ["network.json", "network list"],
|
||||||
}
|
}
|
||||||
|
|
||||||
connections = {}
|
connections = {}
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
import main
|
||||||
|
from core.bot import deliverRelayCommands
|
||||||
|
from utils.logging.log import *
|
||||||
|
|
||||||
|
def provisionUserData(relay, alias, nick, altnick, ident, realname, password):
|
||||||
|
commands = {}
|
||||||
|
commands["controlpanel"] = []
|
||||||
|
commands["controlpanel"].append("AddUser %s %s" % (alias, password))
|
||||||
|
commands["controlpanel"].append("Set Nick %s %s" % (alias, nick))
|
||||||
|
commands["controlpanel"].append("Set Altnick %s %s" % (alias, altnick))
|
||||||
|
commands["controlpanel"].append("Set Ident %s %s" % (alias, ident))
|
||||||
|
commands["controlpanel"].append("Set RealName %s %s" % (alias, realname))
|
||||||
|
deliverRelayCommands(relay, commands)
|
||||||
|
return
|
||||||
|
|
||||||
|
def provisionNetworkData(relay, alias, network, host, port, security, auth, password):
|
||||||
|
commands = {}
|
||||||
|
stage2commands = {}
|
||||||
|
commands["controlpanel"] = []
|
||||||
|
commands["controlpanel"].append("AddNetwork %s %s" % (alias, network))
|
||||||
|
if security == "ssl":
|
||||||
|
commands["controlpanel"].append("SetNetwork TrustAllCerts %s %s true" % (alias, network)) # Don't judge me
|
||||||
|
commands["controlpanel"].append("AddServer %s %s %s +%s" % (alias, network, host, port))
|
||||||
|
elif security == "plain":
|
||||||
|
commands["controlpanel"].append("AddServer %s %s %s %s" % (alias, network, host, port))
|
||||||
|
if auth == "sasl":
|
||||||
|
stage2commands["status"] = []
|
||||||
|
stage2commands["sasl"] = []
|
||||||
|
stage2commands["status"].append("LoadMod sasl")
|
||||||
|
stage2commands["sasl"].append("Mechanism plain")
|
||||||
|
stage2commands["sasl"].append("Set %s %s" % (alias, password))
|
||||||
|
elif auth == "ns":
|
||||||
|
stage2commands["status"] = []
|
||||||
|
stage2commands["nickserv"] = []
|
||||||
|
stage2commands["status"].append("LoadMod NickServ")
|
||||||
|
stage2commands["nickserv"].append("Set %s" % password)
|
||||||
|
deliverRelayCommands(relay, commands, stage2=[[alias+"/"+network, stage2commands]])
|
||||||
|
return
|
||||||
|
|
||||||
|
def provisionRelayForAlias(relay, alias):
|
||||||
|
if "users" in main.relay[relay].keys():
|
||||||
|
if alias in main.relay[relay]["users"]:
|
||||||
|
return "PROVISIONED"
|
||||||
|
else:
|
||||||
|
main.relay[relay]["users"] = []
|
||||||
|
main.relay[relay]["users"].append(alias)
|
||||||
|
provisionUserData(relay, alias, main.alias[alias]["nick"],
|
||||||
|
main.alias[alias]["altnick"],
|
||||||
|
main.alias[alias]["ident"],
|
||||||
|
main.alias[alias]["realname"],
|
||||||
|
main.relay[relay]["password"])
|
||||||
|
main.saveConf("relay")
|
||||||
|
return True
|
||||||
|
|
||||||
|
def provisionRelayForNetwork(relay, alias, network):
|
||||||
|
if "networks" in main.relay[relay].keys():
|
||||||
|
if network in main.relay[relay]["networks"]:
|
||||||
|
return "PROVISIONED"
|
||||||
|
else:
|
||||||
|
main.relay[relay]["networks"] = []
|
||||||
|
main.relay[relay]["networks"].append(network)
|
||||||
|
provisionNetworkData(relay, alias, network,
|
||||||
|
main.network[network]["host"],
|
||||||
|
main.network[network]["port"],
|
||||||
|
main.network[network]["security"],
|
||||||
|
main.network[network]["auth"],
|
||||||
|
main.alias[alias]["password"])
|
||||||
|
main.saveConf("relay")
|
||||||
|
storedNetwork = False
|
||||||
|
num = 1
|
||||||
|
while not storedNetwork:
|
||||||
|
i = str(num)
|
||||||
|
if num == 1000:
|
||||||
|
error("Too many iterations in while trying to choose name for r: %s a: %s n: %s" % (relay, alias, network))
|
||||||
|
return False
|
||||||
|
|
||||||
|
if network+i in main.pool.keys():
|
||||||
|
if main.pool[network+i]["alias"] == alias and main.pool[network+i]["relay"] == relay:
|
||||||
|
return "DUPLICATE"
|
||||||
|
num += 1
|
||||||
|
else:
|
||||||
|
main.pool[network+i] = {"relay": relay,
|
||||||
|
"alias": alias,
|
||||||
|
"network": network}
|
||||||
|
main.saveConf("pool")
|
||||||
|
storedNetwork = True
|
||||||
|
return network+i
|
|
@ -18,12 +18,14 @@ from core.server import Server, ServerFactory
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
listener = ServerFactory()
|
listener = ServerFactory()
|
||||||
if main.config["Listener"]["UseSSL"] == True:
|
if main.config["Listener"]["UseSSL"] == True:
|
||||||
reactor.listenSSL(main.config["Listener"]["Port"], listener, DefaultOpenSSLContextFactory(main.certPath+main.config["Listener"]["Key"], main.certPath+main.config["Listener"]["Certificate"]), interface=main.config["Listener"]["Address"])
|
reactor.listenSSL(main.config["Listener"]["Port"], listener, DefaultOpenSSLContextFactory(main.certPath+main.config["Key"], main.certPath+main.config["Certificate"]), interface=main.config["Listener"]["Address"])
|
||||||
log("Threshold running with SSL on %s:%s" % (main.config["Listener"]["Address"], main.config["Listener"]["Port"]))
|
log("Threshold running with SSL on %s:%s" % (main.config["Listener"]["Address"], main.config["Listener"]["Port"]))
|
||||||
else:
|
else:
|
||||||
reactor.listenTCP(main.config["Listener"]["Port"], listener, interface=main.config["Listener"]["Address"])
|
reactor.listenTCP(main.config["Listener"]["Port"], listener, interface=main.config["Listener"]["Address"])
|
||||||
log("Threshold running on %s:%s" % (main.config["Listener"]["Address"], main.config["Listener"]["Port"]))
|
log("Threshold running on %s:%s" % (main.config["Listener"]["Address"], main.config["Listener"]["Port"]))
|
||||||
for i in main.pool.keys():
|
for i in main.pool.keys():
|
||||||
|
if not "enabled" in main.pool[i]:
|
||||||
|
continue
|
||||||
if main.pool[i]["enabled"] == True:
|
if main.pool[i]["enabled"] == True:
|
||||||
helper.addBot(i)
|
helper.addBot(i)
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,8 @@ def sendInfo(addr, data):
|
||||||
|
|
||||||
def sendAll(data):
|
def sendAll(data):
|
||||||
for i in main.connections:
|
for i in main.connections:
|
||||||
main.connections[i].send(data)
|
if main.connections[i].authed:
|
||||||
|
main.connections[i].send(data)
|
||||||
return
|
return
|
||||||
|
|
||||||
def incorrectUsage(addr, mode):
|
def incorrectUsage(addr, mode):
|
||||||
|
|
Loading…
Reference in New Issue