[SYS] Password management improvements (#1787)

* Use one single password for Access point, OTA and WebUI access
* Enable to change the password during WM onboarding, with the WebUI, and MQTT command
* Remove the default password during the first configuration to connect to the AP
* When using the last 8 digits of the MAC as the password, it can now be changed
* Remove gateway password sending to client
This commit is contained in:
Florian authored and GitHub committed 2023-11-02 09:10:20 -05:00
1 parent 7c48129f37
commit 99de6ef4a6
8 files changed
+129 -41

No files matched your search

+3 -6
View File
@@ -121,9 +121,6 @@ const byte mac[] = {0xDE, 0xED, 0xBA, 0xFE, 0x54, 0x95}; //W5100 ethernet shield
#endif
//#define WM_PWD_FROM_MAC true // enable to set the password from the last 8 digits of the ESP MAC address for enhanced security, enabling this option requires to have access to the MAC address, either through a sticker or with serial monitoring
#ifndef WifiManager_password
# define WifiManager_password "your_password" //this is going to be the WPA2-PSK password for the initial setup access point
#endif
#ifndef WifiManager_ssid
# define WifiManager_ssid Gateway_Name //this is the network name of the initial setup access point
#endif
@@ -407,8 +404,8 @@ int lowpowermode = DEFAULT_LOW_POWER_MODE;
#ifndef ota_hostname
# define ota_hostname Gateway_Name
#endif
#ifndef ota_password
# define ota_password "OTAPASSWORD"
#ifndef gw_password
# define gw_password ""
#endif
#ifndef ota_port
# define ota_port 8266
@@ -733,7 +730,7 @@ char gateway_name[parameters_size + 1] = Gateway_Name;
void connectMQTT();
#ifndef ESPWifiManualSetup
void saveMqttConfig();
void saveConfig();
#endif
unsigned long uptime();
+73 -3
View File
@@ -768,18 +768,18 @@ void handleMQ() {
# ifndef ESPWifiManualSetup
if (update) {
Log.warning(F("[WebUI] Save MQTT and Restart" CR));
Log.warning(F("[WebUI] Save MQTT and Reconnect" CR));
char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1);
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE];
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Save MQTT and Restart").c_str());
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Save MQTT and Reconnect").c_str());
String response = String(buffer);
response += String(restart_script);
response += String(script);
response += String(style);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, reset_body, jsonChar, gateway_name, "Save MQTT and Restart");
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, reset_body, jsonChar, gateway_name, "Save MQTT and Reconnect");
response += String(buffer);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
@@ -816,6 +816,75 @@ void handleMQ() {
server.send(200, "text/html", response);
}
/**
* @brief /CG - Configure Gateway Page
* T: handleCG: uri: /gw, args: 2, method: 1
* T: handleCG Arg: 0, gp=1234
* T: handleCG Arg: 1, save=
*/
void handleCG() {
WEBUI_TRACE_LOG(F("handleCG: uri: %s, args: %d, method: %d" CR), server.uri(), server.args(), server.method());
WEBUI_SECURE
bool update = false;
StaticJsonDocument<JSON_MSG_BUFFER> jsonBuffer;
JsonObject WEBtoSYS = jsonBuffer.to<JsonObject>();
if (server.args()) {
for (uint8_t i = 0; i < server.args(); i++) {
WEBUI_TRACE_LOG(F("handleCG Arg: %d, %s=%s" CR), i, server.argName(i).c_str(), server.arg(i).c_str());
}
if (server.hasArg("save") && server.hasArg("gp") && strcmp(ota_pass, server.arg("gp").c_str())) {
strncpy(ota_pass, server.arg("gp").c_str(), parameters_size);
WEBtoSYS["gw_pass"] = ota_pass;
update = true;
}
}
if (update) {
Log.warning(F("[WebUI] Save Password and Restart" CR));
char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1);
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE];
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Save Password and Restart").c_str());
String response = String(buffer);
response += String(restart_script);
response += String(script);
response += String(style);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, reset_body, jsonChar, gateway_name, "Save Password and Restart");
response += String(buffer);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
server.send(200, "text/html", response);
delay(2000); // Wait for web page to be sent before
String topic = String(mqtt_topic) + String(gateway_name) + String(subjectMQTTtoSYSset);
String output;
serializeJson(WEBtoSYS, output);
Log.notice(F("[WebUI] MQTTtoSYS %s" CR), output.c_str());
MQTTtoSYS((char*)topic.c_str(), WEBtoSYS);
} else {
Log.warning(F("[WebUI] No changes" CR));
}
char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1);
char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE];
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Configure Gateway").c_str());
String response = String(buffer);
response += String(script);
response += String(style);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_gateway_body, jsonChar, gateway_name, ota_pass);
response += String(buffer);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
server.send(200, "text/html", response);
}
/**
* @brief /LO - Configure Logging Page
* T: handleLO: uri: /lo, args: 2, method: 1
@@ -1419,6 +1488,7 @@ void WebUISetup() {
server.on("/cn", handleCN); // Configuration
server.on("/wi", handleWI); // Configure Wifi
server.on("/mq", handleMQ); // Configure MQTT
server.on("/cg", handleCG); // Configure Gateway"
server.on("/wu", handleWU); // Configure WebUI
# ifdef ZgatewayLORA
server.on("/la", handleLA); // Configure LORA
+6 -3
View File
@@ -43,11 +43,12 @@
#define configure_1 "<p><form action='wi' method='get'><button>Configure WiFi</button></form></p>"
#define configure_2 "<p><form action='mq' method='get'><button>Configure MQTT</button></form></p>"
#if defined(ZgatewayCloud)
/*#if defined(ZgatewayCloud)
# define configure_3 "<p><form action='cl' method='get'><button>Configure Cloud</button></form></p>"
#else
# define configure_3
#endif
#endif*/
#define configure_3 "<p><form action='cg' method='get'><button>Configure Gateway</button></form></p>"
#define configure_4 "<p><form action='wu' method='get'><button>Configure WebUI</button></form></p>"
#define configure_5 "<p><form action='lo' method='get'><button>Configure Logging</button></form></p>"
#ifdef ZgatewayLORA
@@ -82,7 +83,7 @@ const char config_body[] = body_header "" configure_1 "" configure_2 "" configur
const char reset_body[] = body_header "<div style='text-align:center;'>%s</div><br><div style='text-align:center;'>Device will restart in a few seconds</div><br>" body_footer_main_menu;
const char config_cloud_body[] = body_header "<fieldset class=\"set1\"><legend><span><b>&nbsp;Cloud Configuration&nbsp;</b></span></legend><form method='get' action='cl'><p><label><input id='cl-en' type='checkbox' %s><b>Enable Cloud Connection</b></label></p><br><p><label><input id='cl-lk' type='checkbox' disabled><b>Cloud Account%s Linked</b></label></p><br><button name='save' type='submit' class='button bgrn'>Save</button></form></fieldset><p><form action='%s' method='get'><input type='hidden' name='macAddress' value='%s'/><input type='hidden' name='redirect_uri' value='%s'/><input type='hidden' name='gateway_name' value='%s'/><input type='hidden' name='uptime' value='%d'/><input type='hidden' name='RT' value='%d'/><button>Link Cloud Account</button></form></p>" body_footer_config_menu;
//const char config_cloud_body[] = body_header "<fieldset class=\"set1\"><legend><span><b>&nbsp;Cloud Configuration&nbsp;</b></span></legend><form method='get' action='cl'><p><label><input id='cl-en' type='checkbox' %s><b>Enable Cloud Connection</b></label></p><br><p><label><input id='cl-lk' type='checkbox' disabled><b>Cloud Account%s Linked</b></label></p><br><button name='save' type='submit' class='button bgrn'>Save</button></form></fieldset><p><form action='%s' method='get'><input type='hidden' name='macAddress' value='%s'/><input type='hidden' name='redirect_uri' value='%s'/><input type='hidden' name='gateway_name' value='%s'/><input type='hidden' name='uptime' value='%d'/><input type='hidden' name='RT' value='%d'/><button>Link Cloud Account</button></form></p>" body_footer_config_menu;
const char token_body[] = body_header "<div style='text-align:center;'>Link Cloud Account</div><br><div style='text-align:center;'>Cloud was successfully linked</div><br><div id=but2d style=\"display: block;\"></div><p><form id=but2 style=\"display: block;\" action='cn' method='get'><button>Configuration</button></form></p>";
@@ -98,6 +99,8 @@ const char config_wifi_body[] = body_header "%s<br><div><a href='/wi?scan='><b>S
const char config_mqtt_body[] = body_header "<fieldset class=\"set1\"><legend><span><b>MQTT Parameters</b></span></legend><form method='get' action='mq'><p><b>MQTT Server</b><br><input id='mh' placeholder=" MQTT_SERVER " value='%s'></p><p><b>MQTT Port</b><br><input id='ml' placeholder=" MQTT_PORT " value='%s'></p><p><b>MQTT Username</b><br><input id='mu' placeholder=" MQTT_USER " value='%s'></p><p><label><b>MQTT Password</b><input type='checkbox' onclick='sp(\"mp\")'></label><br><input id='mp' type='password' placeholder=\"Password\" value='%s'></p><p><b>MQTT Secure Connection</b><br><input id='sc' type='checkbox' %s></p><p><b>Gateway Name</b><br><input id='h' placeholder=" Gateway_Name " value=\"%s\"></p><p><b>MQTT Base Topic</b><br><input id='mt' placeholder='' value='%s'></p><br><button name='save' type='submit' class='button bgrn'>Save</button></form></fieldset>" body_footer_config_menu;
const char config_gateway_body[] = body_header "<fieldset class=\"set1\"><legend><span><b>Gateway Configuration</b></span></legend><form method='get' action='cg'><p><b>Gateway Password (8 characters min)</b><br><input id='gp' type='password' placeholder=\"********\"></p><br><button name='save' type='submit' class='button bgrn'>Save</button></form></fieldset>" body_footer_config_menu;
const char config_logging_body[] = body_header "<fieldset class=\"set1\"><legend><span><b>OpenMQTTGateway Logging</b></span></legend><form method='get' action='lo'><p><b>Log Level</b><br><select id='lo'><option %s value='0'>Silent</option><option %s value='1'>Fatal</option><option %s value='2'>Error</option><option %s value='3'>Warning</option><option %s value='4'>Notice</option><option %s value='5'>Trace</option><option %s value='6'>Verbose</option></select></p><br><button name='save' type='submit' class='button bgrn'>Save</button></form></fieldset>" body_footer_config_menu;
const char config_webui_body[] = body_header "<fieldset class=\"set1\"><legend><span><b>Configure WebUI</b></span></legend><form method='get' action='wu'><p><b>Display Metric</b><br><input id='dm' type='checkbox' %s></p><p><b>Secure WebUI</b><br><input id='sw' type='checkbox' %s></p><br><button name='save' type='submit' class='button bgrn'>Save</button></form></fieldset>" body_footer_config_menu;
+34 -24
View File
@@ -213,7 +213,7 @@ char mqtt_user[parameters_size + 1] = MQTT_USER; // not compulsory only if your
char mqtt_pass[parameters_size + 1] = MQTT_PASS; // not compulsory only if your broker needs authentication
char mqtt_server[parameters_size + 1] = MQTT_SERVER;
char mqtt_port[6] = MQTT_PORT;
char ota_pass[parameters_size + 1] = ota_password;
char ota_pass[parameters_size + 1] = gw_password;
#ifdef USE_MAC_AS_GATEWAY_NAME
# undef WifiManager_ssid
# undef ota_hostname
@@ -221,10 +221,6 @@ char ota_pass[parameters_size + 1] = ota_password;
char WifiManager_ssid[MAC_NAME_MAX_LEN];
char ota_hostname[MAC_NAME_MAX_LEN];
#endif
#ifdef WM_PWD_FROM_MAC
# undef WifiManager_password
char WifiManager_password[9];
#endif
bool connectedOnce = false; //indicate if we have been connected once to MQTT
bool connected = false; //indicate whether we are currently connected. Used to detected re-connection
int failure_number_ntwk = 0; // number of failure connecting to network
@@ -1482,7 +1478,7 @@ void checkButton() {
void checkButton() {}
# endif
void saveMqttConfig() {
void saveConfig() {
Log.trace(F("saving config" CR));
DynamicJsonDocument json(512 + ota_server_cert.length() + mqtt_cert.length());
json["mqtt_server"] = mqtt_server;
@@ -1561,7 +1557,19 @@ bool loadConfigFromFlash() {
}
configFile.close();
}
} else {
Log.notice(F("no config file found defining default values" CR));
# ifdef USE_MAC_AS_GATEWAY_NAME
String s = WiFi.macAddress();
sprintf(gateway_name, "%.2s%.2s%.2s%.2s%.2s%.2s",
s.c_str(), s.c_str() + 3, s.c_str() + 6, s.c_str() + 9, s.c_str() + 12, s.c_str() + 15);
# endif
# ifdef WM_PWD_FROM_MAC // From ESP Mac Address, last 8 digits as the password
sprintf(ota_pass, "%.2s%.2s%.2s%.2s",
s.c_str() + 6, s.c_str() + 9, s.c_str() + 12, s.c_str() + 15);
# endif
}
return result;
}
@@ -1572,18 +1580,12 @@ void setup_wifimanager(bool reset_settings) {
if (reset_settings)
eraseAndRestart();
String s = WiFi.macAddress();
# ifdef USE_MAC_AS_GATEWAY_NAME
sprintf(gateway_name, "%.2s%.2s%.2s%.2s%.2s%.2s",
s.c_str(), s.c_str() + 3, s.c_str() + 6, s.c_str() + 9, s.c_str() + 12, s.c_str() + 15);
String s = WiFi.macAddress();
snprintf(WifiManager_ssid, MAC_NAME_MAX_LEN, "%s_%.2s%.2s", Gateway_Short_Name, s.c_str(), s.c_str() + 3);
strcpy(ota_hostname, WifiManager_ssid);
Log.notice(F("OTA Hostname: %s.local" CR), ota_hostname);
# endif
# ifdef WM_PWD_FROM_MAC // From ESP Mac Address, last 8 digits as the password
sprintf(WifiManager_password, "%.2s%.2s%.2s%.2s",
s.c_str() + 6, s.c_str() + 9, s.c_str() + 12, s.c_str() + 15);
# endif
wifiManager.setDebugOutput(WM_DEBUG_LEVEL);
@@ -1599,7 +1601,7 @@ void setup_wifimanager(bool reset_settings) {
WiFiManagerParameter custom_mqtt_secure("secure", "mqtt secure", "1", 2, mqtt_secure ? "type=\"checkbox\" checked" : "type=\"checkbox\"");
WiFiManagerParameter custom_mqtt_cert("cert", "<br/>mqtt broker cert", mqtt_cert.c_str(), 4096);
WiFiManagerParameter custom_gateway_name("name", "gateway name", gateway_name, parameters_size);
WiFiManagerParameter custom_ota_pass("ota", "ota password", ota_pass, parameters_size);
WiFiManagerParameter custom_ota_pass("ota", "gateway password", ota_pass, parameters_size);
# endif
//WiFiManager
//Local intialization. Once its business is done, there is no need to keep it around
@@ -1648,7 +1650,7 @@ void setup_wifimanager(bool reset_settings) {
{
# ifdef ESP32
if (lowpowermode < 2) {
displayPrint("Connect your phone to WIFI AP:", WifiManager_ssid, WifiManager_password);
displayPrint("Connect your phone to WIFI AP:", WifiManager_ssid, ota_pass);
} else { // in case of low power mode we put the ESP to sleep again if we didn't get connected (typical in case the wifi is down)
# ifdef ZgatewayBT
lowPowerESP32();
@@ -1658,12 +1660,12 @@ void setup_wifimanager(bool reset_settings) {
InfoIndicatorON();
ErrorIndicatorON();
Log.notice(F("Connect your phone to WIFI AP: %s with PWD: %s" CR), WifiManager_ssid, WifiManager_password);
Log.notice(F("Connect your phone to WIFI AP: %s with PWD: %s" CR), WifiManager_ssid, ota_pass);
//fetches ssid and pass and tries to connect
//if it does not connect it starts an access point with the specified name
//and goes into a blocking loop awaiting configuration
if (!wifiManager.autoConnect(WifiManager_ssid, WifiManager_password)) {
if (!wifiManager.autoConnect(WifiManager_ssid, ota_pass)) {
if (!ethConnected) { // If we are using ethernet, we don't want to restart the ESP
Log.warning(F("failed to connect and hit timeout" CR));
delay(3000);
@@ -1723,7 +1725,7 @@ void setup_wifimanager(bool reset_settings) {
}
# endif
//save the custom parameters to FS
saveMqttConfig();
saveConfig();
}
}
# ifdef ESP32_ETHERNET
@@ -2635,7 +2637,7 @@ void MQTTHttpsFWUpdate(char* topicOri, JsonObject& HttpsFwUpdateData) {
pub(subjectRLStoMQTT, jsondata);
ota_server_cert = ota_cert;
# ifndef ESPWifiManualSetup
saveMqttConfig();
saveConfig();
# endif
ESPRestart(6);
break;
@@ -2652,6 +2654,7 @@ void MQTTHttpsFWUpdate(char* topicOri, JsonObject& HttpsFwUpdateData) {
void MQTTtoSYS(char* topicOri, JsonObject& SYSdata) { // json object decoding
if (cmpToMainTopic(topicOri, subjectMQTTtoSYSset)) {
bool restartESP = false;
Log.trace(F("MQTTtoSYS json" CR));
#if defined(ESP8266) || defined(ESP32)
if (SYSdata.containsKey("cmd")) {
@@ -2698,20 +2701,24 @@ void MQTTtoSYS(char* topicOri, JsonObject& SYSdata) { // json object decoding
setESPWifiProtocolTxPower();
# endif
}
ESPRestart(7);
restartESP = true;
}
bool disconnectClient = false; // Trigger client.disconnet if a user/password change doesn't
if (SYSdata.containsKey("mqtt_topic") || SYSdata.containsKey("gateway_name")) {
if (SYSdata.containsKey("mqtt_topic") || SYSdata.containsKey("gateway_name") || SYSdata.containsKey("gw_pass")) {
if (SYSdata.containsKey("mqtt_topic")) {
strncpy(mqtt_topic, SYSdata["mqtt_topic"], parameters_size);
}
if (SYSdata.containsKey("gateway_name")) {
strncpy(gateway_name, SYSdata["gateway_name"], parameters_size);
}
if (SYSdata.containsKey("gw_pass")) {
strncpy(ota_pass, SYSdata["gw_pass"], parameters_size);
restartESP = true;
}
# ifndef ESPWifiManualSetup
saveMqttConfig();
saveConfig();
# endif
disconnectClient = true; // trigger reconnect in loop using the new topic/name
}
@@ -2788,7 +2795,7 @@ void MQTTtoSYS(char* topicOri, JsonObject& SYSdata) { // json object decoding
}
}
# ifndef ESPWifiManualSetup
saveMqttConfig();
saveConfig();
# endif
} else {
if (update_server) {
@@ -2807,7 +2814,7 @@ void MQTTtoSYS(char* topicOri, JsonObject& SYSdata) { // json object decoding
}
connectMQTT();
}
ESPRestart(7);
restartESP = true;
}
# endif
@@ -2846,6 +2853,9 @@ void MQTTtoSYS(char* topicOri, JsonObject& SYSdata) { // json object decoding
}
# endif
#endif
if (restartESP) {
ESPRestart(7);
}
}
}