diff --git a/build b/build index e440e5c..7813681 100644 --- a/build +++ b/build @@ -1 +1 @@ -3 \ No newline at end of file +5 \ No newline at end of file diff --git a/src/RESTAPI/RESTAPI_firmwareAgeHandler.cpp b/src/RESTAPI/RESTAPI_firmwareAgeHandler.cpp index e99981e..5de970a 100644 --- a/src/RESTAPI/RESTAPI_firmwareAgeHandler.cpp +++ b/src/RESTAPI/RESTAPI_firmwareAgeHandler.cpp @@ -37,8 +37,8 @@ namespace OpenWifi { Answer.set(RESTAPI::Protocol::AGES, Objects); return ReturnObject(Answer); } else { - auto DeviceType = GetParameter(RESTAPI::Protocol::DEVICETYPE, ""); - auto Revision = GetParameter(RESTAPI::Protocol::REVISION, ""); + auto DeviceType = ORM::Escape(GetParameter(RESTAPI::Protocol::DEVICETYPE, "")); + auto Revision = ORM::Escape(GetParameter(RESTAPI::Protocol::REVISION, "")); if (DeviceType.empty() || Revision.empty()) { return BadRequest(RESTAPI::Errors::BothDeviceTypeRevision); diff --git a/src/RESTAPI/RESTAPI_firmwaresHandler.cpp b/src/RESTAPI/RESTAPI_firmwaresHandler.cpp index df31d34..68687d0 100644 --- a/src/RESTAPI/RESTAPI_firmwaresHandler.cpp +++ b/src/RESTAPI/RESTAPI_firmwaresHandler.cpp @@ -10,7 +10,7 @@ namespace OpenWifi { void RESTAPI_firmwaresHandler::DoGet() { - std::string DeviceType = GetParameter(RESTAPI::Protocol::DEVICETYPE, ""); + std::string DeviceType = ORM::Escape(GetParameter(RESTAPI::Protocol::DEVICETYPE, "")); bool IdOnly = GetBoolParameter(RESTAPI::Protocol::IDONLY); bool LatestOnly = GetBoolParameter(RESTAPI::Protocol::LATESTONLY); bool rcOnly = GetBoolParameter("rcOnly"); diff --git a/src/RESTAPI/RESTAPI_historyHandler.cpp b/src/RESTAPI/RESTAPI_historyHandler.cpp index 9e5198a..64a8928 100644 --- a/src/RESTAPI/RESTAPI_historyHandler.cpp +++ b/src/RESTAPI/RESTAPI_historyHandler.cpp @@ -9,7 +9,7 @@ namespace OpenWifi { void RESTAPI_historyHandler::DoGet() { - auto SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, ""); + auto SerialNumber = ORM::Escape(GetBinding(RESTAPI::Protocol::SERIALNUMBER, "")); if(SerialNumber.empty()) { return BadRequest(RESTAPI::Errors::MissingSerialNumber); diff --git a/src/RESTObjects/RESTAPI_CertObjects.cpp b/src/RESTObjects/RESTAPI_CertObjects.cpp index 71ed5af..6b30005 100644 --- a/src/RESTObjects/RESTAPI_CertObjects.cpp +++ b/src/RESTObjects/RESTAPI_CertObjects.cpp @@ -30,6 +30,7 @@ namespace OpenWifi::CertObjects { field_to_json(Obj,"revoked", revoked); field_to_json(Obj,"revokeCount", revokeCount); field_to_json(Obj,"synched", synched); + field_to_json(Obj,"expiryDate", expiryDate); } bool CertificateEntry::from_json(const Poco::JSON::Object::Ptr &Obj) { @@ -54,6 +55,7 @@ namespace OpenWifi::CertObjects { field_from_json(Obj,"revoked", revoked); field_from_json(Obj,"revokeCount", revokeCount); field_from_json(Obj,"synched", synched); + field_from_json(Obj,"expiryDate", expiryDate); return true; } catch (...) { } diff --git a/src/RESTObjects/RESTAPI_CertObjects.h b/src/RESTObjects/RESTAPI_CertObjects.h index 29b902f..4baeafa 100644 --- a/src/RESTObjects/RESTAPI_CertObjects.h +++ b/src/RESTObjects/RESTAPI_CertObjects.h @@ -31,6 +31,7 @@ namespace OpenWifi::CertObjects { uint64_t revoked = 0; uint64_t revokeCount = 0; uint64_t synched = 0; + uint64_t expiryDate = 0 ; void to_json(Poco::JSON::Object &Obj) const; bool from_json(const Poco::JSON::Object::Ptr &Obj); diff --git a/src/framework/AuthClient.cpp b/src/framework/AuthClient.cpp index 64c33a5..24c498d 100644 --- a/src/framework/AuthClient.cpp +++ b/src/framework/AuthClient.cpp @@ -76,7 +76,7 @@ namespace OpenWifi { bool AuthClient::RetrieveApiKeyInformation(const std::string & SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, std::uint64_t TID, - bool & Expired, bool & Contacted) { + bool & Expired, bool & Contacted, [[maybe_unused]] bool & Suspended) { try { Types::StringPairVec QueryData; QueryData.push_back(std::make_pair("apikey",SessionToken)); @@ -113,7 +113,7 @@ namespace OpenWifi { } bool AuthClient::IsValidApiKey(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy &UInfo, - std::uint64_t TID, bool &Expired, bool &Contacted) { + std::uint64_t TID, bool &Expired, bool &Contacted, bool & Suspended) { auto User = ApiKeyCache_.get(SessionToken); if (!User.isNull()) { if(User->ExpiresOn < Utils::Now()) { @@ -123,7 +123,7 @@ namespace OpenWifi { } ApiKeyCache_.remove(SessionToken); } - return RetrieveApiKeyInformation(SessionToken, UInfo, TID, Expired, Contacted); + return RetrieveApiKeyInformation(SessionToken, UInfo, TID, Expired, Contacted, Suspended); } } // namespace OpenWifi \ No newline at end of file diff --git a/src/framework/AuthClient.h b/src/framework/AuthClient.h index 44f16db..0ff4f6c 100644 --- a/src/framework/AuthClient.h +++ b/src/framework/AuthClient.h @@ -57,7 +57,7 @@ namespace OpenWifi { bool RetrieveApiKeyInformation(const std::string & SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, std::uint64_t TID, - bool & Expired, bool & Contacted); + bool & Expired, bool & Contacted, bool & Suspended); bool IsAuthorized(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, std::uint64_t TID, @@ -65,7 +65,7 @@ namespace OpenWifi { bool IsValidApiKey(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, std::uint64_t TID, - bool & Expired, bool & Contacted); + bool & Expired, bool & Contacted, bool & Suspended) ; private: diff --git a/src/framework/RESTAPI_Handler.h b/src/framework/RESTAPI_Handler.h index 17e73de..4c72497 100644 --- a/src/framework/RESTAPI_Handler.h +++ b/src/framework/RESTAPI_Handler.h @@ -705,11 +705,12 @@ namespace OpenWifi { return Allowed; } else if(!Internal_ && Request->has("X-API-KEY")) { SessionToken_ = Request->get("X-API-KEY", ""); + bool suspended=false; #ifdef TIP_SECURITY_SERVICE std::uint64_t expiresOn; - if (AuthService()->IsValidApiKey(SessionToken_, UserInfo_.webtoken, UserInfo_.userinfo, Expired, expiresOn)) { + if (AuthService()->IsValidApiKey(SessionToken_, UserInfo_.webtoken, UserInfo_.userinfo, Expired, expiresOn, suspended)) { #else - if (AuthClient()->IsValidApiKey( SessionToken_, UserInfo_, TransactionId_, Expired, Contacted)) { + if (AuthClient()->IsValidApiKey( SessionToken_, UserInfo_, TransactionId_, Expired, Contacted, suspended)) { #endif REST_Requester_ = UserInfo_.userinfo.email; if(Server_.LogIt(Request->getMethod(),true)) { diff --git a/src/framework/orm.h b/src/framework/orm.h index 6b7604f..347b1ad 100644 --- a/src/framework/orm.h +++ b/src/framework/orm.h @@ -25,6 +25,8 @@ #include "Poco/StringTokenizer.h" #include "StorageClass.h" +#include "fmt/format.h" + namespace ORM { enum FieldType { @@ -137,7 +139,7 @@ namespace ORM { return Result; } - template std::string WHERE_AND_(std::string Result, const char *fieldName, const T &Value, Args... args) { + template std::string WHERE_AND_(std::string Result, const char *fieldName, const T & Value, Args... args) { if constexpr(std::is_same_v) { if(!Value.empty()) { @@ -149,12 +151,34 @@ namespace ORM { Result += Escape(Value); Result += "'"; } - } else { + return WHERE_AND_(Result,args...); + } else if constexpr(std::is_same_v) { + if(*Value!=0) { + if(!Result.empty()) + Result += " and "; + Result += fieldName; + Result += '='; + Result += "'"; + Result += Escape(Value); + Result += "'"; + } + return WHERE_AND_(Result,args...); + } else if constexpr (std::is_same_v) { + if(!Result.empty()) + Result += " and "; + Result += fieldName; + Result += '='; + Result += Value ? "true" : "false"; + return WHERE_AND_(Result,args...); + } else if constexpr (std::is_arithmetic_v) { if(!Result.empty()) Result += " and "; Result += fieldName ; Result += '='; Result += std::to_string(Value); + return WHERE_AND_(Result,args...); + } else { + assert(false); } return WHERE_AND_(Result,args...); } @@ -483,15 +507,13 @@ namespace ORM { return false; } - template bool GetRecordExt(RecordType & T , Args... args) { + bool GetRecord(RecordType & T , const std::string &WhereClause) { try { Poco::Data::Session Session = Pool_.get(); Poco::Data::Statement Select(Session); RecordTuple RT; - auto WhereClause = WHERE_AND(args...); - - std::string St = "select " + SelectFields_ + " from " + TableName_ + WhereClause + " limit 1"; + std::string St = "select " + SelectFields_ + " from " + TableName_ + " where " + WhereClause + " limit 1"; Select << ConvertParams(St) , Poco::Data::Keywords::into(RT); diff --git a/src/framework/ow_constants.h b/src/framework/ow_constants.h index ceaf163..cc9146a 100644 --- a/src/framework/ow_constants.h +++ b/src/framework/ow_constants.h @@ -35,7 +35,8 @@ namespace OpenWifi { BAD_MFA_TRANSACTION, MFA_FAILURE, SECURITY_SERVICE_UNREACHABLE, - CANNOT_REFRESH_TOKEN + CANNOT_REFRESH_TOKEN, + ACCOUNT_SUSPENDED }; } @@ -58,6 +59,7 @@ namespace OpenWifi::RESTAPI::Errors { static const struct msg MFA_FAILURE{12,"MFA failure."}; static const struct msg SECURITY_SERVICE_UNREACHABLE{13,"Security service is unreachable, try again later."}; static const struct msg CANNOT_REFRESH_TOKEN{14,"Cannot refresh token."}; + static const struct msg ACCOUNT_SUSPENDED{15,"Account has been suspended."}; static const struct msg MissingUUID{1000,"Missing UUID."}; static const struct msg MissingSerialNumber{1001,"Missing Serial Number."}; @@ -233,6 +235,23 @@ namespace OpenWifi::RESTAPI::Errors { static const struct msg InvalidScriptSelection{1153,"Only script or scriptId must be specified. Not both."}; static const struct msg NoDeviceStatisticsYet{1154,"Device statistics not available yet."}; + static const struct msg AccountSuspended{1155,"You account was suspended. You can only use this site in read-only mode for now."}; + static const struct msg BatchNameAlreadyExists{1156,"Batch name must be unique."}; + static const struct msg RedirectorNameIsInvalid{1157,"Redirector name is invalid."}; + static const struct msg CertificateAlreadyBelongsToYou{1158,"The serial number already belongs to you. Please use the certificate modification API to change the redirector."}; + static const struct msg RelocationDisabledForThisDevice{1159,"Relocation disabled for this device."}; + static const struct msg CannotModifyServerCertificates{1160,"Server certificates cannot be modified."}; + + static const struct msg TransferNotInDispute{1161,"The specified transfer is not being disputed."}; + static const struct msg MissingComment{1162,"Missing comment."}; + static const struct msg EntityNotAllowedToTransfer{1163,"Entity is not allowed to transfer devices."}; + static const struct msg DailyTransferQuotaExceeded{1164,"Entity has exceeded its daily quota."}; + static const struct msg CertificateWasNotRevoked{1165,"Certificate was not revoked, so it may not be re-created."}; + static const struct msg CertificateTransferNoLongerExists{1166,"The device certificate associated with this transfer no longer seem to exist."}; + static const struct msg CertificateTransferEntityNoLongerExists{1167,"The entity tied to this transfer no longer seems to exist."}; + static const struct msg CannotRollBackDueToDigiCert{1168,"The change could not be rolled back at this time. Please try later."}; + static const struct msg CertificateTransferAlreadyRolledBack{1169,"The certificate has already been rolled back."}; + } @@ -485,6 +504,7 @@ namespace OpenWifi::uCentralProtocol::Events { static const char *TELEMETRY = "telemetry"; static const char *DEVICEUPDATE = "deviceupdate"; static const char *VENUE_BROADCAST = "venue_broadcast"; + static const char *ALARM = "alarm"; enum EVENT_MSG { ET_UNKNOWN, @@ -498,7 +518,10 @@ namespace OpenWifi::uCentralProtocol::Events { ET_RECOVERY, ET_DEVICEUPDATE, ET_TELEMETRY, - ET_VENUEBROADCAST + ET_VENUEBROADCAST, + ET_EVENT, + ET_WIFISCAN, + ET_ALARM }; inline EVENT_MSG EventFromString(const std::string & Method) { @@ -524,7 +547,13 @@ namespace OpenWifi::uCentralProtocol::Events { return ET_TELEMETRY; else if(strcmp(VENUE_BROADCAST,Method.c_str())==0) return ET_VENUEBROADCAST; - return ET_UNKNOWN; + else if(strcmp(EVENT,Method.c_str())==0) + return ET_EVENT; + else if(strcmp(WIFISCAN,Method.c_str())==0) + return ET_WIFISCAN; + else if(strcmp(ALARM,Method.c_str())==0) + return ET_WIFISCAN; + return ET_ALARM; }; } diff --git a/src/framework/utils.cpp b/src/framework/utils.cpp index 2b0e16f..a03f0a5 100644 --- a/src/framework/utils.cpp +++ b/src/framework/utils.cpp @@ -109,6 +109,11 @@ uint64_t MACToInt(const std::string &MAC) { return Result; } +[[nodiscard]] bool ValidHostname(const std::string &Hostname) { + static std::regex HostNameRegex("^(?!-)[A-Za-z0-9-]+([\\-\\.]{1}[a-z0-9]+)*\\.[A-Za-z]{2,6}$"); + return std::regex_match(Hostname,HostNameRegex); +} + [[nodiscard]] std::string ToHex(const std::vector & B) { std::string R; R.reserve(B.size()*2); @@ -560,4 +565,11 @@ bool ExtractBase64CompressedData(const std::string &CompressedData, return false; } + [[nodiscard]] std::uint64_t ConvertDate(const std::string &Date) { + Poco::DateTime DT; + int TZ; + Poco::DateTimeParser::parse(Poco::DateTimeFormat::ISO8601_FORMAT,Date,DT,TZ); + return DT.timestamp().epochTime(); + } + } diff --git a/src/framework/utils.h b/src/framework/utils.h index b587837..7a8255a 100644 --- a/src/framework/utils.h +++ b/src/framework/utils.h @@ -73,6 +73,7 @@ namespace OpenWifi::Utils { [[nodiscard]] bool ValidSerialNumber(const std::string &Serial); [[nodiscard]] bool ValidUUID(const std::string &UUID); + [[nodiscard]] bool ValidHostname(const std::string &hostname); template std::string ComputeHash(Args&&... args) { Poco::SHA2Engine E; @@ -121,6 +122,8 @@ namespace OpenWifi::Utils { [[nodiscard]] std::string SanitizeToken(const std::string &Token); [[nodiscard]] bool ValidateURI(const std::string &uri); + [[nodiscard]] std::uint64_t ConvertDate(const std::string &d); + template< typename T > std::string int_to_hex( T i ) {