Compare commits
29 Commits
Author | SHA1 | Date |
---|---|---|
Bandie | d0db0a7d94 | |
Bandie | 384c7368b2 | |
Bandie | 63e52b8c3e | |
Bandie | 4622833ff5 | |
Bandie | 57fb2f7b99 | |
Bandie | 3e7f23ccd1 | |
Bandie | abf6a0f563 | |
Bandie | 6687604446 | |
Bandie | 1a3e532b29 | |
Bandie | 36dd610965 | |
Bandie | 2141418097 | |
Bandie | 6d24484430 | |
Bandie | 9b03d6f928 | |
Bandie | dc027362f0 | |
Bandie | 406accc716 | |
Bandie | 72c68cabde | |
Bandie | a7d27c5ee9 | |
Bandie | 600524809c | |
Bandie | ae3043b1de | |
Bandie | b17e6c9353 | |
Bandie | aef87bed4a | |
Bandie | 4a09411676 | |
Bandie | 0822b9407c | |
Bandie | 032b2facaf | |
Bandie | b02757dae0 | |
Sir_Boops | 47483e641a | |
Bandie Canis | 0f73da0295 | |
Bandie Canis | 93a88fc322 | |
Bandie Canis | f5aa131048 |
|
@ -1,28 +1,28 @@
|
|||
#!/bin/bash
|
||||
|
||||
## Server private key
|
||||
echo -n "Where to save your server's key file? ($PWD/ding_server.key): "
|
||||
echo -n "Where to save your server's key file? ($PWD/dingd.key): "
|
||||
read temp
|
||||
|
||||
if [ -n "$temp" ]
|
||||
then
|
||||
save=$temp
|
||||
else
|
||||
save="$PWD/ding_server.key"
|
||||
save="$PWD/dingd.key"
|
||||
fi
|
||||
key=$save
|
||||
openssl genrsa -out $save 4096
|
||||
|
||||
|
||||
## CSR
|
||||
echo -n "Where to save your Certificate Signing Request (CSR)? ($PWD/ding_server.csr): "
|
||||
echo -n "Where to save your Certificate Signing Request (CSR)? ($PWD/dingd.csr): "
|
||||
read temp
|
||||
|
||||
if [ -n "$temp" ]
|
||||
then
|
||||
save=$temp
|
||||
else
|
||||
save="$PWD/ding_server.csr"
|
||||
save="$PWD/dingd.csr"
|
||||
fi
|
||||
csr=$save
|
||||
echo -e "\033[01;33mPlease enter some information. THEY MUST BE DIFFERENT FROM THE CA's INFORMATION.\033[00m"
|
||||
|
@ -50,14 +50,14 @@ else
|
|||
loadCAkey="$PWD/CA.key"
|
||||
fi
|
||||
|
||||
echo -n "Where to save your signed server certificate? ($PWD/ding_server.crt): "
|
||||
echo -n "Where to save your signed server certificate? ($PWD/dingd.crt): "
|
||||
read temp
|
||||
|
||||
if [ -n "$temp" ]
|
||||
then
|
||||
save=$temp
|
||||
else
|
||||
save="$PWD/ding_server.crt"
|
||||
save="$PWD/dingd.crt"
|
||||
fi
|
||||
|
||||
echo -n "How many days should the certificate be valid? (365): "
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
#!/bin/bash
|
||||
|
||||
## Server private key
|
||||
echo -n "Where to save your client's key file? ($PWD/ding_client.key): "
|
||||
echo -n "Where to save your client's key file? ($PWD/ding.key): "
|
||||
read temp
|
||||
|
||||
if [ -n "$temp" ]
|
||||
then
|
||||
save=$temp
|
||||
else
|
||||
save="$PWD/ding_client.key"
|
||||
save="$PWD/ding.key"
|
||||
fi
|
||||
key=$save
|
||||
openssl genrsa -out $save 4096
|
||||
|
||||
|
||||
## CSR
|
||||
echo -n "Where to save your Certificate Signing Request (CSR)? ($PWD/ding_client.csr): "
|
||||
echo -n "Where to save your Certificate Signing Request (CSR)? ($PWD/ding.csr): "
|
||||
read temp
|
||||
|
||||
if [ -n "$temp" ]
|
||||
then
|
||||
save=$temp
|
||||
else
|
||||
save="$PWD/ding_client.csr"
|
||||
save="$PWD/ding.csr"
|
||||
fi
|
||||
csr=$save
|
||||
echo -e "\033[01;33mPlease enter some information. THEY MUST BE DIFFERENT FROM THE CA's AND SERVER's INFORMATION.\033[00m"
|
||||
|
@ -50,14 +50,14 @@ else
|
|||
loadCAkey="$PWD/CA.key"
|
||||
fi
|
||||
|
||||
echo -n "Where to save your signed client certificate? ($PWD/ding_client.crt): "
|
||||
echo -n "Where to save your signed client certificate? ($PWD/ding.crt): "
|
||||
read temp
|
||||
|
||||
if [ -n "$temp" ]
|
||||
then
|
||||
save=$temp
|
||||
else
|
||||
save="$PWD/ding_client.crt"
|
||||
save="$PWD/ding.crt"
|
||||
fi
|
||||
|
||||
echo -n "How many days should the certificate be valid? (365): "
|
||||
|
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2017, Bandie Canis
|
||||
Copyright (c) 2017, Bandie <bandie@chaospott.de>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
48
README.md
48
README.md
|
@ -1,26 +1,54 @@
|
|||
# ding
|
||||
## What is ding?
|
||||
ding is a client-server thing written in python. Its aim is to execute a set of commands remotely which can be set in the server's config file.
|
||||
ding is a client-server thing written in python3. Its aim is to execute a set of commands remotely. The commands can be set in the server's config file.
|
||||
|
||||
|
||||
## How does it work?
|
||||
The server awaits commands sent by the client. A command must be defined in the server's config file, else the server won't do anything.
|
||||
The server will wait for a command to be sent by a client. If the command is present within the server's config file it will then execute the command, else nothing will happen.
|
||||
|
||||
|
||||
## What about ding's security?
|
||||
The authentication is done by an SSL Client Certificate signed by an (own generated) Certificate Authority. The scripts for generating a CA and signing a Server/Client Certificate are also in here to make it (relatively) easy. [ You need only to press enter in the most cases, type in some certificate information and entering a previously defined CA password. ]
|
||||
The authentication is done via a SSL Client Certificate signed by an (self generated) Certificate Authority. The scripts for generating a CA and signing the Server/Client Certificates are also included to make it (relatively) easy. [ This involves typing in a few certificate details and entering a previously defined CA password. ]
|
||||
|
||||
|
||||
## Pic or didn't happen
|
||||
![Screenshot of CircleArt](/img/dingScreenshot.png)
|
||||
[Can't read a thing?](https://raw.githubusercontent.com/Bandie/ding/master/img/dingScreenshot.png)
|
||||
![Screenshot of ding](https://git.chaospott.de/Bandie/ding/raw/branch/master/img/dingScreenshot.png)
|
||||
|
||||
|
||||
## Requirements
|
||||
* Install python3 on your target computers.
|
||||
|
||||
|
||||
## Installation
|
||||
In all steps please read carefully what the certification generate scripts want from you. The certificate information needn't to be true at all and can be random. They only need to be different from each other.
|
||||
At every step please read carefully what the generate certificates scripts want from you. The information on the certificates doesn't need to be true and can be totally random. They only need to be different from one another.
|
||||
|
||||
Step 1 to 3 can only be run on UNIX or GNU/Linux.
|
||||
|
||||
1. Run `./1_generateCA.sh` to generate a CA.
|
||||
2. Run `./2_generateServCert.sh` to generate a signed Server Certificate.
|
||||
3. Run `./3_generateClientCert.sh` to generate a signed Client Certificate.
|
||||
4. Move `ding_client`, `ding_client.cfg`, `ding_client.crt`, `ding_client.key` and `CA.crt` to the computer which should be able to send commands to the server.
|
||||
5. Do some configuration on the server and client (ding\_server.cfg, ding\_client.cfg).
|
||||
6. Start the server using `./ding_server`. You may want to put this in a tmux session ([Ctrl+B, D] ;) ).
|
||||
7. Try out the client using `./ding_client <command>`.
|
||||
4. Move `ding`, `ding.cfg`, `ding.crt`, `ding.key` and `CA.crt` to the computer which should be able to send commands to the server.
|
||||
* UNIX or GNU/Linux: Also move `ding.cfg` to that computer.
|
||||
* Windows: Also move `ding.win.cfg` to that computer.
|
||||
5. Do some configuration on the server and client (`dingd.cfg`, `ding.cfg` or `dingd.win.cfg`, `ding.win.cfg` on Windows).
|
||||
6. Start the server using `./dingd` or `python .\dingd` on Windows. (You may want to put this in a tmux session. [Ctrl+B, D] ;) ).
|
||||
7. Try out the client using `./ding <command>` òr `python .\ding <command>` on Windows.
|
||||
|
||||
### A word about the commands
|
||||
It works much better to use (bash) scripts instead of executing the commands directly.
|
||||
|
||||
## Optional: Cleartext password with timeout
|
||||
If you want to be sure that this power won't be abused by bad people using your computer, you may want to add a password (saved in cleartext).
|
||||
The password will be sent inside the TLS connection.
|
||||
|
||||
### Warning! Beware of the shell history!
|
||||
You might want to do something like `$ history -c` after sending the password via the client or play around with bash's HISTCONTROL variable.
|
||||
|
||||
### How to enable the password
|
||||
|
||||
1. Open your `dingd.cfg` or `dingd.win.cfg`.
|
||||
2. Set `pw_on=true`.
|
||||
3. Set a password, like `password=abc def`.
|
||||
4. Set a password timeout: `pwtimeout=10` for 10 seconds.
|
||||
|
||||
If you have a password with special characters as in spaces and the like, you may want to use quotation marks around your password. `./ding "abc def"` or `python .\ding "abc def"` on Windows.
|
||||
|
|
|
@ -3,18 +3,32 @@
|
|||
# Author: Bandie Canis
|
||||
# License: 2-Clause BSD License
|
||||
|
||||
import sys, ssl, socket
|
||||
import sys, ssl, socket, os, getopt
|
||||
import configparser
|
||||
|
||||
CONFIG = "ding_client.cfg"
|
||||
|
||||
def readConfig():
|
||||
cfg = configparser.SafeConfigParser()
|
||||
host = None
|
||||
port = 0
|
||||
cafile = None
|
||||
certfile = None
|
||||
keyfile = None
|
||||
exitcode = 1
|
||||
|
||||
def init(conf):
|
||||
|
||||
if(conf == None):
|
||||
if(os.name == 'nt'):
|
||||
CONFIG = "ding.win.cfg"
|
||||
else:
|
||||
CONFIG = "ding.cfg"
|
||||
else:
|
||||
CONFIG = conf
|
||||
|
||||
cfg = configparser.ConfigParser()
|
||||
try:
|
||||
cfg.read(CONFIG)
|
||||
|
||||
global host, port, cafile, certfile, keyfile
|
||||
|
||||
host = cfg.get("Client", "host")
|
||||
port = int(cfg.get("Client", "port"))
|
||||
|
||||
|
@ -22,37 +36,41 @@ def readConfig():
|
|||
certfile = cfg.get("Client", "certfile")
|
||||
keyfile = cfg.get("Client", "keyfile")
|
||||
except configparser.NoSectionError:
|
||||
print("No suitable config found. Expecting some config in", CONFIG)
|
||||
print("No suitable config found. Expecting some config in", CONFIG, file=sys.stderr)
|
||||
quit(3)
|
||||
|
||||
|
||||
def send(conn, cmd):
|
||||
|
||||
global exitcode
|
||||
|
||||
conn.connect((host, port))
|
||||
buf = conn.recv(1024)
|
||||
if(buf == b"OK 1337\n"):
|
||||
if(buf == b"OK 1337\n"):
|
||||
conn.sendall(cmd)
|
||||
buf = conn.recv(1024)
|
||||
if(buf == b"OK CMD"):
|
||||
exitcode = 0
|
||||
elif(buf == b"ERR NO_CMD"):
|
||||
print("Error. Server said: The command doesn't exist/isn't set.", file=sys.stderr)
|
||||
print("Error. Server said: The command isn't set on the server.", file=sys.stderr)
|
||||
exitcode = 1
|
||||
elif(buf == b"ERR CMD_ERR"):
|
||||
print("Error. Server said: The command doesn't work because the file doesn't exist on the server.")
|
||||
print("Error. Server said: The command doesn't work because the file doesn't exist on the server.", file=sys.stderr)
|
||||
exitcode = 2
|
||||
elif(buf == b"ERR PW"):
|
||||
print("Error. Password required. The password was wrong.", file=sys.stderr)
|
||||
exitcode = 4
|
||||
elif(b"OK PW" in buf):
|
||||
bufr=str(buf.decode('utf-8'))
|
||||
print("Password accepted. Timeout:", bufr.replace("OK PW ",""), "seconds.")
|
||||
|
||||
else:
|
||||
conn.sendall(b"NO.")
|
||||
print("The server seems to be crazy. Nothing sent.", file=sys.stderr)
|
||||
|
||||
conn.close()
|
||||
quit(exitcode)
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
def main(arg):
|
||||
try:
|
||||
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
|
||||
context.verify_mode = ssl.CERT_REQUIRED
|
||||
|
@ -70,7 +88,7 @@ def main():
|
|||
|
||||
|
||||
try:
|
||||
send(conn, bytes(sys.argv[1], sys.stdin.encoding))
|
||||
send(conn, bytes(arg[0], sys.stdin.encoding))
|
||||
except IndexError:
|
||||
print(sys.argv[0], ": Missing argument.\nSyntax: ", sys.argv[0], " <COMMAND>", file=sys.stderr)
|
||||
except ConnectionRefusedError:
|
||||
|
@ -83,7 +101,16 @@ def main():
|
|||
|
||||
|
||||
if(__name__ == "__main__"):
|
||||
readConfig()
|
||||
main()
|
||||
quit(exitcode)
|
||||
try:
|
||||
conf = None
|
||||
opts, args = getopt.getopt(sys.argv[1:], "c:")
|
||||
for o, a in opts:
|
||||
if o == "-c":
|
||||
conf = a
|
||||
init(conf)
|
||||
main(args)
|
||||
except getopt.GetoptError as e:
|
||||
print("Error using options. Allowed options:\n-c [FILE] - Config file\n")
|
||||
quit(2)
|
||||
|
||||
quit(exitcode)
|
|
@ -5,6 +5,6 @@ port=13573
|
|||
|
||||
cafile=CA.crt
|
||||
#Client Certificate/key signed by the CA above
|
||||
certfile=ding_client.crt
|
||||
keyfile=ding_client.key
|
||||
certfile=ding.crt
|
||||
keyfile=ding.key
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
[Client]
|
||||
host=localhost
|
||||
port=13573
|
||||
|
||||
|
||||
cafile=CA.crt
|
||||
#Client Certificate/key signed by the CA above
|
||||
certfile=ding.crt
|
||||
keyfile=ding.key
|
||||
|
134
ding_server
134
ding_server
|
@ -1,134 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Author: Bandie Canis
|
||||
# License: 2-Clause BSD license
|
||||
|
||||
import ssl, socket, subprocess, time
|
||||
import configparser
|
||||
|
||||
CONFIG = "ding_server.cfg"
|
||||
|
||||
def getTimestamp():
|
||||
t = "[" + time.strftime("%Y-%m-%d %H:%M:%S") + "]"
|
||||
return t
|
||||
|
||||
def execFromConfig(option):
|
||||
cfg = configparser.SafeConfigParser()
|
||||
cfg.read(CONFIG)
|
||||
|
||||
try:
|
||||
cmd = cfg.get("Commands", option).replace("\"", "").replace("\'", "")
|
||||
cmd = cmd.split(" ")
|
||||
try:
|
||||
subprocess.Popen(cmd)
|
||||
return 0
|
||||
|
||||
except FileNotFoundError:
|
||||
print(getTimestamp(), "Can't execute", cmd, ". File not found.")
|
||||
return 2
|
||||
|
||||
except configparser.NoOptionError:
|
||||
print(getTimestamp(), "No execution set:", option)
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
while True:
|
||||
newsocket, fromaddr = bindsocket.accept()
|
||||
try:
|
||||
connstream = context.wrap_socket(newsocket, server_side=True)
|
||||
print(getTimestamp(), "Incoming connection:", fromaddr[0])
|
||||
connstream.send(b"OK 1337\n")
|
||||
|
||||
con_loop = True
|
||||
while con_loop:
|
||||
try:
|
||||
buf = connstream.recv(1024)
|
||||
if not buf: break
|
||||
buf = buf.decode("utf-8").upper()
|
||||
except ssl.SSLEOFError:
|
||||
print(getTimestamp(), "SSL-EOF-Error.")
|
||||
con_loop = False
|
||||
except ConnectionResetError:
|
||||
print(getTimestamp(), "Connection reset.")
|
||||
serve()
|
||||
|
||||
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")
|
||||
|
||||
|
||||
except ssl.SSLError as e:
|
||||
print(getTimestamp(), e)
|
||||
|
||||
except EOFError:
|
||||
print(getTimestamp(), "EOF")
|
||||
|
||||
def init():
|
||||
|
||||
global host, port, cafile, certfile, keyfile, context, bindsocket
|
||||
|
||||
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("\'","")
|
||||
except configparser.NoOptionError as e:
|
||||
print("Error in configuration file:", e)
|
||||
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)
|
||||
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)
|
||||
|
||||
print("Running ding server on ", host, ":", port,
|
||||
"\nCAFile: ", cafile,
|
||||
"\nCertfile: ", certfile,
|
||||
"\nKeyfile: ", keyfile,
|
||||
"\n===========",
|
||||
sep="")
|
||||
|
||||
|
||||
if(__name__ == "__main__"):
|
||||
|
||||
try:
|
||||
init()
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
print("\r\rServer stopped.")
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
[Server]
|
||||
host=localhost
|
||||
port=13573
|
||||
|
||||
[Security]
|
||||
# Certificate of the OWN CA
|
||||
cafile=CA.crt
|
||||
|
||||
# Server's certificate [signed by the CA above]
|
||||
certfile=ding_server.crt
|
||||
|
||||
# Server's private key
|
||||
keyfile=ding_server.key
|
||||
|
||||
|
||||
[Commands]
|
||||
# Syntax:
|
||||
# SERVER_COMMAND: Command --which --should_be --executed
|
||||
lock: xscreensaver-command -lock
|
|
@ -0,0 +1,195 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Author: Bandie Canis
|
||||
# License: 2-Clause BSD license
|
||||
|
||||
import ssl, socket, subprocess, time, os, sys, getopt
|
||||
import configparser
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
def getTimestamp():
|
||||
t = "[" + time.strftime("%Y-%m-%d %H:%M:%S") + "]"
|
||||
return t
|
||||
|
||||
def execFromConfig(option, pw=False):
|
||||
cfg = configparser.ConfigParser()
|
||||
cfg.read(CONFIG)
|
||||
|
||||
if(pw):
|
||||
if(option == password):
|
||||
return 4
|
||||
else:
|
||||
return 5
|
||||
|
||||
else:
|
||||
|
||||
try:
|
||||
cmd = cfg.get("Commands", option).replace("\"", "").replace("\'", "")
|
||||
cmd = cmd.split(" ")
|
||||
try:
|
||||
subprocess.Popen(cmd)
|
||||
return 0
|
||||
|
||||
except FileNotFoundError:
|
||||
print(getTimestamp(), "Can't execute", cmd, ". File not found.")
|
||||
return 2
|
||||
|
||||
except configparser.NoOptionError:
|
||||
print(getTimestamp(), "No execution set:", option)
|
||||
return 1
|
||||
|
||||
def main():
|
||||
while True:
|
||||
newsocket, fromaddr = bindsocket.accept()
|
||||
try:
|
||||
connstream = context.wrap_socket(newsocket, server_side=True)
|
||||
print(getTimestamp(), "Incoming connection:", fromaddr[0])
|
||||
connstream.send(b"OK 1337\n")
|
||||
|
||||
con_loop = True
|
||||
while con_loop:
|
||||
global tmppw_on, pw_on, pwtimeout
|
||||
if('timeout' in locals() and timeout<time.time()):
|
||||
del timeout
|
||||
tmppw_on=pw_on
|
||||
print(getTimestamp(), "Locked.")
|
||||
|
||||
try:
|
||||
buf = connstream.recv(1024)
|
||||
if not buf: break
|
||||
buf = buf.decode("utf-8")
|
||||
except ssl.SSLEOFError:
|
||||
print(getTimestamp(), "SSL-EOF-Error.")
|
||||
con_loop = False
|
||||
except ConnectionResetError:
|
||||
print(getTimestamp(), "Connection reset.")
|
||||
serve()
|
||||
|
||||
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
|
||||
|
||||
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")
|
||||
|
||||
except ssl.SSLError as e:
|
||||
print(getTimestamp(), e)
|
||||
|
||||
except EOFError:
|
||||
print(getTimestamp(), "EOF")
|
||||
|
||||
def init(cfg=None):
|
||||
|
||||
global CONFIG, host, port, cafile, certfile, keyfile, pw_on, password, pwtimeout, tmppw_on, context, bindsocket
|
||||
|
||||
if(cfg==None):
|
||||
if(os.name == 'nt'):
|
||||
CONFIG = "dingd.win.cfg"
|
||||
else:
|
||||
CONFIG = "dingd.cfg"
|
||||
else:
|
||||
CONFIG = cfg
|
||||
|
||||
cfg = configparser.ConfigParser()
|
||||
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("\'","")
|
||||
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
|
||||
except configparser.NoSectionError as e:
|
||||
print("Error in configuration file:", e, file=sys.stderr)
|
||||
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)
|
||||
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)
|
||||
|
||||
print("Running dingd on ", host, ":", port,
|
||||
"\nConfig: ", CONFIG,
|
||||
"\nCAFile: ", cafile,
|
||||
"\nCertfile: ", certfile,
|
||||
"\nKeyfile: ", keyfile,
|
||||
"\nPassword lock: ", pw_on,
|
||||
"\nPassword timeout: ", pwtimeout,
|
||||
"\n===========",
|
||||
sep="")
|
||||
|
||||
|
||||
|
||||
if(__name__ == "__main__"):
|
||||
try:
|
||||
conf = None
|
||||
opts, args = getopt.getopt(sys.argv[1:], "c:")
|
||||
for o, a in opts:
|
||||
if o == "-c":
|
||||
conf = a
|
||||
init(conf)
|
||||
main()
|
||||
except getopt.GetoptError as e:
|
||||
print("Error using options. Allowed options:\n-c [FILE] - Config file\n")
|
||||
quit(2)
|
||||
except KeyboardInterrupt:
|
||||
print("\r\rServer stopped.")
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
[Server]
|
||||
host=localhost
|
||||
port=13573
|
||||
|
||||
[Security]
|
||||
# Certificate of the OWN CA
|
||||
cafile=CA.crt
|
||||
|
||||
# Server's certificate [signed by the CA above]
|
||||
certfile=dingd.crt
|
||||
|
||||
# Server's private key
|
||||
keyfile=dingd.key
|
||||
|
||||
## Optional cleartext password
|
||||
# To unlock the commands you need to send the password before sending the command.
|
||||
# Example:
|
||||
# $ ./ding_client "My password"
|
||||
# $ ./ding_client lock
|
||||
|
||||
# Password on? (true/false)
|
||||
pw_on=false
|
||||
|
||||
# Password (if you use spaces or other stuff you need to embrace the password in quotation marks, like ./ding_client "abc def"
|
||||
password=abc def
|
||||
|
||||
# Password timeout in seconds
|
||||
pwtimeout=10
|
||||
|
||||
|
||||
[Commands]
|
||||
# Syntax:
|
||||
# SERVER_COMMAND: Command --which --should_be --executed
|
||||
lock: xscreensaver-command -lock
|
|
@ -0,0 +1,41 @@
|
|||
[Server]
|
||||
host=localhost
|
||||
port=13573
|
||||
|
||||
[Security]
|
||||
# Certificate of the OWN CA
|
||||
cafile=CA.crt
|
||||
|
||||
# Server's certificate [signed by the CA above]
|
||||
certfile=dingd.crt
|
||||
|
||||
# Server's private key
|
||||
keyfile=dingd.key
|
||||
|
||||
## Optional cleartext password
|
||||
# To unlock the commands you need to send the password before sending the command.
|
||||
# Example:
|
||||
# python .\ding_client "My password"
|
||||
# python .\ding_client lock
|
||||
|
||||
# Password on? (true/false)
|
||||
pw_on=false
|
||||
|
||||
# The password.
|
||||
# If you have a password with special characters as in spaces and the like, you may want to use quotation marks around your password: python .\ding_client "abc def"
|
||||
password=abc def
|
||||
|
||||
# Password timeout in seconds
|
||||
pwtimeout=10
|
||||
|
||||
|
||||
[Commands]
|
||||
# Syntax:
|
||||
# SERVER_COMMAND: Command --which --should_be --executed
|
||||
#
|
||||
# For cmd.exe:
|
||||
# a_cmd_command: C:\Windows\System32\cmd.exe /C <Your cmd commands here>
|
||||
#
|
||||
# For powershell:
|
||||
# a_ps_command: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe <Powershell commands here>
|
||||
lock: C:\Windows\System32\rundll32.exe user32.dll,LockWorkStation
|
Binary file not shown.
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 102 KiB |
|
@ -0,0 +1,10 @@
|
|||
[Unit]
|
||||
Description=dingd Service
|
||||
|
||||
[Service]
|
||||
ExecStart=/root/ding/dingd -c /path/to/config/file/dingd.cfg
|
||||
Restart=on-failure
|
||||
RestartSec=5s
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
Loading…
Reference in New Issue