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 Sep 24 18:16:47 2019 +0000
Revision:
130:9a5b8fe308f1
Child:
134:3d0abf4cd097
Added http

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 130:9a5b8fe308f1 1 #include "http.h"
andrewboyson 130:9a5b8fe308f1 2 #include "http-connection.h"
andrewboyson 130:9a5b8fe308f1 3 #include "web.h"
andrewboyson 130:9a5b8fe308f1 4 #include "mstimer.h"
andrewboyson 130:9a5b8fe308f1 5 #include "log.h"
andrewboyson 130:9a5b8fe308f1 6
andrewboyson 130:9a5b8fe308f1 7 bool HttpGetTrace()
andrewboyson 130:9a5b8fe308f1 8 {
andrewboyson 130:9a5b8fe308f1 9 return WebTrace;
andrewboyson 130:9a5b8fe308f1 10 }
andrewboyson 130:9a5b8fe308f1 11
andrewboyson 130:9a5b8fe308f1 12 void HttpReset(int connection)
andrewboyson 130:9a5b8fe308f1 13 {
andrewboyson 130:9a5b8fe308f1 14 HttpConnectionReset(connection);
andrewboyson 130:9a5b8fe308f1 15 }
andrewboyson 130:9a5b8fe308f1 16 bool HttpResponse(int connection, bool clientFinished, int* pWindowSize, char* pWindow, uint32_t windowPositionInStream)
andrewboyson 130:9a5b8fe308f1 17 {
andrewboyson 130:9a5b8fe308f1 18 int status = HttpPoll(connection, clientFinished);
andrewboyson 130:9a5b8fe308f1 19 bool finished;
andrewboyson 130:9a5b8fe308f1 20 switch (status)
andrewboyson 130:9a5b8fe308f1 21 {
andrewboyson 130:9a5b8fe308f1 22 case HTTP_WAIT: finished = false; *pWindowSize = 0; break;
andrewboyson 130:9a5b8fe308f1 23 case HTTP_FINISHED: finished = true; *pWindowSize = 0; break;
andrewboyson 130:9a5b8fe308f1 24 case HTTP_HAVE_SOMETHING_TO_SEND: finished = HttpAdd(connection, pWindowSize, pWindow, windowPositionInStream); break;
andrewboyson 130:9a5b8fe308f1 25 }
andrewboyson 130:9a5b8fe308f1 26 return finished;
andrewboyson 130:9a5b8fe308f1 27 }
andrewboyson 130:9a5b8fe308f1 28 bool HttpAdd(int connectionId, int* pWindowSize, char* pWindow, uint32_t windowPositionInStream)
andrewboyson 130:9a5b8fe308f1 29 {
andrewboyson 130:9a5b8fe308f1 30 HttpAddStart(windowPositionInStream, *pWindowSize, pWindow); //We have something to send so start the buffer
andrewboyson 130:9a5b8fe308f1 31 *pWindowSize = 0;
andrewboyson 130:9a5b8fe308f1 32
andrewboyson 130:9a5b8fe308f1 33 struct HttpConnection* pConnection = HttpConnectionOrNull(connectionId);
andrewboyson 130:9a5b8fe308f1 34 if (!pConnection) return false; //Protects the gap between the connection being established and the request being started
andrewboyson 130:9a5b8fe308f1 35
andrewboyson 130:9a5b8fe308f1 36 int todo = pConnection->toDo; //Make a copy so that we don't modify todo in the state
andrewboyson 130:9a5b8fe308f1 37
andrewboyson 130:9a5b8fe308f1 38 WebAddResponse(todo);
andrewboyson 130:9a5b8fe308f1 39
andrewboyson 130:9a5b8fe308f1 40 *pWindowSize = HttpAddLength();
andrewboyson 130:9a5b8fe308f1 41
andrewboyson 130:9a5b8fe308f1 42 return !HttpAddFilled(); //If we haven't used a full buffer then we have finished
andrewboyson 130:9a5b8fe308f1 43 }
andrewboyson 130:9a5b8fe308f1 44 int HttpPoll(int connectionId, bool clientFinished)
andrewboyson 130:9a5b8fe308f1 45 {
andrewboyson 130:9a5b8fe308f1 46 struct HttpConnection* pConnection = HttpConnectionOrNull(connectionId);
andrewboyson 130:9a5b8fe308f1 47 if (!pConnection) return HTTP_WAIT; //Protects the gap between the connection being established and the request being started
andrewboyson 130:9a5b8fe308f1 48
andrewboyson 130:9a5b8fe308f1 49 if (!pConnection->toDo)
andrewboyson 130:9a5b8fe308f1 50 {
andrewboyson 130:9a5b8fe308f1 51 if (clientFinished) return HTTP_FINISHED; //The client hasn't requested anything and never will so finish
andrewboyson 130:9a5b8fe308f1 52 else return HTTP_WAIT; //The client hasn't requested anything yet but still could
andrewboyson 130:9a5b8fe308f1 53 }
andrewboyson 130:9a5b8fe308f1 54 if (!pConnection->postComplete ) return HTTP_WAIT; //Wait for the request (usually a POST) to finish
andrewboyson 130:9a5b8fe308f1 55 if (!MsTimerAbsolute(pConnection->delayUntil)) return HTTP_WAIT; //Wait a while (usually after a LOGIN attempt)
andrewboyson 130:9a5b8fe308f1 56
andrewboyson 130:9a5b8fe308f1 57 return HTTP_HAVE_SOMETHING_TO_SEND;
andrewboyson 130:9a5b8fe308f1 58 }
andrewboyson 130:9a5b8fe308f1 59 void HttpRequest(int connectionId, int windowSize, char* pWindow, uint32_t windowPositionInStream)
andrewboyson 130:9a5b8fe308f1 60 {
andrewboyson 130:9a5b8fe308f1 61 struct HttpConnection* pConnection;
andrewboyson 130:9a5b8fe308f1 62 if (!windowPositionInStream)
andrewboyson 130:9a5b8fe308f1 63 {
andrewboyson 130:9a5b8fe308f1 64 pConnection = HttpConnectionNew(connectionId);
andrewboyson 130:9a5b8fe308f1 65 }
andrewboyson 130:9a5b8fe308f1 66 else
andrewboyson 130:9a5b8fe308f1 67 {
andrewboyson 130:9a5b8fe308f1 68 pConnection = HttpConnectionOrNull(connectionId);
andrewboyson 130:9a5b8fe308f1 69 if (!pConnection)
andrewboyson 130:9a5b8fe308f1 70 {
andrewboyson 130:9a5b8fe308f1 71 LogTimeF("WebRequest - no connection corresponds to id %d\r\n", connectionId);
andrewboyson 130:9a5b8fe308f1 72 return;
andrewboyson 130:9a5b8fe308f1 73 }
andrewboyson 130:9a5b8fe308f1 74 }
andrewboyson 130:9a5b8fe308f1 75
andrewboyson 130:9a5b8fe308f1 76 pConnection->delayUntil = MsTimerCount; //Default to no delay unless modified;
andrewboyson 130:9a5b8fe308f1 77
andrewboyson 130:9a5b8fe308f1 78 //Handle request for the first packet of data received but leave todo the same after that.
andrewboyson 130:9a5b8fe308f1 79 int contentLength = 0;
andrewboyson 130:9a5b8fe308f1 80 int contentStart = 0;
andrewboyson 130:9a5b8fe308f1 81 if (windowSize && windowPositionInStream == 0)
andrewboyson 130:9a5b8fe308f1 82 {
andrewboyson 130:9a5b8fe308f1 83 //Read the headers
andrewboyson 130:9a5b8fe308f1 84 char* pMethod;
andrewboyson 130:9a5b8fe308f1 85 char* pPath;
andrewboyson 130:9a5b8fe308f1 86 char* pQuery;
andrewboyson 130:9a5b8fe308f1 87 char* pLastModified;
andrewboyson 130:9a5b8fe308f1 88 char* pCookies;
andrewboyson 130:9a5b8fe308f1 89 contentStart = HttpRequestRead(pWindow, windowSize, &pMethod, &pPath, &pQuery, &pLastModified, &pCookies, &contentLength);
andrewboyson 130:9a5b8fe308f1 90
andrewboyson 130:9a5b8fe308f1 91 //Ask the web server what to do
andrewboyson 130:9a5b8fe308f1 92 pConnection->toDo = WebDecideWhatToDo(pPath, pLastModified);
andrewboyson 130:9a5b8fe308f1 93
andrewboyson 130:9a5b8fe308f1 94 //Handle the query
andrewboyson 130:9a5b8fe308f1 95 int stop = WebHandleQuery(pQuery, pCookies, &pConnection->toDo, &pConnection->delayUntil); //return -1 on stop; 0 on continue
andrewboyson 130:9a5b8fe308f1 96 if (stop)
andrewboyson 130:9a5b8fe308f1 97 {
andrewboyson 130:9a5b8fe308f1 98 pConnection->postComplete = true;
andrewboyson 130:9a5b8fe308f1 99 return;
andrewboyson 130:9a5b8fe308f1 100 }
andrewboyson 130:9a5b8fe308f1 101 }
andrewboyson 130:9a5b8fe308f1 102
andrewboyson 130:9a5b8fe308f1 103 //Do the upload of anything that needs it. Todos it doesn't understand are ignored.
andrewboyson 130:9a5b8fe308f1 104 if (!pConnection->postComplete) WebHandlePost(pConnection->toDo, contentLength, contentStart, windowSize, pWindow, windowPositionInStream, &pConnection->postComplete);
andrewboyson 130:9a5b8fe308f1 105 }