From 5296770703fc744c2e16b37e645450be72017817 Mon Sep 17 00:00:00 2001 From: luc lebosse Date: Mon, 4 Jul 2016 17:27:03 +0200 Subject: [PATCH] Allow to have admin and user authentication admin is for wifi / esp settings user is for printer settings admin and user ID can be defined in config.h [ESP555] allows to reset user password to default one --- README.md | 10 ++- esp3d/command.cpp | 17 +++++ esp3d/config.cpp | 5 +- esp3d/config.h | 24 ++++--- esp3d/data/header.inc | 2 +- esp3d/webinterface.cpp | 147 ++++++++++++++++++++++++++--------------- esp3d/webinterface.h | 13 +++- 7 files changed, 148 insertions(+), 70 deletions(-) diff --git a/README.md b/README.md index 00a0a3a2..0fc96a6c 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,9 @@ Web Page refresh: 3 secondes User: admin Password: admin +User:user +Password: user + These are the pages defined using template: Home page :
@@ -98,10 +101,11 @@ Because SPIFFS is flat filesystem, no directory management is necessary, so it i Additionally 404.tpl (the page not found) and restart.tpl(restart page when applying changes) are not mandatory, a fail safe version is embeded if they are not present. ##Direct commands: - +``` -restart module from host/printer: [ESP888]RESTART -Get IP (only printer see answer): [ESP111]M117 - -reset EEPROM and restart: [ESP444]RESET + -reset EEPROM and restart: [ESP444]RESET + -reset user password: [ESP555] -display EEPROM content: [ESP444]CONFIG -go to safe mode without restart: [ESP444]SAFEMODE -SSID: [ESP100] @@ -110,7 +114,7 @@ Additionally 404.tpl (the page not found) and restart.tpl(restart page when appl -AP mode: [ESP103]AP -IP Static: [ESP104]STATIC -IP DHCP: [ESP104]DHCP - + ``` ##Installation * For stable: Please use [Arduino IDE 1.6.5](http://arduino.cc/en/Main/Software) with the esp8266 module from board manager use 2.0.0 stable version by adding in your preferences http://arduino.esp8266.com/version/2.0.0/package_esp8266com_index.json diff --git a/esp3d/command.cpp b/esp3d/command.cpp index 41377ac1..f929b27a 100644 --- a/esp3d/command.cpp +++ b/esp3d/command.cpp @@ -100,6 +100,23 @@ void COMMAND::execute_command(int cmd,String cmd_params) CONFIG::print_config(); } break; + case 555: + { + String sadminPassword; + if (!CONFIG::read_string(EP_ADMIN_PWD, sadminPassword , MAX_LOCAL_PASSWORD_LENGTH)) { + sadminPassword=FPSTR(DEFAULT_ADMIN_PWD); + } + if (cmd_params == sadminPassword.c_str()) { + if(CONFIG::write_string(EP_USER_PWD,FPSTR(DEFAULT_USER_PWD))) { + Serial.println("\nOk"); + } + else { + Serial.println("\nFailed"); + } + } + else Serial.println("\nFailed"); + break; + } case 888: if (cmd_params=="RESTART") { Serial.print("\r"); diff --git a/esp3d/config.cpp b/esp3d/config.cpp index 6b0540c3..c5078eb3 100644 --- a/esp3d/config.cpp +++ b/esp3d/config.cpp @@ -229,7 +229,10 @@ bool CONFIG::reset_config() if(!CONFIG::write_buffer(EP_E_FEEDRATE,(const byte *)&DEFAULT_E_FEEDRATE,INTEGER_LENGTH)) { return false; } - if(!CONFIG::write_string(EP_ADMIN_PWD,FPSTR(DEFAULT_ADMIN))) { + if(!CONFIG::write_string(EP_ADMIN_PWD,FPSTR(DEFAULT_ADMIN_PWD))) { + return false; + } + if(!CONFIG::write_string(EP_USER_PWD,FPSTR(DEFAULT_USER_PWD))) { return false; } return true; diff --git a/esp3d/config.h b/esp3d/config.h index b9bb0822..6b50a18b 100644 --- a/esp3d/config.h +++ b/esp3d/config.h @@ -20,8 +20,8 @@ //definition #define REPETIER 0 -#define REPETIER4DV 1 -#define MARLIN 2 +#define REPETIER4DV 1 +#define MARLIN 2 #define SMOOTHIEWARE 3 //comment to disable @@ -57,7 +57,6 @@ //#define DEBUG_ESP3D #ifdef DEBUG_ESP3D - #define LOG(string) {File logfile = SPIFFS.open("/log.txt", "a+");logfile.print(string);logfile.close();} #else #define LOG(string) {} @@ -69,7 +68,7 @@ #include #include "wifi.h" //version and sources location -#define FW_VERSION "0.7.52" +#define FW_VERSION "0.7.7" #define REPOSITORY "https://github.com/luc-github/ESP8266" @@ -90,7 +89,7 @@ #define EP_IP_MODE 99 //1 byte = flag #define EP_IP_VALUE 100 //4 bytes xxx.xxx.xxx.xxx #define EP_MASK_VALUE 104 //4 bytes xxx.xxx.xxx.xxx -#define EP_GATEWAY_VALUE 108 //4 bytes xxx.xxx.xxx.xxx +#define EP_GATEWAY_VALUE 108 //4 bytes xxx.xxx.xxx.xxx #define EP_BAUD_RATE 112 //4 bytes = int #define EP_PHY_MODE 116 //1 byte = flag #define EP_SLEEP_MODE 117 //1 byte = flag @@ -105,8 +104,9 @@ #define EP_Z_FEEDRATE 168//4 bytes = int #define EP_E_FEEDRATE 172//4 bytes = int #define EP_ADMIN_PWD 176//21 bytes 20+1 = string ; warning does not support multibyte char like chinese - - +#define EP_USER_PWD 197//21 bytes 20+1 = string ; warning does not support multibyte char like chinese +//next available is 218 +//space left 256 - 218 = 38 //default values #define DEFAULT_WIFI_MODE AP_MODE @@ -131,7 +131,11 @@ const int DEFAULT_DATA_PORT = 8888; const int DEFAULT_XY_FEEDRATE=1000; const int DEFAULT_Z_FEEDRATE =100; const int DEFAULT_E_FEEDRATE=400; -const char DEFAULT_ADMIN [] PROGMEM = "admin"; +const char DEFAULT_ADMIN_PWD [] PROGMEM = "admin"; +const char DEFAULT_USER_PWD [] PROGMEM = "user"; +const char DEFAULT_ADMIN_LOGIN [] PROGMEM = "admin"; +const char DEFAULT_USER_LOGIN [] PROGMEM = "user"; + //sizes #define EEPROM_SIZE 256 //max is 512 @@ -139,8 +143,8 @@ const char DEFAULT_ADMIN [] PROGMEM = "admin"; #define MIN_SSID_LENGTH 1 #define MAX_PASSWORD_LENGTH 64 #define MIN_PASSWORD_LENGTH 8 -#define MAX_ADMIN_PASSWORD_LENGTH 16 -#define MIN_ADMIN_PASSWORD_LENGTH 1 +#define MAX_LOCAL_PASSWORD_LENGTH 16 +#define MIN_LOCAL_PASSWORD_LENGTH 1 #define IP_LENGTH 4 #define INTEGER_LENGTH 4 #define MAX_HOSTNAME_LENGTH 32 diff --git a/esp3d/data/header.inc b/esp3d/data/header.inc index a06b694e..19f77fe3 100644 --- a/esp3d/data/header.inc +++ b/esp3d/data/header.inc @@ -17,7 +17,7 @@ $INCLUDE[css.inc]$ 3D Printer Extra Settings   - Admin + $LOGIN_ID$
diff --git a/esp3d/webinterface.cpp b/esp3d/webinterface.cpp index 236bc086..ee578b69 100644 --- a/esp3d/webinterface.cpp +++ b/esp3d/webinterface.cpp @@ -40,11 +40,14 @@ extern "C" { #endif #define MAX_AUTH_IP 10 -#define UPLOAD_STATUS_NONE 0 -#define UPLOAD_STATUS_FAILED 1 -#define UPLOAD_STATUS_CANCELLED 2 -#define UPLOAD_STATUS_SUCCESSFUL 3 -#define UPLOAD_STATUS_ONGOING 4 + +typedef enum { + UPLOAD_STATUS_NONE = 0, + UPLOAD_STATUS_FAILED = 1, + UPLOAD_STATUS_CANCELLED = 2, + UPLOAD_STATUS_SUCCESSFUL = 3, + UPLOAD_STATUS_ONGOING =4 +} upload_status_type; const char PAGE_404 [] PROGMEM ="\n\nRedirecting... \n\n\n
Unknown page - you will be redirected...\n

\nif not redirected,
click here\n

\n\n\n\n
\n\n\n\n"; const char PAGE_RESTART [] PROGMEM ="\n\nRestarting... \n\n\n
Restarting, please wait....\n
\n\n
\n\n\n\n"; @@ -207,6 +210,7 @@ const char EEPROM_NOWRITE [] PROGMEM = "Error: Cannot write to EEPROM"; const char KEY_WEB_UPDATE [] PROGMEM = "$WEB_UPDATE_VISIBILITY$"; const char KEY_STA_SIGNAL [] PROGMEM = "$STA_SIGNAL$"; const char KEY_DATA_PORT_VISIBILITY [] PROGMEM = "$DATA_PORT_VISIBILITY$"; +const char KEY_LOGIN_ID [] PROGMEM = "$LOGIN_ID$"; bool WEBINTERFACE_CLASS::isHostnameValid(const char * hostname) { @@ -261,11 +265,11 @@ bool WEBINTERFACE_CLASS::isPasswordValid(const char * password) return true; } -bool WEBINTERFACE_CLASS::isAdminPasswordValid(const char * password) +bool WEBINTERFACE_CLASS::isLocalPasswordValid(const char * password) { char c; //limited size - if ((strlen(password)>MAX_ADMIN_PASSWORD_LENGTH)|| (strlen(password)MAX_LOCAL_PASSWORD_LENGTH)|| (strlen(password)is_authenticated()) { - ValuesList.add(FPSTR(VALUE_ITEM_VISIBLE)); - } else { - ValuesList.add(FPSTR(VALUE_ITEM_HIDDEN)); - } + + //login + GeLogin(KeysList, ValuesList,web_interface->is_authenticated()); //IP+Web GetIpWeb(KeysList, ValuesList); - + //Hostname if (WiFi.getMode()==WIFI_STA ) { KeysList.add(FPSTR(KEY_MODE)); @@ -1040,12 +1059,14 @@ void handle_web_interface_configSys() const __FlashStringHelper *smodemdisplaylist[]= {FPSTR(VALUE_NONE),FPSTR(VALUE_LIGHT),FPSTR(VALUE_MODEM),FPSTR(VALUE_MODEM)}; STORESTRINGS_CLASS KeysList ; STORESTRINGS_CLASS ValuesList ; - - if (!web_interface->is_authenticated()) { + + level_authenticate_type auth_level= web_interface->is_authenticated(); + if (auth_level != LEVEL_ADMIN) { web_interface->WebServer.sendContent_P(NOT_AUTH_CS); return; } - + //login + GeLogin(KeysList, ValuesList,auth_level); //IP+Web GetIpWeb(KeysList, ValuesList); //mode @@ -1232,12 +1253,13 @@ void handle_password() //int ipos; STORESTRINGS_CLASS KeysList ; STORESTRINGS_CLASS ValuesList ; - - if (!web_interface->is_authenticated()) { + level_authenticate_type auth_level= web_interface->is_authenticated(); + if (auth_level == LEVEL_GUEST) { web_interface->WebServer.sendContent_P(NOT_AUTH_PW); return; } - + //login + GeLogin(KeysList, ValuesList,auth_level); //IP+Web GetIpWeb(KeysList, ValuesList); //mode @@ -1256,7 +1278,7 @@ void handle_password() //Password sPassword =web_interface->WebServer.arg("PASSWORD"); sPassword2 = web_interface->WebServer.arg("PASSWORD2"); - if (!web_interface->isAdminPasswordValid(sPassword.c_str()) ) { + if (!web_interface->isLocalPasswordValid(sPassword.c_str()) ) { msg_alert_error=true; smsg.concat(F("Error: Incorrect password
")); KeysList.add(FPSTR(KEY_USER_PASSWORD_STATUS)); @@ -1276,7 +1298,10 @@ void handle_password() //if no error apply the change if (msg_alert_error==false) { //save - if(!CONFIG::write_string(EP_ADMIN_PWD,sPassword.c_str())) { + bool res; + if (auth_level == LEVEL_ADMIN) res = CONFIG::write_string(EP_ADMIN_PWD,sPassword.c_str()) ; + else res = CONFIG::write_string(EP_USER_PWD,sPassword.c_str()) ; + if (!res) { msg_alert_error=true; smsg = FPSTR(EEPROM_NOWRITE); } else { @@ -1352,11 +1377,13 @@ void handle_web_interface_configAP() STORESTRINGS_CLASS KeysList ; STORESTRINGS_CLASS ValuesList ; - if (!web_interface->is_authenticated()) { + level_authenticate_type auth_level= web_interface->is_authenticated(); + if (auth_level != LEVEL_ADMIN) { web_interface->WebServer.sendContent_P(NOT_AUTH_AP); return; } - + //login + GeLogin(KeysList, ValuesList,auth_level); //IP+Web GetIpWeb(KeysList, ValuesList); //mode @@ -1692,11 +1719,13 @@ void handle_web_interface_configSTA() STORESTRINGS_CLASS KeysList ; STORESTRINGS_CLASS ValuesList ; - if (!web_interface->is_authenticated()) { + level_authenticate_type auth_level= web_interface->is_authenticated(); + if (auth_level != LEVEL_ADMIN) { web_interface->WebServer.sendContent_P(NOT_AUTH_STA); return; } - + //login + GeLogin(KeysList, ValuesList,auth_level); //IP+Web GetIpWeb(KeysList, ValuesList); //mode @@ -1998,11 +2027,15 @@ void handle_web_interface_printer() STORESTRINGS_CLASS KeysList ; STORESTRINGS_CLASS ValuesList ; - if (!web_interface->is_authenticated()) { + level_authenticate_type auth_level= web_interface->is_authenticated(); + if (auth_level == LEVEL_GUEST) { web_interface->WebServer.sendContent_P(NOT_AUTH_PRT); return; } + //login + GeLogin(KeysList, ValuesList,auth_level); + //IP+Web GetIpWeb(KeysList, ValuesList); //mode @@ -2069,12 +2102,14 @@ void handle_web_settings() int ixy_feedrate,iz_feedrate,ie_feedrate; STORESTRINGS_CLASS KeysList ; STORESTRINGS_CLASS ValuesList ; - - if (!web_interface->is_authenticated()) { + level_authenticate_type auth_level= web_interface->is_authenticated(); + if (auth_level != LEVEL_ADMIN) { web_interface->WebServer.sendContent_P(NOT_AUTH_SET); return; } web_interface->blockserial = false; + //login + GeLogin(KeysList, ValuesList,auth_level); //IP+Web GetIpWeb(KeysList, ValuesList); //mode @@ -2196,6 +2231,7 @@ void handle_web_settings() void handle_web_interface_status() { static const char NO_TEMP_LINE[] PROGMEM = "\"temperature\":\"0\",\"target\":\"0\",\"active\":\"0\""; + //we do not care if need authentication - just reset counter web_interface->is_authenticated(); Serial.println(F("M114")); int tagpos,tagpos2; @@ -2699,6 +2735,7 @@ void WebUpdateUpload() void handleUpdate() { + //upload can be long so better to reset time out web_interface->is_authenticated(); String jsonfile = "{\"status\":\"" ; jsonfile+=intTostr(web_interface->_upload_status); @@ -2715,7 +2752,7 @@ void handleUpdate() void handleFileList() { - if (!web_interface->is_authenticated()) { + if (web_interface->is_authenticated() != LEVEL_ADMIN) { return; } String path = "/"; @@ -2769,7 +2806,7 @@ void handleFileList() void handleSDFileList() { - if (!web_interface->is_authenticated()) { + if (web_interface->is_authenticated() == LEVEL_GUEST) { return; } String jsonfile = "{\"status\":\"" ; @@ -2810,7 +2847,7 @@ void handle_not_found() { static const char NOT_AUTH_NF [] PROGMEM = "HTTP/1.1 301 OK\r\nLocation: /HOME\r\nCache-Control: no-cache\r\n\r\n"; - if (!web_interface->is_authenticated()) { + if (web_interface->is_authenticated() == LEVEL_GUEST) { web_interface->WebServer.sendContent_P(NOT_AUTH_NF); return; } @@ -2895,7 +2932,7 @@ void handle_login() //USER sUser = web_interface->WebServer.arg("USER"); #ifdef AUTHENTICATION_FEATURE - if (sUser!="admin") { + if ( !((sUser==FPSTR(DEFAULT_ADMIN_LOGIN)) || (sUser==FPSTR(DEFAULT_USER_LOGIN)))) { msg_alert_error=true; smsg.concat(F("Error : Incorrect User
")); KeysList.add(FPSTR(KEY_USER_STATUS)); @@ -2903,13 +2940,20 @@ void handle_login() } //Password sPassword = web_interface->WebServer.arg("PASSWORD"); - String scurrentPassword; + String sadminPassword; - if (!CONFIG::read_string(EP_ADMIN_PWD, scurrentPassword , MAX_ADMIN_PASSWORD_LENGTH)) { - scurrentPassword=FPSTR(DEFAULT_ADMIN); + if (!CONFIG::read_string(EP_ADMIN_PWD, sadminPassword , MAX_LOCAL_PASSWORD_LENGTH)) { + sadminPassword=FPSTR(DEFAULT_ADMIN_PWD); } + + String suserPassword; - if (strcmp(sPassword.c_str(),scurrentPassword.c_str())!=0) { + if (!CONFIG::read_string(EP_USER_PWD, suserPassword , MAX_LOCAL_PASSWORD_LENGTH)) { + suserPassword=FPSTR(DEFAULT_USER_PWD); + } + + if(!(((sUser==FPSTR(DEFAULT_ADMIN_LOGIN)) && (strcmp(sPassword.c_str(),sadminPassword.c_str())==0)) || + ((sUser==FPSTR(DEFAULT_USER_LOGIN)) && (strcmp(sPassword.c_str(),suserPassword.c_str()) == 0)))) { msg_alert_error=true; smsg.concat(F("Error: Incorrect password
")); KeysList.add(FPSTR(KEY_USER_PASSWORD_STATUS)); @@ -2925,6 +2969,8 @@ void handle_login() if (msg_alert_error==false) { #ifdef AUTHENTICATION_FEATURE auth_ip * current_auth = new auth_ip; + if(sUser==FPSTR(DEFAULT_ADMIN_LOGIN))current_auth->level = LEVEL_ADMIN; + else current_auth->level = LEVEL_USER; current_auth->ip=web_interface->WebServer.client().remoteIP(); strcpy(current_auth->sessionID,web_interface->create_session_ID()); current_auth->last_time=millis(); @@ -2955,12 +3001,10 @@ void handle_login() KeysList.add(FPSTR(KEY_RETURN)); ValuesList.add(sReturn); - KeysList.add(FPSTR(KEY_DISCONNECT_VISIBILITY)); - if (web_interface->is_authenticated()) { - ValuesList.add(FPSTR(VALUE_ITEM_VISIBLE)); - } else { - ValuesList.add(FPSTR(VALUE_ITEM_HIDDEN)); - } + level_authenticate_type auth_level= web_interface->is_authenticated(); + //login + GeLogin(KeysList, ValuesList,auth_level); + //IP+Web GetIpWeb(KeysList, ValuesList); //mode @@ -3022,7 +3066,7 @@ void handle_restart() void handle_web_command() { - if (!web_interface->is_authenticated()) { + if (web_interface->is_authenticated() == LEVEL_GUEST) { return; } //check we have proper parameter @@ -3152,7 +3196,7 @@ char * WEBINTERFACE_CLASS::create_session_ID() return sessionID; } //check authentification -bool WEBINTERFACE_CLASS::is_authenticated() +level_authenticate_type WEBINTERFACE_CLASS::is_authenticated() { #ifdef AUTHENTICATION_FEATURE if (WebServer.hasHeader("Cookie")) { @@ -3166,9 +3210,9 @@ bool WEBINTERFACE_CLASS::is_authenticated() return ResetAuthIP(ip,sessionID.c_str()); } } - return false; + return LEVEL_GUEST; #else - return true; + return LEVEL_ADMIN; #endif } @@ -3184,9 +3228,8 @@ bool WEBINTERFACE_CLASS::AddAuthIP(auth_ip * item) return true; } -bool WEBINTERFACE_CLASS::ResetAuthIP(IPAddress ip,const char * sessionID) +level_authenticate_type WEBINTERFACE_CLASS::ResetAuthIP(IPAddress ip,const char * sessionID) { - bool done=false; auth_ip * current = _head; auth_ip * previous = NULL; //get time @@ -3210,14 +3253,14 @@ bool WEBINTERFACE_CLASS::ResetAuthIP(IPAddress ip,const char * sessionID) if (strcmp(sessionID,current->sessionID)==0) { //reset time current->last_time=millis(); - return true; + return current->level; } } previous = current; current=current->_next; } } - return done; + return LEVEL_GUEST; } WEBINTERFACE_CLASS * web_interface; diff --git a/esp3d/webinterface.h b/esp3d/webinterface.h index 24aa5d09..6b82861f 100644 --- a/esp3d/webinterface.h +++ b/esp3d/webinterface.h @@ -29,8 +29,15 @@ #define MAX_EXTRUDERS 4 +typedef enum { + LEVEL_GUEST = 0, + LEVEL_USER = 1, + LEVEL_ADMIN = 2 +} level_authenticate_type; + struct auth_ip { IPAddress ip; + level_authenticate_type level; char sessionID[17]; uint32_t last_time; auth_ip * _next; @@ -45,7 +52,7 @@ public: File fsUploadFile; bool isSSIDValid(const char * ssid); bool isPasswordValid(const char * password); - bool isAdminPasswordValid(const char * password); + bool isLocalPasswordValid(const char * password); bool isHostnameValid(const char * hostname); bool isIPValid(const char * IP); String answer4M105; @@ -59,10 +66,10 @@ public: STORESTRINGS_CLASS status_msg; bool restartmodule; char * create_session_ID(); - bool is_authenticated(); + level_authenticate_type is_authenticated(); bool AddAuthIP(auth_ip * item); bool blockserial; - bool ResetAuthIP(IPAddress ip,const char * sessionID); + level_authenticate_type ResetAuthIP(IPAddress ip,const char * sessionID); uint8_t _upload_status; private: