mirror of https://github.com/lumapu/ahoy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
3.4 KiB
122 lines
3.4 KiB
//-----------------------------------------------------------------------------
|
|
// 2024 Ahoy, https://github.com/lumpapu/ahoy
|
|
// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#ifndef __PROTECTION_H__
|
|
#define __PROTECTION_H__
|
|
#pragma once
|
|
|
|
#include <array>
|
|
#include <cstdint>
|
|
|
|
#include "../config/config.h"
|
|
#include "../utils/helper.h"
|
|
|
|
class Protection {
|
|
protected:
|
|
explicit Protection(const char *pwd) {
|
|
mPwd = pwd;
|
|
mLogoutTimeout = 0;
|
|
mWebIp.fill(0);
|
|
mApiIp.fill(0);
|
|
mToken.fill(0);
|
|
}
|
|
|
|
public:
|
|
Protection(Protection &other) = delete;
|
|
void operator=(const Protection &) = delete;
|
|
|
|
static Protection* getInstance(const char *pwd) {
|
|
if(nullptr == mInstance)
|
|
mInstance = new Protection(pwd);
|
|
return mInstance;
|
|
}
|
|
|
|
void tickSecond() { // auto logout
|
|
if(0 != mLogoutTimeout) {
|
|
if (0 == --mLogoutTimeout) {
|
|
if(mPwd[0] != '\0')
|
|
lock(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
void lock(bool fromWeb) {
|
|
mWebIp.fill(0);
|
|
if(fromWeb)
|
|
return;
|
|
|
|
mApiIp.fill(0);
|
|
mToken.fill(0);
|
|
}
|
|
|
|
char *unlock(const char *clientIp, bool loginFromWeb) {
|
|
mLogoutTimeout = LOGOUT_TIMEOUT;
|
|
|
|
if(loginFromWeb)
|
|
ah::ip2Arr(static_cast<uint8_t*>(mWebIp.data()), clientIp);
|
|
else {
|
|
ah::ip2Arr(static_cast<uint8_t*>(mApiIp.data()), clientIp);
|
|
genToken();
|
|
}
|
|
|
|
return reinterpret_cast<char*>(mToken.data());
|
|
}
|
|
|
|
void resetLockTimeout(void) {
|
|
if(0 != mLogoutTimeout)
|
|
mLogoutTimeout = LOGOUT_TIMEOUT;
|
|
}
|
|
|
|
bool isProtected(const char *clientIp, const char *token, bool askedFromWeb) const {
|
|
if(mPwd[0] == '\0') // no password set
|
|
return false;
|
|
|
|
if(askedFromWeb)
|
|
return !isIdentical(clientIp, mWebIp);
|
|
|
|
if(nullptr == token)
|
|
return true;
|
|
|
|
if('*' == token[0]) // call from WebUI
|
|
return !isIdentical(clientIp, mWebIp);
|
|
|
|
if(isIdentical(clientIp, mApiIp))
|
|
return (0 != strncmp(token, mToken.data(), 16));
|
|
|
|
return false;
|
|
}
|
|
|
|
private:
|
|
void genToken() {
|
|
mToken.fill(0);
|
|
for(uint8_t i = 0; i < 16; i++) {
|
|
mToken[i] = random(1, 35);
|
|
// convert to ascii number 1-9 (zero isn't allowed) or upper
|
|
// case character A-Z
|
|
mToken[i] += (mToken[i] < 10) ? 0x30 : 0x37;
|
|
}
|
|
}
|
|
|
|
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:
|
|
static Protection *mInstance;
|
|
|
|
private:
|
|
const char *mPwd;
|
|
uint16_t mLogoutTimeout = 0;
|
|
std::array<uint8_t, 4> mWebIp, mApiIp;
|
|
std::array<char, 17> mToken;
|
|
};
|
|
|
|
#endif /*__PROTECTION_H__*/
|
|
|