# - Mike Warot's capabilities demo version 0.008 # Copyright (C) 2008 Michael A. Warot, all rights reserved. # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # # Based on webserver.py Copyright Jon Berg , turtlemeat.com # version - new capabilites # 01 - moved to port 81 to avoid built in IIS in XP, etc. # 02 - added code from Rogier Steehouder to allow for keyboard interrupt of the server when running from the command line # 03 - add code to display requested path # 04 - get a random number and display it if the request is /token # turns out that Mersenne Twister is an available random number generator... close enough to cryptographic for a while. 8) # 05 - keep a list of tokens we hand out, display on the main page # 06 - allow deletion of a token from the list # 07 - after deleting token, gets you back to the main page # 08 - added GPL language (version 3 of the gpl, don't want this to end up in a Tivo) and startup hint in the command window # # import string,cgi,time, socket, random from os import curdir, sep from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer validtokens = [] # start with no tokens version = '0.008' # code from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/499376 which allows for keyboard interrupt of the server when running from command line+ class Server(HTTPServer): """HTTPServer class with timeout.""" def get_request(self): """Get the request and client address from the socket.""" # 10 second timeout self.socket.settimeout(10.0) result = None while result is None: try: result = self.socket.accept() except socket.timeout: pass # Reset timeout on the new socket result[0].settimeout(None) return result class MyHandler(BaseHTTPRequestHandler): def do_GET(self): global validtokens try: if self.path.endswith(".html"): f = open(curdir + sep + self.path) #self.path has /test.html #note that this potentially makes every file on your computer readable by the internet self.send_response(200) self.send_header('Content-type', 'text/html') self.end_headers() self.wfile.write(f.read()) f.close() return if self.path.endswith(".esp"): #our dynamic content self.send_response(200) self.send_header('Content-type', 'text/html') self.end_headers() self.wfile.write("hey, today is the" + str(time.localtime()[7])) self.wfile.write(" day in the year " + str(time.localtime()[0])) self.wfile.write("
Your path is : " + self.path + "") return if self.path.endswith("token"): # get a random number and return it self.send_response(200) self.send_header('Content-type', 'text/html') self.end_headers() x = "%032x" % (random.getrandbits(128)) validtokens = validtokens + [ x ] self.wfile.write(x) return # default out to a welcome page self.send_response(200) self.send_header('Content-type', 'text/html') self.end_headers() self.wfile.write('this is the default content, not served from a file
') self.wfile.write('Here are the valid tokens:
') self.wfile.write('
'); for i in validtokens: self.wfile.write(''); self.wfile.write(i+'') self.wfile.write('') self.wfile.write('
') return except IOError: self.send_error(404,'File Not Found: %s' % self.path) def do_POST(self): global validtokens # Parse the form data posted form = cgi.FieldStorage( fp=self.rfile, headers=self.headers, environ={'REQUEST_METHOD':'POST', 'CONTENT_TYPE':self.headers['Content-Type'], }) cap = form["capability"].value if (cap in validtokens) and self.path.endswith("delete"): validtokens.remove(cap) self.send_response(200) self.send_header('Refresh','2; url=/') # 2 seconds gives us time to debug this thing, and see the output self.send_header('Content-type', 'text/html') self.end_headers() self.wfile.write('Please return to the index page') pass else: # Begin the response if we didn't have a valid delete token request self.send_response(200) self.send_header('Content-type', 'text/html') self.end_headers() self.wfile.write('Client: %s\n' % str(self.client_address)) self.wfile.write('Path: %s\n' % self.path) self.wfile.write('Form data:\n') # Echo back information about what was posted in the form for field in form.keys(): field_item = form[field] if field_item.filename: # The field contains an uploaded file file_data = field_item.file.read() file_len = len(file_data) del file_data self.wfile.write('\tUploaded %s (%d bytes)\n' % (field,file_len)) else: # Regular form value self.wfile.write('\t%s=%s\n' % (field, form[field].value)) pass def main(): try: server = Server(('', 81), MyHandler) # port 81 to avoid IIS, Apache, etc. print "Welcome to Mike Warot's capability based security demo web server, version "+version print 'You can access it at http://127.0.0.1:81' print 'Use control-c to tell it to shut down, which may take up to 10 seconds' print 'started httpserver...' server.serve_forever() except KeyboardInterrupt: print '^C received, shutting down server' server.socket.close() if __name__ == '__main__': main()