There it is.

This commit is contained in:
Bandie Canis 2017-09-30 14:51:23 +02:00
parent e7d44a152e
commit b524f113dc
8 changed files with 450 additions and 0 deletions

43
1_generateCA.sh Executable file
View File

@ -0,0 +1,43 @@
#!/bin/bash
echo "###################"
echo "# CA generation #"
echo -e "###################\n"
## CA Private key
echo -n "Where to save your CA key file? ($PWD/CA.key): "
read temp
if [ -n "$temp" ]
then
save=$temp
else
save="$PWD/CA.key"
fi
CAkey=$save
openssl genrsa -aes256 -out $save 8192
## CA Certificate
echo -n "Where to save your CA certificate? ($PWD/CA.crt): "
read temp
if [ -n "$temp" ]
then
save=$temp
else
save="$PWD/CA.crt"
fi
echo -n "How many days should the certificate be valid? (3650): "
read temp
if [[ $temp =~ ^[0-9]+$ ]]
then
days=$temp
else
days=3650
fi
echo -e "\033[01;33mPlease enter some information about the CA.\033[00m"
openssl req -new -x509 -days $days -key $CAkey -out $save

73
2_generateServCert.sh Executable file
View File

@ -0,0 +1,73 @@
#!/bin/bash
## Server private key
echo -n "Where to save your server's key file? ($PWD/ding_server.key): "
read temp
if [ -n "$temp" ]
then
save=$temp
else
save="$PWD/ding_server.key"
fi
key=$save
openssl genrsa -out $save 4096
## CSR
echo -n "Where to save your Certificate Signing Request (CSR)? ($PWD/ding_server.csr): "
read temp
if [ -n "$temp" ]
then
save=$temp
else
save="$PWD/ding_server.csr"
fi
csr=$save
echo -e "\033[01;33mPlease enter some information. THEY MUST BE DIFFERENT FROM THE CA's INFORMATION.\033[00m"
openssl req -new -key $key -out $save -sha512
## Signing
echo -n "Path of your CA Certificate? ($PWD/CA.crt): "
read temp
if [ -n "$temp" ]
then
loadCAcrt=$temp
else
loadCAcrt="$PWD/CA.crt"
fi
echo -n "Path of your CA key? ($PWD/CA.key): "
read temp
if [ -n "$temp" ]
then
loadCAkey=$temp
else
loadCAkey="$PWD/CA.key"
fi
echo -n "Where to save your signed server certificate? ($PWD/ding_server.crt): "
read temp
if [ -n "$temp" ]
then
save=$temp
else
save="$PWD/ding_server.crt"
fi
echo -n "How many days should the certificate be valid? (365): "
read temp
if [ -n "$temp" ]
then
t=$temp
else
t=365
fi
openssl x509 -req -in $csr -CA $loadCAcrt -CAkey $loadCAkey -CAcreateserial -out $save -days $t -sha512
rm $csr

73
3_generateClientCert.sh Executable file
View File

@ -0,0 +1,73 @@
#!/bin/bash
## Server private key
echo -n "Where to save your client's key file? ($PWD/ding_client.key): "
read temp
if [ -n "$temp" ]
then
save=$temp
else
save="$PWD/ding_client.key"
fi
key=$save
openssl genrsa -out $save 4096
## CSR
echo -n "Where to save your Certificate Signing Request (CSR)? ($PWD/ding_client.csr): "
read temp
if [ -n "$temp" ]
then
save=$temp
else
save="$PWD/ding_client.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"
openssl req -new -key $key -out $save -sha512
## Signing
echo -n "Path of your CA Certificate? ($PWD/CA.crt): "
read temp
if [ -n "$temp" ]
then
loadCAcrt=$temp
else
loadCAcrt="$PWD/CA.crt"
fi
echo -n "Path of your CA key? ($PWD/CA.key): "
read temp
if [ -n "$temp" ]
then
loadCAkey=$temp
else
loadCAkey="$PWD/CA.key"
fi
echo -n "Where to save your signed client certificate? ($PWD/ding_client.crt): "
read temp
if [ -n "$temp" ]
then
save=$temp
else
save="$PWD/ding_client.crt"
fi
echo -n "How many days should the certificate be valid? (365): "
read temp
if [ -n "$temp" ]
then
t=$temp
else
t=365
fi
openssl x509 -req -in $csr -CA $loadCAcrt -CAkey $loadCAkey -CAcreateserial -out $save -days $t -sha512
rm $csr

23
README.md Normal file
View File

@ -0,0 +1,23 @@
# 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.
## How does it work?
The server awaits the client's commands. A command sent by the client must be defined in the server's config file, else the server won't do anything.
## 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. ]
## Installation
In all steps please read carefully, what the generating script want from you.
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 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>`.

82
ding_client Executable file
View File

@ -0,0 +1,82 @@
#!/usr/bin/env python3
import sys, ssl, socket
import configparser
CONFIG = "ding_client.cfg"
def readConfig():
cfg = configparser.SafeConfigParser()
try:
cfg.read(CONFIG)
global host, port, cafile, certfile, keyfile
host = cfg.get("Client", "host")
port = int(cfg.get("Client", "port"))
cafile = cfg.get("Client", "cafile")
certfile = cfg.get("Client", "certfile")
keyfile = cfg.get("Client", "keyfile")
except configparser.NoSectionError:
print("No suitable config found. Expecting some config in", CONFIG)
quit(3)
def send(conn, cmd):
global exitcode
conn.connect((host, port))
buf = conn.recv(1024)
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)
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.")
exitcode = 2
else:
conn.sendall(b"NO.")
print("The server seems to be crazy. Nothing sent.", file=sys.stderr)
conn.close()
def main():
try:
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
context.verify_mode = ssl.CERT_REQUIRED
context.load_verify_locations(cafile)
context.load_cert_chain(certfile=certfile, keyfile=keyfile)
except FileNotFoundError as e:
print(e)
print("Please check your paths in the config file. (Have you forgotten to generate the Certificates?)", sep="", file=sys.stderr)
quit(2)
conn = context.wrap_socket(socket.socket())
try:
send(conn, bytes(sys.argv[1], sys.stdin.encoding))
except IndexError:
print(sys.argv[0], ": Missing argument.\nSyntax: ", sys.argv[0], " <COMMAND>", file=sys.stderr)
except ConnectionRefusedError:
print("Connection refused.", file=sys.stderr)
quit(1)
except ssl.SSLError:
print("Wrong certificate.", file=sys.stderr);
quit(3)
if(__name__ == "__main__"):
readConfig()
main()
quit(exitcode)

10
ding_client.cfg Normal file
View File

@ -0,0 +1,10 @@
[Client]
host=localhost
port=13573
cafile=CA.crt
#Client Certificate/key signed by the CA above
certfile=ding_client.crt
keyfile=ding_client.key

127
ding_server Executable file
View File

@ -0,0 +1,127 @@
#!/usr/bin/env python3
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:
bindsocket = socket.socket()
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.")

19
ding_server.cfg Normal file
View File

@ -0,0 +1,19 @@
[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