Mercurial > templog
changeset 492:23c6cf01d237
working kinda
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Tue, 11 Feb 2014 23:47:53 +0800 |
parents | f2e990b99637 |
children | 1800a07f20e0 |
files | web/config.py web/log.py web/secure.py web/templog.py web/views/set.tpl |
diffstat | 5 files changed, 99 insertions(+), 22 deletions(-) [+] |
line wrap: on
line diff
--- a/web/config.py Tue Feb 11 22:11:03 2014 +0800 +++ b/web/config.py Tue Feb 11 23:47:53 2014 +0800 @@ -4,11 +4,15 @@ SERIAL_HOST='home.example.com' SERIAL_PORT=1999 + DATA_PATH = '/home/matt/templog/web/data' -HMAC_KEY = 'a hmac key' # override in local config file - -ALLOWED_USERS = [] # local config. list of sha1 hashes of client ssl keys +# local config items +HMAC_KEY = 'a hmac key' +ALLOWED_USERS = [] # list of sha1 hashes of client ssl keys +SSH_HOST = 'remotehost' +SSH_KEYFILE = '/home/matt/.ssh/somekey' +SSH_PROG = 'ssh' UPDATE_URL = 'http://evil.ucc.asn.au/~matt/templog/update'
--- a/web/log.py Tue Feb 11 22:11:03 2014 +0800 +++ b/web/log.py Tue Feb 11 23:47:53 2014 +0800 @@ -15,6 +15,7 @@ import struct import binascii import json +import subprocess from colorsys import hls_to_rgb import config @@ -269,24 +270,25 @@ debugf.write("Updated sensors in %.2f secs\n" % timedelta) debugf.flush() +_FIELD_DEFAULTS = { + 'fridge_setpoint': 16, + 'fridge_difference': 0.2, + 'overshoot_delay': 720, # 12 minutes + 'overshoot_factor': 1, # ºC + 'disabled': False, + 'nowort': True, + 'fridge_range_lower': 3, + 'fridge_range_upper': 3, + } + def get_params(): - _FIELD_DEFAULTS = { - 'fridge_setpoint': 16, - 'fridge_difference': 0.2, - 'overshoot_delay': 720, # 12 minutes - 'overshoot_factor': 1, # ºC - 'disabled': False, - 'nowort': True, - 'fridge_range_lower': 3, - 'fridge_range_upper': 3, - } r = [] vals = read_current_params() for k, v in _FIELD_DEFAULTS.iteritems(): - n = {'name': k, 'value': vals[k]} + n = {'name': k, 'value': type(v)(vals[k])} if type(v) is bool: kind = 'yesno' else: @@ -305,6 +307,54 @@ return json.dumps(r, sort_keys=True, indent=4) +def send_params(params): + # 'templog_receive' is ignored due to authorized_keys + # restrictions + args = [config.SSH_PROG, '-i', config.SSH_KEYFILE, + config.SSH_HOST, 'templog_receive'] + try: + p = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE) + (out, err) = p.communicate(json.dumps(params)) + except OSError, e: + print>>sys.stderr, e + return "Failed update" -def get_csrf_blob(user_ident): - return "aaa" + if 'Good Update' in out: + return True + + print>>sys.stderr, "Strange return from update:" + print>>sys.stderr, out + return "Unexpected update result" + +def same_type(a, b): + ta = type(a) + tb = type(b) + + if ta == int: + ta = float + if tb == int: + tb = float + + return (ta == tb) + +def update_params(p): + params = {} + for i in p: + params[i['name']] = i['value'] + + if params.viewkeys() != _FIELD_DEFAULTS.viewkeys(): + diff = params.viewkeys() ^ _FIELD_DEFAULTS.viewkeys() + return "Key mismatch, difference %s" % str(diff) + + for k, v in params.items(): + if not same_type(v, _FIELD_DEFAULTS[k]): + return "Bad type for %s, %s vs %s" % (k , type(v), type(_FIELD_DEFAULTS[k])) + + ret = send_params(params) + if ret is not True: + return "Failed sending params: %s" % ret + + return True + + +
--- a/web/secure.py Tue Feb 11 22:11:03 2014 +0800 +++ b/web/secure.py Tue Feb 11 23:47:53 2014 +0800 @@ -54,27 +54,33 @@ def check_csrf_blob(blob): toks = blob.split('-') if len(toks) != 3: + print>>sys.stderr, "wrong toks" return False user, expiry, mac = toks if user != get_user_hash(): + print>>sys.stderr, "wrong user" return False try: exp = int(expiry) except ValueError: + print>>sys.stderr, "failed exp" return False if exp < 1000000000: return False - if exp > time.time(): + if exp < time.time(): + print>>sys.stderr, "expired %d %d" % (exp, time.time()) return False check_content = "%s-%s" % (user, expiry) - check_mac = hmac.new(_csrf_key, content).hexdigest() + check_mac = hmac.new(_csrf_key, check_content).hexdigest() if mac == check_mac: + print>>sys.stderr, "good hmac" return True + print>>sys.stderr, "fail" return False
--- a/web/templog.py Tue Feb 11 22:11:03 2014 +0800 +++ b/web/templog.py Tue Feb 11 23:47:53 2014 +0800 @@ -50,12 +50,21 @@ return log.graph_png(start_epoch, length_minutes * 60) @route('/set/update', method='post') -def update(): +def set_update(): post_json = json.loads(request.forms.data) csrf_blob = post_json['csrf_blob'] - return str(post_json['params']) + if not secure.check_csrf_blob(csrf_blob): + bottle.response.status = 403 + return "Bad csrf" + + ret = log.update_params(post_json['params']) + if not ret is True: + bottle.response.status = 403 + return ret + + return "Good" @route('/set') def set(): @@ -139,4 +148,3 @@ if __name__ == '__main__': main() -
--- a/web/views/set.tpl Tue Feb 11 22:11:03 2014 +0800 +++ b/web/views/set.tpl Tue Feb 11 23:47:53 2014 +0800 @@ -76,6 +76,10 @@ margin-top: 10pt; } +span.inputrow { + //vertical-align: center; +} + </style> <title>Set templog</title> </head> @@ -85,9 +89,11 @@ <div id="{id}"> <span class="existing">{title} <span id="oldvalue">{oldvaluetext}{unit}</span></span> <br/> +<span class="inputrow"> <input type="number" class="input" name="input_{name}" /> <input type="button" class="button_down" value="-"/> <input type="button" class="button_up" value="+"/> +</span> </div> </script> @@ -95,8 +101,10 @@ <div id="{id}"> <span class="existing">{title} <span id="oldvalue">{oldvaluetext}</span></span> <br/> +<span class="inputrow"> <input type="button" class="button_no yesno" value="No"/> <input type="button" class="button_yes yesno" value="Yes"/> +</span> </div> </script> @@ -158,7 +166,8 @@ req.fail(function(data, status, hdr) { self.trigger("status", - "Failed: " + status + "\n" + hdr.responseText) + "Failed: " + data.status + ' ' + + data.statusText + ' ' + data.responseText) }); } }