#!{{ extra_eggs_interpreter }} import cgi import cgitb import Cookie import base64 import hashlib import hmac import jinja2 import os import subprocess import urllib cgitb.enable(display=0, logdir="/tmp/cgi.log") form = cgi.FieldStorage() cookie = Cookie.SimpleCookie() cgi_path = "{{ cgi_directory }}" monitor_password_path = "{{ monitor_password_path }}" monitor_password_script_path = "{{ monitor_password_script_path }}" monitor_apache_password_command = "{{ apache_update_command }}" monitor_rewrite = "{{ ' '.join(rewrite_element.keys()) }}" ######## # Password functions ####### def crypt(word, salt="$$"): salt = salt.split("$") algo = salt[0] or 'sha1' if algo in hashlib.algorithms: H = getattr(hashlib, algo) elif algo == "plain": return "%s$%s" % (algo, word) else: raise ValueError rounds = min(max(0, int(salt[1])), 30) if salt[1] else 9 salt = salt[2] or base64.b64encode(os.urandom(12), "./") h = hmac.new(salt, word, H).digest() for x in xrange(1, 1 << rounds): h = H(h).digest() return "%s$%s$%s$%s" % (algo, rounds, salt, base64.b64encode(h, "./").rstrip("=")) def is_password_set(): if not os.path.exists(monitor_password_path): return False hashed_password = open(monitor_password_path, 'r').read() try: void, algo, salt, hsh = hashed_password.split('$') except ValueError: return False return True def set_password(raw_password): hashed_password = crypt(raw_password) subprocess.check_call(monitor_apache_password_command + " %s" % raw_password, shell=True) open(monitor_password_path, 'w').write(hashed_password) def check_password(raw_password): """ Returns a boolean of whether the raw_password was correct. Handles encryption formats behind the scenes. """ if not os.path.exists(monitor_password_path) or not raw_password: return False hashed_password = open(monitor_password_path, 'r').read() return hashed_password == crypt(raw_password, hashed_password) ### End of password functions def forward_form(): command = os.path.join(cgi_path, form['posting-script'].value) params_dict = {} for f in form: params_dict[f] = form[f].value del params_dict['posting-script'] os.environ['QUERY_STRING'] = urllib.urlencode(params_dict) try: if os.access(command, os.X_OK): print '\n', subprocess.check_output([command]) except subprocess.CalledProcessError: print "There is a problem with sub-process" pass def return_document(command=None): if not command: script = form['script'].value command = os.path.join(cgi_path, script) #XXX this functions should be called only for display, #so a priori it doesn't need form data os.environ['QUERY_STRING'] = '' try: if os.access(command, os.X_OK): print '\n', subprocess.check_output([command]) elif os.access(command, os.R_OK): print open(command).read() else: raise OSError except (subprocess.CalledProcessError, OSError) as e: print "<p>Error :</p><pre>%s</pre>" % e def make_menu(): # Transform deep-2 tree in json folder_list = {} for folder in os.listdir(cgi_path): if os.path.isdir(os.path.join(cgi_path, folder)): folder_list[folder] = [] for folder in folder_list: for file in os.listdir(os.path.join(cgi_path, folder)): if os.path.isfile(os.path.join(cgi_path, folder, file)): folder_list[folder].append(file) return folder_list def get_cookie_password(): cookie_string = os.environ.get('HTTP_COOKIE') if cookie_string: cookie.load(cookie_string) try: return cookie['password'].value except KeyError: pass return None def set_cookie_password(password): cookie['password'] = password print cookie, "; Path=/; HttpOnly" # Beginning of response print "Content-Type: text/html" password = None # Check if user is logged if "password_2" in form and "password" in form: password_2 = form['password_2'].value password_1 = form['password'].value password = get_cookie_password() if not is_password_set() or check_password(password): if password_2 == password_1: password = password_1 set_password(password) set_cookie_password(password) elif "password" in form: password = form['password'].value if is_password_set() and check_password(password): set_cookie_password(password) else: password = get_cookie_password() print '\n' if not is_password_set(): return_document(monitor_password_script_path) elif not check_password(password): print "<html><head>" print """ <link rel="stylesheet" href="static/pure-min.css"> <link rel="stylesheet" href="static/style.css">""" print "</head><body>" if password is None: print "<h1>This is the monitoring interface</h1>" else: print "<h1>Error</h1><p>Wrong password</p>" print """ <p>Please enter the monitor_password in the next field to access the data</p> <form action="/index.cgi" method="post" class="pure-form-aligned"> Password : <input type="password" name="password"> <button type="submit" class="pure-button pure-button-primary">Access</button> </form> </body></html>""" # redirection to the required script/page else: print if "posting-script" in form: forward_form() elif "script" in form: return_document() else: html_base = jinja2.Template(open('{{ index_template }}').read()) print print html_base.render(tree=make_menu(), default_page="{{ default_page }}", monitor_rewrite=monitor_rewrite)