// // Created by stephane bourque on 2023-09-27. // #include "RESTAPI_radius_endpoint_handler.h" #include #include namespace OpenWifi { void RESTAPI_radius_endpoint_handler::DoGet() { auto id = GetBinding("id"); if(id.empty()) { return BadRequest(RESTAPI::Errors::MissingAuthenticationInformation); } RecordType Record; if(DB_.GetRecord("id",id,Record)) { return ReturnObject(Record); } return NotFound(); } void RESTAPI_radius_endpoint_handler::DoDelete() { auto id = GetBinding("id"); if(id.empty()) { return BadRequest(RESTAPI::Errors::MissingAuthenticationInformation); } RecordType Record; if(DB_.GetRecord("id",id,Record)) { DB_.DeleteRecord("id",id); ProvObjects::RADIUSEndpointUpdateStatus Status; Status.ChangeConfiguration(); return OK(); } 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; } static bool ValidRadiusServer(const std::vector &ServerList) { return std::all_of(ServerList.begin(),ServerList.end(),[](const ProvObjects::RADIUSServer &Server)->bool { return ValidRadiusServer(Server); }); } void RESTAPI_radius_endpoint_handler::DoPost() { auto id = GetBinding("id"); if(id.empty()) { return BadRequest(RESTAPI::Errors::MissingAuthenticationInformation); } const auto &RawObject = ParsedBody_; RecordType NewRecord; if(!NewRecord.from_json(RawObject)) { return BadRequest(RESTAPI::Errors::InvalidJSONDocument); } if(GWObjects::RadiusEndpointType(NewRecord.Type)==GWObjects::RadiusEndpointType::unknown) { return BadRequest(RESTAPI::Errors::InvalidRadiusTypeEndpoint); } if(GWObjects::RadiusPoolStrategy(NewRecord.PoolStrategy)==GWObjects::RadiusPoolStrategy::unknown) { return BadRequest(RESTAPI::Errors::InvalidRadiusEndpointPoolStrategy); } if(!NewRecord.RadiusServers.empty() && !NewRecord.RadsecServers.empty()) { return BadRequest(RESTAPI::Errors::EndpointMustHaveOneTypeOfServers); } auto EndPointType = GWObjects::RadiusEndpointType(NewRecord.Type); switch(EndPointType) { case GWObjects::RadiusEndpointType::radsec: case GWObjects::RadiusEndpointType::orion: case GWObjects::RadiusEndpointType::globalreach: { if(NewRecord.RadsecServers.empty()) { return BadRequest(RESTAPI::Errors::EndpointMustHaveOneTypeOfServers); } } break; case GWObjects::RadiusEndpointType::generic: { 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==GWObjects::RadiusEndpointType::generic) { 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 GWObjects::RadiusEndpointType::orion: { for(const auto &Server:NewRecord.RadsecServers) { if(!StorageService()->OrionAccountsDB().Exists("id",Server.UseOpenRoamingAccount)) { return BadRequest(RESTAPI::Errors::OrionAccountMustExist); } } } break; case GWObjects::RadiusEndpointType::globalreach: { for(const auto &Server:NewRecord.RadsecServers) { if(!StorageService()->GLBLRCertsDB().Exists("id",Server.UseOpenRoamingAccount)) { return BadRequest(RESTAPI::Errors::GlobalReachCertMustExist); } } } break; case GWObjects::RadiusEndpointType::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; DB_.GetRecord("id", NewRecord.info.id, AddedRecord); ProvObjects::RADIUSEndpointUpdateStatus Status; Status.ChangeConfiguration(); return ReturnObject(AddedRecord); } return BadRequest(RESTAPI::Errors::RecordNotCreated); } void RESTAPI_radius_endpoint_handler::DoPut() { auto id = GetBinding("id"); if(id.empty()) { return BadRequest(RESTAPI::Errors::MissingAuthenticationInformation); } const auto &RawObject = ParsedBody_; RecordType ModifiedRecord; if(!ModifiedRecord.from_json(RawObject)) { return BadRequest(RESTAPI::Errors::InvalidJSONDocument); } RecordType Existing; if(!DB_.GetRecord("id",id,Existing)) { return NotFound(); } AssignIfPresent(RawObject,"NasIdentifier", Existing.NasIdentifier); AssignIfPresent(RawObject,"AccountingInterval", Existing.AccountingInterval); ProvObjects::UpdateObjectInfo(RawObject, UserInfo_.userinfo, Existing.info); if(DB_.UpdateRecord("id", Existing.info.id, Existing)) { RecordType AddedRecord; DB_.GetRecord("id", Existing.info.id, AddedRecord); ProvObjects::RADIUSEndpointUpdateStatus Status; Status.ChangeConfiguration(); return ReturnObject(AddedRecord); } return BadRequest(RESTAPI::Errors::NotImplemented); } } // OpenWifi