From a39f2c86d34ae7e2ce5f4b5de0580ac1fac84d9c Mon Sep 17 00:00:00 2001 From: Jonathan Hui Date: Mon, 18 Mar 2019 12:25:28 -0700 Subject: [PATCH] [dtls] do not allow Open() or Bind() when DTLS session is started (#3694) --- src/core/meshcop/dtls.cpp | 39 ++++++++++++++++++++++++++------------- src/core/meshcop/dtls.hpp | 36 +++++++++++++++++++++++------------- 2 files changed, 49 insertions(+), 26 deletions(-) diff --git a/src/core/meshcop/dtls.cpp b/src/core/meshcop/dtls.cpp index ddd978c5e..0f7c0c716 100644 --- a/src/core/meshcop/dtls.cpp +++ b/src/core/meshcop/dtls.cpp @@ -59,7 +59,7 @@ namespace MeshCoP { Dtls::Dtls(Instance &aInstance, bool aLayerTwoSecurity) : InstanceLocator(aInstance) - , mState(kStateStopped) + , mState(kStateClosed) , mPskLength(0) , mVerifyPeerCertificate(true) , mTimer(aInstance, &Dtls::HandleTimer, this) @@ -166,6 +166,7 @@ otError Dtls::Open(ReceiveHandler aReceiveHandler, ConnectedHandler aConnectedHa mReceiveHandler = aReceiveHandler; mConnectedHandler = aConnectedHandler; mContext = aContext; + mState = kStateOpen; exit: return error; @@ -173,6 +174,10 @@ exit: otError Dtls::Connect(const Ip6::SockAddr &aSockAddr) { + otError error; + + VerifyOrExit(mState == kStateOpen, error = OT_ERROR_INVALID_STATE); + memcpy(&mPeerAddress.mPeerAddr, &aSockAddr.mAddress, sizeof(mPeerAddress.mPeerAddr)); mPeerAddress.mPeerPort = aSockAddr.mPort; @@ -185,7 +190,10 @@ otError Dtls::Connect(const Ip6::SockAddr &aSockAddr) mPeerAddress.mInterfaceId = 0; } - return Setup(true); + error = Setup(true); + +exit: + return error; } void Dtls::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo) @@ -198,7 +206,12 @@ void Dtls::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageI { ThreadNetif &netif = GetNetif(); - if (mState == MeshCoP::Dtls::kStateStopped) + switch (mState) + { + case MeshCoP::Dtls::kStateClosed: + ExitNow(); + + case MeshCoP::Dtls::kStateOpen: { Ip6::SockAddr sockAddr; @@ -218,12 +231,14 @@ void Dtls::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageI mPeerAddress.SetSockPort(aMessageInfo.GetSockPort()); SuccessOrExit(Setup(false)); + break; } - else - { + + default: // Once DTLS session is started, communicate only with a peer. VerifyOrExit((mPeerAddress.GetPeerAddr() == aMessageInfo.GetPeerAddr()) && (mPeerAddress.GetPeerPort() == aMessageInfo.GetPeerPort())); + break; } #if OPENTHREAD_ENABLE_BORDER_AGENT || OPENTHREAD_ENABLE_COMMISSIONER @@ -244,13 +259,12 @@ otError Dtls::Bind(uint16_t aPort) otError error; Ip6::SockAddr sockaddr; + VerifyOrExit(mState == kStateOpen, error = OT_ERROR_INVALID_STATE); VerifyOrExit(mTransportCallback == NULL, error = OT_ERROR_ALREADY); sockaddr.mPort = aPort; SuccessOrExit(error = mSocket.Bind(sockaddr)); - mState = kStateStopped; - exit: return error; } @@ -259,11 +273,10 @@ otError Dtls::Bind(TransportCallback aCallback, void *aContext) { otError error = OT_ERROR_NONE; + VerifyOrExit(mState == kStateOpen, error = OT_ERROR_INVALID_STATE); VerifyOrExit(mSocket.GetSockName().mPort == 0, error = OT_ERROR_ALREADY); VerifyOrExit(mTransportCallback == NULL, error = OT_ERROR_ALREADY); - mState = kStateStopped; - mTransportCallback = aCallback; mTransportContext = aContext; @@ -276,7 +289,7 @@ otError Dtls::Setup(bool aClient) int rval; // do not handle new connection before guard time expired - VerifyOrExit(mState == kStateStopped, rval = MBEDTLS_ERR_SSL_TIMEOUT); + VerifyOrExit(mState == kStateOpen, rval = MBEDTLS_ERR_SSL_TIMEOUT); mState = kStateInitializing; @@ -380,7 +393,7 @@ otError Dtls::Setup(bool aClient) exit: if ((mState == kStateInitializing) && (rval != 0)) { - mState = kStateStopped; + mState = kStateOpen; FreeMbedtls(); } @@ -448,7 +461,7 @@ void Dtls::Stop(void) { Close(); - mState = kStateStopped; + mState = kStateClosed; mTransportCallback = NULL; mTransportContext = NULL; mTimerSet = false; @@ -828,7 +841,7 @@ void Dtls::HandleTimer(void) break; case kStateCloseNotify: - mState = kStateStopped; + mState = kStateOpen; mTimer.Stop(); break; diff --git a/src/core/meshcop/dtls.hpp b/src/core/meshcop/dtls.hpp index abacb191f..56bf8346a 100644 --- a/src/core/meshcop/dtls.hpp +++ b/src/core/meshcop/dtls.hpp @@ -83,7 +83,8 @@ public: enum State { - kStateStopped = 0, + kStateClosed = 0, + kStateOpen, kStateInitializing, kStateConnecting, kStateConnected, @@ -161,7 +162,8 @@ public: * * @param[in] aSockAddr A reference to the remote sockaddr. * - * @retval OT_ERROR_NONE Successfully started the DTLS service. + * @retval OT_ERROR_NONE Successfully started the DTLS service. + * @retval OT_ERROR_INVALID_STATE The DTLS service is not in state kStateOpen. * */ otError Connect(const Ip6::SockAddr &aSockAddr); @@ -175,7 +177,8 @@ public: * * @param[in] aClient TRUE if setup for client, otherwise setup for server. * - * @retval OT_ERROR_NONE Successfully started the DTLS service. + * @retval OT_ERROR_NONE Successfully started the DTLS service. + * @retval OT_ERROR_INVALID_STATE The DTLS service is not in state kStateClosed. * */ otError Setup(bool aClient); @@ -185,8 +188,9 @@ public: * * @param[in] aPort The port to bind. * - * @retval OT_ERROR_NONE Successfully binded the DTLS service. - * @retval OT_ERROR_ALREADY Already bound. + * @retval OT_ERROR_NONE Successfully binded the DTLS service. + * @retval OT_ERROR_INVALID_STATE The DTLS service is not in state kStateOpen. + * @retval OT_ERROR_ALREADY Already bound. * */ otError Bind(uint16_t aPort); @@ -197,8 +201,9 @@ public: * @param[in] aCallback A pointer to a function for sending messages. * @param[in] aContext A pointer to arbitrary context information. * - * @retval OT_ERROR_NONE Successfully binded the DTLS service. - * @retval OT_ERROR_ALREADY Already bound. + * @retval OT_ERROR_NONE Successfully binded the DTLS service. + * @retval OT_ERROR_INVALID_STATE The DTLS service is not in state kStateOpen. + * @retval OT_ERROR_ALREADY Already bound. * */ otError Bind(TransportCallback aCallback, void *aContext); @@ -206,20 +211,24 @@ public: /** * This method indicates whether or not the DTLS session is active. * + * In other words, the state is kStateConnecting, kStateConnected, or kStateCloseNotify. + * * @retval TRUE If DTLS session is active. * @retval FALSE If DTLS session is not active. * */ - bool IsConnectionActive(void) { return mState != kStateStopped; } + bool IsConnectionActive(void) const { return mState >= kStateConnecting; } /** * This method indicates whether or not the DTLS session is connected. * + * In other words, the state is kStateConnected. + * * @retval TRUE The DTLS session is connected. * @retval FALSE The DTLS session is not connected. * */ - bool IsConnected(void) { return mState == kStateConnected; } + bool IsConnected(void) const { return mState == kStateConnected; } /** * This method close the current session. @@ -236,10 +245,11 @@ public: /** * This method returns the DTLS connection state. * - * @retval kStateStopped If the DTLS service has not been started. - * @retval kStateConnecting If the DTLS service is establishing a connection. - * @retval kStateConnected If the DTLS service has a connection established. - * @retval kStateCloseNotify If the DTLS service is closing a connection. + * @retval kStateClosed The UDP socket closed. + * @retval kStateOpen The UDP socket is open. + * @retval kStateConnecting The DTLS service is establishing a connection. + * @retval kStateConnected The DTLS service has a connection established. + * @retval kStateCloseNotify The DTLS service is closing a connection. * */ State GetState(void) const { return mState; }