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
Parent:
119:794e5985d6c8
Child:
138:44d84506b2f6
Added http

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 109:3e82f62c7e1f 1 #include <stdio.h>
andrewboyson 109:3e82f62c7e1f 2
andrewboyson 109:3e82f62c7e1f 3 #include "http.h"
andrewboyson 109:3e82f62c7e1f 4 #include "web-nav-base.h"
andrewboyson 112:f29bb9b99059 5 #include "web-nav-this.h"
andrewboyson 109:3e82f62c7e1f 6 #include "web-site-name.h"
andrewboyson 109:3e82f62c7e1f 7 #include "mac.h"
andrewboyson 109:3e82f62c7e1f 8 #include "ip4addr.h"
andrewboyson 109:3e82f62c7e1f 9 #include "ip6addr.h"
andrewboyson 109:3e82f62c7e1f 10
andrewboyson 119:794e5985d6c8 11 void WebAddNavItem(int highlight, const char* href, const char* title)
andrewboyson 109:3e82f62c7e1f 12 {
andrewboyson 109:3e82f62c7e1f 13 char *p;
andrewboyson 109:3e82f62c7e1f 14 HttpAddText("<li ");
andrewboyson 109:3e82f62c7e1f 15 if (highlight) p = "class='this'";
andrewboyson 109:3e82f62c7e1f 16 else p = " ";
andrewboyson 109:3e82f62c7e1f 17 HttpAddText(p);
andrewboyson 109:3e82f62c7e1f 18 HttpAddText("><a href='");
andrewboyson 109:3e82f62c7e1f 19 HttpAddText(href);
andrewboyson 109:3e82f62c7e1f 20 HttpAddText("'>");
andrewboyson 109:3e82f62c7e1f 21 HttpAddText(title);
andrewboyson 109:3e82f62c7e1f 22 HttpAddText("</a></li>\r\n");
andrewboyson 109:3e82f62c7e1f 23 }
andrewboyson 109:3e82f62c7e1f 24 void WebAddNav(int page)
andrewboyson 109:3e82f62c7e1f 25 {
andrewboyson 109:3e82f62c7e1f 26 HttpAddText("<a class='tab-shortcut' href='#main-content'>Skip to content</a>\r\n");
andrewboyson 109:3e82f62c7e1f 27
andrewboyson 109:3e82f62c7e1f 28 HttpAddText("<nav><ul>\r\n");
andrewboyson 112:f29bb9b99059 29 WebNavThis(page);
andrewboyson 109:3e82f62c7e1f 30 WebNavBase(page);
andrewboyson 109:3e82f62c7e1f 31 HttpAddText("</ul></nav>\r\n");
andrewboyson 109:3e82f62c7e1f 32 }
andrewboyson 109:3e82f62c7e1f 33
andrewboyson 109:3e82f62c7e1f 34 void WebAddHeader(const char* title, const char* style, const char* script)
andrewboyson 109:3e82f62c7e1f 35 {
andrewboyson 109:3e82f62c7e1f 36 HttpAddText("<!DOCTYPE html>\r\n"
andrewboyson 109:3e82f62c7e1f 37 "<html>\r\n"
andrewboyson 109:3e82f62c7e1f 38 "<head>\r\n");
andrewboyson 109:3e82f62c7e1f 39 HttpAddText(" <title>");
andrewboyson 109:3e82f62c7e1f 40 HttpAddText(WEB_SITE_NAME);
andrewboyson 109:3e82f62c7e1f 41 if (title)
andrewboyson 109:3e82f62c7e1f 42 {
andrewboyson 109:3e82f62c7e1f 43 HttpAddText(" - ");
andrewboyson 109:3e82f62c7e1f 44 HttpAddText(title);
andrewboyson 109:3e82f62c7e1f 45 }
andrewboyson 109:3e82f62c7e1f 46 HttpAddText("</title>\r\n");
andrewboyson 109:3e82f62c7e1f 47
andrewboyson 109:3e82f62c7e1f 48 HttpAddText(" <link rel='stylesheet' href='/base.css' type='text/css'/>\r\n");
andrewboyson 109:3e82f62c7e1f 49 if (style)
andrewboyson 109:3e82f62c7e1f 50 {
andrewboyson 109:3e82f62c7e1f 51 HttpAddText(" <link rel='stylesheet' href='/");
andrewboyson 109:3e82f62c7e1f 52 HttpAddText(style);
andrewboyson 109:3e82f62c7e1f 53 HttpAddText("' type='text/css'/>\r\n");
andrewboyson 109:3e82f62c7e1f 54 }
andrewboyson 109:3e82f62c7e1f 55 if (script)
andrewboyson 109:3e82f62c7e1f 56 {
andrewboyson 109:3e82f62c7e1f 57 HttpAddText(" <script src='/");
andrewboyson 109:3e82f62c7e1f 58 HttpAddText(script);
andrewboyson 109:3e82f62c7e1f 59 HttpAddText("' type='text/javascript'></script>\r\n");
andrewboyson 109:3e82f62c7e1f 60 }
andrewboyson 109:3e82f62c7e1f 61 HttpAddText(" <meta name='viewport' content='width=device-width, initial-scale=1'>\r\n"
andrewboyson 109:3e82f62c7e1f 62 " <link rel='icon' href='/favicon.ico' type='image/x-icon'/>\r\n"
andrewboyson 109:3e82f62c7e1f 63 "</head>\r\n"
andrewboyson 109:3e82f62c7e1f 64 "<body>\r\n");
andrewboyson 109:3e82f62c7e1f 65
andrewboyson 109:3e82f62c7e1f 66 }
andrewboyson 109:3e82f62c7e1f 67 void WebAddH1(const char* pageName)
andrewboyson 109:3e82f62c7e1f 68 {
andrewboyson 109:3e82f62c7e1f 69 HttpAddText("<h1 id='main-content'>");
andrewboyson 109:3e82f62c7e1f 70 HttpAddText(WEB_SITE_NAME);
andrewboyson 109:3e82f62c7e1f 71 HttpAddText(" - ");
andrewboyson 109:3e82f62c7e1f 72 HttpAddText(pageName);
andrewboyson 109:3e82f62c7e1f 73 HttpAddText("</h1>\r\n");
andrewboyson 109:3e82f62c7e1f 74 }
andrewboyson 109:3e82f62c7e1f 75 void WebAddH2(const char* text)
andrewboyson 109:3e82f62c7e1f 76 {
andrewboyson 109:3e82f62c7e1f 77 HttpAddText("<h2>");
andrewboyson 109:3e82f62c7e1f 78 HttpAddText(text);
andrewboyson 109:3e82f62c7e1f 79 HttpAddText("</h2>\r\n");
andrewboyson 109:3e82f62c7e1f 80 }
andrewboyson 109:3e82f62c7e1f 81 void WebAddEnd()
andrewboyson 109:3e82f62c7e1f 82 {
andrewboyson 109:3e82f62c7e1f 83 HttpAddText("</body>\r\n"
andrewboyson 109:3e82f62c7e1f 84 "</html>\r\n");
andrewboyson 109:3e82f62c7e1f 85 }
andrewboyson 109:3e82f62c7e1f 86
andrewboyson 119:794e5985d6c8 87 void WebAddLabelledPrefixSuffix(const char* label, const char* prefix, const char* text, const char* suffix)
andrewboyson 109:3e82f62c7e1f 88 {
andrewboyson 109:3e82f62c7e1f 89 HttpAddText("<div class='line'>\r\n");
andrewboyson 109:3e82f62c7e1f 90 HttpAddF (" <div>%s</div>\r\n", label);
andrewboyson 109:3e82f62c7e1f 91 HttpAddF (" <div>%s%s%s</div>\r\n", prefix, text, suffix);
andrewboyson 109:3e82f62c7e1f 92 HttpAddText("</div>\r\n");
andrewboyson 109:3e82f62c7e1f 93 }
andrewboyson 119:794e5985d6c8 94 void WebAddLabelledText(const char* label, const char* text)
andrewboyson 109:3e82f62c7e1f 95 {
andrewboyson 109:3e82f62c7e1f 96 HttpAddText("<div class='line'>\r\n");
andrewboyson 109:3e82f62c7e1f 97 HttpAddF (" <div>%s</div>\r\n", label);
andrewboyson 109:3e82f62c7e1f 98 HttpAddF (" <div>%s</div>\r\n", text);
andrewboyson 109:3e82f62c7e1f 99 HttpAddText("</div>\r\n");
andrewboyson 109:3e82f62c7e1f 100 }
andrewboyson 109:3e82f62c7e1f 101
andrewboyson 119:794e5985d6c8 102 void WebAddLabelledMac(const char* label, const char* mac)
andrewboyson 109:3e82f62c7e1f 103 {
andrewboyson 109:3e82f62c7e1f 104 HttpAddText("<div class='line'>\r\n");
andrewboyson 109:3e82f62c7e1f 105 HttpAddF (" <div>%s</div>\r\n", label);
andrewboyson 109:3e82f62c7e1f 106 HttpAddText(" <div>"); MacHttp(mac); HttpAddText("</div>\r\n");
andrewboyson 109:3e82f62c7e1f 107 HttpAddText("</div>\r\n");
andrewboyson 109:3e82f62c7e1f 108 }
andrewboyson 109:3e82f62c7e1f 109
andrewboyson 119:794e5985d6c8 110 void WebAddLabelledIp4(const char* label, uint32_t ip)
andrewboyson 109:3e82f62c7e1f 111 {
andrewboyson 109:3e82f62c7e1f 112 HttpAddText("<div class='line'>\r\n");
andrewboyson 109:3e82f62c7e1f 113 HttpAddF (" <div>%s</div>\r\n", label);
andrewboyson 109:3e82f62c7e1f 114 HttpAddText(" <div>"); Ip4AddressHttp(ip); HttpAddText("</div>\r\n");
andrewboyson 109:3e82f62c7e1f 115 HttpAddText("</div>\r\n");
andrewboyson 109:3e82f62c7e1f 116 }
andrewboyson 109:3e82f62c7e1f 117
andrewboyson 119:794e5985d6c8 118 void WebAddLabelledIp6(const char* label, const char* ip)
andrewboyson 109:3e82f62c7e1f 119 {
andrewboyson 109:3e82f62c7e1f 120 HttpAddText("<div class='line'>\r\n");
andrewboyson 109:3e82f62c7e1f 121 HttpAddF (" <div>%s</div>\r\n", label);
andrewboyson 109:3e82f62c7e1f 122 HttpAddText(" <div>"); Ip6AddressHttp(ip); HttpAddText("</div>\r\n");
andrewboyson 109:3e82f62c7e1f 123 HttpAddText("</div>\r\n");
andrewboyson 109:3e82f62c7e1f 124 }
andrewboyson 119:794e5985d6c8 125 void WebAddLabelledOnOff(const char* label, bool value)
andrewboyson 109:3e82f62c7e1f 126 {
andrewboyson 109:3e82f62c7e1f 127 if (value) WebAddLabelledText(label, "On");
andrewboyson 109:3e82f62c7e1f 128 else WebAddLabelledText(label, "Off");
andrewboyson 109:3e82f62c7e1f 129 }
andrewboyson 119:794e5985d6c8 130 void WebAddLabelledLed(const char* label, bool value)
andrewboyson 118:53430a2a2595 131 {
andrewboyson 118:53430a2a2595 132 HttpAddText("<div class='line'>\r\n");
andrewboyson 118:53430a2a2595 133 HttpAddF (" <div>%s</div>\r\n", label);
andrewboyson 118:53430a2a2595 134 HttpAddF (" <div class='led' dir='%s'></div>\r\n", value ? "rtl" : "ltr");
andrewboyson 118:53430a2a2595 135 HttpAddText("</div>\r\n");
andrewboyson 118:53430a2a2595 136 }
andrewboyson 119:794e5985d6c8 137 void WebAddLabelledInt(const char* label, int value)
andrewboyson 109:3e82f62c7e1f 138 {
andrewboyson 109:3e82f62c7e1f 139 char text[30];
andrewboyson 109:3e82f62c7e1f 140 snprintf(text, sizeof(text), "%8d", value); //Right align with enough spaces so that the length is always constant.
andrewboyson 109:3e82f62c7e1f 141 WebAddLabelledText(label, text);
andrewboyson 109:3e82f62c7e1f 142 }
andrewboyson 119:794e5985d6c8 143 void WebAddInputText(const char* label, float inputwidth, const char* value, const char* action, const char* name)
andrewboyson 109:3e82f62c7e1f 144 {
andrewboyson 109:3e82f62c7e1f 145 HttpAddF ("<form action='%s' method='get'>\r\n", action);
andrewboyson 109:3e82f62c7e1f 146 HttpAddText("<div class='line'>\r\n");
andrewboyson 109:3e82f62c7e1f 147 HttpAddF (" <div>%s</div>\r\n", label);
andrewboyson 109:3e82f62c7e1f 148 HttpAddF (" <input type='text' name='%s' style='width:%.1fem;' value='%s'>\r\n", name, inputwidth, value);
andrewboyson 109:3e82f62c7e1f 149 HttpAddText("</div>\r\n");
andrewboyson 109:3e82f62c7e1f 150 HttpAddText("<input type='submit' value='Set' style='display:none;'>\r\n");
andrewboyson 109:3e82f62c7e1f 151 HttpAddF ("</form>\r\n");
andrewboyson 109:3e82f62c7e1f 152
andrewboyson 109:3e82f62c7e1f 153 }
andrewboyson 119:794e5985d6c8 154 void WebAddInputInt(const char* label, float inputwidth, int value, const char* action, const char* name)
andrewboyson 109:3e82f62c7e1f 155 {
andrewboyson 109:3e82f62c7e1f 156 char text[30];
andrewboyson 109:3e82f62c7e1f 157 snprintf(text, sizeof(text), "%d", value);
andrewboyson 109:3e82f62c7e1f 158 WebAddInputText(label, inputwidth, text, action, name);
andrewboyson 109:3e82f62c7e1f 159 }
andrewboyson 119:794e5985d6c8 160 void WebAddInputButton(const char* label, const char* value, const char* action, const char* name)
andrewboyson 109:3e82f62c7e1f 161 {
andrewboyson 109:3e82f62c7e1f 162 HttpAddF ("<form action='%s' method='get'>\r\n", action);
andrewboyson 109:3e82f62c7e1f 163 HttpAddF ("<input type='hidden' name='%s'>\r\n", name);
andrewboyson 109:3e82f62c7e1f 164 HttpAddText("<div class='line'>\r\n");
andrewboyson 109:3e82f62c7e1f 165 HttpAddF (" <div>%s</div>\r\n", label);
andrewboyson 109:3e82f62c7e1f 166 HttpAddF (" <input type='submit' value='%s'>\r\n", value);
andrewboyson 109:3e82f62c7e1f 167 HttpAddText("</div>\r\n");
andrewboyson 109:3e82f62c7e1f 168 HttpAddText("</form>\r\n");
andrewboyson 109:3e82f62c7e1f 169 }
andrewboyson 119:794e5985d6c8 170 void WebAddAjaxInputToggle(const char* label, const char* id, const char* name)
andrewboyson 109:3e82f62c7e1f 171 {
andrewboyson 109:3e82f62c7e1f 172 HttpAddText("<div class='line'>\r\n");
andrewboyson 109:3e82f62c7e1f 173 HttpAddF (" <div>%s</div>\r\n", label);
andrewboyson 109:3e82f62c7e1f 174 HttpAddF (" <div class='toggle' id='%s' tabindex='0' dir='ltr' onclick='AjaxRequest(\"%s=1\")' onkeydown='return event.keyCode != 13 || AjaxRequest(\"%s=1\")'>\r\n", id, name, name);
andrewboyson 109:3e82f62c7e1f 175 HttpAddText(" <div class='slot'></div><div class='knob'></div>\r\n");
andrewboyson 109:3e82f62c7e1f 176 HttpAddText(" </div>\r\n");
andrewboyson 109:3e82f62c7e1f 177 HttpAddText("</div>\r\n");
andrewboyson 109:3e82f62c7e1f 178 }
andrewboyson 119:794e5985d6c8 179 void WebAddAjaxLed(const char* label, const char* id)
andrewboyson 109:3e82f62c7e1f 180 {
andrewboyson 109:3e82f62c7e1f 181 HttpAddText("<div class='line'>\r\n");
andrewboyson 109:3e82f62c7e1f 182 HttpAddF (" <div>%s</div>\r\n", label);
andrewboyson 109:3e82f62c7e1f 183 HttpAddF (" <div class='led' id='%s' dir='ltr'></div>\r\n", id);
andrewboyson 109:3e82f62c7e1f 184 HttpAddText("</div>\r\n");
andrewboyson 109:3e82f62c7e1f 185 }
andrewboyson 119:794e5985d6c8 186 void WebAddAjaxInput(const char* label, float inputwidth, const char* id, const char* name)
andrewboyson 109:3e82f62c7e1f 187 {
andrewboyson 109:3e82f62c7e1f 188 HttpAddText("<div class='line'>\r\n");
andrewboyson 109:3e82f62c7e1f 189 HttpAddF (" <div>%s</div>\r\n", label);
andrewboyson 109:3e82f62c7e1f 190 HttpAddF (" <input type='text' style='width:%.1fem;' id='%s' onchange='AjaxRequest(\"%s=\" + this.value)'>\r\n", inputwidth, id, name);
andrewboyson 109:3e82f62c7e1f 191 HttpAddText("</div>\r\n");
andrewboyson 109:3e82f62c7e1f 192 }
andrewboyson 119:794e5985d6c8 193 void WebAddAjaxInputSuffix(const char* label, float inputwidth, const char* id, const char* name, const char* suffix)
andrewboyson 109:3e82f62c7e1f 194 {
andrewboyson 109:3e82f62c7e1f 195 HttpAddText("<div class='line'>\r\n");
andrewboyson 109:3e82f62c7e1f 196 HttpAddF (" <div>%s</div>\r\n", label);
andrewboyson 109:3e82f62c7e1f 197 HttpAddF (" <input type='text' style='width:%.1fem;' id='%s' onchange='AjaxRequest(\"%s=\" + this.value)'>%s\r\n", inputwidth, id, name, suffix);
andrewboyson 109:3e82f62c7e1f 198 HttpAddText("</div>\r\n");
andrewboyson 109:3e82f62c7e1f 199 }
andrewboyson 119:794e5985d6c8 200 void WebAddAjaxLabelled(const char* label, const char* id)
andrewboyson 109:3e82f62c7e1f 201 {
andrewboyson 109:3e82f62c7e1f 202 HttpAddText("<div class='line'>\r\n");
andrewboyson 109:3e82f62c7e1f 203 HttpAddF (" <div>%s</div>\r\n", label);
andrewboyson 109:3e82f62c7e1f 204 HttpAddF (" <div id='%s'></div>\r\n", id);
andrewboyson 109:3e82f62c7e1f 205 HttpAddText("</div>\r\n");
andrewboyson 109:3e82f62c7e1f 206 }
andrewboyson 119:794e5985d6c8 207 void WebAddAjaxLabelledSuffix(const char* label, const char* id, const char* suffix)
andrewboyson 109:3e82f62c7e1f 208 {
andrewboyson 109:3e82f62c7e1f 209 HttpAddText("<div class='line'>\r\n");
andrewboyson 109:3e82f62c7e1f 210 HttpAddF (" <div>%s</div>\r\n", label);
andrewboyson 109:3e82f62c7e1f 211 HttpAddF (" <div><span id='%s'></span>%s</div>\r\n", id, suffix);
andrewboyson 109:3e82f62c7e1f 212 HttpAddText("</div>\r\n");
andrewboyson 109:3e82f62c7e1f 213 }
andrewboyson 119:794e5985d6c8 214 void WebAddAjaxInputLabelId(const char* labelId, float inputwidth, const char* id, const char* name)
andrewboyson 109:3e82f62c7e1f 215 {
andrewboyson 109:3e82f62c7e1f 216 HttpAddText("<div class='line'>\r\n");
andrewboyson 109:3e82f62c7e1f 217 HttpAddF (" <div id='%s'></div>\r\n", labelId);
andrewboyson 109:3e82f62c7e1f 218 HttpAddF (" <input type='text' style='width:%.1fem;' id='%s' onchange='AjaxRequest(\"%s=\" + this.value)'>\r\n", inputwidth, id, name);
andrewboyson 109:3e82f62c7e1f 219 HttpAddText("</div>\r\n");
andrewboyson 109:3e82f62c7e1f 220 }
andrewboyson 109:3e82f62c7e1f 221
andrewboyson 109:3e82f62c7e1f 222