Added authentication support

This commit is contained in:
Sebastian Lohff 2012-04-16 16:36:40 +02:00
parent 15d4890e3b
commit fbc87e0991
1 changed files with 57 additions and 0 deletions

View File

@ -8,6 +8,7 @@
__version__ = '0.3.2' __version__ = '0.3.2'
import argparse import argparse
import base64
import cgi import cgi
import BaseHTTPServer import BaseHTTPServer
import commands import commands
@ -303,6 +304,7 @@ class ServeFile():
self.dirCreated = False self.dirCreated = False
self.useSSL = useSSL self.useSSL = useSSL
self.cert = self.key = None self.cert = self.key = None
self.auth = None
if self.serveMode not in range(3): if self.serveMode not in range(3):
self.serveMode = None self.serveMode = None
@ -390,6 +392,11 @@ class ServeFile():
def _getKey(self): def _getKey(self):
return self.key return self.key
def setAuth(self, user, password):
if len(user) == "" or len(password) == "":
raise ServeFileException("User and password both need to be at least one character long")
self.auth = base64.b64encode("%s:%s" % (user, password))
def _createServer(self, handler): def _createServer(self, handler):
server = None server = None
if self.useSSL: if self.useSSL:
@ -455,6 +462,13 @@ class ServeFile():
FilePutter.targetDir = self.target FilePutter.targetDir = self.target
handler = FilePutter handler = FilePutter
if self.auth:
# do authentication
AuthenticationHandler.authString = self.auth
class AuthenticatedHandler(AuthenticationHandler, handler):
pass
handler = AuthenticatedHandler
if self.useSSL: if self.useSSL:
# secure handler # secure handler
@catchSSLErrors @catchSSLErrors
@ -463,6 +477,38 @@ class ServeFile():
handler = AlreadySecuredHandler handler = AlreadySecuredHandler
return handler return handler
class AuthenticationHandler():
# base64 encoded user:password string for authentication
authString = None
realm = "Restricted area"
def handle_one_request(self):
""" Overloaded function to handle one request.
Before calling the responsible do_METHOD function, check credentials
"""
self.raw_requestline = self.rfile.readline()
if not self.raw_requestline:
self.close_connection = 1
return
if not self.parse_request(): # An error code has been sent, just exit
return
authorized = False
if "Authorization" in self.headers:
if self.headers["Authorization"] == ("Basic " + self.authString):
authorized = True
if authorized:
mname = 'do_' + self.command
if not hasattr(self, mname):
self.send_error(501, "Unsupported method (%r)" % self.command)
return
method = getattr(self, mname)
method()
else:
self.send_response(401)
self.send_header("WWW-Authenticate", "Basic realm=\"%s\"" % self.realm)
def main(): def main():
parser = argparse.ArgumentParser(description='Serve a single file via HTTP') parser = argparse.ArgumentParser(description='Serve a single file via HTTP')
parser.add_argument('--version', action='version', version='%(prog)s ' + __version__) parser.add_argument('--version', action='version', version='%(prog)s ' + __version__)
@ -477,6 +523,8 @@ def main():
help="Keyfile to use for SSL. If no cert is given with --cert the keyfile will also be searched for a cert") 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, \ parser.add_argument('--cert', type=str, \
help="Certfile to use for SSL") help="Certfile to use for SSL")
parser.add_argument('-a', '--auth', type=str, metavar='user:password', \
help="Set user and password for HTTP basic authentication")
args = parser.parse_args() args = parser.parse_args()
@ -493,6 +541,12 @@ def main():
print "Error: You need to turn on ssl with --ssl when specifying certs/keys" print "Error: You need to turn on ssl with --ssl when specifying certs/keys"
sys.exit(1) sys.exit(1)
if args.auth:
dpos = args.auth.find(":")
if dpos <= 0 or dpos == (len(args.auth)-1):
print "Error: User and password for HTTP basic auth need to be both at least one character long and have to be seperated by a \":\""
sys.exit(1)
mode = None mode = None
if args.upload: if args.upload:
mode = ServeFile.MODE_UPLOAD mode = ServeFile.MODE_UPLOAD
@ -507,6 +561,9 @@ def main():
if args.ssl and args.key: if args.ssl and args.key:
cert = args.cert or args.key cert = args.cert or args.key
server.setSSLKeys(cert, args.key) server.setSSLKeys(cert, args.key)
if args.auth:
user, password = args.auth.split(":", 1)
server.setAuth(user, password)
server.serve() server.serve()
except ServeFileException, e: except ServeFileException, e:
print e print e