forked from tianhuil/SimpleHTTPAuthServer
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathsauth.py
141 lines (118 loc) · 4.04 KB
/
sauth.py
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
"""
Sauth:
A simple authenticated web server handler
license="GNU General Public License v3"
"""
__version__ = "1.1.0"
__prog__ = "sauth"
from http.server import SimpleHTTPRequestHandler, HTTPServer
import os
import sys
import base64
import ssl
import socketserver
import click
CERT_FILE = os.path.expanduser("~/.ssh/cert.pem")
KEY_FILE = os.path.expanduser("~/.ssh/key.pem")
SSL_CMD = "openssl req -newkey rsa:2048 -new -nodes -x509 " "-days 3650 -keyout {0} -out {1}".format(
KEY_FILE, CERT_FILE
)
class SimpleHTTPAuthHandler(SimpleHTTPRequestHandler):
"""Main class to present webpages and authentication."""
username = ""
password = ""
def __init__(self, request, client_address, server):
key = "{}:{}".format(self.username, self.password).encode("ascii")
self.key = base64.b64encode(key)
self.valid_header = b"Basic " + self.key
super().__init__(request, client_address, server)
def do_HEAD(self):
"""head method"""
print("send header")
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
def do_authhead(self):
"""do authentication"""
print("send header")
self.send_response(401)
self.send_header("WWW-Authenticate", 'Basic realm="Test"')
self.send_header("Content-type", "text/html")
self.end_headers()
def do_GET(self):
"""Present frontpage with user authentication."""
auth_header = self.headers.get("Authorization", "").encode("ascii")
if auth_header is None:
self.do_authhead()
self.wfile.write(b"no auth header received")
elif auth_header == self.valid_header:
SimpleHTTPRequestHandler.do_GET(self)
else:
self.do_authhead()
self.wfile.write(auth_header)
self.wfile.write(b"not authenticated")
class ThreadingSimpleServer(socketserver.ThreadingMixIn, HTTPServer):
"""
Not to be confused with http.server.ThreadingHTTPServer that appears in 3.7
"""
def serve_http(
ip="",
port=80,
https=True,
start_dir=None,
use_threads=False,
):
"""setting up server"""
if https:
httpd.socket = ssl.wrap_socket(httpd.socket, keyfile=KEY_FILE, certfile=CERT_FILE, server_side=True)
if start_dir:
print("Changing dir to {cd}".format(cd=start_dir))
os.chdir(start_dir)
if use_threads:
server = ThreadingSimpleServer((ip, port), SimpleHTTPAuthHandler)
else:
server = HTTPServer((ip, port), SimpleHTTPAuthHandler)
print(
'Serving "{}" directory on {}://{}:{} {}'.format(
os.getcwd(),
"https" if https else "http",
ip,
port,
"using threading" if use_threads else "",
).strip()
)
try:
while 1:
sys.stdout.flush()
server.handle_request()
except KeyboardInterrupt:
print("\nKeyboard Interrupt received. Shutting server. Bye!")
@click.command()
@click.argument("username")
@click.argument("password")
@click.argument("ip", default="0.0.0.0")
@click.argument("port", default=8333)
@click.option("-d", "--dir", help="use different directory")
@click.option("-s", "--https", help="use https", is_flag=True)
@click.option(
"-t",
"--thread",
"use_threads",
is_flag=True,
help="serve each request in a different thread",
)
def main(dir, ip, port, username, password, https, use_threads):
"""
Start http server with basic authentication current directory.
"""
if https and not (os.path.exists(CERT_FILE) and os.path.exists(KEY_FILE)):
print(file=sys.stderr)
print("Missing {} or {}".format(CERT_FILE, KEY_FILE), file=sys.stderr)
print("Run `{}`".format(SSL_CMD), file=sys.stderr)
print(file=sys.stderr)
sys.exit(1)
SimpleHTTPAuthHandler.username = username
SimpleHTTPAuthHandler.password = password
serve_http(ip=ip, port=port, https=https, start_dir=dir, use_threads=use_threads)
if __name__ == "__main__":
main()