diff --git a/CMakeLists.txt b/CMakeLists.txt index 86837a5..2c67c56 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -216,6 +216,7 @@ add_executable(owprov src/RESTAPI/RESTAPI_radiusendpoint_list_handler.h src/RESTAPI/RESTAPI_radius_endpoint_handler.cpp src/RESTAPI/RESTAPI_radius_endpoint_handler.h + src/OrionWifi.h ) target_link_libraries(owprov PUBLIC diff --git a/build b/build index d2e1cef..abc4eff 100644 --- a/build +++ b/build @@ -1 +1 @@ -44 \ No newline at end of file +46 \ No newline at end of file diff --git a/src/OpenRoamin_GlobalReach.cpp b/src/OpenRoamin_GlobalReach.cpp index eab6a10..133d193 100644 --- a/src/OpenRoamin_GlobalReach.cpp +++ b/src/OpenRoamin_GlobalReach.cpp @@ -16,181 +16,190 @@ namespace OpenWifi { - int OpenRoaming_GlobalReach::Start() { - poco_information(Logger(), "Starting..."); - InitCache(); - return 0; - } + namespace GlobalReach { + int OpenRoaming::Start() { + poco_information(Logger(), "Starting..."); + InitCache(); + return 0; + } - void OpenRoaming_GlobalReach::Stop() { - poco_information(Logger(), "Stopping..."); - poco_information(Logger(), "Stopped..."); - } + void OpenRoaming::Stop() { + poco_information(Logger(), "Stopping..."); + poco_information(Logger(), "Stopped..."); + } + + void OpenRoaming::InitCache() { + + auto F = [&](const ProvObjects::GLBLRAccountInfo &Info) { + poco_information(Logger(), fmt::format("Adding {} to cache.", Info.info.name)); + if (!Info.privateKey.empty() && !Info.GlobalReachAcctId.empty()) { + MakeToken(Info.GlobalReachAcctId, Info.privateKey); + } + return true; + }; - void OpenRoaming_GlobalReach::InitCache() { + StorageService()->GLBLRAccountInfoDB().Iterate(F); + } - auto F=[&](const ProvObjects::GLBLRAccountInfo &Info) { - poco_information(Logger(),fmt::format("Adding {} to cache.",Info.info.name)); - if(!Info.privateKey.empty() && !Info.GlobalReachAcctId.empty() ) { - MakeToken(Info.GlobalReachAcctId, Info.privateKey); + bool OpenRoaming::CreateRADSECCertificate( + const std::string &GlobalReachAccountId, + const std::string &Name, + const std::string &CSR, + ProvObjects::GLBLRCertificateInfo &NewCertificate) { + + try { + std::cout << __LINE__ << ":" << GlobalReachAccountId << std::endl; + auto BearerToken = MakeToken(GlobalReachAccountId); + Poco::URI URI{"https://config.openro.am/v1/radsec/issue"}; + std::string Path(URI.getPathAndQuery()); + Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_POST, Path, + Poco::Net::HTTPMessage::HTTP_1_1); + Request.add("Authorization", "Bearer " + BearerToken); + + Poco::Net::HTTPSClientSession Session(URI.getHost(), URI.getPort()); + Session.setTimeout(Poco::Timespan(10000, 10000)); + Poco::JSON::Object CertRequestBody; + CertRequestBody.set("name", Name); + CertRequestBody.set("csr", CSR); + + std::ostringstream os; + CertRequestBody.stringify(os); + Request.setContentType("application/json"); + Request.setContentLength((long) os.str().size()); + + auto &Body = Session.sendRequest(Request); + Body << os.str(); + + Poco::Net::HTTPResponse Response; + std::istream &is = Session.receiveResponse(Response); + if (Response.getStatus() == Poco::Net::HTTPResponse::HTTP_OK) { + Poco::JSON::Parser P; + auto Result = P.parse(is).extract(); + RESTAPIHandler::AssignIfPresent(Result, "certificate", NewCertificate.certificate); + RESTAPIHandler::AssignIfPresent(Result, "certificate_chain", NewCertificate.certificateChain); + RESTAPIHandler::AssignIfPresent(Result, "certificate_id", NewCertificate.certificateId); + RESTAPIHandler::AssignIfPresent(Result, "expires_at", NewCertificate.expiresAt); + return true; + } + Poco::JSON::Parser P; + std::ostringstream oos; + auto Result = P.parse(is).extract(); + Result->stringify(oos); + } catch (const Poco::Exception &E) { + poco_error(Logger(), + fmt::format("Could not create a new RADSEC certificate: {},{}", E.name(), E.displayText())); } - return true; - }; + return false; + } - StorageService()->GLBLRAccountInfoDB().Iterate(F); - } + bool OpenRoaming::GetRADSECCertificate( + const std::string &GlobalReachAccountId, + std::string &CertificateId, + ProvObjects::GLBLRCertificateInfo &NewCertificate) { - bool OpenRoaming_GlobalReach::CreateRADSECCertificate( - const std::string &GlobalReachAccountId, - const std::string &Name, - const std::string &CSR, - ProvObjects::GLBLRCertificateInfo &NewCertificate) { + try { + Poco::URI URI{fmt::format("https://config.openro.am/v1/radsec/cert/{}", CertificateId)}; - try { - std::cout << __LINE__ << ":" << GlobalReachAccountId << std::endl; - auto BearerToken = MakeToken(GlobalReachAccountId); - Poco::URI URI{"https://config.openro.am/v1/radsec/issue"}; - std::string Path(URI.getPathAndQuery()); - Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_POST, Path, - Poco::Net::HTTPMessage::HTTP_1_1); - Request.add("Authorization", "Bearer " + BearerToken); + std::string Path(URI.getPathAndQuery()); - Poco::Net::HTTPSClientSession Session(URI.getHost(), URI.getPort()); - Session.setTimeout(Poco::Timespan(10000, 10000)); - Poco::JSON::Object CertRequestBody; - CertRequestBody.set("name", Name); - CertRequestBody.set("csr", CSR); + Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_GET, Path, + Poco::Net::HTTPMessage::HTTP_1_1); - std::ostringstream os; - CertRequestBody.stringify(os); - Request.setContentType("application/json"); - Request.setContentLength((long) os.str().size()); + auto BearerToken = MakeToken(GlobalReachAccountId); + Request.add("Authorization", "Bearer " + BearerToken); - auto &Body = Session.sendRequest(Request); - Body << os.str(); + Poco::Net::HTTPSClientSession Session(URI.getHost(), URI.getPort()); + Session.setTimeout(Poco::Timespan(10000, 10000)); - Poco::Net::HTTPResponse Response; - std::istream &is = Session.receiveResponse(Response); - if (Response.getStatus() == Poco::Net::HTTPResponse::HTTP_OK) { - Poco::JSON::Parser P; - auto Result = P.parse(is).extract(); - RESTAPIHandler::AssignIfPresent(Result,"certificate",NewCertificate.certificate); - RESTAPIHandler::AssignIfPresent(Result,"certificate_chain",NewCertificate.certificateChain); - RESTAPIHandler::AssignIfPresent(Result,"certificate_id",NewCertificate.certificateId); - RESTAPIHandler::AssignIfPresent(Result,"expires_at",NewCertificate.expiresAt); - return true; + Session.sendRequest(Request); + + Poco::Net::HTTPResponse Response; + std::istream &is = Session.receiveResponse(Response); + if (Response.getStatus() == Poco::Net::HTTPResponse::HTTP_OK) { + Poco::JSON::Parser P; + auto Result = P.parse(is).extract(); + RESTAPIHandler::AssignIfPresent(Result, "certificate", NewCertificate.certificate); + RESTAPIHandler::AssignIfPresent(Result, "certificate_chain", NewCertificate.certificateChain); + RESTAPIHandler::AssignIfPresent(Result, "certificate_id", NewCertificate.certificateId); + RESTAPIHandler::AssignIfPresent(Result, "expires_at", NewCertificate.expiresAt); + return true; + } + } catch (const Poco::Exception &E) { + poco_error(Logger(), fmt::format("Could not retrieve the certificate from GlobalReach: {},{}", E.name(), + E.displayText())); } - Poco::JSON::Parser P; - std::ostringstream oos; - auto Result = P.parse(is).extract(); - Result->stringify(oos); - } catch( const Poco::Exception &E) { - poco_error(Logger(),fmt::format("Could not create a new RADSEC certificate: {},{}",E.name(),E.displayText())); + return false; } - return false; - } - bool OpenRoaming_GlobalReach::GetRADSECCertificate( - const std::string &GlobalReachAccountId, - std::string &CertificateId, - ProvObjects::GLBLRCertificateInfo &NewCertificate) { + std::string + OpenRoaming::MakeToken(const std::string &GlobalReachAccountId, const std::string &PrivateKey) { + try { + Poco::JWT::Token token; + token.setType("JWT"); + token.setAlgorithm("ES256"); + token.setIssuedAt(std::time(nullptr)); + + token.payload().set("iss", GlobalReachAccountId); + token.payload().set("iat", (unsigned long) std::time(nullptr)); + + Poco::SharedPtr Key; + auto KeyHash = Utils::ComputeHash(PrivateKey); + auto KeyHint = PrivateKeys_.find(GlobalReachAccountId); + if (KeyHint != PrivateKeys_.end() && PrivateKey.empty()) { + Key = KeyHint->second.second; + } else { + if (PrivateKey.empty()) { + return ""; + } + Poco::TemporaryFile F; + std::ofstream ofs(F.path().c_str(), + std::ios_base::trunc | std::ios_base::out | std::ios_base::binary); + ofs << PrivateKey; + ofs.close(); + auto NewKey = Poco::SharedPtr( + new Poco::Crypto::ECKey("", F.path(), "")); + Key = NewKey; + PrivateKeys_[GlobalReachAccountId] = std::make_pair(KeyHash, NewKey); + } + + Poco::JWT::Signer Signer; + Signer.setECKey(Key); + Signer.addAllAlgorithms(); + return Signer.sign(token, Poco::JWT::Signer::ALGO_ES256); + } catch (const Poco::Exception &E) { + poco_error(Logger(), + fmt::format("Cannot create a Global Reach token: {},{}", E.name(), E.displayText())); + } + return ""; + } - try { - Poco::URI URI{fmt::format("https://config.openro.am/v1/radsec/cert/{}", CertificateId)}; + bool + OpenRoaming::VerifyAccount(const std::string &GlobalReachAccountId, const std::string &PrivateKey, + std::string &Name) { + auto BearerToken = MakeToken(GlobalReachAccountId, PrivateKey); + Poco::URI URI{"https://config.openro.am/v1/config"}; std::string Path(URI.getPathAndQuery()); - Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_GET, Path, Poco::Net::HTTPMessage::HTTP_1_1); - - auto BearerToken = MakeToken(GlobalReachAccountId); Request.add("Authorization", "Bearer " + BearerToken); Poco::Net::HTTPSClientSession Session(URI.getHost(), URI.getPort()); Session.setTimeout(Poco::Timespan(10000, 10000)); - Session.sendRequest(Request); - Poco::Net::HTTPResponse Response; std::istream &is = Session.receiveResponse(Response); if (Response.getStatus() == Poco::Net::HTTPResponse::HTTP_OK) { Poco::JSON::Parser P; auto Result = P.parse(is).extract(); - RESTAPIHandler::AssignIfPresent(Result,"certificate",NewCertificate.certificate); - RESTAPIHandler::AssignIfPresent(Result,"certificate_chain",NewCertificate.certificateChain); - RESTAPIHandler::AssignIfPresent(Result,"certificate_id",NewCertificate.certificateId); - RESTAPIHandler::AssignIfPresent(Result,"expires_at",NewCertificate.expiresAt); + if (Result->has("name")) { + Name = Result->get("name").toString(); + } return true; } - } catch( const Poco::Exception &E) { - poco_error(Logger(),fmt::format("Could not retrieve the certificate from GlobalReach: {},{}",E.name(),E.displayText())); + return false; } - return false; - } - - std::string OpenRoaming_GlobalReach::MakeToken(const std::string &GlobalReachAccountId, const std::string &PrivateKey) { - try { - Poco::JWT::Token token; - token.setType("JWT"); - token.setAlgorithm("ES256"); - token.setIssuedAt(std::time(nullptr)); - - token.payload().set("iss", GlobalReachAccountId); - token.payload().set("iat", (unsigned long) std::time(nullptr)); - - Poco::SharedPtr Key; - auto KeyHash = Utils::ComputeHash(PrivateKey); - auto KeyHint = PrivateKeys_.find(GlobalReachAccountId); - if (KeyHint != PrivateKeys_.end() && PrivateKey.empty() ) { - Key = KeyHint->second.second; - } else { - if (PrivateKey.empty()) { - return ""; - } - Poco::TemporaryFile F; - std::ofstream ofs(F.path().c_str(), std::ios_base::trunc | std::ios_base::out | std::ios_base::binary); - ofs << PrivateKey; - ofs.close(); - auto NewKey = Poco::SharedPtr( - new Poco::Crypto::ECKey("", F.path(), "")); - Key = NewKey; - PrivateKeys_[GlobalReachAccountId] = std::make_pair(KeyHash, NewKey); - } - Poco::JWT::Signer Signer; - Signer.setECKey(Key); - Signer.addAllAlgorithms(); - return Signer.sign(token, Poco::JWT::Signer::ALGO_ES256); - } catch (const Poco::Exception &E) { - poco_error(Logger(),fmt::format("Cannot create a Global Reach token: {},{}",E.name(),E.displayText())); - } - return ""; } - bool OpenRoaming_GlobalReach::VerifyAccount(const std::string &GlobalReachAccountId, const std::string &PrivateKey, std::string &Name) { - auto BearerToken = MakeToken(GlobalReachAccountId, PrivateKey); - - Poco::URI URI{"https://config.openro.am/v1/config"}; - std::string Path(URI.getPathAndQuery()); - Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_GET, Path, - Poco::Net::HTTPMessage::HTTP_1_1); - Request.add("Authorization", "Bearer " + BearerToken); - - Poco::Net::HTTPSClientSession Session(URI.getHost(), URI.getPort()); - Session.setTimeout(Poco::Timespan(10000, 10000)); - Session.sendRequest(Request); - Poco::Net::HTTPResponse Response; - std::istream &is = Session.receiveResponse(Response); - if(Response.getStatus()==Poco::Net::HTTPResponse::HTTP_OK) { - Poco::JSON::Parser P; - auto Result = P.parse(is).extract(); - if(Result->has("name")) { - Name = Result->get("name").toString(); - } - return true; - } - return false; - } - - } // OpenWifi \ No newline at end of file diff --git a/src/OpenRoamin_GlobalReach.h b/src/OpenRoamin_GlobalReach.h index 6cb009e..72bb309 100644 --- a/src/OpenRoamin_GlobalReach.h +++ b/src/OpenRoamin_GlobalReach.h @@ -10,34 +10,43 @@ namespace OpenWifi { - class OpenRoaming_GlobalReach : public SubSystemServer { - public: - static auto instance() { - static auto instance_ = new OpenRoaming_GlobalReach; - return instance_; - } - - int Start() override; - void Stop() override; - bool CreateRADSECCertificate(const std::string &AccountName, - const std::string &Name, - const std::string &CSR, - ProvObjects::GLBLRCertificateInfo &NewCertificate); - bool GetRADSECCertificate(const std::string &AccountName, std::string & CertificateId, ProvObjects::GLBLRCertificateInfo &NewCertificate); - bool VerifyAccount(const std::string &GlobalReachAccountId, const std::string &PrivateKey, std::string &Name); - void InitCache(); - - private: - std::string MakeToken(const std::string &GlobalReachAccountId, const std::string &PrivateKey=""); - - std::map>> PrivateKeys_; - - OpenRoaming_GlobalReach() noexcept - : SubSystemServer("OpenRoaming_GlobalReach", "GLBL-REACH", "globalreach") { - } - }; - - inline auto OpenRoaming_GlobalReach() { return OpenRoaming_GlobalReach::instance(); } + namespace GlobalReach { + class OpenRoaming : public SubSystemServer { + public: + static auto instance() { + static auto instance_ = new OpenRoaming; + return instance_; + } + + int Start() override; + + void Stop() override; + + bool CreateRADSECCertificate(const std::string &AccountName, + const std::string &Name, + const std::string &CSR, + ProvObjects::GLBLRCertificateInfo &NewCertificate); + + bool GetRADSECCertificate(const std::string &AccountName, std::string &CertificateId, + ProvObjects::GLBLRCertificateInfo &NewCertificate); + + bool + VerifyAccount(const std::string &GlobalReachAccountId, const std::string &PrivateKey, std::string &Name); + + void InitCache(); + + private: + std::string MakeToken(const std::string &GlobalReachAccountId, const std::string &PrivateKey = ""); + + std::map>> PrivateKeys_; + + OpenRoaming() noexcept + : SubSystemServer("OpenRoaming_GlobalReach", "GLBL-REACH", "globalreach") { + } + }; + } + + inline auto OpenRoaming_GlobalReach() { return GlobalReach::OpenRoaming::instance(); } } // OpenWifi diff --git a/src/OrionWifi.h b/src/OrionWifi.h new file mode 100644 index 0000000..9f2aba5 --- /dev/null +++ b/src/OrionWifi.h @@ -0,0 +1,19 @@ +// +// Created by stephane bourque on 2023-09-28. +// + +#pragma once + +#include +#include + +namespace OpenWifi { + + namespace Orion { + inline const std::vector ServerAddresses = { + Poco::Net::SocketAddress("216.239.32.91:2083"), + Poco::Net::SocketAddress("216.239.34.91:2083") + }; + } + +} \ No newline at end of file diff --git a/src/RESTAPI/RESTAPI_radius_endpoint_handler.cpp b/src/RESTAPI/RESTAPI_radius_endpoint_handler.cpp index e9f3bc5..84bd00e 100644 --- a/src/RESTAPI/RESTAPI_radius_endpoint_handler.cpp +++ b/src/RESTAPI/RESTAPI_radius_endpoint_handler.cpp @@ -3,15 +3,9 @@ // #include "RESTAPI_radius_endpoint_handler.h" +#include namespace OpenWifi { - static inline bool ValidEndpointTypes(const std::string &T) { - return T=="radius" || T=="radsec" || T=="globalreach" || T=="orion"; - } - - static inline bool ValidPoolStrategy(const std::string &T) { - return T=="none" || T=="random" || T=="weighted"; - } void RESTAPI_radius_endpoint_handler::DoGet() { auto id = GetBinding("id"); @@ -40,6 +34,17 @@ namespace OpenWifi { return NotFound(); } + static bool ValidPort(std::uint32_t P) { + return P>0 && P<65535; + } + + static bool ValidRadiusServer(const ProvObjects::RADIUSServer &S) { + if(S.Hostname.empty() || !ValidPort(S.Port) || !Utils::ValidIP(S.IP) || S.Secret.empty()) { + return false; + } + return true; + } + void RESTAPI_radius_endpoint_handler::DoPost() { auto id = GetBinding("id"); if(id.empty()) { @@ -52,19 +57,98 @@ namespace OpenWifi { return BadRequest(RESTAPI::Errors::InvalidJSONDocument); } - if(!ValidEndpointTypes(NewRecord.Type)) { + if(RadiusEndpointDB::EndpointType(NewRecord.Type)!=RadiusEndpointDB::EndpointType::unknown) { return BadRequest(RESTAPI::Errors::InvalidRadiusTypeEndpoint); } - if(!ValidPoolStrategy(NewRecord.PoolStrategy)) { + if(RadiusEndpointDB::PoolStrategy(NewRecord.PoolStrategy)!=RadiusEndpointDB::PoolStrategy::unknown) { return BadRequest(RESTAPI::Errors::InvalidRadiusEndpointPoolStrategy); } if(!NewRecord.RadiusServers.empty() && !NewRecord.RadsecServers.empty()) { return BadRequest(RESTAPI::Errors::EndpointMustHaveOneTypeOfServers); } - if(NewRecord.Index.empty()) { + + auto EndPointType = RadiusEndpointDB::EndpointType(NewRecord.Type); + switch(EndPointType) { + case RadiusEndpointDB::EndpointType::radsec: + case RadiusEndpointDB::EndpointType::orion: + case RadiusEndpointDB::EndpointType::globalreach: + { + if(NewRecord.RadsecServers.empty()) { + return BadRequest(RESTAPI::Errors::EndpointMustHaveOneTypeOfServers); + } + } break; + case RadiusEndpointDB::EndpointType::radius: { + if(NewRecord.RadiusServers.empty()) { + return BadRequest(RESTAPI::Errors::EndpointMustHaveOneTypeOfServers); + } + } break; + default: + return BadRequest(RESTAPI::Errors::EndpointMustHaveOneTypeOfServers); + } + + if(NewRecord.Index.empty() || !RadiusEndpointDB::ValidIndex(NewRecord.Index)) { + return BadRequest(RESTAPI::Errors::RadiusEndpointIndexInvalid); + } + + // Make sure that nobody is using that index + auto where = fmt::format(" index='{}' ", NewRecord.Index); + if(DB_.Count(where)!=0) { return BadRequest(RESTAPI::Errors::RadiusEndpointIndexInvalid); } + if(EndPointType==RadiusEndpointDB::EndpointType::radius) { + for(const auto &Server:NewRecord.RadiusServers) { + if(!ValidRadiusServer(Server.Authentication) || + !ValidRadiusServer(Server.Accounting) || + !ValidRadiusServer(Server.CoA)) { + return BadRequest(RESTAPI::Errors::InvalidRadiusServer); + } + } + } else { + switch(EndPointType) { + case RadiusEndpointDB::EndpointType::orion: { + for(const auto &Server:NewRecord.RadsecServers) { + if(!StorageService()->OrionAccountsDB().Exists("id",Server.UseOpenRoamingAccount)) { + return BadRequest(RESTAPI::Errors::OrionAccountMustExist); + } + } + } break; + case RadiusEndpointDB::EndpointType::globalreach: { + for(const auto &Server:NewRecord.RadsecServers) { + if(!StorageService()->GLBLRCertsDB().Exists("id",Server.UseOpenRoamingAccount)) { + return BadRequest(RESTAPI::Errors::GlobalReachCertMustExist); + } + } + } break; + case RadiusEndpointDB::EndpointType::radsec: { + for(const auto &Server:NewRecord.RadsecServers) { + if(Server.Certificate.empty() || !Utils::ValidX509Certificate(Server.Certificate)) { + return BadRequest(RESTAPI::Errors::InvalidRadsecMainCertificate); + } + if(Server.CaCerts.empty() || !Utils::ValidX509Certificate(Server.CaCerts)) { + return BadRequest(RESTAPI::Errors::InvalidRadsecCaCertificate); + } + if(Server.PrivateKey.empty() || !Utils::VerifyPrivateKey(Server.PrivateKey)) { + return BadRequest(RESTAPI::Errors::InvalidRadsecPrivteKey); + } + if(!Utils::ValidIP(Server.IP)) { + return BadRequest(RESTAPI::Errors::InvalidRadsecIPAddress); + } + if(!(Server.Port>0 && Server.Port<65535)) { + return BadRequest(RESTAPI::Errors::InvalidRadsecPort); + } + if(Server.Secret.empty()) { + return BadRequest(RESTAPI::Errors::InvalidRadsecSecret); + } + } + + } break; + default: { + + } + } + } + ProvObjects::CreateObjectInfo(RawObject,UserInfo_.userinfo,NewRecord.info); if(DB_.CreateRecord(NewRecord)) { RecordType AddedRecord; diff --git a/src/framework/ow_constants.h b/src/framework/ow_constants.h index 870dfc5..33f8819 100644 --- a/src/framework/ow_constants.h +++ b/src/framework/ow_constants.h @@ -420,6 +420,16 @@ namespace OpenWifi::RESTAPI::Errors { static const struct msg InvalidRadiusEndpointPoolStrategy { 1179, "Invalid RADIUS Server Endpoint Pool strategy." }; static const struct msg EndpointMustHaveOneTypeOfServers { 1180, "All servers must be either RADIUS or RADSEC." }; static const struct msg RadiusEndpointIndexInvalid { 1181, "Index must be an address between 0.0.1.1 and 0.0.2.254" }; + static const struct msg RadiusEndpointIndexMustBeUnique { 1182, "Index must be unique." }; + static const struct msg OrionAccountMustExist { 1183, "Orion account must exist." }; + static const struct msg GlobalReachCertMustExist { 1184, "Global Reach certificate must exist." }; + static const struct msg InvalidRadsecMainCertificate { 1185, "Invalid Radsec main certificate." }; + static const struct msg InvalidRadsecCaCertificate { 1186, "Invalid Radsec CA certificates." }; + static const struct msg InvalidRadsecPrivteKey { 1187, "Invalid Radsec Private key." }; + static const struct msg InvalidRadsecIPAddress { 1188, "Invalid Radsec IP Address." }; + static const struct msg InvalidRadsecPort { 1189, "Invalid Radsec Port." }; + static const struct msg InvalidRadsecSecret { 1190, "Invalid Radsec Secret." }; + static const struct msg InvalidRadiusServer { 1191, "Invalid Radius Server." }; static const struct msg SimulationDoesNotExist { 7000, "Simulation Instance ID does not exist." diff --git a/src/framework/utils.cpp b/src/framework/utils.cpp index 6c34cdb..3ec4a3d 100644 --- a/src/framework/utils.cpp +++ b/src/framework/utils.cpp @@ -783,6 +783,10 @@ namespace OpenWifi::Utils { return false; } + bool VerifyPrivateKey(const std::string &key) { + return VerifyECKey(key) || VerifyRSAKey(key); + } + bool ValidX509Certificate([[ maybe_unused]] const std::string &Cert) { try { diff --git a/src/framework/utils.h b/src/framework/utils.h index cf708bd..669e7b4 100644 --- a/src/framework/utils.h +++ b/src/framework/utils.h @@ -247,6 +247,24 @@ namespace OpenWifi::Utils { return count; } + inline std::uint32_t IPtoInt(const std::string &A) { + Poco::Net::IPAddress IP; + std::uint32_t Result=0; + + if(Poco::Net::IPAddress::tryParse(A,IP)) { + for(const auto i:IP.toBytes()) { + Result <<= 8; + Result += i; + } + } + return Result; + } + + inline bool ValidIP(const std::string &IPstr) { + Poco::Net::IPAddress IP; + return Poco::Net::IPAddress::tryParse(IPstr,IP); + } + struct CSRCreationParameters { std::string Country, Province, City, Organization, CommonName; @@ -261,6 +279,7 @@ namespace OpenWifi::Utils { std::string generateStrongPassword(int minLength, int maxLength, int numDigits, int minLowercase, int minSpecial, int minUppercase); bool VerifyECKey(const std::string &key); bool VerifyRSAKey(const std::string &key); + bool VerifyPrivateKey(const std::string &key); bool ValidX509Certificate(const std::string &Cert); bool ValidX509Certificate(const std::vector &Certs); diff --git a/src/storage/storage_radius_endpoints.h b/src/storage/storage_radius_endpoints.h index 61b1e35..db24478 100644 --- a/src/storage/storage_radius_endpoints.h +++ b/src/storage/storage_radius_endpoints.h @@ -30,6 +30,58 @@ namespace OpenWifi { RadiusEndpointDB(OpenWifi::DBType T, Poco::Data::SessionPool &P, Poco::Logger &L); virtual ~RadiusEndpointDB(){}; bool Upgrade(uint32_t from, uint32_t &to) override; + + enum class PoolStrategy { + none, random, weighted, unknown + }; + + enum class EndpointType { + radius, radsec, globalreach, orion, unknown + }; + + static inline EndpointType EndpointType(const std::string &T) { + if(T=="radius") return EndpointType::radius; + if(T=="radsec") return EndpointType::radsec; + if(T=="globalreach") return EndpointType::globalreach; + if(T=="orion") return EndpointType::orion; + return EndpointType::unknown; + } + + static inline PoolStrategy PoolStrategy(const std::string &T) { + if(T=="none") return PoolStrategy::none; + if(T=="random") return PoolStrategy::random; + if(T=="weighted") return PoolStrategy::weighted; + return PoolStrategy::unknown; + } + + static inline std::string to_string(enum EndpointType T) { + switch(T) { + case EndpointType::radius: return "radius"; + case EndpointType::radsec: return "radsec"; + case EndpointType::globalreach: return "globalreach"; + case EndpointType::orion: return "orion"; + default: + return "unknown"; + } + } + + static inline std::string to_string(enum PoolStrategy T) { + switch(T) { + case PoolStrategy::none: return "none"; + case PoolStrategy::random: return "random"; + case PoolStrategy::weighted: return "weighted"; + default: + return "unknown"; + } + } + + static inline bool ValidIndex(const std::string &I) { + static uint32_t Low = Utils::IPtoInt("0.0.1.1"); + static uint32_t High = Utils::IPtoInt("0.0.2.254"); + auto IP = Utils::IPtoInt(I); + return (IP>=Low) && (IP<=High); + } + private: };