Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
213 changes: 141 additions & 72 deletions src/wolfio.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ Possible IO enable options:
* HAVE_HTTP_CLIENT: Enables HTTP client API's default: off
(unless HAVE_OCSP or HAVE_CRL_IO defined)
* HAVE_IO_TIMEOUT: Enables support for connect timeout default: off
*
* DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER: This flag has effect only if
* ASN_NO_TIME is enabled. If enabled invalid peers messages are ignored
* indefinetely. If not enabled EmbedReceiveFrom will return timeout after
* DTLS_RECEIVEFROM_MAX_INVALID_PEER number of packets from invalid peers. When
* enabled, without a timer, EmbedReceivefrom can't check if the timeout is
* expired and it may never return under a continous flow of invalid packets.
* default: off
*/


Expand All @@ -59,6 +67,11 @@ Possible IO enable options:
but they'll still need SetCallback xxx() at end of file
*/

#if defined(NO_ASN_TIME) && !defined(DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER) \
&& !defined(DTLS_RECEIVEFROM_MAX_INVALID_PEER)
#define DTLS_RECEIVEFROM_MAX_INVALID_PEER 10
#endif

#if defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT)

/* Translates return codes returned from
Expand Down Expand Up @@ -333,7 +346,7 @@ static int sockAddrEqual(
if (a->ss_family != b->ss_family)
return 0;

if (a->ss_family == AF_INET) {
if (a->ss_family == WOLFSSL_IP4) {

if (aLen < (XSOCKLENT)sizeof(SOCKADDR_IN))
return 0;
Expand All @@ -349,7 +362,7 @@ static int sockAddrEqual(
}

#ifdef WOLFSSL_IPV6
if (a->ss_family == AF_INET6) {
if (a->ss_family == WOLFSSL_IP6) {
SOCKADDR_IN6 *a6, *b6;

if (aLen < (XSOCKLENT)sizeof(SOCKADDR_IN6))
Expand All @@ -367,11 +380,20 @@ static int sockAddrEqual(

return 1;
}
#endif /* WOLFSSL_HAVE_IPV6 */
#endif /* WOLFSSL_IPV6 */

return 0;
}

#ifndef WOLFSSL_IPV6
static int PeerIsIpv6(const SOCKADDR_S *peer, XSOCKLENT len)
{
if (len < sizeof(peer->ss_family))
return 0;
return peer->ss_family == WOLFSSL_IP6;
}
#endif /* !WOLFSSL_IPV6 */

static int isDGramSock(int sfd)
{
char type = 0;
Expand Down Expand Up @@ -400,13 +422,24 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
SOCKADDR_S lclPeer;
SOCKADDR_S* peer;
XSOCKLENT peerSz = 0;
#ifndef NO_ASN_TIME
word32 start = 0;
#elif !defined(DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER)
word32 invalidPeerPackets = 0;
#endif

WOLFSSL_ENTER("EmbedReceiveFrom");

if (dtlsCtx->connected) {
peer = NULL;
}
else if (dtlsCtx->userSet) {
#ifndef WOLFSSL_IPV6
if (PeerIsIpv6((SOCKADDR_S*)dtlsCtx->peer.sa, dtlsCtx->peer.sz)) {
WOLFSSL_MSG("ipv6 dtls peer set but no ipv6 support compiled");
return NOT_COMPILED_IN;
}
#endif
peer = &lclPeer;
XMEMSET(&lclPeer, 0, sizeof(lclPeer));
peerSz = sizeof(lclPeer);
Expand Down Expand Up @@ -438,10 +471,26 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
}
#endif /* WOLFSSL_DTLS13 */

if (!doDtlsTimeout)
dtls_timeout = 0;
do {

if (!wolfSSL_get_using_nonblock(ssl)) {
if (!doDtlsTimeout) {
dtls_timeout = 0;
}
else {
#ifndef NO_ASN_TIME
if (start == 0) {
start = LowResTimer();
}
else {
dtls_timeout -= LowResTimer() - start;
Comment thread
julek-wolfssl marked this conversation as resolved.
Outdated
start = LowResTimer();
if (dtls_timeout < 0 || dtls_timeout > DTLS_TIMEOUT_MAX)
return WOLFSSL_CBIO_ERR_TIMEOUT;
Comment thread
julek-wolfssl marked this conversation as resolved.
Outdated
}
#endif
}

if (!wolfSSL_get_using_nonblock(ssl)) {
#ifdef USE_WINDOWS_API
DWORD timeout = dtls_timeout * 1000;
#ifdef WOLFSSL_DTLS13
Expand All @@ -464,87 +513,101 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
#endif /* WOLFSSL_DTLS13 */
timeout.tv_sec = dtls_timeout;
#endif
if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
sizeof(timeout)) != 0) {
if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
sizeof(timeout)) != 0) {
WOLFSSL_MSG("setsockopt rcvtimeo failed");
}
}
}
#ifndef NO_ASN_TIME
else if(IsSCR(ssl)) {
if (ssl->dtls_start_timeout &&
LowResTimer() - ssl->dtls_start_timeout > (word32)dtls_timeout) {
ssl->dtls_start_timeout = 0;
return WOLFSSL_CBIO_ERR_TIMEOUT;
}
else if (!ssl->dtls_start_timeout) {
ssl->dtls_start_timeout = LowResTimer();
else if (IsSCR(ssl)) {
if (ssl->dtls_start_timeout &&
LowResTimer() - ssl->dtls_start_timeout >
(word32)dtls_timeout) {
ssl->dtls_start_timeout = 0;
return WOLFSSL_CBIO_ERR_TIMEOUT;
}
else if (!ssl->dtls_start_timeout) {
ssl->dtls_start_timeout = LowResTimer();
}
}
}
#endif /* !NO_ASN_TIME */

recvd = (int)DTLS_RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags,
(SOCKADDR*)peer, peer != NULL ? &peerSz : NULL);
recvd = (int)DTLS_RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags,
(SOCKADDR*)peer, peer != NULL ? &peerSz : NULL);

/* From the RECV(2) man page
* The returned address is truncated if the buffer provided is too small; in
* this case, addrlen will return a value greater than was supplied to the
* call.
*/
if (dtlsCtx->connected) {
/* No need to sanitize the value of peerSz */
}
else if (dtlsCtx->userSet) {
/* Truncate peer size */
if (peerSz > (XSOCKLENT)sizeof(lclPeer))
peerSz = (XSOCKLENT)sizeof(lclPeer);
}
else {
/* Truncate peer size */
if (peerSz > (XSOCKLENT)dtlsCtx->peer.bufSz)
peerSz = (XSOCKLENT)dtlsCtx->peer.bufSz;
}
/* From the RECV(2) man page
* The returned address is truncated if the buffer provided is too
* small; in this case, addrlen will return a value greater than was
* supplied to the call.
*/
if (dtlsCtx->connected) {
/* No need to sanitize the value of peerSz */
}
else if (dtlsCtx->userSet) {
/* Truncate peer size */
if (peerSz > (XSOCKLENT)sizeof(lclPeer))
peerSz = (XSOCKLENT)sizeof(lclPeer);
}
else {
/* Truncate peer size */
if (peerSz > (XSOCKLENT)dtlsCtx->peer.bufSz)
peerSz = (XSOCKLENT)dtlsCtx->peer.bufSz;
}

recvd = TranslateReturnCode(recvd, sd);
recvd = TranslateReturnCode(recvd, sd);

if (recvd < 0) {
WOLFSSL_MSG("Embed Receive From error");
recvd = TranslateIoError(recvd);
if (recvd == WOLFSSL_CBIO_ERR_WANT_READ &&
!wolfSSL_dtls_get_using_nonblock(ssl)) {
recvd = WOLFSSL_CBIO_ERR_TIMEOUT;
if (recvd < 0) {
WOLFSSL_MSG("Embed Receive From error");
recvd = TranslateIoError(recvd);
if (recvd == WOLFSSL_CBIO_ERR_WANT_READ &&
!wolfSSL_dtls_get_using_nonblock(ssl)) {
recvd = WOLFSSL_CBIO_ERR_TIMEOUT;
}
return recvd;
}
return recvd;
}
else if (recvd == 0) {
if (!isDGramSock(sd)) {
/* Closed TCP connection */
recvd = WOLFSSL_CBIO_ERR_CONN_CLOSE;
else if (recvd == 0) {
if (!isDGramSock(sd)) {
/* Closed TCP connection */
recvd = WOLFSSL_CBIO_ERR_CONN_CLOSE;
}
else {
WOLFSSL_MSG("Ignoring 0-length datagram");
continue;
}
return recvd;
}
else {
WOLFSSL_MSG("Ignoring 0-length datagram");
else if (dtlsCtx->connected) {
/* Nothing to do */
}
else if (dtlsCtx->userSet) {
/* Check we received the packet from the correct peer */
if (dtlsCtx->peer.sz > 0 &&
(peerSz != (XSOCKLENT)dtlsCtx->peer.sz ||
!sockAddrEqual(peer, peerSz, (SOCKADDR_S*)dtlsCtx->peer.sa,
dtlsCtx->peer.sz))) {
WOLFSSL_MSG(" Ignored packet from invalid peer");
#if defined(NO_ASN_TIME) && \
!defined(DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER)
if (doDtlsTimeout) {
invalidPeerPackets++;
if (invalidPeerPackets > DTLS_RECEIVEFROM_MAX_INVALID_PEER)
return wolfSSL_dtls_get_using_nonblock(ssl)
? WOLFSSL_CBIO_ERR_WANT_READ
: WOLFSSL_CBIO_ERR_TIMEOUT;
}
#endif /* NO_ASN_TIME && !DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER */
continue;
}
}
return recvd;
}
else if (dtlsCtx->connected) {
/* Nothing to do */
}
else if (dtlsCtx->userSet) {
/* Check we received the packet from the correct peer */
if (dtlsCtx->peer.sz > 0 &&
(peerSz != (XSOCKLENT)dtlsCtx->peer.sz ||
!sockAddrEqual(peer, peerSz, (SOCKADDR_S*)dtlsCtx->peer.sa,
dtlsCtx->peer.sz))) {
WOLFSSL_MSG(" Ignored packet from invalid peer");
return WOLFSSL_CBIO_ERR_WANT_READ;
else {
/* Store size of saved address */
dtlsCtx->peer.sz = peerSz;
}
}
else {
/* Store size of saved address */
dtlsCtx->peer.sz = peerSz;
}
#ifndef NO_ASN_TIME
ssl->dtls_start_timeout = 0;
ssl->dtls_start_timeout = 0;
#endif /* !NO_ASN_TIME */
break;
} while (1);

return recvd;
}
Expand All @@ -569,6 +632,12 @@ int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
else if (!dtlsCtx->connected) {
peer = (const SOCKADDR_S*)dtlsCtx->peer.sa;
peerSz = dtlsCtx->peer.sz;
#ifndef WOLFSSL_IPV6
if (PeerIsIpv6(peer, peerSz)) {
WOLFSSL_MSG("ipv6 dtls peer setted but no ipv6 support compiled");
return NOT_COMPILED_IN;
}
#endif
}

sent = (int)DTLS_SENDTO_FUNCTION(sd, buf, sz, ssl->wflags,
Expand Down
Loading