Browse Source

0.8.78

* fixed protection
pull/1433/head
lumapu 1 year ago
parent
commit
d5cecbb5b0
  1. 2
      src/CHANGES.md
  2. 12
      src/app.h
  3. 5
      src/appInterface.h
  4. 2
      src/defines.h
  5. 72
      src/web/Protection.h
  6. 6
      src/web/RestApi.h
  7. 6
      src/web/web.h

2
src/CHANGES.md

@ -1,6 +1,6 @@
# Development Changes # Development Changes
## 0.8.78 - 2024-02-09 ## 0.8.78 - 2024-02-10
* finalized API token access #1415 * finalized API token access #1415
## 0.8.77 - 2024-02-08 ## 0.8.77 - 2024-02-08

12
src/app.h

@ -247,8 +247,8 @@ class app : public IApp, public ah::Scheduler {
#endif #endif
} }
void lock(void) override { void lock(bool fromWeb) override {
mProtection->lock(); mProtection->lock(fromWeb);
} }
char *unlock(const char *clientIp, bool loginFromWeb) override { char *unlock(const char *clientIp, bool loginFromWeb) override {
@ -259,12 +259,8 @@ class app : public IApp, public ah::Scheduler {
mProtection->resetLockTimeout(); mProtection->resetLockTimeout();
} }
bool isProtected(void) const override { bool isProtected(const char *clientIp, const char *token, bool askedFromWeb) const override {
return mProtection->isProtected(); return mProtection->isProtected(clientIp, token, askedFromWeb);
}
bool isProtected(const char *token, bool askedFromWeb) const override {
return mProtection->isProtected(token, askedFromWeb);
} }
bool getNrfEnabled(void) override { bool getNrfEnabled(void) override {

5
src/appInterface.h

@ -61,11 +61,10 @@ class IApp {
virtual uint32_t getMqttRxCnt() = 0; virtual uint32_t getMqttRxCnt() = 0;
virtual uint32_t getMqttTxCnt() = 0; virtual uint32_t getMqttTxCnt() = 0;
virtual void lock(void) = 0; virtual void lock(bool fromWeb) = 0;
virtual char *unlock(const char *clientIp, bool loginFromWeb) = 0; virtual char *unlock(const char *clientIp, bool loginFromWeb) = 0;
virtual void resetLockTimeout(void) = 0; virtual void resetLockTimeout(void) = 0;
virtual bool isProtected(void) const = 0; virtual bool isProtected(const char *clientIp, const char *token, bool askedFromWeb) const = 0;
virtual bool isProtected(const char *token, bool askedFromWeb) const = 0;
virtual uint16_t getHistoryValue(uint8_t type, uint16_t i) = 0; virtual uint16_t getHistoryValue(uint8_t type, uint16_t i) = 0;
virtual uint16_t getHistoryMaxDay() = 0; virtual uint16_t getHistoryMaxDay() = 0;

2
src/defines.h

@ -13,7 +13,7 @@
//------------------------------------- //-------------------------------------
#define VERSION_MAJOR 0 #define VERSION_MAJOR 0
#define VERSION_MINOR 8 #define VERSION_MINOR 8
#define VERSION_PATCH 77 #define VERSION_PATCH 78
//------------------------------------- //-------------------------------------
typedef struct { typedef struct {

72
src/web/Protection.h

@ -18,12 +18,9 @@ class Protection {
explicit Protection(const char *pwd) { explicit Protection(const char *pwd) {
mPwd = pwd; mPwd = pwd;
mLogoutTimeout = 0; mLogoutTimeout = 0;
mLoginIp.fill(0); mWebIp.fill(0);
mApiIp.fill(0);
mToken.fill(0); mToken.fill(0);
// no password set - unlock
if(pwd[0] == '\0')
mProtected = false;
} }
public: public:
@ -40,27 +37,30 @@ class Protection {
// auto logout // auto logout
if(0 != mLogoutTimeout) { if(0 != mLogoutTimeout) {
if (0 == --mLogoutTimeout) { if (0 == --mLogoutTimeout) {
if(mPwd[0] != '\0') { if(mPwd[0] != '\0')
mProtected = true; lock(false);
}
} }
} }
} }
void lock(void) { void lock(bool fromWeb) {
mProtected = true; mWebIp.fill(0);
mLoginIp.fill(0); if(fromWeb)
return;
mApiIp.fill(0);
mToken.fill(0); mToken.fill(0);
} }
char *unlock(const char *clientIp, bool loginFromWeb) { char *unlock(const char *clientIp, bool loginFromWeb) {
mLogoutTimeout = LOGOUT_TIMEOUT; mLogoutTimeout = LOGOUT_TIMEOUT;
mProtected = false;
if(loginFromWeb) if(loginFromWeb)
ah::ip2Arr(static_cast<uint8_t*>(mLoginIp.data()), clientIp); ah::ip2Arr(static_cast<uint8_t*>(mWebIp.data()), clientIp);
else else {
ah::ip2Arr(static_cast<uint8_t*>(mApiIp.data()), clientIp);
genToken(); genToken();
}
return reinterpret_cast<char*>(mToken.data()); return reinterpret_cast<char*>(mToken.data());
} }
@ -70,30 +70,19 @@ class Protection {
mLogoutTimeout = LOGOUT_TIMEOUT; mLogoutTimeout = LOGOUT_TIMEOUT;
} }
bool isProtected(void) const { bool isProtected(const char *clientIp, const char *token, bool askedFromWeb) const {
return mProtected; if(mPwd[0] == '\0') // no password set
}
bool isProtected(const char *token, bool askedFromWeb) const { // token == clientIp
if(mProtected)
return true;
if(mPwd[0] == '\0')
return false; return false;
if(askedFromWeb) { // check IP address if(askedFromWeb)
std::array<uint8_t, 4> ip; return !isIdentical(clientIp, mWebIp);
ah::ip2Arr(static_cast<uint8_t*>(ip.data()), token);
for(uint8_t i = 0; i < 4; i++) { // API call
if(mLoginIp[i] != ip[i]) if(0 == mToken[0]) // token is zero, from WebUi (logged in)
return true; return !isIdentical(clientIp, mWebIp);
}
} else { // API call - check token
if(0 == mToken[0]) // token is zero
return true;
if(isIdentical(clientIp, mApiIp))
return (0 != strncmp(token, mToken.data(), 16)); return (0 != strncmp(token, mToken.data(), 16));
}
return false; return false;
} }
@ -106,8 +95,18 @@ class Protection {
if(mToken[i] < 10) if(mToken[i] < 10)
mToken[i] += 0x30; // convert to ascii number 1-9 (zero isn't allowed) mToken[i] += 0x30; // convert to ascii number 1-9 (zero isn't allowed)
else else
mToken[i] += 0x37; // convert to ascii upper case character mToken[i] += 0x37; // convert to ascii upper case character A-Z
}
} }
bool isIdentical(const char *clientIp, const std::array<uint8_t, 4> cmp) const {
std::array<uint8_t, 4> ip;
ah::ip2Arr(static_cast<uint8_t*>(ip.data()), clientIp);
for(uint8_t i = 0; i < 4; i++) {
if(cmp[i] != ip[i])
return false;
}
return true;
} }
protected: protected:
@ -115,9 +114,8 @@ class Protection {
private: private:
const char *mPwd; const char *mPwd;
bool mProtected = true;
uint16_t mLogoutTimeout = 0; uint16_t mLogoutTimeout = 0;
std::array<uint8_t, 4> mLoginIp; std::array<uint8_t, 4> mWebIp, mApiIp;
std::array<char, 17> mToken; std::array<char, 17> mToken;
}; };

6
src/web/RestApi.h

@ -266,7 +266,7 @@ class RestApi {
obj[F("modules")] = String(mApp->getVersionModules()); obj[F("modules")] = String(mApp->getVersionModules());
obj[F("build")] = String(AUTO_GIT_HASH); obj[F("build")] = String(AUTO_GIT_HASH);
obj[F("env")] = String(ENV_NAME); obj[F("env")] = String(ENV_NAME);
obj[F("menu_prot")] = mApp->isProtected(request->client()->remoteIP().toString().c_str(), true); obj[F("menu_prot")] = mApp->isProtected(request->client()->remoteIP().toString().c_str(), "", true);
obj[F("menu_mask")] = (uint16_t)(mConfig->sys.protectionMask ); obj[F("menu_mask")] = (uint16_t)(mConfig->sys.protectionMask );
obj[F("menu_protEn")] = (bool) (mConfig->sys.adminPwd[0] != '\0'); obj[F("menu_protEn")] = (bool) (mConfig->sys.adminPwd[0] != '\0');
obj[F("cst_lnk")] = String(mConfig->plugin.customLink); obj[F("cst_lnk")] = String(mConfig->plugin.customLink);
@ -844,7 +844,7 @@ class RestApi {
if(mConfig->sys.adminPwd[0] != '\0') { // check if admin password is set if(mConfig->sys.adminPwd[0] != '\0') { // check if admin password is set
if(strncmp("*", clientIP, 1) != 0) { // no call from MqTT if(strncmp("*", clientIP, 1) != 0) { // no call from MqTT
const char* token = jsonIn["token"]; const char* token = jsonIn["token"];
if(mApp->isProtected(token, false)) { if(mApp->isProtected(clientIP, token, false)) {
jsonOut[F("error")] = F(IS_PROTECTED); jsonOut[F("error")] = F(IS_PROTECTED);
return false; return false;
} }
@ -897,7 +897,7 @@ class RestApi {
if(mConfig->sys.adminPwd[0] != '\0') { // check if admin password is set if(mConfig->sys.adminPwd[0] != '\0') { // check if admin password is set
if(strncmp("*", clientIP, 1) != 0) { // no call from MqTT if(strncmp("*", clientIP, 1) != 0) { // no call from MqTT
const char* token = jsonIn["token"]; const char* token = jsonIn["token"];
if(mApp->isProtected(token, false)) { if(mApp->isProtected(clientIP, token, false)) {
jsonOut[F("error")] = F(IS_PROTECTED); jsonOut[F("error")] = F(IS_PROTECTED);
return false; return false;
} }

6
src/web/web.h

@ -227,7 +227,7 @@ class Web {
} }
void checkProtection(AsyncWebServerRequest *request) { void checkProtection(AsyncWebServerRequest *request) {
if(mApp->isProtected(request->client()->remoteIP().toString().c_str(), true)) { if(mApp->isProtected(request->client()->remoteIP().toString().c_str(), "", true)) {
checkRedirect(request); checkRedirect(request);
return; return;
} }
@ -328,7 +328,7 @@ class Web {
DPRINTLN(DBG_VERBOSE, F("onLogout")); DPRINTLN(DBG_VERBOSE, F("onLogout"));
checkProtection(request); checkProtection(request);
mApp->lock(); mApp->lock(true);
AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), system_html, system_html_len); AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), system_html, system_html_len);
response->addHeader(F("Content-Encoding"), "gzip"); response->addHeader(F("Content-Encoding"), "gzip");
@ -455,7 +455,7 @@ class Web {
// protection // protection
if (request->arg("adminpwd") != "{PWD}") { if (request->arg("adminpwd") != "{PWD}") {
request->arg("adminpwd").toCharArray(mConfig->sys.adminPwd, PWD_LEN); request->arg("adminpwd").toCharArray(mConfig->sys.adminPwd, PWD_LEN);
mApp->lock(); mApp->lock(false);
} }
mConfig->sys.protectionMask = 0x0000; mConfig->sys.protectionMask = 0x0000;
for (uint8_t i = 0; i < 7; i++) { for (uint8_t i = 0; i < 7; i++) {

Loading…
Cancel
Save