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.

web-add.c

Committer:
andrewboyson
Date:
2020-06-09
Revision:
141:1dac268a197d
Parent:
138:44d84506b2f6
Child:
142:b472ba95b018

File content as of revision 141:1dac268a197d:

#include <stdio.h>

#include "http.h"
#include "web-nav-base.h"
#include "web-nav-this.h"
#include "web-site-name.h"
#include "mac.h"
#include "ip4addr.h"
#include "ip6addr.h"

void WebAddNavItem(int highlight, const char* href, const char* title)
{
    char *p;
    HttpAddText("<li ");
    if (highlight) p = "class='this'";
    else           p = "            ";
    HttpAddText(p);
    HttpAddText("><a href='");
    HttpAddText(href);
    HttpAddText("'>");
    HttpAddText(title);
    HttpAddText("</a></li>\r\n");
}
void WebAddNav(int page)
{
    HttpAddText("<a class='tab-shortcut' href='#main-content'>Skip to content</a>\r\n");

    HttpAddText("<nav><ul>\r\n");
    WebNavThis(page);
    WebNavBase(page);
    HttpAddText("</ul></nav>\r\n");
}

void WebAddHeader(const char* title, const char* style, const char* script)
{
    HttpAddText("<!DOCTYPE html>\r\n"
                     "<html>\r\n"
                     "<head>\r\n");
    HttpAddText("   <title>");
    HttpAddText(WEB_SITE_NAME);
    if (title)
    {
        HttpAddText(" - ");
        HttpAddText(title);
    }
    HttpAddText("</title>\r\n");

    HttpAddText("   <link rel='stylesheet' href='/base.css' type='text/css'/>\r\n");
    if (style)
    {
        HttpAddText("   <link rel='stylesheet' href='/");
        HttpAddText(style);
        HttpAddText("' type='text/css'/>\r\n");
    }
    if (script)
    {
        HttpAddText("   <script src='/");
        HttpAddText(script);
        HttpAddText("' type='text/javascript'></script>\r\n");
    }
    HttpAddText("   <meta name='viewport' content='width=device-width, initial-scale=1'>\r\n"
                     "   <link rel='icon'       href='/favicon.ico' type='image/x-icon'/>\r\n"
                     "</head>\r\n"
                     "<body>\r\n");

}
void WebAddH1(const char* pageName)
{
    HttpAddText("<h1 id='main-content'>");
    HttpAddText(WEB_SITE_NAME);
    HttpAddText(" - ");
    HttpAddText(pageName);
    HttpAddText("</h1>\r\n");
}
void WebAddH2(const char* text)
{
    HttpAddText("<h2>");
    HttpAddText(text);
    HttpAddText("</h2>\r\n");
}
void WebAddEnd()
{
    HttpAddText("</body>\r\n"
                "</html>\r\n");
}

void WebAddLabelledPrefixSuffix(const char* label, const char* prefix, const char* text, const char* suffix)
{
    HttpAddText("<div class='line'>\r\n");
    HttpAddF   ("  <div>%s</div>\r\n", label);
    HttpAddF   ("  <div>%s%s%s</div>\r\n", prefix, text, suffix);
    HttpAddText("</div>\r\n");
}
void WebAddLabelledText(const char* label, const char* text)
{
    HttpAddText("<div class='line'>\r\n");
    HttpAddF   ("  <div>%s</div>\r\n", label);
    HttpAddF   ("  <div>%s</div>\r\n", text);
    HttpAddText("</div>\r\n");
}

void WebAddLabelledMac(const char* label, const char* mac)
{
    HttpAddText("<div class='line'>\r\n");
    HttpAddF   ("  <div>%s</div>\r\n", label);
    HttpAddText("  <div>"); MacHttp(mac); HttpAddText("</div>\r\n");
    HttpAddText("</div>\r\n");
}

void WebAddLabelledIp4(const char* label, uint32_t ip)
{
    HttpAddText("<div class='line'>\r\n");
    HttpAddF   ("  <div>%s</div>\r\n", label);
    HttpAddText("  <div>"); Ip4AddressHttp(ip); HttpAddText("</div>\r\n");
    HttpAddText("</div>\r\n");
}

void WebAddLabelledIp6(const char* label, const char* ip)
{
    HttpAddText("<div class='line'>\r\n");
    HttpAddF   ("  <div>%s</div>\r\n", label);
    HttpAddText("  <div>"); Ip6AddressHttp(ip); HttpAddText("</div>\r\n");
    HttpAddText("</div>\r\n");
}
void WebAddLabelledOnOff(const char* label, bool value)
{
    if (value) WebAddLabelledText(label, "On");
    else       WebAddLabelledText(label, "Off");
}
void WebAddLabelledLed(const char* label, bool value)
{
    HttpAddText("<div class='line'>\r\n");
    HttpAddF   ("  <div>%s</div>\r\n", label);
    HttpAddF   ("  <div class='led' dir='%s'></div>\r\n", value ? "rtl" : "ltr");
    HttpAddText("</div>\r\n");
}
void WebAddLabelledInt(const char* label, int value)
{
    char text[30];
    snprintf(text, sizeof(text), "%8d", value); //Right align with enough spaces so that the length is always constant. 
    WebAddLabelledText(label, text);
}
void WebAddInputText(const char* label, float inputwidth, const char* value, const char* action, const char* name)
{
    HttpAddF   ("<form action='%s' method='get'>\r\n", action);
    HttpAddText("<div class='line'>\r\n");
    HttpAddF   ("  <div>%s</div>\r\n", label);
    HttpAddF   ("  <input type='text' name='%s' style='width:%.1fem;' value='%s'>\r\n", name, inputwidth, value);
    HttpAddText("</div>\r\n");
    HttpAddText("<input type='submit' value='Set' style='display:none;'>\r\n");
    HttpAddF   ("</form>\r\n");

}
void WebAddInputInt(const char* label, float inputwidth, int value, const char* action, const char* name)
{    
    char text[30];
    snprintf(text, sizeof(text), "%d", value);
    WebAddInputText(label, inputwidth, text, action, name);
}
void WebAddInputButton(const char* label, const char* value, const char* action, const char* name)
{
    HttpAddF   ("<form action='%s' method='get'>\r\n", action);
    HttpAddF   ("<input type='hidden' name='%s'>\r\n", name);
    HttpAddText("<div class='line'>\r\n");
    HttpAddF   ("  <div>%s</div>\r\n", label);
    HttpAddF   ("  <input type='submit' value='%s'>\r\n", value);
    HttpAddText("</div>\r\n");
    HttpAddText("</form>\r\n");
}
void WebAddAjaxInputToggle(const char* label, const char* id, const char* name)
{
    HttpAddText("<div class='line'>\r\n");
    HttpAddF   ("  <div>%s</div>\r\n", label);
    HttpAddF   ("  <div class='toggle' id='%s' tabindex='0' dir='ltr' onclick='AjaxSendNameValue(\"%s\", \"1\")' onkeydown='return event.keyCode != 13 || AjaxSendNameValue(\"%s\", \"1\")'>\r\n", id, name, name);
    HttpAddText("    <div class='slot'></div><div class='knob'></div>\r\n");
    HttpAddText("  </div>\r\n");
    HttpAddText("</div>\r\n");
}
void WebAddAjaxLed(const char* label, const char* id)
{
    HttpAddText("<div class='line'>\r\n");
    HttpAddF   ("  <div>%s</div>\r\n", label);
    HttpAddF   ("  <div class='led' id='%s' dir='ltr'></div>\r\n", id);
    HttpAddText("</div>\r\n");
}
void WebAddAjaxInput(const char* label, float inputwidth, const char* id, const char* name)
{
    HttpAddText("<div class='line'>\r\n");
    HttpAddF   ("  <div>%s</div>\r\n", label);
    HttpAddF   ("  <input type='text' style='width:%.1fem;' id='%s' onchange='AjaxSendNameValue(\"%s\", this.value)'>\r\n", inputwidth, id, name);
    HttpAddText("</div>\r\n");
}
void WebAddAjaxInputSuffix(const char* label, float inputwidth, const char* id, const char* name, const char* suffix)
{
    HttpAddText("<div class='line'>\r\n");
    HttpAddF   ("  <div>%s</div>\r\n", label);
    HttpAddF   ("  <input type='text' style='width:%.1fem;' id='%s' onchange='AjaxSendNameValue(\"%s\", this.value)'>%s\r\n", inputwidth, id, name, suffix);
    HttpAddText("</div>\r\n");
}
void WebAddAjaxLabelled(const char* label, const char* id)
{
    HttpAddText("<div class='line'>\r\n");
    HttpAddF   ("  <div>%s</div>\r\n", label);
    HttpAddF   ("  <div id='%s'></div>\r\n", id);
    HttpAddText("</div>\r\n");
}
void WebAddAjaxLabelledSuffix(const char* label, const char* id, const char* suffix)
{
    HttpAddText("<div class='line'>\r\n");
    HttpAddF   ("  <div>%s</div>\r\n", label);
    HttpAddF   ("  <div><span id='%s'></span>%s</div>\r\n", id, suffix);
    HttpAddText("</div>\r\n");
}
void WebAddAjaxInputLabelId(const char* labelId, float inputwidth, const char* id, const char* name)
{
    HttpAddText("<div class='line'>\r\n");
    HttpAddF   ("  <div id='%s'></div>\r\n", labelId);
    HttpAddF   ("  <input type='text' style='width:%.1fem;' id='%s' onchange='AjaxSendNameValue(\"%s\", this.value)'>\r\n", inputwidth, id, name);
    HttpAddText("</div>\r\n");
}