[tmf] validate method as POST centrally in resource handlers (#12661)

This commit updates the central CoAP resource handlers in TMF agents
(`Agent::HandleResource`, `BackboneTmfAgent::HandleResource`, and
`Manager::CoapDtlsSession::HandleResource`) to verify that the
incoming request method is a POST request. If the URI is recognized
but the method is not POST, a `kCodeMethodNotAllowed` response is
now sent.

Since all TMF requests are now guaranteed to be POST requests before
reaching their specific handlers, the `IsPostRequest()` checks in
individual handlers are removed. Additionally, the
`IsConfirmablePostRequest()` and `IsNonConfirmablePostRequest()`
helper methods in `Coap::Message` are removed and their usages are
simplified to `IsConfirmable()` and `IsNonConfirmable()` in the
respective handlers.
This commit is contained in:
Abtin Keshavarzian
2026-03-10 22:07:43 -05:00
committed by GitHub
parent d9fce062c7
commit 3559cbd55a
21 changed files with 44 additions and 63 deletions
@@ -74,6 +74,12 @@ bool BackboneTmfAgent::HandleResource(const char *aUriPath, ot::Coap::Msg &aMsg)
bool didHandle = true;
Uri uri = UriFromPath(aUriPath);
if ((uri != kUriUnknown) && !aMsg.IsPostRequest())
{
IgnoreError(SendAckResponse(aMsg, ot::Coap::kCodeMethodNotAllowed));
ExitNow();
}
#define Case(kUri, Type) \
case kUri: \
Get<Type>().HandleTmf<kUri>(aMsg); \
@@ -93,6 +99,7 @@ bool BackboneTmfAgent::HandleResource(const char *aUriPath, ot::Coap::Msg &aMsg)
#undef Case
exit:
return didHandle;
}
+3 -4
View File
@@ -149,7 +149,7 @@ void Manager::HandleMulticastListenerRegistration(const Coap::Msg &aMsg)
bool hasCommissionerSessionIdTlv = false;
bool processTimeoutTlv = false;
VerifyOrExit(aMsg.IsConfirmablePostRequest(), error = kErrorParse);
VerifyOrExit(aMsg.IsConfirmable(), error = kErrorParse);
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
// Required by Test Specification 5.10.22 DUA-TC-26, only for certification purpose
@@ -366,7 +366,7 @@ void Manager::HandleDuaRegistration(const Coap::Msg &aMsg)
#endif
VerifyOrExit(aMsg.mMessageInfo.GetPeerAddr().GetIid().IsRoutingLocator(), error = kErrorDrop);
VerifyOrExit(aMsg.IsConfirmablePostRequest(), error = kErrorParse);
VerifyOrExit(aMsg.IsConfirmable(), error = kErrorParse);
SuccessOrExit(error = Tlv::Find<ThreadTargetTlv>(aMsg.mMessage, target));
SuccessOrExit(error = Tlv::Find<ThreadMeshLocalEidTlv>(aMsg.mMessage, meshLocalIid));
@@ -542,7 +542,7 @@ template <> void Manager::HandleTmf<kUriBackboneQuery>(Coap::Msg &aMsg)
VerifyOrExit(aMsg.mMessageInfo.IsHostInterface(), error = kErrorDrop);
VerifyOrExit(Get<Local>().IsPrimary(), error = kErrorInvalidState);
VerifyOrExit(aMsg.IsNonConfirmablePostRequest(), error = kErrorParse);
VerifyOrExit(aMsg.IsNonConfirmable(), error = kErrorParse);
SuccessOrExit(error = Tlv::Find<ThreadTargetTlv>(aMsg.mMessage, dua));
@@ -574,7 +574,6 @@ template <> void Manager::HandleTmf<kUriBackboneAnswer>(Coap::Msg &aMsg)
VerifyOrExit(aMsg.mMessageInfo.IsHostInterface(), error = kErrorDrop);
VerifyOrExit(Get<Local>().IsPrimary(), error = kErrorInvalidState);
VerifyOrExit(aMsg.IsPostRequest(), error = kErrorParse);
proactive = !aMsg.IsConfirmable();
-4
View File
@@ -91,10 +91,6 @@ exit:
bool HeaderInfo::IsRequest(void) const { return IsValueInRange<uint8_t>(mCode, kCodeGet, kCodeDelete); }
bool HeaderInfo::IsConfirmablePostRequest(void) const { return IsConfirmable() && IsPostRequest(); }
bool HeaderInfo::IsNonConfirmablePostRequest(void) const { return IsNonConfirmable() && IsPostRequest(); }
//---------------------------------------------------------------------------------------------------------------------
// `Message`
-16
View File
@@ -390,22 +390,6 @@ public:
*/
bool IsReset(void) const { return (mType == kTypeReset); }
/**
* Indicates whether or not the header is a confirmable Post request (`kTypeConfirmable` with`kCodePost`).
*
* @retval TRUE Message is a confirmable Post request.
* @retval FALSE Message is not a confirmable Post request.
*/
bool IsConfirmablePostRequest(void) const;
/**
* Indicates whether the message is a non-confirmable Post request (`kTypeNonConfirmable` with `kCodePost`).
*
* @retval TRUE Message is a non-confirmable Post request.
* @retval FALSE Message is not a non-confirmable Post request.
*/
bool IsNonConfirmablePostRequest(void) const;
/**
* Checks if the message requires a reset response if an error during low level CoAP processing occurred.
*
+9 -2
View File
@@ -375,7 +375,7 @@ template <> void Manager::HandleTmf<kUriRelayRx>(Coap::Msg &aMsg)
VerifyOrExit(mIsRunning);
VerifyOrExit(aMsg.IsNonConfirmablePostRequest());
VerifyOrExit(aMsg.IsNonConfirmable());
LogInfo("Received %s from %s", UriToString<kUriRelayRx>(), aMsg.mMessageInfo.GetPeerAddr().ToString().AsCString());
@@ -589,6 +589,12 @@ bool Manager::CoapDtlsSession::HandleResource(const char *aUriPath, Coap::Msg &a
bool didHandle = true;
Uri uri = UriFromPath(aUriPath);
if ((uri != kUriUnknown) && !aMsg.IsPostRequest())
{
IgnoreError(SendAckResponse(aMsg, ot::Coap::kCodeMethodNotAllowed));
ExitNow();
}
switch (uri)
{
case kUriCommissionerPetition:
@@ -623,6 +629,7 @@ bool Manager::CoapDtlsSession::HandleResource(const char *aUriPath, Coap::Msg &a
break;
}
exit:
return didHandle;
}
@@ -990,7 +997,7 @@ void Manager::CoapDtlsSession::HandleTmfRelayTx(Coap::Msg &aMsg)
OwnedPtr<Coap::Message> message;
OffsetRange offsetRange;
VerifyOrExit(aMsg.IsNonConfirmablePostRequest());
VerifyOrExit(aMsg.IsNonConfirmable());
#if OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
if (IsEnroller())
+2 -2
View File
@@ -220,7 +220,7 @@ void Admitter::ForwardJoinerRelayToEnrollers(const Coap::Msg &aMsg)
VerifyOrExit(mCommissionerPetitioner.IsActiveCommissioner());
VerifyOrExit(aMsg.IsNonConfirmablePostRequest());
VerifyOrExit(aMsg.IsNonConfirmable());
SuccessOrExit(Tlv::Find<JoinerIidTlv>(aMsg.mMessage, joinerIid));
LogInfo("Processing %s from joiner %s", UriToString<kUriRelayRx>(), joinerIid.ToString().AsCString());
@@ -1122,7 +1122,7 @@ void Manager::CoapDtlsSession::HandleEnrollerTmf(Uri aUri, const Coap::Msg &aMsg
Error error = kErrorNone;
StateTlv::State responseState;
VerifyOrExit(aMsg.IsConfirmablePostRequest());
VerifyOrExit(aMsg.IsConfirmable());
LogInfo("Receive %s", Admitter::EnrollerUriToString(aUri));
+4 -4
View File
@@ -813,7 +813,7 @@ template <> void Commissioner::HandleTmf<kUriRelayRx>(Coap::Msg &aMsg)
VerifyOrExit(mState == kStateActive, error = kErrorInvalidState);
VerifyOrExit(aMsg.IsNonConfirmablePostRequest());
VerifyOrExit(aMsg.IsNonConfirmable());
SuccessOrExit(error = Tlv::Find<JoinerUdpPortTlv>(aMsg.mMessage, joinerPort));
SuccessOrExit(error = Tlv::Find<JoinerIidTlv>(aMsg.mMessage, joinerIid));
@@ -882,7 +882,7 @@ void Commissioner::HandleJoinerSessionTimer(void)
template <> void Commissioner::HandleTmf<kUriDatasetChanged>(Coap::Msg &aMsg)
{
VerifyOrExit(mState == kStateActive);
VerifyOrExit(aMsg.IsConfirmablePostRequest());
VerifyOrExit(aMsg.IsConfirmable());
LogInfo("Received %s", UriToString<kUriDatasetChanged>());
@@ -1073,7 +1073,7 @@ template <> void Commissioner::HandleTmf<kUriEnergyReport>(Coap::Msg &aMsg)
uint32_t mask;
EnergyListTlv energyListTlv;
VerifyOrExit(aMsg.IsConfirmablePostRequest());
VerifyOrExit(aMsg.IsConfirmable());
LogInfo("Received %s", UriToString<kUriEnergyReport>());
@@ -1127,7 +1127,7 @@ template <> void Commissioner::HandleTmf<kUriPanIdConflict>(Coap::Msg &aMsg)
uint16_t panId;
uint32_t mask;
VerifyOrExit(aMsg.IsConfirmablePostRequest());
VerifyOrExit(aMsg.IsConfirmable());
LogInfo("Received %s", UriToString<kUriPanIdConflict>());
+1 -1
View File
@@ -421,7 +421,7 @@ template <> void Joiner::HandleTmf<kUriJoinerEntrust>(Coap::Msg &aMsg)
Error error;
Dataset::Info datasetInfo;
VerifyOrExit(mState == kStateEntrust && aMsg.IsConfirmablePostRequest(), error = kErrorDrop);
VerifyOrExit(mState == kStateEntrust && aMsg.IsConfirmable(), error = kErrorDrop);
LogInfo("Received %s", UriToString<kUriJoinerEntrust>());
LogCert("[THCI] direction=recv | type=JOIN_ENT.ntf");
+1 -1
View File
@@ -159,7 +159,7 @@ template <> void JoinerRouter::HandleTmf<kUriRelayTx>(Coap::Msg &aMsg)
Message::Settings settings(kNoLinkSecurity, Message::kPriorityNet);
Ip6::MessageInfo messageInfo;
VerifyOrExit(aMsg.IsNonConfirmablePostRequest(), error = kErrorDrop);
VerifyOrExit(aMsg.IsNonConfirmable(), error = kErrorDrop);
LogInfo("Received %s", UriToString<kUriRelayTx>());
+1 -1
View File
@@ -1103,7 +1103,7 @@ template <> void TcatAgent::HandleTmf<kUriTcatEnable>(Coap::Msg &aMsg)
uint16_t durationSec = 0;
uint32_t durationMs;
VerifyOrExit(aMsg.IsConfirmablePostRequest());
VerifyOrExit(aMsg.IsConfirmable());
LogInfo("Received %s from %s", UriToString<kUriTcatEnable>(),
aMsg.mMessageInfo.GetPeerAddr().ToString().AsCString());
message = Get<Tmf::Agent>().AllocateAndInitResponseFor(aMsg.mMessage);
+2 -4
View File
@@ -652,7 +652,7 @@ template <> void AddressResolver::HandleTmf<kUriAddressNotify>(Coap::Msg &aMsg)
CacheEntry *entry;
CacheEntry *prev;
VerifyOrExit(aMsg.IsConfirmablePostRequest());
VerifyOrExit(aMsg.IsConfirmable());
SuccessOrExit(Tlv::Find<ThreadTargetTlv>(aMsg.mMessage, target));
SuccessOrExit(Tlv::Find<ThreadMeshLocalEidTlv>(aMsg.mMessage, meshLocalIid));
@@ -747,8 +747,6 @@ template <> void AddressResolver::HandleTmf<kUriAddressError>(Coap::Msg &aMsg)
Ip6::Address destination;
#endif
VerifyOrExit(aMsg.IsPostRequest(), error = kErrorDrop);
LogInfo("Received %s", UriToString<kUriAddressError>());
if (aMsg.IsConfirmable() && !aMsg.mMessageInfo.GetSockAddr().IsMulticast())
@@ -819,7 +817,7 @@ template <> void AddressResolver::HandleTmf<kUriAddressQuery>(Coap::Msg &aMsg)
Ip6::Address target;
uint32_t lastTransactionTime;
VerifyOrExit(aMsg.IsNonConfirmablePostRequest());
VerifyOrExit(aMsg.IsNonConfirmable());
SuccessOrExit(Tlv::Find<ThreadTargetTlv>(aMsg.mMessage, target));
@@ -58,7 +58,6 @@ template <> void AnnounceBeginServer::HandleTmf<kUriAnnounceBegin>(Coap::Msg &aM
uint8_t count;
uint16_t period;
VerifyOrExit(aMsg.IsPostRequest());
SuccessOrExit(MeshCoP::ChannelMaskTlv::FindIn(aMsg.mMessage, mask));
SuccessOrExit(Tlv::Find<MeshCoP::CountTlv>(aMsg.mMessage, count));
+1 -1
View File
@@ -99,7 +99,7 @@ template <> void AnycastLocator::HandleTmf<kUriAnycastLocate>(Coap::Msg &aMsg)
{
Coap::Message *message = nullptr;
VerifyOrExit(aMsg.IsConfirmablePostRequest());
VerifyOrExit(aMsg.IsConfirmable());
message = Get<Tmf::Agent>().AllocateAndInitResponseFor(aMsg.mMessage);
VerifyOrExit(message != nullptr);
-3
View File
@@ -572,8 +572,6 @@ template <> void DuaManager::HandleTmf<kUriDuaRegistrationNotify>(Coap::Msg &aMs
{
Error error;
VerifyOrExit(aMsg.IsPostRequest(), error = kErrorParse);
if (aMsg.IsConfirmable() && Get<Tmf::Agent>().SendAckResponse(aMsg) == kErrorNone)
{
LogInfo("Sent %s ack", UriToString<kUriDuaRegistrationNotify>());
@@ -581,7 +579,6 @@ template <> void DuaManager::HandleTmf<kUriDuaRegistrationNotify>(Coap::Msg &aMs
error = ProcessDuaResponse(aMsg.mMessage);
exit:
OT_UNUSED_VARIABLE(error);
LogInfo("Received %s: %s", UriToString<kUriDuaRegistrationNotify>(), ErrorToString(error));
}
-2
View File
@@ -58,8 +58,6 @@ template <> void EnergyScanServer::HandleTmf<kUriEnergyScan>(Coap::Msg &aMsg)
uint32_t mask;
MeshCoP::Tlv tlv;
VerifyOrExit(aMsg.IsPostRequest());
SuccessOrExit(Tlv::Find<MeshCoP::CountTlv>(aMsg.mMessage, count));
count = Clamp(count, kMinCount, kMaxCount);
+2 -2
View File
@@ -3462,7 +3462,7 @@ Error Mle::AddrSolicitInfo::ParseFrom(const Coap::Msg &aMsg)
Error error;
VerifyOrExit(aMsg.IsConfirmablePostRequest(), error = kErrorParse);
VerifyOrExit(aMsg.IsConfirmable(), error = kErrorParse);
SuccessOrExit(error = Tlv::Find<ThreadExtMacAddressTlv>(aMsg.mMessage, mExtAddress));
SuccessOrExit(error = Tlv::Find<ThreadStatusTlv>(aMsg.mMessage, mReason));
@@ -3634,7 +3634,7 @@ template <> void Mle::HandleTmf<kUriAddressRelease>(Coap::Msg &aMsg)
VerifyOrExit(mRole == kRoleLeader);
VerifyOrExit(aMsg.IsConfirmablePostRequest());
VerifyOrExit(aMsg.IsConfirmable());
Log(kMessageReceive, kTypeAddressRelease, aMsg.mMessageInfo.GetPeerAddr());
+3 -8
View File
@@ -555,8 +555,6 @@ exit:
template <> void Server::HandleTmf<kUriDiagnosticGetQuery>(Coap::Msg &aMsg)
{
VerifyOrExit(aMsg.IsPostRequest());
LogInfo("Received %s from %s", UriToString<kUriDiagnosticGetQuery>(),
aMsg.mMessageInfo.GetPeerAddr().ToString().AsCString());
@@ -571,9 +569,6 @@ template <> void Server::HandleTmf<kUriDiagnosticGetQuery>(Coap::Msg &aMsg)
#elif OPENTHREAD_FTD
PrepareAndSendAnswers(aMsg.mMessageInfo.GetPeerAddr(), aMsg.mMessage);
#endif
exit:
return;
}
#if OPENTHREAD_MTD
@@ -911,7 +906,7 @@ template <> void Server::HandleTmf<kUriDiagnosticGetRequest>(Coap::Msg &aMsg)
Error error = kErrorNone;
Coap::Message *response = nullptr;
VerifyOrExit(aMsg.IsConfirmablePostRequest(), error = kErrorDrop);
VerifyOrExit(aMsg.IsConfirmable(), error = kErrorDrop);
LogInfo("Received %s from %s", UriToString<kUriDiagnosticGetRequest>(),
aMsg.mMessageInfo.GetPeerAddr().ToString().AsCString());
@@ -933,7 +928,7 @@ template <> void Server::HandleTmf<kUriDiagnosticReset>(Coap::Msg &aMsg)
uint8_t type;
Tlv tlv;
VerifyOrExit(aMsg.IsConfirmablePostRequest());
VerifyOrExit(aMsg.IsConfirmable());
LogInfo("Received %s from %s", UriToString<kUriDiagnosticReset>(),
aMsg.mMessageInfo.GetPeerAddr().ToString().AsCString());
@@ -1079,7 +1074,7 @@ exit:
template <> void Client::HandleTmf<kUriDiagnosticGetAnswer>(Coap::Msg &aMsg)
{
VerifyOrExit(aMsg.IsConfirmablePostRequest());
VerifyOrExit(aMsg.IsConfirmable());
LogInfo("Received %s from %s", ot::UriToString<kUriDiagnosticGetAnswer>(),
aMsg.mMessageInfo.GetPeerAddr().ToString().AsCString());
-1
View File
@@ -52,7 +52,6 @@ template <> void PanIdQueryServer::HandleTmf<kUriPanIdQuery>(Coap::Msg &aMsg)
uint16_t panId;
uint32_t mask;
VerifyOrExit(aMsg.IsPostRequest());
SuccessOrExit(MeshCoP::ChannelMaskTlv::FindIn(aMsg.mMessage, mask));
SuccessOrExit(Tlv::Find<MeshCoP::PanIdTlv>(aMsg.mMessage, panId));
+7
View File
@@ -72,6 +72,12 @@ bool Agent::HandleResource(const char *aUriPath, Msg &aMsg)
bool didHandle = true;
Uri uri = UriFromPath(aUriPath);
if ((uri != kUriUnknown) && !aMsg.IsPostRequest())
{
IgnoreError(SendAckResponse(aMsg, ot::Coap::kCodeMethodNotAllowed));
ExitNow();
}
#define Case(kUri, Type) \
case kUri: \
Get<Type>().HandleTmf<kUri>(aMsg); \
@@ -159,6 +165,7 @@ bool Agent::HandleResource(const char *aUriPath, Msg &aMsg)
#undef Case
exit:
return didHandle;
}
+1 -1
View File
@@ -110,7 +110,7 @@ exit:
template <> void Client::HandleTmf<kUriHistoryAnswer>(Coap::Msg &aMsg)
{
VerifyOrExit(aMsg.IsConfirmablePostRequest());
VerifyOrExit(aMsg.IsConfirmable());
IgnoreError(Get<Tmf::Agent>().SendAckResponse(aMsg));
LogInfo("Received %s from %s", ot::UriToString<kUriHistoryAnswer>(),
@@ -49,8 +49,6 @@ Server::Server(Instance &aInstance)
template <> void Server::HandleTmf<kUriHistoryQuery>(Coap::Msg &aMsg)
{
VerifyOrExit(aMsg.IsPostRequest());
LogInfo("Received %s from %s", UriToString<kUriHistoryQuery>(),
aMsg.mMessageInfo.GetPeerAddr().ToString().AsCString());
@@ -60,9 +58,6 @@ template <> void Server::HandleTmf<kUriHistoryQuery>(Coap::Msg &aMsg)
}
PrepareAndSendAnswers(aMsg.mMessageInfo.GetPeerAddr(), aMsg.mMessage);
exit:
return;
}
Error Server::AllocateAnswer(Coap::Message *&aAnswer, AnswerInfo &aInfo)