diff --git a/configs/fne-config.example.yml b/configs/fne-config.example.yml index f4c0f9b4..fecd8228 100644 --- a/configs/fne-config.example.yml +++ b/configs/fne-config.example.yml @@ -179,6 +179,9 @@ master: kmfServicesEnabled: false # Port number to listen on for P25 OTAR KMF services. kmfOtarPort: 64414 + # Flag indicating whether or not P25 OTAR KMF services will allow RID 0 (broadcast) key requests. + # NOTE: This is used for peer key requests (NOT OTAR REQUESTS). + kmfAllowRID0: false # Flag indicating whether or not verbose debug logging for P25 OTAR KMF services is enabled. kmfDebug: false diff --git a/src/common/network/BaseNetwork.cpp b/src/common/network/BaseNetwork.cpp index ed0a92f7..6c413c15 100644 --- a/src/common/network/BaseNetwork.cpp +++ b/src/common/network/BaseNetwork.cpp @@ -124,7 +124,7 @@ bool BaseNetwork::writeGrantReq(const uint8_t mode, const uint32_t srcId, const /* Writes enc. key request to the network. */ -bool BaseNetwork::writeKeyReq(const uint16_t kId, const uint8_t algId) +bool BaseNetwork::writeKeyReq(const uint16_t kId, const uint8_t algId, const uint32_t srcId) { using namespace p25::defines; using namespace p25::kmm; @@ -136,6 +136,7 @@ bool BaseNetwork::writeKeyReq(const uint16_t kId, const uint8_t algId) ::memset(buffer, 0x00U, DATA_PACKET_LENGTH); KMMModifyKey modifyKeyCmd = KMMModifyKey(); + modifyKeyCmd.setSrcLLId(srcId); modifyKeyCmd.setDecryptInfoFmt(KMM_DECRYPT_INSTRUCT_NONE); modifyKeyCmd.setAlgId(algId); modifyKeyCmd.setKId(kId); diff --git a/src/common/network/BaseNetwork.h b/src/common/network/BaseNetwork.h index 1e2f038d..b8013519 100644 --- a/src/common/network/BaseNetwork.h +++ b/src/common/network/BaseNetwork.h @@ -461,9 +461,10 @@ namespace network * @brief Writes a enc. key request to the network. * @param kId Key ID. * @param algId Algorithm ID. + * @param srcId Source Radio ID. * @returns bool True, if request was sent, otherwise false. */ - bool writeKeyReq(const uint16_t kId, const uint8_t algId); + bool writeKeyReq(const uint16_t kId, const uint8_t algId, const uint32_t srcId = 0U); /** * @brief Writes the local activity log to the network. diff --git a/src/fne/network/TrafficNetwork.cpp b/src/fne/network/TrafficNetwork.cpp index b6be0e07..95600a92 100644 --- a/src/fne/network/TrafficNetwork.cpp +++ b/src/fne/network/TrafficNetwork.cpp @@ -35,9 +35,9 @@ using namespace compress; #include #include #include +#include // --------------------------------------------------------------------------- -#include // Constants // --------------------------------------------------------------------------- @@ -89,6 +89,7 @@ TrafficNetwork::TrafficNetwork(HostFNE* host, const std::string& address, uint16 m_parrotOnlyOriginating(false), m_parrotOverrideSrcId(0U), m_kmfServicesEnabled(false), + m_kmfAllowRID0(false), m_ridLookup(nullptr), m_tidLookup(nullptr), m_peerListLookup(nullptr), @@ -287,6 +288,7 @@ void TrafficNetwork::setOptions(yaml::Node& conf, bool printOptions) m_kmfServicesEnabled = false; LogWarning(LOG_MASTER, "FNE is compiled without OpenSSL support, KMF services are unavailable."); #endif // ENABLE_SSL + m_kmfAllowRID0 = conf["kmfAllowRID0"].as(false); m_callCollisionTimeout = conf["callCollisionTimeout"].as(5U); @@ -401,6 +403,7 @@ void TrafficNetwork::setOptions(yaml::Node& conf, bool printOptions) LogInfo(" P25 OTAR KMF Services Enabled: %s", m_kmfServicesEnabled ? "yes" : "no"); LogInfo(" P25 OTAR KMF Listening Address: %s", m_address.c_str()); LogInfo(" P25 OTAR KMF Listening Port: %u", kmfOtarPort); + LogInfo(" P25 KMF Allow RID 0 Requests: %s", m_kmfAllowRID0 ? "yes" : "no"); LogInfo(" High Availability Enabled: %s", m_haEnabled ? "yes" : "no"); if (m_haEnabled) { LogInfo(" Advertised HA WAN IP: %s", m_advertisedHAAddress.c_str()); @@ -1809,32 +1812,42 @@ void TrafficNetwork::taskNetworkRx(NetPacketRequest* req) KMMModifyKey* modifyKey = static_cast(frame.get()); if (modifyKey->getAlgId() > 0U && modifyKey->getKId() > 0U) { uint32_t requestingRid = modifyKey->getSrcLLId(); - lookups::RadioId ridEntry = network->m_ridLookup->find(requestingRid); - if (ridEntry.radioDefault()) { - LogError(LOG_MASTER, "PEER %u (%s) requested enc. key but RID %u has no key policy entry, no response", - peerId, connection->identWithQualifier().c_str(), requestingRid); - break; - } - if (!ridEntry.radioEnabled()) { - LogError(LOG_MASTER, "PEER %u (%s) requested enc. key but RID %u is disabled, no response", - peerId, connection->identWithQualifier().c_str(), requestingRid); - break; - } + if (requestingRid > 0U) { + lookups::RadioId ridEntry = network->m_ridLookup->find(requestingRid); + if (ridEntry.radioDefault()) { + LogError(LOG_MASTER, "PEER %u (%s) requested enc. key but RID %u has no key policy entry, no response", + peerId, connection->identWithQualifier().c_str(), requestingRid); + break; + } - if (!ridEntry.canRequestKeys()) { - LogError(LOG_MASTER, "PEER %u (%s) requested enc. key but RID %u cannot request keys, no response", - peerId, connection->identWithQualifier().c_str(), requestingRid); - break; - } + if (!ridEntry.radioEnabled()) { + LogError(LOG_MASTER, "PEER %u (%s) requested enc. key but RID %u is disabled, no response", + peerId, connection->identWithQualifier().c_str(), requestingRid); + break; + } - std::vector allowedKIds = ridEntry.allowedKIds(); + if (!ridEntry.canRequestKeys()) { + LogError(LOG_MASTER, "PEER %u (%s) requested enc. key but RID %u cannot request keys, no response", + peerId, connection->identWithQualifier().c_str(), requestingRid); + break; + } - // check if this RID is allowed to request the KID in question - if (!allowedKIds.empty() && std::find(allowedKIds.begin(), allowedKIds.end(), modifyKey->getKId()) == allowedKIds.end()) { - LogError(LOG_MASTER, "PEER %u (%s) requested enc. key kID = $%04X but RID %u is not permitted for that key, no response", - peerId, connection->identWithQualifier().c_str(), modifyKey->getKId(), requestingRid); - break; + std::vector allowedKIds = ridEntry.allowedKIds(); + + // check if this RID is allowed to request the KID in question + if (!allowedKIds.empty() && std::find(allowedKIds.begin(), allowedKIds.end(), modifyKey->getKId()) == allowedKIds.end()) { + LogError(LOG_MASTER, "PEER %u (%s) requested enc. key kID = $%04X but RID %u is not permitted for that key, no response", + peerId, connection->identWithQualifier().c_str(), modifyKey->getKId(), requestingRid); + break; + } + } + else { + if (!network->m_kmfAllowRID0) { + LogError(LOG_MASTER, "PEER %u (%s) requested enc. key with RID 0 but such requests are not allowed, no response", + peerId, connection->identWithQualifier().c_str()); + break; + } } LogInfoEx(LOG_MASTER, "PEER %u (%s) requested enc. key, algId = $%02X, kID = $%04X", peerId, connection->identWithQualifier().c_str(), diff --git a/src/fne/network/TrafficNetwork.h b/src/fne/network/TrafficNetwork.h index b7687b95..d6e29eb0 100644 --- a/src/fne/network/TrafficNetwork.h +++ b/src/fne/network/TrafficNetwork.h @@ -327,6 +327,7 @@ namespace network uint32_t m_parrotOverrideSrcId; bool m_kmfServicesEnabled; + bool m_kmfAllowRID0; lookups::RadioIdLookup* m_ridLookup; lookups::TalkgroupRulesLookup* m_tidLookup;