-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpython3HTTPSAuthServer.py
More file actions
executable file
·148 lines (131 loc) · 5.38 KB
/
python3HTTPSAuthServer.py
File metadata and controls
executable file
·148 lines (131 loc) · 5.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/env python3
from http.server import HTTPServer, SimpleHTTPRequestHandler
import ssl, os, sys, argparse, base64
NARGS = len(sys.argv)
ARGS = {}
tempfiles = []
def Get_Args():
AO = argparse.ArgumentParser(description="Python HTTPS Auth Server")
AO.add_argument("-i", "--ip", help="Bind IP (Default all interfaces 0.0.0.0)", type=str, default="0.0.0.0")
AO.add_argument("-p", "--port", help="Bind port, default 8443", type=int, default=8443)
AO.add_argument("-a", "--auth", help="HTTP BASIC auth [username:password]", type=str, default=None)
AO.add_argument("-s", "--https", help="Use HTTPS", action="store_true")
AO.add_argument("-c", "--cert", help="If you brought your own CERT, then by all means... [fullpath]", type=str, default=None)
AO.add_argument("-k", "--privatekey", help="If you brought your own PRIVATE_KEY, then by all means... [fullpath]", type=str, default=None)
AP, AP_garbage = AO.parse_known_args()
ARGS = vars(AP)
if (ARGS['cert'] and not ARGS['privatekey']) or (ARGS['privatekey'] and not ARGS['cert']):
print("[!] You can BYOC only when providing BOTH a certfile and matching private key! Else NEITHER, and generate a self-signed automatically")
sys.exit()
return ARGS
def gencert():
## We're just going to generate self-signed certs...
# https://www.linux.org/threads/creating-a-self-signed-certificate-with-python.9038/
# https://markusholtermann.eu/2016/09/ssl-all-the-things-in-python/
from OpenSSL import crypto, SSL
from pprint import pprint
from time import gmtime, mktime
from os.path import exists, join
from random import choice, randint
from string import ascii_letters
import tempfile, pathlib, os.path
CN = "SSLS"
k = crypto.PKey()
k.generate_key(crypto.TYPE_RSA, 4096)
cert = crypto.X509()
cert.get_subject().C = "".join([choice(ascii_letters[:26]) for i in range(2)])
cert.get_subject().ST = "".join([choice(ascii_letters[:26]) for i in range(2)])
cert.get_subject().L = "".join([choice(ascii_letters[:26]) for i in range(0, randint(2,32))])
cert.get_subject().O = "".join([choice(ascii_letters[:26]) for i in range(0, randint(2,32))])
cert.get_subject().OU = "".join([choice(ascii_letters[:26]) for i in range(0, randint(2,32))])
cert.get_subject().CN = CN
cert.set_serial_number(randint(1000,9999))
cert.gmtime_adj_notBefore(0)
cert.gmtime_adj_notAfter(604800) # 7 days...
cert.set_issuer(cert.get_subject())
cert.set_pubkey(k)
cert.sign(k, 'sha256')
CERT_FILE = "%s.crt" % CN
PEM_FILE = "%s.pem" % CN
PUBKEY_FILE = "%s.pub" % CN
dirpath = tempfile.gettempdir()
cert_dir = dirpath + os.path.sep
C_F = join(cert_dir, CERT_FILE)
K_F = join(cert_dir, PEM_FILE)
P_F = join(cert_dir, PUBKEY_FILE)
global tempfiles
tempfiles.append(C_F)
tempfiles.append(K_F)
tempfiles.append(P_F)
print("[#] Generating disposible, one-time-use, self-signed cert files in: %s" % cert_dir)
print("[.]%s\n[.]%s\n[.]%s" % (C_F, K_F, P_F))
open(C_F, 'wt').write((crypto.dump_certificate(crypto.FILETYPE_PEM, cert)).decode("utf-8"))
open(K_F, 'wt').write((crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey=k)).decode("utf-8"))
open(P_F, 'wt').write((crypto.dump_publickey(crypto.FILETYPE_PEM, pkey=k)).decode("utf-8"))
return C_F, K_F, P_F
class AuthHandler(SimpleHTTPRequestHandler):
## Based on https://gist.github.com/fxsjy/5465353 , just refactored, 'sall
''' Main class to present webpages and authentication. '''
def do_HEAD(self):
print("send header")
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
def do_AUTHHEAD(self):
print("send header")
self.send_response(401)
self.send_header('WWW-Authenticate', 'Basic realm=\"PROD\"')
self.send_header('Content-type', 'text/html')
self.end_headers()
def do_GET(self):
global ARGS
key = base64.b64encode(bytes(ARGS['auth'].encode("utf-8")))
''' Present frontpage with user authentication. '''
if self.headers.get('Authorization') == None:
self.do_AUTHHEAD()
self.wfile.write(bytes('no auth header received'.encode("utf-8")))
pass
elif self.headers.get('Authorization') == 'Basic '+key.decode('utf-8'):
SimpleHTTPRequestHandler.do_GET(self)
pass
else:
self.do_AUTHHEAD()
self.wfile.write(bytes(self.headers.get('Authorization').encode("utf-8")))
self.wfile.write(bytes('not authenticated'.encode("utf-8")))
pass
def build_server(ARGS):
if not ARGS['auth'] == None:
httpd = HTTPServer((ARGS['ip'], ARGS['port']), AuthHandler)
else:
httpd = HTTPServer((ARGS['ip'], ARGS['port']), SimpleHTTPRequestHandler)
if ARGS['https']:
if ARGS['cert'] and ARGS['privatekey']:
CERT = ARGS['cert']
PEM = ARGS['privatekey']
else:
global tempfiles
CERT, PEM, PUBKEY = gencert()
httpd.socket = ssl.wrap_socket (httpd.socket, certfile=CERT, keyfile=PEM, server_side=True)
try:
print("[#] Now serving HTTP%s on %s:%s %s" % (
"S" if ARGS['https'] else "",
ARGS['ip'],
ARGS['port'],
"with AUTH "+ARGS['auth'] if ARGS['auth'] else ""
))
print("[#] Ctrl+C to stop server\n")
httpd.serve_forever()
except TypeError:
pass
except KeyboardInterrupt:
if len(tempfiles) > 0:
for item in tempfiles:
os.remove(item)
sys.exit()
def main():
global ARGS
ARGS = Get_Args()
build_server(ARGS)
sys.exit()
if __name__=="__main__":
main()