ding/dingd

186 lines
5.1 KiB
Plaintext
Raw Permalink Normal View History

2017-09-30 12:51:23 +00:00
#!/usr/bin/env python3
2017-09-30 15:02:06 +00:00
# Author: Bandie Canis
# License: 2-Clause BSD license
2018-03-28 22:58:36 +00:00
import ssl, socket, subprocess, time, os, sys
2017-09-30 12:51:23 +00:00
import configparser
2018-04-04 14:24:52 +00:00
CONFIG = None
host = None
port = 0
cafile = None
certfile = None
keyfile = None
pw_on = None
password = None
pwtimeout = 30
tmppw_on = None
context = None
bindsocket = None
2017-09-30 12:51:23 +00:00
def getTimestamp():
t = "[" + time.strftime("%Y-%m-%d %H:%M:%S") + "]"
return t
2018-02-01 00:36:25 +00:00
def execFromConfig(option, pw=False):
2017-09-30 12:51:23 +00:00
cfg = configparser.SafeConfigParser()
2018-04-04 14:24:52 +00:00
cfg.read(CONFIG)
2017-09-30 12:51:23 +00:00
2018-02-01 00:36:25 +00:00
if(pw):
if(option == password):
return 4
else:
return 5
else:
2017-09-30 12:51:23 +00:00
try:
2018-02-01 00:36:25 +00:00
cmd = cfg.get("Commands", option).replace("\"", "").replace("\'", "")
cmd = cmd.split(" ")
try:
subprocess.Popen(cmd)
return 0
2017-09-30 12:51:23 +00:00
2018-02-01 00:36:25 +00:00
except FileNotFoundError:
print(getTimestamp(), "Can't execute", cmd, ". File not found.")
return 2
2017-09-30 12:51:23 +00:00
2018-02-01 00:36:25 +00:00
except configparser.NoOptionError:
print(getTimestamp(), "No execution set:", option)
return 1
2017-09-30 12:51:23 +00:00
def main():
while True:
newsocket, fromaddr = bindsocket.accept()
try:
2018-04-04 14:33:36 +00:00
connstream = context.wrap_socket(newsocket, server_side=True)
2017-09-30 12:51:23 +00:00
print(getTimestamp(), "Incoming connection:", fromaddr[0])
connstream.send(b"OK 1337\n")
2018-04-04 14:44:09 +00:00
2017-09-30 12:51:23 +00:00
con_loop = True
while con_loop:
2018-02-01 00:36:25 +00:00
global tmppw_on, pw_on, pwtimeout
if('timeout' in locals() and timeout<time.time()):
del timeout
tmppw_on=pw_on
print(getTimestamp(), "Locked.")
2018-04-04 14:59:19 +00:00
2017-09-30 12:51:23 +00:00
try:
buf = connstream.recv(1024)
if not buf: break
2018-02-01 00:36:25 +00:00
buf = buf.decode("utf-8")
2017-09-30 12:51:23 +00:00
except ssl.SSLEOFError:
print(getTimestamp(), "SSL-EOF-Error.")
con_loop = False
except ConnectionResetError:
print(getTimestamp(), "Connection reset.")
serve()
2018-02-01 00:36:25 +00:00
if(tmppw_on):
retval = execFromConfig(buf, True)
if(retval == 5):
print(getTimestamp(), " ", fromaddr[0], ": Wrong Password.", sep="")
connstream.send(b"ERR PW")
if(retval == 4):
print(getTimestamp(), " ", fromaddr[0], ": Unlocked for ", pwtimeout, "sec.", sep="")
pwokstr = "OK PW " + str(pwtimeout)
connstream.send(bytes(pwokstr, "utf-8"))
timeout=time.time() + pwtimeout
tmppw_on = False
2018-04-04 14:51:26 +00:00
2018-02-01 00:36:25 +00:00
else:
print(getTimestamp(), " ", fromaddr[0], ": ", buf, sep="")
retval = execFromConfig(buf)
if(retval == 0):
connstream.send(b"OK CMD")
elif(retval == 1):
connstream.send(b"ERR NO_CMD")
elif(retval == 2):
connstream.send(b"ERR CMD_ERR")
2017-09-30 12:51:23 +00:00
except ssl.SSLError as e:
print(getTimestamp(), e)
except EOFError:
print(getTimestamp(), "EOF")
def init():
2018-02-01 13:09:35 +00:00
global CONFIG, host, port, cafile, certfile, keyfile, pw_on, password, pwtimeout, tmppw_on, context, bindsocket
2018-04-04 15:20:17 +00:00
2018-02-01 13:09:35 +00:00
if(os.name == 'nt'):
2018-03-28 22:58:36 +00:00
CONFIG = "dingd.win.cfg"
2018-02-01 13:09:35 +00:00
else:
2018-03-28 22:58:36 +00:00
CONFIG = "dingd.cfg"
2018-02-01 13:09:35 +00:00
2017-09-30 12:51:23 +00:00
cfg = configparser.SafeConfigParser()
cfg.read(CONFIG)
try:
host=cfg.get("Server", "host").replace("\"","").replace("\'","")
port=int(cfg.get("Server", "port").replace("\"","").replace("\'",""))
cafile=cfg.get("Security", "cafile").replace("\"","").replace("\'","")
certfile=cfg.get("Security", "certfile").replace("\"","").replace("\'","")
keyfile=cfg.get("Security", "keyfile").replace("\"","").replace("\'","")
2018-02-01 00:36:25 +00:00
pw_on=cfg.get("Security", "pw_on").replace("\"","").replace("\'","")
password=cfg.get("Security", "password").replace("\"","").replace("\'","")
pwtimeout=int(cfg.get("Security", "pwtimeout").replace("\"","").replace("\'",""))
if(pw_on.upper() == "TRUE"):
pw_on = True
else:
pw_on = False
tmppw_on=pw_on
2018-03-28 22:58:36 +00:00
except configparser.NoSectionError as e:
print("Error in configuration file:", e, file=sys.stderr)
2017-09-30 12:51:23 +00:00
quit(1)
try:
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH, cafile=cafile)
context.load_cert_chain(certfile=certfile, keyfile=keyfile)
context.verify_mode = ssl.CERT_REQUIRED
context.load_verify_locations(cafile=cafile)
except FileNotFoundError as e:
print(e)
print("Please check your paths in the config file. (Have you forgotten to generate the Certificates?)")
quit(2)
try:
if(":" in host):
bindsocket = socket.socket(family=socket.AF_INET6)
else:
bindsocket = socket.socket(family=socket.AF_INET)
2017-09-30 12:51:23 +00:00
bindsocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
bindsocket.bind((host, port))
bindsocket.listen(5)
except socket.gaierror:
print("Error: Hostname error. Name or service not known.")
quit(1)
except PermissionError:
print("Error: Can't bind for port number ", port, ". Permission denied.", sep="")
quit(1)
2018-04-04 14:59:19 +00:00
2018-04-04 14:24:52 +00:00
print("Running dingd on ", host, ":", port,
2018-02-01 13:09:35 +00:00
"\nConfig: ", CONFIG,
2018-04-04 14:24:52 +00:00
"\nCAFile: ", cafile,
"\nCertfile: ", certfile,
2017-09-30 12:51:23 +00:00
"\nKeyfile: ", keyfile,
2018-02-01 00:36:25 +00:00
"\nPassword lock: ", pw_on,
"\nPassword timeout: ", pwtimeout,
2017-09-30 12:51:23 +00:00
"\n===========",
sep="")
2018-02-01 00:36:25 +00:00
2017-09-30 12:51:23 +00:00
if(__name__ == "__main__"):
try:
init()
main()
except KeyboardInterrupt:
print("\r\rServer stopped.")