-
Notifications
You must be signed in to change notification settings - Fork 5
/
server.py
145 lines (124 loc) · 4.7 KB
/
server.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
142
143
144
145
# -*- coding: utf-8 -*
#import socket module
from socket import *
import sys
import re
import ssl
import traceback
##########################################################
#global params
##########################################################
HOST = "127.0.0.1"
PORT = 8800
FILE = "index.html"
ssl_version = None
certfile = "./ssl/certificate.pem"
keyfile = "./ssl/key.pem"
ciphers = None
option_test_switch = 0 # to test, change to 1
version_dict = {
"tlsv1.0" : ssl.PROTOCOL_TLSv1,
"tlsv1.1" : ssl.PROTOCOL_TLSv1_1,
"tlsv1.2" : ssl.PROTOCOL_TLSv1_2,
"sslv23" : ssl.PROTOCOL_SSLv23,
"sslv3" : ssl.PROTOCOL_SSLv3,
}
##########################################################
# Param Hander: get sslContext options through user input
##########################################################
for i in range(1, len(sys.argv)):
arg = sys.argv[i]
if re.match("[-]{,2}(tlsv|sslv)[0-9.]{,3}", arg, re.I):
ssl_version = re.sub("-", "", arg)
if re.match("[-]{,2}ciphers", arg, re.I):
ciphers = sys.argv[i + 1]
if re.match("[-]{,2}cacert", arg, re.I):
certfile = sys.argv[i + 1]
if re.match("^[0-9]{,3}\.[0-9]{,3}\.[0-9]{,3}\.[0-9]{,3}|localhost$", arg, re.I):
HOST = arg
if re.match("^[0-9]{,5}$", arg):
PORT = arg
if re.match("^[0-9a-zA-Z_/]+\.[0-9a-zA-Z-_/]+$", arg, re.I):
FILE = arg
if option_test_switch == 1:
print "ver=", ssl_version, "ciphers=",ciphers, "certfile=", certfile, \
"keyfile=", keyfile, "HOST=", HOST, "PORT=", PORT, "FILE=", FILE
##########################################################
# Init and configure SSLContext, then Wrap socket
# Params: socket sock
# str ssl_version
# str keyfile
# str certificate
# str ciphers
# Exception: SSLError
##########################################################
def ssl_wrap_socket(sock, ssl_version=None, keyfile=None, certfile=None, ciphers=None):
#1. init a context with given version(if any)
if ssl_version is not None and ssl_version in version_dict:
#create a new SSL context with specified TLS version
sslContext = ssl.SSLContext(version_dict[ssl_version])
if option_test_switch == 1:
print "ssl_version loaded!! =", ssl_version
else:
#if not specified, default
sslContext = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
if ciphers is not None:
#if specified, set certain ciphersuite
sslContext.set_ciphers(ciphers)
if option_test_switch == 1:
print "ciphers loaded!! =", ciphers
#server-side must load certfile and keyfile, so no if-else
sslContext.load_cert_chain(certfile, keyfile)
print "ssl loaded!! certfile=", certfile, "keyfile=", keyfile
try:
return sslContext.wrap_socket(sock, server_side = True)
except ssl.SSLError as e:
print "wrap socket failed!"
print traceback.format_exc()
#4. Prepare a sever socket
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind((HOST, eval(PORT)))
serverSocket.listen(10)
#######################################################
# Init socket and start connection (from hw1)
#######################################################
while True:
#Establish the connection
print 'Ready to serve...'
newSocket, addr = serverSocket.accept()
connectionSocket = ssl_wrap_socket(newSocket, ssl_version, keyfile, certfile, ciphers)
if not connectionSocket:
continue
try:
message = connectionSocket.recv(1024)
print "message=", message
filename = message.split()[1]
print "filename=", filename
f = open(filename[1:])
outputdata = f.read()
f.close()
#Send one HTTP header line into socket
#refrence website: https://goo.gl/UGTC9Q
response_headers = {
'Content-Type': 'text/html; encoding=utf8',
'Content-Length': len(outputdata),
'Connection': 'close',
}
response_headers_raw = ''.join('%s: %s\n' % (k, v) for k, v in \
response_headers.iteritems())
connectionSocket.send('HTTP/1.1 200 OK')
connectionSocket.send(response_headers_raw)
connectionSocket.send('\n')
#Send the content of the requested file to the client
connectionSocket.send(outputdata)
#close socket after sending
connectionSocket.shutdown(SHUT_RDWR)
connectionSocket.close()
except IOError:
#Send response message for file not found
connectionSocket.send("404 Not Found")
#Close client socket
connectionSocket.shutdown(SHUT_RDWR)
connectionSocket.close()
serverSocket.close()
sys.exit(0)