Common stuff for all my devices' web server pages: css, login, log, ipv4, ipv6, firmware update, clock, reset info etc.

Dependents:   oldheating gps motorhome heating

Security

A password has to be set whenever there has been a software reset. Resets following faults or power on do not require a new password as the hash is restored from the RTC GPREG register.

The password is not saved on the device; instead a 32 bit hash of the password is saved. It would take 2^31 attempts to brute force the password: this could be done in under a month if an attempt were possible every millisecond. To prevent this a 200 ms delay is introduced in the reply to the login form, that gives a more reasonable 13 years to brute force the password.

Once the password is accepted a random session id is created. This is 36 bit to give six base 64 characters but without an extra delay. If an attempt could be made every ms then this would still take over a year to brute force.

The most likely attack would to use a dictionary with, say, 10 million entries against the password which would still take 20 days to do.

Committer:
andrewboyson
Date:
Wed Jul 31 15:09:15 2019 +0000
Revision:
127:bd6dd135009d
Parent:
110:8ab752842d25
Amalgamated Reply into Poll function

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 94:d7226b2c14b6 1 //Clock script
andrewboyson 14:c3c43c8faf0e 2 'use strict';
andrewboyson 14:c3c43c8faf0e 3
andrewboyson 95:8c9dda8a0caf 4 let pseudo = new Clock();
andrewboyson 95:8c9dda8a0caf 5 let rtc = new Clock();
andrewboyson 94:d7226b2c14b6 6
andrewboyson 94:d7226b2c14b6 7 let pseudoDisplay = false;
andrewboyson 94:d7226b2c14b6 8 let pseudoStartMs = 0;
andrewboyson 94:d7226b2c14b6 9
andrewboyson 94:d7226b2c14b6 10 let diffMs = 0;
andrewboyson 94:d7226b2c14b6 11 let rtcIsSet = false;
andrewboyson 94:d7226b2c14b6 12 let clockIsSet = false;
andrewboyson 94:d7226b2c14b6 13 let sourceIsOk = false;
andrewboyson 94:d7226b2c14b6 14 let rateIsLocked = false;
andrewboyson 94:d7226b2c14b6 15 let timeIsLocked = false;
andrewboyson 14:c3c43c8faf0e 16
andrewboyson 94:d7226b2c14b6 17 let ppb = 0;
andrewboyson 94:d7226b2c14b6 18 let ppbdivisor = 0;
andrewboyson 94:d7226b2c14b6 19 let ppbmaxchange = 0;
andrewboyson 94:d7226b2c14b6 20 let syncedlimitppb = 0;
andrewboyson 94:d7226b2c14b6 21 let syncedhysppb = 0;
andrewboyson 94:d7226b2c14b6 22 let slewdivisor = 0;
andrewboyson 94:d7226b2c14b6 23 let slewmax = 0;
andrewboyson 94:d7226b2c14b6 24 let syncedlimitns = 0;
andrewboyson 94:d7226b2c14b6 25 let syncedhysns = 0;
andrewboyson 94:d7226b2c14b6 26 let maxoffsetsecs = 0;
andrewboyson 94:d7226b2c14b6 27 let govTrace = false;
andrewboyson 14:c3c43c8faf0e 28
andrewboyson 94:d7226b2c14b6 29 let ntpserver = '';
andrewboyson 94:d7226b2c14b6 30 let ntpinitial = 0;
andrewboyson 94:d7226b2c14b6 31 let ntpnormal = 0;
andrewboyson 94:d7226b2c14b6 32 let ntpretry = 0;
andrewboyson 94:d7226b2c14b6 33 let ntpoffset = 0;
andrewboyson 94:d7226b2c14b6 34 let ntpmaxdelay = 0;
andrewboyson 94:d7226b2c14b6 35
andrewboyson 94:d7226b2c14b6 36 let scanavg = 0;
andrewboyson 94:d7226b2c14b6 37 let scanmax = 0;
andrewboyson 94:d7226b2c14b6 38 let scanmin = 0;
andrewboyson 94:d7226b2c14b6 39
andrewboyson 94:d7226b2c14b6 40 const DISPLAY_LEAP_MS = 10000;
andrewboyson 94:d7226b2c14b6 41
andrewboyson 94:d7226b2c14b6 42 function parseLinesTime(text)
andrewboyson 14:c3c43c8faf0e 43 {
andrewboyson 94:d7226b2c14b6 44 let lines = text.split('\n');
andrewboyson 96:eb2eb75bad0f 45 rtc.ms = Ajax.date.getTime();
andrewboyson 94:d7226b2c14b6 46 rtc.ms += parseInt(lines[0], 16);
andrewboyson 95:8c9dda8a0caf 47 rtc.ms -= Ajax.ms;
andrewboyson 95:8c9dda8a0caf 48 diffMs = rtc.ms + Ajax.ms - Date.now();
andrewboyson 95:8c9dda8a0caf 49 rtcIsSet = Ajax.hexToBit(lines[1], 0);
andrewboyson 95:8c9dda8a0caf 50 clockIsSet = Ajax.hexToBit(lines[1], 1);
andrewboyson 95:8c9dda8a0caf 51 sourceIsOk = Ajax.hexToBit(lines[1], 2);
andrewboyson 95:8c9dda8a0caf 52 rateIsLocked = Ajax.hexToBit(lines[1], 3);
andrewboyson 95:8c9dda8a0caf 53 timeIsLocked = Ajax.hexToBit(lines[1], 4);
andrewboyson 95:8c9dda8a0caf 54 rtc.leapEnable = Ajax.hexToBit(lines[1], 5);
andrewboyson 95:8c9dda8a0caf 55 rtc.leapForward = Ajax.hexToBit(lines[1], 6);
andrewboyson 95:8c9dda8a0caf 56 govTrace = Ajax.hexToBit(lines[1], 7);
andrewboyson 95:8c9dda8a0caf 57 rtc.months1970 = parseInt(lines[2], 16);
andrewboyson 94:d7226b2c14b6 58 rtc.leaps = parseInt(lines[3], 16);
andrewboyson 14:c3c43c8faf0e 59 }
andrewboyson 94:d7226b2c14b6 60 function parseLinesGov(text)
andrewboyson 14:c3c43c8faf0e 61 {
andrewboyson 94:d7226b2c14b6 62 let lines = text.split('\n');
andrewboyson 94:d7226b2c14b6 63 ppb = parseInt(lines[0], 16);
andrewboyson 94:d7226b2c14b6 64 ppbdivisor = parseInt(lines[1], 16);
andrewboyson 94:d7226b2c14b6 65 ppbmaxchange = parseInt(lines[2], 16);
andrewboyson 94:d7226b2c14b6 66 syncedlimitppb = parseInt(lines[3], 16);
andrewboyson 94:d7226b2c14b6 67 syncedhysppb = parseInt(lines[4], 16);
andrewboyson 94:d7226b2c14b6 68 slewdivisor = parseInt(lines[5], 16);
andrewboyson 94:d7226b2c14b6 69 slewmax = parseInt(lines[6], 16);
andrewboyson 94:d7226b2c14b6 70 syncedlimitns = parseInt(lines[7], 16);
andrewboyson 94:d7226b2c14b6 71 syncedhysns = parseInt(lines[8], 16);
andrewboyson 94:d7226b2c14b6 72 maxoffsetsecs = parseInt(lines[9], 16);
andrewboyson 14:c3c43c8faf0e 73 }
andrewboyson 94:d7226b2c14b6 74 function parseLinesNtp(text)
andrewboyson 94:d7226b2c14b6 75 {
andrewboyson 94:d7226b2c14b6 76 let lines = text.split('\n');
andrewboyson 94:d7226b2c14b6 77 ntpserver = lines[0];
andrewboyson 94:d7226b2c14b6 78 ntpinitial = parseInt(lines[1], 16);
andrewboyson 94:d7226b2c14b6 79 ntpnormal = parseInt(lines[2], 16);
andrewboyson 94:d7226b2c14b6 80 ntpretry = parseInt(lines[3], 16);
andrewboyson 94:d7226b2c14b6 81 ntpoffset = parseInt(lines[4], 16);
andrewboyson 94:d7226b2c14b6 82 ntpmaxdelay = parseInt(lines[5], 16);
andrewboyson 94:d7226b2c14b6 83 }
andrewboyson 94:d7226b2c14b6 84 function parseLinesScan(text)
andrewboyson 14:c3c43c8faf0e 85 {
andrewboyson 94:d7226b2c14b6 86 let lines = text.split('\n');
andrewboyson 94:d7226b2c14b6 87 scanavg = parseInt(lines[0], 16);
andrewboyson 94:d7226b2c14b6 88 scanmax = parseInt(lines[1], 16);
andrewboyson 94:d7226b2c14b6 89 scanmin = parseInt(lines[2], 16);
andrewboyson 94:d7226b2c14b6 90 }
andrewboyson 95:8c9dda8a0caf 91 function parse()
andrewboyson 94:d7226b2c14b6 92 {
andrewboyson 95:8c9dda8a0caf 93 let topics = Ajax.response.split('\f');
andrewboyson 94:d7226b2c14b6 94 parseLinesTime(topics[0]);
andrewboyson 94:d7226b2c14b6 95 parseLinesGov (topics[1]);
andrewboyson 94:d7226b2c14b6 96 parseLinesNtp (topics[2]);
andrewboyson 94:d7226b2c14b6 97 parseLinesScan(topics[3]);
andrewboyson 94:d7226b2c14b6 98 }
andrewboyson 95:8c9dda8a0caf 99 function display()
andrewboyson 94:d7226b2c14b6 100 {
andrewboyson 94:d7226b2c14b6 101 let elem;
andrewboyson 95:8c9dda8a0caf 102 elem = Ajax.getElementOrNull('ajax-rtc-set' ); if (elem) elem.setAttribute('dir', rtcIsSet ? 'rtl' : 'ltr');
andrewboyson 95:8c9dda8a0caf 103 elem = Ajax.getElementOrNull('ajax-clock-set' ); if (elem) elem.setAttribute('dir', clockIsSet ? 'rtl' : 'ltr');
andrewboyson 95:8c9dda8a0caf 104 elem = Ajax.getElementOrNull('ajax-source-ok' ); if (elem) elem.setAttribute('dir', sourceIsOk ? 'rtl' : 'ltr');
andrewboyson 95:8c9dda8a0caf 105 elem = Ajax.getElementOrNull('ajax-rate-locked' ); if (elem) elem.setAttribute('dir', rateIsLocked ? 'rtl' : 'ltr');
andrewboyson 95:8c9dda8a0caf 106 elem = Ajax.getElementOrNull('ajax-time-locked' ); if (elem) elem.setAttribute('dir', timeIsLocked ? 'rtl' : 'ltr');
andrewboyson 14:c3c43c8faf0e 107
andrewboyson 95:8c9dda8a0caf 108 elem = Ajax.getElementOrNull('ajax-leap-enable' ); if (elem) elem.setAttribute('dir', rtc.leapEnable ? 'rtl' : 'ltr');
andrewboyson 95:8c9dda8a0caf 109 elem = Ajax.getElementOrNull('ajax-leap-forward' ); if (elem) elem.setAttribute('dir', rtc.leapForward ? 'rtl' : 'ltr');
andrewboyson 14:c3c43c8faf0e 110
andrewboyson 95:8c9dda8a0caf 111 elem = Ajax.getElementOrNull('ajax-leap-year' ); if (elem) elem.value = rtc.months1970 ? rtc.leapYear : '';
andrewboyson 95:8c9dda8a0caf 112 elem = Ajax.getElementOrNull('ajax-leap-month' ); if (elem) elem.value = rtc.months1970 ? rtc.leapMonth : '';
andrewboyson 94:d7226b2c14b6 113
andrewboyson 95:8c9dda8a0caf 114 elem = Ajax.getElementOrNull('ajax-leap-count' ); if (elem) elem.value = rtc.leaps;
andrewboyson 94:d7226b2c14b6 115
andrewboyson 95:8c9dda8a0caf 116 elem = Ajax.getElementOrNull('ajax-ppb' ); if (elem) elem.value = ppb;
andrewboyson 95:8c9dda8a0caf 117 elem = Ajax.getElementOrNull('ajax-ppb-divisor' ); if (elem) elem.value = ppbdivisor;
andrewboyson 95:8c9dda8a0caf 118 elem = Ajax.getElementOrNull('ajax-ppb-max-chg' ); if (elem) elem.value = ppbmaxchange;
andrewboyson 95:8c9dda8a0caf 119 elem = Ajax.getElementOrNull('ajax-ppb-syn-lim' ); if (elem) elem.value = syncedlimitppb;
andrewboyson 95:8c9dda8a0caf 120 elem = Ajax.getElementOrNull('ajax-ppb-syn-hys' ); if (elem) elem.value = syncedhysppb;
andrewboyson 95:8c9dda8a0caf 121 elem = Ajax.getElementOrNull('ajax-off-divisor' ); if (elem) elem.value = slewdivisor;
andrewboyson 95:8c9dda8a0caf 122 elem = Ajax.getElementOrNull('ajax-off-max' ); if (elem) elem.value = slewmax;
andrewboyson 95:8c9dda8a0caf 123 elem = Ajax.getElementOrNull('ajax-off-syn-lim' ); if (elem) elem.value = syncedlimitns / 1000000;
andrewboyson 95:8c9dda8a0caf 124 elem = Ajax.getElementOrNull('ajax-off-syn-hys' ); if (elem) elem.value = syncedhysns / 1000000;
andrewboyson 95:8c9dda8a0caf 125 elem = Ajax.getElementOrNull('ajax-off-rst-lim' ); if (elem) elem.value = maxoffsetsecs;
andrewboyson 95:8c9dda8a0caf 126 elem = Ajax.getElementOrNull('ajax-gov-trace' ); if (elem) elem.setAttribute('dir', govTrace ? 'rtl' : 'ltr');
andrewboyson 94:d7226b2c14b6 127
andrewboyson 95:8c9dda8a0caf 128 elem = Ajax.getElementOrNull('ajax-ntp-server' ); if (elem) elem.value = ntpserver;
andrewboyson 95:8c9dda8a0caf 129 elem = Ajax.getElementOrNull('ajax-ntp-initial' ); if (elem) elem.value = ntpinitial;
andrewboyson 95:8c9dda8a0caf 130 elem = Ajax.getElementOrNull('ajax-ntp-normal' ); if (elem) elem.value = ntpnormal / 60;
andrewboyson 95:8c9dda8a0caf 131 elem = Ajax.getElementOrNull('ajax-ntp-retry' ); if (elem) elem.value = ntpretry;
andrewboyson 95:8c9dda8a0caf 132 elem = Ajax.getElementOrNull('ajax-ntp-offset' ); if (elem) elem.value = ntpoffset;
andrewboyson 95:8c9dda8a0caf 133 elem = Ajax.getElementOrNull('ajax-ntp-max-delay'); if (elem) elem.value = ntpmaxdelay;
andrewboyson 94:d7226b2c14b6 134
andrewboyson 95:8c9dda8a0caf 135 elem = Ajax.getElementOrNull('ajax-scan-avg' ); if (elem) elem.textContent = scanavg;
andrewboyson 95:8c9dda8a0caf 136 elem = Ajax.getElementOrNull('ajax-scan-max' ); if (elem) elem.textContent = scanmax;
andrewboyson 95:8c9dda8a0caf 137 elem = Ajax.getElementOrNull('ajax-scan-min' ); if (elem) elem.textContent = scanmin;
andrewboyson 94:d7226b2c14b6 138
andrewboyson 95:8c9dda8a0caf 139 elem = Ajax.getElementOrNull('ajax-date-diff' ); if (elem) elem.textContent = diffMs;
andrewboyson 14:c3c43c8faf0e 140 }
andrewboyson 14:c3c43c8faf0e 141
andrewboyson 95:8c9dda8a0caf 142 function handleTick() //This typically called every 100ms
andrewboyson 14:c3c43c8faf0e 143 {
andrewboyson 94:d7226b2c14b6 144 if (pseudoDisplay)
andrewboyson 14:c3c43c8faf0e 145 {
andrewboyson 95:8c9dda8a0caf 146 pseudo.adjustLeap (Ajax.ms);
andrewboyson 95:8c9dda8a0caf 147 pseudo.displayTime(Ajax.ms);
andrewboyson 95:8c9dda8a0caf 148 if (Ajax.ms >= pseudoStartMs + DISPLAY_LEAP_MS + 500) pseudoDisplay = false;
andrewboyson 14:c3c43c8faf0e 149 }
andrewboyson 94:d7226b2c14b6 150 else
andrewboyson 94:d7226b2c14b6 151 {
andrewboyson 95:8c9dda8a0caf 152 rtc.adjustLeap (Ajax.ms);
andrewboyson 95:8c9dda8a0caf 153 rtc.displayTime(Ajax.ms);
andrewboyson 94:d7226b2c14b6 154 }
andrewboyson 14:c3c43c8faf0e 155 }
andrewboyson 14:c3c43c8faf0e 156
andrewboyson 95:8c9dda8a0caf 157 function displayLeap() //Called by display leap button in HTML
andrewboyson 14:c3c43c8faf0e 158 {
andrewboyson 94:d7226b2c14b6 159 pseudoDisplay = true;
andrewboyson 95:8c9dda8a0caf 160 pseudoStartMs = Ajax.ms;
andrewboyson 94:d7226b2c14b6 161
andrewboyson 94:d7226b2c14b6 162 pseudo.leapEnable = true;
andrewboyson 94:d7226b2c14b6 163 pseudo.leapForward = rtc.leapForward;
andrewboyson 94:d7226b2c14b6 164 pseudo.leaps = rtc.leaps;
andrewboyson 94:d7226b2c14b6 165 pseudo.leapMonth = rtc.leapMonth;
andrewboyson 94:d7226b2c14b6 166 pseudo.leapYear = rtc.leapYear;
andrewboyson 95:8c9dda8a0caf 167 pseudo.ms = Date.UTC(rtc.leapYear, rtc.leapMonth - 1, 1) - DISPLAY_LEAP_MS / 2 - Ajax.ms;
andrewboyson 14:c3c43c8faf0e 168 }
andrewboyson 95:8c9dda8a0caf 169 Ajax.server = '/clock-ajax';
andrewboyson 95:8c9dda8a0caf 170 Ajax.onResponse = function() { parse(); display(); };
andrewboyson 95:8c9dda8a0caf 171 Ajax.onTick = handleTick;
andrewboyson 95:8c9dda8a0caf 172 Ajax.init();