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:
Tue Apr 16 19:18:27 2019 +0000
Revision:
94:d7226b2c14b6
Parent:
77:4689596a2f3f
Child:
95:8c9dda8a0caf
Used a class for the utc time to handle both the server 'real' time and a pseudo 'next leap' time. Also split the includes into building blocks so that many of the js scripts could be made up from them.

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