Browse Source

0.8.77

* merge PR: BugFix: ACK #1414
* fix suspicious if condition #1416
* prepared API token for access, not functional #1415
pull/1417/head
lumapu 12 months ago
parent
commit
15349520d2
  1. 5
      src/CHANGES.md
  2. 2
      src/app.cpp
  3. 8
      src/app.h
  4. 3
      src/appInterface.h
  5. 2
      src/defines.h
  6. 32
      src/web/Protection.h
  7. 53
      src/web/RestApi.h
  8. 10
      src/web/lang.h
  9. 2
      src/web/web.h

5
src/CHANGES.md

@ -1,5 +1,10 @@
# Development Changes # Development Changes
## 0.8.77 - 2024-02-08
* merge PR: BugFix: ACK #1414
* fix suspicious if condition #1416
* prepared API token for access, not functional #1415
## 0.8.76 - 2024-02-07 ## 0.8.76 - 2024-02-07
* revert changes from yesterday regarding snprintf and its size #1410, #1411 * revert changes from yesterday regarding snprintf and its size #1410, #1411
* reduced cppcheck linter warnings significantly * reduced cppcheck linter warnings significantly

2
src/app.cpp

@ -239,7 +239,7 @@ void app::updateNtp(void) {
} }
} }
if ((mSunrise == 0) && (mConfig->sun.lat) && (mConfig->sun.lon)) { if ((0 == mSunrise) && (0.0 != mConfig->sun.lat) && (0.0 != mConfig->sun.lon)) {
mCalculatedTimezoneOffset = (int8_t)((mConfig->sun.lon >= 0 ? mConfig->sun.lon + 7.5 : mConfig->sun.lon - 7.5) / 15) * 3600; mCalculatedTimezoneOffset = (int8_t)((mConfig->sun.lon >= 0 ? mConfig->sun.lon + 7.5 : mConfig->sun.lon - 7.5) / 15) * 3600;
tickCalcSunrise(); tickCalcSunrise();
} }

8
src/app.h

@ -251,8 +251,8 @@ class app : public IApp, public ah::Scheduler {
mProtection->lock(); mProtection->lock();
} }
void unlock(const char *clientIp) override { char *unlock(const char *clientIp) override {
mProtection->unlock(clientIp); return mProtection->unlock(clientIp);
} }
void resetLockTimeout(void) override { void resetLockTimeout(void) override {
@ -267,6 +267,10 @@ class app : public IApp, public ah::Scheduler {
return mProtection->isProtected(clientIp); return mProtection->isProtected(clientIp);
} }
bool isProtected(const char *clientIp, const char *token) const override {
return mProtection->isProtected(clientIp, token);
}
bool getNrfEnabled(void) override { bool getNrfEnabled(void) override {
return mConfig->nrf.enabled; return mConfig->nrf.enabled;
} }

3
src/appInterface.h

@ -62,10 +62,11 @@ class IApp {
virtual uint32_t getMqttTxCnt() = 0; virtual uint32_t getMqttTxCnt() = 0;
virtual void lock(void) = 0; virtual void lock(void) = 0;
virtual void unlock(const char *clientIp) = 0; virtual char *unlock(const char *clientIp) = 0;
virtual void resetLockTimeout(void) = 0; virtual void resetLockTimeout(void) = 0;
virtual bool isProtected(void) const = 0; virtual bool isProtected(void) const = 0;
virtual bool isProtected(const char *clientIp) const = 0; virtual bool isProtected(const char *clientIp) const = 0;
virtual bool isProtected(const char *clientIp, const char *token) 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 76 #define VERSION_PATCH 77
//------------------------------------- //-------------------------------------
typedef struct { typedef struct {

32
src/web/Protection.h

@ -19,6 +19,7 @@ class Protection {
mPwd = pwd; mPwd = pwd;
mLogoutTimeout = 0; mLogoutTimeout = 0;
mLoginIp.fill(0); mLoginIp.fill(0);
mToken.fill(0);
// no password set - unlock // no password set - unlock
if(pwd[0] == '\0') if(pwd[0] == '\0')
@ -50,13 +51,17 @@ class Protection {
mLoginIp.fill(0); mLoginIp.fill(0);
} }
void unlock(const char *clientIp) { char *unlock(const char *clientIp) {
mLogoutTimeout = LOGOUT_TIMEOUT; mLogoutTimeout = LOGOUT_TIMEOUT;
mProtected = false; mProtected = false;
ah::ip2Arr(static_cast<uint8_t*>(mLoginIp.data()), clientIp); ah::ip2Arr(static_cast<uint8_t*>(mLoginIp.data()), clientIp);
genToken();
return reinterpret_cast<char*>(mToken.data());
} }
void resetLockTimeout(void) { void resetLockTimeout(void) {
if(0 != mLogoutTimeout)
mLogoutTimeout = LOGOUT_TIMEOUT; mLogoutTimeout = LOGOUT_TIMEOUT;
} }
@ -64,6 +69,16 @@ class Protection {
return mProtected; 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 *clientIp) const {
if(mProtected) if(mProtected)
return true; return true;
@ -81,14 +96,27 @@ class Protection {
return false; return false;
} }
private:
void genToken() {
mToken.fill(0);
for(uint8_t i = 0; i < 16; i++) {
mToken[i] = random(1, 35);
if(mToken[i] < 10)
mToken[i] += 0x30; // convert to ascii number 1-9 (zero isn't allowed)
else
mToken[i] += 0x37; // convert to ascii upper case character
}
}
protected: protected:
static Protection *mInstance; static Protection *mInstance;
private: private:
const char *mPwd; const char *mPwd;
bool mProtected = true; bool mProtected = true;
uint16_t mLogoutTimeout = LOGOUT_TIMEOUT; uint16_t mLogoutTimeout = 0;
std::array<uint8_t, 4> mLoginIp; std::array<uint8_t, 4> mLoginIp;
std::array<char, 17> mToken;
}; };
#endif /*__PROTECTION_H__*/ #endif /*__PROTECTION_H__*/

53
src/web/RestApi.h

@ -70,7 +70,7 @@ class RestApi {
if(obj[F("path")] == "ctrl") if(obj[F("path")] == "ctrl")
setCtrl(obj, dummy, "*"); setCtrl(obj, dummy, "*");
else if(obj[F("path")] == "setup") else if(obj[F("path")] == "setup")
setSetup(obj, dummy); setSetup(obj, dummy, "*");
} }
private: private:
@ -169,7 +169,7 @@ class RestApi {
if(path == "ctrl") if(path == "ctrl")
root[F("success")] = setCtrl(obj, root, request->client()->remoteIP().toString().c_str()); root[F("success")] = setCtrl(obj, root, request->client()->remoteIP().toString().c_str());
else if(path == "setup") else if(path == "setup")
root[F("success")] = setSetup(obj, root); root[F("success")] = setSetup(obj, root, request->client()->remoteIP().toString().c_str());
else { else {
root[F("success")] = false; root[F("success")] = false;
root[F("error")] = F(PATH_NOT_FOUND) + path; root[F("error")] = F(PATH_NOT_FOUND) + path;
@ -831,23 +831,44 @@ class RestApi {
} }
bool setCtrl(JsonObject jsonIn, JsonObject jsonOut, const char *clientIP) { bool setCtrl(JsonObject jsonIn, JsonObject jsonOut, const char *clientIP) {
Inverter<> *iv = mSys->getInverterByPos(jsonIn[F("id")]); if(F("auth") == jsonIn[F("cmd")]) {
bool accepted = true; if(String(jsonIn["val"]) == String(mConfig->sys.adminPwd))
if(NULL == iv) { jsonOut["token"] = mApp->unlock(clientIP);
jsonOut[F("error")] = F(INV_INDEX_INVALID) + jsonIn[F("id")].as<String>(); else {
jsonOut[F("error")] = F(AUTH_ERROR);
return false; return false;
} }
jsonOut[F("id")] = jsonIn[F("id")]; 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') { if(mConfig->sys.adminPwd[0] != '\0') { // check if admin password is set
if(strncmp("*", clientIP, 1) != 0) { // no call from API (MqTT) if(strncmp("*", clientIP, 1) != 0) { // no call from MqTT
if(mApp->isProtected(clientIP)) { if(mApp->isProtected(clientIP)) {
jsonOut[F("error")] = F(INV_IS_PROTECTED); jsonOut[F("error")] = F(IS_PROTECTED);
return false; return false;
} }
} }
} }
Inverter<> *iv = mSys->getInverterByPos(jsonIn[F("id")]);
bool accepted = true;
if(NULL == iv) {
jsonOut[F("error")] = F(INV_INDEX_INVALID) + jsonIn[F("id")].as<String>();
return false;
}
jsonOut[F("id")] = jsonIn[F("id")];
if(F("power") == jsonIn[F("cmd")]) if(F("power") == jsonIn[F("cmd")])
accepted = iv->setDevControlRequest((jsonIn[F("val")] == 1) ? TurnOn : TurnOff); accepted = iv->setDevControlRequest((jsonIn[F("val")] == 1) ? TurnOn : TurnOff);
else if(F("restart") == jsonIn[F("cmd")]) else if(F("restart") == jsonIn[F("cmd")])
@ -882,7 +903,17 @@ class RestApi {
return true; return true;
} }
bool setSetup(JsonObject jsonIn, JsonObject jsonOut) { bool setSetup(JsonObject jsonIn, JsonObject jsonOut, const char *clientIP) {
/*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);
return false;
}
}
}*/
#if !defined(ETHERNET) #if !defined(ETHERNET)
if(F("scan_wifi") == jsonIn[F("cmd")]) if(F("scan_wifi") == jsonIn[F("cmd")])
mApp->scanAvailNetworks(); mApp->scanAvailNetworks();

10
src/web/lang.h

@ -30,6 +30,12 @@
#define INV_INDEX_INVALID "inverter index invalid: " #define INV_INDEX_INVALID "inverter index invalid: "
#endif #endif
#ifdef LANG_DE
#define AUTH_ERROR "Authentifizierungsfehler"
#else /*LANG_EN*/
#define AUTH_ERROR "authentication error"
#endif
#ifdef LANG_DE #ifdef LANG_DE
#define UNKNOWN_CMD "unbekanntes Kommando: '" #define UNKNOWN_CMD "unbekanntes Kommando: '"
#else /*LANG_EN*/ #else /*LANG_EN*/
@ -37,9 +43,9 @@
#endif #endif
#ifdef LANG_DE #ifdef LANG_DE
#define INV_IS_PROTECTED "nicht angemeldet, Kommando nicht möglich!" #define IS_PROTECTED "nicht angemeldet, Kommando nicht möglich!"
#else /*LANG_EN*/ #else /*LANG_EN*/
#define INV_IS_PROTECTED "not logged in, command not possible!" #define IS_PROTECTED "not logged in, command not possible!"
#endif #endif
#ifdef LANG_DE #ifdef LANG_DE

2
src/web/web.h

@ -782,7 +782,7 @@ class Web {
// report value // report value
if (0 == channel) { if (0 == channel) {
// Report a _total value if also channel values were reported. Otherwise report without _total // Report a _total value if also channel values were reported. Otherwise report without _total
char total[7]; char total[7] = {0};
if (metricDeclared) { if (metricDeclared) {
// A declaration and value for channels have been delivered. So declare and deliver a _total metric // A declaration and value for channels have been delivered. So declare and deliver a _total metric
snprintf(total, sizeof(total), "_total"); snprintf(total, sizeof(total), "_total");

Loading…
Cancel
Save