forked from seba/servefile
HTTPS works
This commit is contained in:
parent
edb1582626
commit
afe666db91
106
servefile
106
servefile
|
@ -21,6 +21,14 @@ from subprocess import Popen, PIPE
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
# only activate SSL if available
|
||||||
|
HAVE_SSL = False
|
||||||
|
try:
|
||||||
|
from OpenSSL import SSL, crypto
|
||||||
|
HAVE_SSL = True
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
def getDateStrNow():
|
def getDateStrNow():
|
||||||
""" Get the current time formatted for HTTP header """
|
""" Get the current time formatted for HTTP header """
|
||||||
now = datetime.datetime.fromtimestamp(time.mktime(time.gmtime()))
|
now = datetime.datetime.fromtimestamp(time.mktime(time.gmtime()))
|
||||||
|
@ -201,7 +209,6 @@ class FilePutter(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||||
self.send_response(100)
|
self.send_response(100)
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
|
|
||||||
print "Saving uploaded file to %s" % cleanFileName
|
|
||||||
target = open(cleanFileName, "w")
|
target = open(cleanFileName, "w")
|
||||||
target.write(self.rfile.read(int(self.headers['Content-Length'])))
|
target.write(self.rfile.read(int(self.headers['Content-Length'])))
|
||||||
target.close()
|
target.close()
|
||||||
|
@ -242,6 +249,41 @@ class FilePutter(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||||
class ThreadedHTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
|
class ThreadedHTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def catchSSLErrors(BaseSSLClass):
|
||||||
|
""" Class decorator which catches SSL errors and prints them. """
|
||||||
|
class X(BaseSSLClass):
|
||||||
|
def handle_one_request(self, *args, **kwargs):
|
||||||
|
try:
|
||||||
|
BaseSSLClass.handle_one_request(self, *args, **kwargs)
|
||||||
|
except SSL.Error, e:
|
||||||
|
if str(e) == "":
|
||||||
|
print "%s SSL Error (Empty error message)" % (self.client_address[0],)
|
||||||
|
else:
|
||||||
|
print "%s SSL Error: %s" % (self.client_address[0], e)
|
||||||
|
return X
|
||||||
|
|
||||||
|
class SecureThreadedHTTPServer(ThreadedHTTPServer):
|
||||||
|
def __init__(self, pubKey, privKey, *args, **kwargs):
|
||||||
|
ThreadedHTTPServer.__init__(self, *args, **kwargs)
|
||||||
|
ctx = SSL.Context(SSL.SSLv23_METHOD)
|
||||||
|
ctx.use_certificate_file(pubKey)
|
||||||
|
ctx.use_privatekey_file(privKey)
|
||||||
|
|
||||||
|
self.bsocket = socket.socket(self.address_family, self.socket_type)
|
||||||
|
self.socket = SSL.Connection(ctx, self.bsocket)
|
||||||
|
|
||||||
|
self.server_bind()
|
||||||
|
self.server_activate()
|
||||||
|
|
||||||
|
def shutdown_request(self, request):
|
||||||
|
request.shutdown()
|
||||||
|
|
||||||
|
class SecureHandler():
|
||||||
|
def setup(self):
|
||||||
|
self.connection = self.request
|
||||||
|
self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
|
||||||
|
self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
|
||||||
|
|
||||||
class ServeFileException(Exception):
|
class ServeFileException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -250,11 +292,13 @@ class ServeFile():
|
||||||
|
|
||||||
(MODE_SINGLE, MODE_UPLOAD, MODE_DIRLIST) = range(3)
|
(MODE_SINGLE, MODE_UPLOAD, MODE_DIRLIST) = range(3)
|
||||||
|
|
||||||
def __init__(self, target, port=8080, serveMode=0):
|
def __init__(self, target, port=8080, serveMode=0, useSSL=False):
|
||||||
self.target = target
|
self.target = target
|
||||||
self.port = port
|
self.port = port
|
||||||
self.serveMode = serveMode
|
self.serveMode = serveMode
|
||||||
self.dirCreated = False
|
self.dirCreated = False
|
||||||
|
self.useSSL = useSSL
|
||||||
|
self.certPath = self.keyPath = None
|
||||||
|
|
||||||
if self.serveMode not in range(3):
|
if self.serveMode not in range(3):
|
||||||
self.serveMode = None
|
self.serveMode = None
|
||||||
|
@ -281,7 +325,7 @@ class ServeFile():
|
||||||
else:
|
else:
|
||||||
del(os.environ['LC_ALL'])
|
del(os.environ['LC_ALL'])
|
||||||
if proc.wait() != 0:
|
if proc.wait() != 0:
|
||||||
print "Error: Could not locate any ips for you."
|
# we couldn't find any ip address
|
||||||
proc = None
|
proc = None
|
||||||
if proc:
|
if proc:
|
||||||
ips = proc.stdout.read().strip().split("\n")
|
ips = proc.stdout.read().strip().split("\n")
|
||||||
|
@ -290,9 +334,28 @@ class ServeFile():
|
||||||
return ips
|
return ips
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def setupSSLKeys(self, cert, key):
|
||||||
|
self.certPath = cert
|
||||||
|
self.keyPath = key
|
||||||
|
|
||||||
|
def _getCert(self):
|
||||||
|
return self.certPath
|
||||||
|
|
||||||
|
def _getKey(self):
|
||||||
|
return self.keyPath
|
||||||
|
|
||||||
|
def _createServer(self, handler):
|
||||||
|
server = None
|
||||||
|
if self.useSSL:
|
||||||
|
server = SecureThreadedHTTPServer(self._getCert(), self._getKey(), ('', self.port), handler)
|
||||||
|
else:
|
||||||
|
server = ThreadedHTTPServer(('', self.port), handler)
|
||||||
|
return server
|
||||||
|
|
||||||
def serve(self):
|
def serve(self):
|
||||||
self.handler = self._confAndFindHandler()
|
self.handler = self._confAndFindHandler()
|
||||||
server = ThreadedHTTPServer(('', self.port), self.handler)
|
self.server = self._createServer(self.handler)
|
||||||
|
|
||||||
if self.serveMode != self.MODE_UPLOAD:
|
if self.serveMode != self.MODE_UPLOAD:
|
||||||
print "Serving \"%s\" under port %d" % (self.target, self.port)
|
print "Serving \"%s\" under port %d" % (self.target, self.port)
|
||||||
else:
|
else:
|
||||||
|
@ -305,13 +368,13 @@ class ServeFile():
|
||||||
print "Could not find any addresses"
|
print "Could not find any addresses"
|
||||||
else:
|
else:
|
||||||
for ip in ips:
|
for ip in ips:
|
||||||
print "http://%s:%d/" % (ip, self.port)
|
print "http%s://%s:%d/" % (self.useSSL and "s" or "", ip, self.port)
|
||||||
print ""
|
print ""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
server.serve_forever()
|
self.server.serve_forever()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
server.socket.close()
|
self.server.socket.close()
|
||||||
|
|
||||||
# cleanup potential upload directory
|
# cleanup potential upload directory
|
||||||
if self.dirCreated and len(os.listdir(self.target)) == 0:
|
if self.dirCreated and len(os.listdir(self.target)) == 0:
|
||||||
|
@ -343,6 +406,13 @@ class ServeFile():
|
||||||
raise ServeFileException("Error: Upload directory already exists and is a file")
|
raise ServeFileException("Error: Upload directory already exists and is a file")
|
||||||
FilePutter.targetDir = self.target
|
FilePutter.targetDir = self.target
|
||||||
handler = FilePutter
|
handler = FilePutter
|
||||||
|
|
||||||
|
if self.useSSL:
|
||||||
|
# secure handler
|
||||||
|
@catchSSLErrors
|
||||||
|
class AlreadySecuredHandler(SecureHandler, handler):
|
||||||
|
pass
|
||||||
|
handler = AlreadySecuredHandler
|
||||||
return handler
|
return handler
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -353,10 +423,27 @@ def main():
|
||||||
help='port to listen on')
|
help='port to listen on')
|
||||||
parser.add_argument('-u', '--upload', action="store_true", default=False, \
|
parser.add_argument('-u', '--upload', action="store_true", default=False, \
|
||||||
help="Enable uploads to a given directory")
|
help="Enable uploads to a given directory")
|
||||||
|
parser.add_argument('--ssl', action="store_true", default=False, \
|
||||||
|
help="Enable SSL. If no key/cert is specified one will be generated.")
|
||||||
|
parser.add_argument('--key', type=str, \
|
||||||
|
help="Keyfile to use for SSL. If no cert is given with --cert the keyfile will also be searched for a cert")
|
||||||
|
parser.add_argument('--cert', type=str, \
|
||||||
|
help="Certfile to use for SSL")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
# check for invalid option combinations
|
# check for invalid option combinations
|
||||||
|
if args.ssl and not HAVE_SSL:
|
||||||
|
print "Error: SSL is not available, please install pyssl (python-openssl)"
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if args.cert and not args.key:
|
||||||
|
print "Error: Please specify a key along with your cert"
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if not args.ssl and (args.cert or args.key):
|
||||||
|
print "Error: You need to turn on ssl with --ssl when specifying certs/keys"
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
mode = None
|
mode = None
|
||||||
if args.upload:
|
if args.upload:
|
||||||
|
@ -368,7 +455,10 @@ def main():
|
||||||
|
|
||||||
server = None
|
server = None
|
||||||
try:
|
try:
|
||||||
server = ServeFile(args.target, args.port, mode)
|
server = ServeFile(args.target, args.port, mode, args.ssl)
|
||||||
|
if args.ssl and args.key:
|
||||||
|
cert = args.cert or args.key
|
||||||
|
server.setupSSLKeys(cert, args.key)
|
||||||
server.serve()
|
server.serve()
|
||||||
except ServeFileException, e:
|
except ServeFileException, e:
|
||||||
print e
|
print e
|
||||||
|
|
Loading…
Reference in New Issue