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 May 11 11:00:00 2021 +0000
Revision:
160:daa94b75b94c
Parent:
159:bda5b89e8c19
CSS modified to not change the text colour when hovering over a disabled button: it still does for buttons which are enabled.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 130:9a5b8fe308f1 1 #include <stdio.h>
andrewboyson 130:9a5b8fe308f1 2 #include <stdlib.h>
andrewboyson 130:9a5b8fe308f1 3
andrewboyson 130:9a5b8fe308f1 4 static int hexToInt(char c)
andrewboyson 130:9a5b8fe308f1 5 {
andrewboyson 130:9a5b8fe308f1 6 int nibble;
andrewboyson 130:9a5b8fe308f1 7 if (c >= '0' && c <= '9') nibble = c - '0';
andrewboyson 130:9a5b8fe308f1 8 if (c >= 'A' && c <= 'F') nibble = c - 'A' + 0xA;
andrewboyson 130:9a5b8fe308f1 9 if (c >= 'a' && c <= 'f') nibble = c - 'a' + 0xA;
andrewboyson 130:9a5b8fe308f1 10 return nibble;
andrewboyson 130:9a5b8fe308f1 11 }
andrewboyson 130:9a5b8fe308f1 12 void HttpQueryUnencode(char* pValue)
andrewboyson 130:9a5b8fe308f1 13 {
andrewboyson 159:bda5b89e8c19 14 if (!pValue) return;
andrewboyson 130:9a5b8fe308f1 15 char* pDst = pValue;
andrewboyson 130:9a5b8fe308f1 16 int a;
andrewboyson 130:9a5b8fe308f1 17 for (char* pSrc = pValue; *pSrc; pSrc++)
andrewboyson 130:9a5b8fe308f1 18 {
andrewboyson 130:9a5b8fe308f1 19 char c = *pSrc;
andrewboyson 130:9a5b8fe308f1 20 switch (c)
andrewboyson 130:9a5b8fe308f1 21 {
andrewboyson 130:9a5b8fe308f1 22 case '+':
andrewboyson 130:9a5b8fe308f1 23 c = ' ';
andrewboyson 130:9a5b8fe308f1 24 break;
andrewboyson 130:9a5b8fe308f1 25 case '%':
andrewboyson 130:9a5b8fe308f1 26 c = *++pSrc;
andrewboyson 130:9a5b8fe308f1 27 if (c == 0) break;
andrewboyson 130:9a5b8fe308f1 28 a = hexToInt(c);
andrewboyson 130:9a5b8fe308f1 29 a <<= 4;
andrewboyson 130:9a5b8fe308f1 30 c = *++pSrc;
andrewboyson 130:9a5b8fe308f1 31 if (c == 0) break;
andrewboyson 130:9a5b8fe308f1 32 a += hexToInt(c);
andrewboyson 130:9a5b8fe308f1 33 c = a;
andrewboyson 130:9a5b8fe308f1 34 break;
andrewboyson 130:9a5b8fe308f1 35 default:
andrewboyson 130:9a5b8fe308f1 36 c = *pSrc;
andrewboyson 130:9a5b8fe308f1 37 break;
andrewboyson 130:9a5b8fe308f1 38 }
andrewboyson 130:9a5b8fe308f1 39 *pDst++ = c;
andrewboyson 130:9a5b8fe308f1 40 }
andrewboyson 130:9a5b8fe308f1 41 *pDst = 0;
andrewboyson 130:9a5b8fe308f1 42 }
andrewboyson 130:9a5b8fe308f1 43 char* HttpQuerySplit(char* p, char** ppName, char** ppValue) //returns the start of the next name value pair
andrewboyson 130:9a5b8fe308f1 44 {
andrewboyson 130:9a5b8fe308f1 45 *ppName = p; //Record the start of the name
andrewboyson 130:9a5b8fe308f1 46 *ppValue = NULL;
andrewboyson 130:9a5b8fe308f1 47
andrewboyson 130:9a5b8fe308f1 48 while (*p != '=') //Loop to an '='
andrewboyson 130:9a5b8fe308f1 49 {
andrewboyson 130:9a5b8fe308f1 50 if (*p == 0) return 0;
andrewboyson 130:9a5b8fe308f1 51 p++;
andrewboyson 130:9a5b8fe308f1 52 }
andrewboyson 130:9a5b8fe308f1 53 *p = 0; //Terminate the name by replacing the '=' with a NUL char
andrewboyson 130:9a5b8fe308f1 54 p++; //Move on to the start of the value
andrewboyson 130:9a5b8fe308f1 55 *ppValue = p; //Record the start of the value
andrewboyson 130:9a5b8fe308f1 56 while (*p != '&') //Loop to a '&'
andrewboyson 130:9a5b8fe308f1 57 {
andrewboyson 130:9a5b8fe308f1 58 if (*p == 0) return 0;
andrewboyson 130:9a5b8fe308f1 59 p++;
andrewboyson 130:9a5b8fe308f1 60 }
andrewboyson 130:9a5b8fe308f1 61 *p = 0; //Terminate the value by replacing the '&' with a NULL
andrewboyson 130:9a5b8fe308f1 62 return p + 1;
andrewboyson 130:9a5b8fe308f1 63 }
andrewboyson 130:9a5b8fe308f1 64 int HttpQueryValueAsInt(char* pValue)
andrewboyson 130:9a5b8fe308f1 65 {
andrewboyson 159:bda5b89e8c19 66 if (pValue) return (int)strtol(pValue, NULL, 10);
andrewboyson 159:bda5b89e8c19 67 return 0;
andrewboyson 130:9a5b8fe308f1 68 }
andrewboyson 141:1dac268a197d 69 double HttpQueryValueAsDouble(char* pValue)
andrewboyson 141:1dac268a197d 70 {
andrewboyson 141:1dac268a197d 71 return strtod(pValue, NULL);
andrewboyson 141:1dac268a197d 72 }
andrewboyson 130:9a5b8fe308f1 73 char* HttpCookiesSplit(char* p, char** ppName, char** ppValue) //returns the start of the next name value pair
andrewboyson 130:9a5b8fe308f1 74 {
andrewboyson 130:9a5b8fe308f1 75 *ppValue = NULL;
andrewboyson 130:9a5b8fe308f1 76 *ppName = NULL;
andrewboyson 130:9a5b8fe308f1 77
andrewboyson 130:9a5b8fe308f1 78 *ppName = p; //Record the start of the name
andrewboyson 130:9a5b8fe308f1 79 while (*p != '=') //Loop to an '='
andrewboyson 130:9a5b8fe308f1 80 {
andrewboyson 130:9a5b8fe308f1 81 if (*p == 0) return 0;
andrewboyson 130:9a5b8fe308f1 82 p++;
andrewboyson 130:9a5b8fe308f1 83 }
andrewboyson 130:9a5b8fe308f1 84 *p = 0; //Terminate the name by replacing the '=' with a NUL char
andrewboyson 130:9a5b8fe308f1 85 p++; //Move on to the start of the value
andrewboyson 130:9a5b8fe308f1 86 *ppValue = p; //Record the start of the value
andrewboyson 130:9a5b8fe308f1 87 while (*p != ';') //Loop to a ';'
andrewboyson 130:9a5b8fe308f1 88 {
andrewboyson 130:9a5b8fe308f1 89 if (*p == 0) return 0;
andrewboyson 130:9a5b8fe308f1 90 p++;
andrewboyson 130:9a5b8fe308f1 91 }
andrewboyson 130:9a5b8fe308f1 92 *p = 0; //Terminate the value by replacing the ';' with a NULL
andrewboyson 130:9a5b8fe308f1 93 p++;
andrewboyson 130:9a5b8fe308f1 94 if (*p == 0) return 0;
andrewboyson 130:9a5b8fe308f1 95 while (*p == ' ') p++; //Move past any spaces after the ';'
andrewboyson 130:9a5b8fe308f1 96 return p;
andrewboyson 130:9a5b8fe308f1 97 }