Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions servefile/servefile.py
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,7 @@ def handle_one_request(self, *args, **kwargs):


class SecureThreadedHTTPServer(ThreadedHTTPServer):
def __init__(self, pubKey, privKey, server_address, RequestHandlerClass, bind_and_activate=True):
def __init__(self, pubKey, privKey, camtlsKey, server_address, RequestHandlerClass, bind_and_activate=True):
ThreadedHTTPServer.__init__(self, server_address, RequestHandlerClass, bind_and_activate)

# choose TLS1.2 or TLS1, if available
Expand All @@ -788,6 +788,10 @@ def __init__(self, pubKey, privKey, server_address, RequestHandlerClass, bind_an
ctx.use_certificate_file(pubKey)
ctx.use_privatekey_file(privKey)

if camtlsKey:
ctx.load_verify_locations(camtlsKey)
ctx.set_verify(SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT, None)

self.bsocket = socket.socket(self.address_family, self.socket_type)
self.socket = SSL.Connection(ctx, self.bsocket)

Expand Down Expand Up @@ -838,6 +842,7 @@ def __init__(self, target, port=8080, serveMode=0, useSSL=False):
self.dirCreated = False
self.useSSL = useSSL
self.cert = self.key = None
self.camtls = None
self.auth = None
self.maxUploadSize = 0
self.listenIPv4 = True
Expand Down Expand Up @@ -892,10 +897,11 @@ def getIPs(self):
return ips
return None

def setSSLKeys(self, cert, key):
def setSSLKeys(self, cert, key, camtls):
""" Set SSL cert/key. Can be either path to file or pyopenssl X509/PKey object. """
self.cert = cert
self.key = key
self.camtls = camtls

def setMaxUploadSize(self, limit):
""" Set the maximum upload size in byte """
Expand Down Expand Up @@ -960,6 +966,9 @@ def _getCert(self):
def _getKey(self):
return self.key

def _getCAmTLS(self):
return self.camtls

def setAuth(self, user, password, realm=None):
if not user or not password:
raise ServeFileException("User and password both need to be at least one character.")
Expand All @@ -981,7 +990,7 @@ def _createServer(self, handler, withv6=False):
if not self._getKey():
self.genKeyPair()
try:
server = SecureThreadedHTTPServer(self._getCert(), self._getKey(),
server = SecureThreadedHTTPServer(self._getCert(), self._getKey(), self._getCAmTLS(),
(listenIp, self.port), handler, bind_and_activate=False)
except SSL.Error as e:
raise ServeFileException("SSL error: Could not read SSL public/private key "
Expand Down Expand Up @@ -1167,6 +1176,8 @@ def main():
"will also be searched for a cert")
parser.add_argument('--cert', type=str,
help="Certfile to use for SSL")
parser.add_argument('--camtls', type=str,
help="Certfile for mutual tls")
parser.add_argument('-a', '--auth', type=str, metavar='user:password',
help="Set user and password for HTTP basic authentication")
parser.add_argument('--realm', type=str, default=None,
Expand Down Expand Up @@ -1216,7 +1227,11 @@ def main():
print("Error: Please specify a key along with your cert.")
sys.exit(1)

if not args.ssl and (args.cert or args.key):
if args.camtls and (not args.cert or not args.key):
print("Error: You need to specify server cert with --cert and server cert key with --key.")
sys.exit(1)

if not args.ssl and (args.cert or args.key or args.camtls):
print("Error: You need to enable ssl with --ssl when specifying certs/keys.")
sys.exit(1)

Expand Down Expand Up @@ -1276,7 +1291,10 @@ def main():
server.setMaxUploadSize(maxUploadSize)
if args.ssl and args.key:
cert = args.cert or args.key
server.setSSLKeys(cert, args.key)
if args.camtls:
server.setSSLKeys(cert, args.key, args.camtls)
else:
server.setSSLKeys(cert, args.key, None)
if args.auth:
user, password = args.auth.split(":", 1)
server.setAuth(user, password, args.realm)
Expand Down