From 8b2db4abfa24a9a6d596661860a4bd9dd3e52502 Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 9 Feb 2024 00:25:25 +0100 Subject: [PATCH] 0.8.78 * try to finalize API token protection --- src/CHANGES.md | 3 +++ src/app.h | 12 ++++-------- src/appInterface.h | 5 ++--- src/web/Protection.h | 40 +++++++++++++++++++++------------------- src/web/RestApi.h | 24 +++++++----------------- src/web/web.h | 4 ++-- 6 files changed, 39 insertions(+), 49 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index b75ba2b3..ea067bd2 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,8 @@ # Development Changes +## 0.8.78 - 2024-02-09 +* finalized API token access #1415 + ## 0.8.77 - 2024-02-08 * merge PR: BugFix: ACK #1414 * fix suspicious if condition #1416 diff --git a/src/app.h b/src/app.h index be20f26f..1a4e780d 100644 --- a/src/app.h +++ b/src/app.h @@ -251,8 +251,8 @@ class app : public IApp, public ah::Scheduler { mProtection->lock(); } - char *unlock(const char *clientIp) override { - return mProtection->unlock(clientIp); + char *unlock(const char *clientIp, bool loginFromWeb) override { + return mProtection->unlock(clientIp, loginFromWeb); } void resetLockTimeout(void) override { @@ -263,12 +263,8 @@ class app : public IApp, public ah::Scheduler { return mProtection->isProtected(); } - bool isProtected(const char *clientIp) const override { - return mProtection->isProtected(clientIp); - } - - bool isProtected(const char *clientIp, const char *token) const override { - return mProtection->isProtected(clientIp, token); + bool isProtected(const char *token, bool askedFromWeb) const override { + return mProtection->isProtected(token, askedFromWeb); } bool getNrfEnabled(void) override { diff --git a/src/appInterface.h b/src/appInterface.h index 937908e2..f0d2b2a0 100644 --- a/src/appInterface.h +++ b/src/appInterface.h @@ -62,11 +62,10 @@ class IApp { virtual uint32_t getMqttTxCnt() = 0; virtual void lock(void) = 0; - virtual char *unlock(const char *clientIp) = 0; + virtual char *unlock(const char *clientIp, bool loginFromWeb) = 0; virtual void resetLockTimeout(void) = 0; virtual bool isProtected(void) const = 0; - virtual bool isProtected(const char *clientIp) const = 0; - virtual bool isProtected(const char *clientIp, const char *token) 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 getHistoryMaxDay() = 0; diff --git a/src/web/Protection.h b/src/web/Protection.h index f62f1380..b9eeef95 100644 --- a/src/web/Protection.h +++ b/src/web/Protection.h @@ -40,8 +40,9 @@ class Protection { // auto logout if(0 != mLogoutTimeout) { if (0 == --mLogoutTimeout) { - if(mPwd[0] != '\0') + if(mPwd[0] != '\0') { mProtected = true; + } } } } @@ -49,13 +50,17 @@ class Protection { void lock(void) { mProtected = true; mLoginIp.fill(0); + mToken.fill(0); } - char *unlock(const char *clientIp) { + char *unlock(const char *clientIp, bool loginFromWeb) { mLogoutTimeout = LOGOUT_TIMEOUT; mProtected = false; - ah::ip2Arr(static_cast(mLoginIp.data()), clientIp); - genToken(); + + if(loginFromWeb) + ah::ip2Arr(static_cast(mLoginIp.data()), clientIp); + else + genToken(); return reinterpret_cast(mToken.data()); } @@ -69,28 +74,25 @@ class Protection { return mProtected; } - bool isProtected(const char *clientIp, const char *token) const { - if(isProtected(clientIp)) - return true; - - if(0 == mToken[0]) // token is zero - return true; - - return (0 != strncmp(token, mToken.data(), 16)); - } - - bool isProtected(const char *clientIp) const { + bool isProtected(const char *token, bool askedFromWeb) const { // token == clientIp if(mProtected) return true; if(mPwd[0] == '\0') return false; - std::array ip; - ah::ip2Arr(static_cast(ip.data()), clientIp); - for(uint8_t i = 0; i < 4; i++) { - if(mLoginIp[i] != ip[i]) + if(askedFromWeb) { // check IP address + std::array ip; + ah::ip2Arr(static_cast(ip.data()), token); + for(uint8_t i = 0; i < 4; i++) { + if(mLoginIp[i] != ip[i]) + return true; + } + } else { // API call - check token + if(0 == mToken[0]) // token is zero return true; + + return (0 != strncmp(token, mToken.data(), 16)); } return false; diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 59b786d7..5103f3ba 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -266,7 +266,7 @@ class RestApi { obj[F("modules")] = String(mApp->getVersionModules()); obj[F("build")] = String(AUTO_GIT_HASH); obj[F("env")] = String(ENV_NAME); - obj[F("menu_prot")] = mApp->isProtected(request->client()->remoteIP().toString().c_str()); + 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_protEn")] = (bool) (mConfig->sys.adminPwd[0] != '\0'); obj[F("cst_lnk")] = String(mConfig->plugin.customLink); @@ -833,7 +833,7 @@ class RestApi { bool setCtrl(JsonObject jsonIn, JsonObject jsonOut, const char *clientIP) { if(F("auth") == jsonIn[F("cmd")]) { if(String(jsonIn["val"]) == String(mConfig->sys.adminPwd)) - jsonOut["token"] = mApp->unlock(clientIP); + jsonOut["token"] = mApp->unlock(clientIP, false); else { jsonOut[F("error")] = F(AUTH_ERROR); return false; @@ -841,20 +841,10 @@ class RestApi { return true; } - /*if(mConfig->sys.adminPwd[0] != '\0') { // check if admin password is set - if(strncmp("*", clientIP, 1) != 0) { // no call from MqTT - const char* token = jsonIn["token"]; - if(mApp->isProtected(clientIP, token)) { - jsonOut[F("error")] = F(IS_PROTECTED); - jsonOut[F("bla")] = String(token); - return false; - } - } - }*/ - if(mConfig->sys.adminPwd[0] != '\0') { // check if admin password is set if(strncmp("*", clientIP, 1) != 0) { // no call from MqTT - if(mApp->isProtected(clientIP)) { + const char* token = jsonIn["token"]; + if(mApp->isProtected(token, false)) { jsonOut[F("error")] = F(IS_PROTECTED); return false; } @@ -904,15 +894,15 @@ class RestApi { } bool setSetup(JsonObject jsonIn, JsonObject jsonOut, const char *clientIP) { - /*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 const char* token = jsonIn["token"]; - if(mApp->isProtected(clientIP, token)) { + if(mApp->isProtected(token, false)) { jsonOut[F("error")] = F(IS_PROTECTED); return false; } } - }*/ + } #if !defined(ETHERNET) if(F("scan_wifi") == jsonIn[F("cmd")]) diff --git a/src/web/web.h b/src/web/web.h index 76503f0b..7ed41f92 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -227,7 +227,7 @@ class Web { } void checkProtection(AsyncWebServerRequest *request) { - if(mApp->isProtected(request->client()->remoteIP().toString().c_str())) { + if(mApp->isProtected(request->client()->remoteIP().toString().c_str(), true)) { checkRedirect(request); return; } @@ -314,7 +314,7 @@ class Web { if (request->args() > 0) { if (String(request->arg("pwd")) == String(mConfig->sys.adminPwd)) { - mApp->unlock(request->client()->remoteIP().toString().c_str()); + mApp->unlock(request->client()->remoteIP().toString().c_str(), true); request->redirect("/"); } }