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. 34
      src/web/Protection.h
  7. 55
      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
## 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
* revert changes from yesterday regarding snprintf and its size #1410, #1411
* 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;
tickCalcSunrise();
}

8
src/app.h

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

3
src/appInterface.h

@ -62,10 +62,11 @@ class IApp {
virtual uint32_t getMqttTxCnt() = 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 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 uint16_t getHistoryValue(uint8_t type, uint16_t i) = 0;
virtual uint16_t getHistoryMaxDay() = 0;

2
src/defines.h

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

34
src/web/Protection.h

@ -19,6 +19,7 @@ class Protection {
mPwd = pwd;
mLogoutTimeout = 0;
mLoginIp.fill(0);
mToken.fill(0);
// no password set - unlock
if(pwd[0] == '\0')
@ -50,20 +51,34 @@ class Protection {
mLoginIp.fill(0);
}
void unlock(const char *clientIp) {
char *unlock(const char *clientIp) {
mLogoutTimeout = LOGOUT_TIMEOUT;
mProtected = false;
ah::ip2Arr(static_cast<uint8_t*>(mLoginIp.data()), clientIp);
genToken();
return reinterpret_cast<char*>(mToken.data());
}
void resetLockTimeout(void) {
mLogoutTimeout = LOGOUT_TIMEOUT;
if(0 != mLogoutTimeout)
mLogoutTimeout = LOGOUT_TIMEOUT;
}
bool isProtected(void) const {
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 {
if(mProtected)
return true;
@ -81,14 +96,27 @@ class Protection {
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:
static Protection *mInstance;
private:
const char *mPwd;
bool mProtected = true;
uint16_t mLogoutTimeout = LOGOUT_TIMEOUT;
uint16_t mLogoutTimeout = 0;
std::array<uint8_t, 4> mLoginIp;
std::array<char, 17> mToken;
};
#endif /*__PROTECTION_H__*/

55
src/web/RestApi.h

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

10
src/web/lang.h

@ -30,6 +30,12 @@
#define INV_INDEX_INVALID "inverter index invalid: "
#endif
#ifdef LANG_DE
#define AUTH_ERROR "Authentifizierungsfehler"
#else /*LANG_EN*/
#define AUTH_ERROR "authentication error"
#endif
#ifdef LANG_DE
#define UNKNOWN_CMD "unbekanntes Kommando: '"
#else /*LANG_EN*/
@ -37,9 +43,9 @@
#endif
#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*/
#define INV_IS_PROTECTED "not logged in, command not possible!"
#define IS_PROTECTED "not logged in, command not possible!"
#endif
#ifdef LANG_DE

2
src/web/web.h

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

Loading…
Cancel
Save