Skip to content

Commit 1218cfb

Browse files
Merge pull request #6087 from rizlik/embed_recv_from_fix_peer
dtls: improve different peer recvfrom and better error reporting on ipv6
2 parents 188a99b + 5182fe3 commit 1218cfb

3 files changed

Lines changed: 336 additions & 77 deletions

File tree

src/wolfio.c

Lines changed: 141 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ Possible IO enable options:
5151
* HAVE_HTTP_CLIENT: Enables HTTP client API's default: off
5252
(unless HAVE_OCSP or HAVE_CRL_IO defined)
5353
* HAVE_IO_TIMEOUT: Enables support for connect timeout default: off
54+
*
55+
* DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER: This flag has effect only if
56+
* ASN_NO_TIME is enabled. If enabled invalid peers messages are ignored
57+
* indefinetely. If not enabled EmbedReceiveFrom will return timeout after
58+
* DTLS_RECEIVEFROM_MAX_INVALID_PEER number of packets from invalid peers. When
59+
* enabled, without a timer, EmbedReceivefrom can't check if the timeout is
60+
* expired and it may never return under a continous flow of invalid packets.
61+
* default: off
5462
*/
5563

5664

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

70+
#if defined(NO_ASN_TIME) && !defined(DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER) \
71+
&& !defined(DTLS_RECEIVEFROM_MAX_INVALID_PEER)
72+
#define DTLS_RECEIVEFROM_MAX_INVALID_PEER 10
73+
#endif
74+
6275
#if defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT)
6376

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

336-
if (a->ss_family == AF_INET) {
349+
if (a->ss_family == WOLFSSL_IP4) {
337350

338351
if (aLen < (XSOCKLENT)sizeof(SOCKADDR_IN))
339352
return 0;
@@ -349,7 +362,7 @@ static int sockAddrEqual(
349362
}
350363

351364
#ifdef WOLFSSL_IPV6
352-
if (a->ss_family == AF_INET6) {
365+
if (a->ss_family == WOLFSSL_IP6) {
353366
SOCKADDR_IN6 *a6, *b6;
354367

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

368381
return 1;
369382
}
370-
#endif /* WOLFSSL_HAVE_IPV6 */
383+
#endif /* WOLFSSL_IPV6 */
371384

372385
return 0;
373386
}
374387

388+
#ifndef WOLFSSL_IPV6
389+
static int PeerIsIpv6(const SOCKADDR_S *peer, XSOCKLENT len)
390+
{
391+
if (len < sizeof(peer->ss_family))
392+
return 0;
393+
return peer->ss_family == WOLFSSL_IP6;
394+
}
395+
#endif /* !WOLFSSL_IPV6 */
396+
375397
static int isDGramSock(int sfd)
376398
{
377399
char type = 0;
@@ -400,13 +422,24 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
400422
SOCKADDR_S lclPeer;
401423
SOCKADDR_S* peer;
402424
XSOCKLENT peerSz = 0;
425+
#ifndef NO_ASN_TIME
426+
word32 start = 0;
427+
#elif !defined(DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER)
428+
word32 invalidPeerPackets = 0;
429+
#endif
403430

404431
WOLFSSL_ENTER("EmbedReceiveFrom");
405432

406433
if (dtlsCtx->connected) {
407434
peer = NULL;
408435
}
409436
else if (dtlsCtx->userSet) {
437+
#ifndef WOLFSSL_IPV6
438+
if (PeerIsIpv6((SOCKADDR_S*)dtlsCtx->peer.sa, dtlsCtx->peer.sz)) {
439+
WOLFSSL_MSG("ipv6 dtls peer set but no ipv6 support compiled");
440+
return NOT_COMPILED_IN;
441+
}
442+
#endif
410443
peer = &lclPeer;
411444
XMEMSET(&lclPeer, 0, sizeof(lclPeer));
412445
peerSz = sizeof(lclPeer);
@@ -438,10 +471,26 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
438471
}
439472
#endif /* WOLFSSL_DTLS13 */
440473

441-
if (!doDtlsTimeout)
442-
dtls_timeout = 0;
474+
do {
443475

444-
if (!wolfSSL_get_using_nonblock(ssl)) {
476+
if (!doDtlsTimeout) {
477+
dtls_timeout = 0;
478+
}
479+
else {
480+
#ifndef NO_ASN_TIME
481+
if (start == 0) {
482+
start = LowResTimer();
483+
}
484+
else {
485+
dtls_timeout -= LowResTimer() - start;
486+
start = LowResTimer();
487+
if (dtls_timeout < 0 || dtls_timeout > DTLS_TIMEOUT_MAX)
488+
return WOLFSSL_CBIO_ERR_TIMEOUT;
489+
}
490+
#endif
491+
}
492+
493+
if (!wolfSSL_get_using_nonblock(ssl)) {
445494
#ifdef USE_WINDOWS_API
446495
DWORD timeout = dtls_timeout * 1000;
447496
#ifdef WOLFSSL_DTLS13
@@ -464,87 +513,101 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
464513
#endif /* WOLFSSL_DTLS13 */
465514
timeout.tv_sec = dtls_timeout;
466515
#endif
467-
if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
468-
sizeof(timeout)) != 0) {
516+
if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
517+
sizeof(timeout)) != 0) {
469518
WOLFSSL_MSG("setsockopt rcvtimeo failed");
519+
}
470520
}
471-
}
472521
#ifndef NO_ASN_TIME
473-
else if(IsSCR(ssl)) {
474-
if (ssl->dtls_start_timeout &&
475-
LowResTimer() - ssl->dtls_start_timeout > (word32)dtls_timeout) {
476-
ssl->dtls_start_timeout = 0;
477-
return WOLFSSL_CBIO_ERR_TIMEOUT;
478-
}
479-
else if (!ssl->dtls_start_timeout) {
480-
ssl->dtls_start_timeout = LowResTimer();
522+
else if (IsSCR(ssl)) {
523+
if (ssl->dtls_start_timeout &&
524+
LowResTimer() - ssl->dtls_start_timeout >
525+
(word32)dtls_timeout) {
526+
ssl->dtls_start_timeout = 0;
527+
return WOLFSSL_CBIO_ERR_TIMEOUT;
528+
}
529+
else if (!ssl->dtls_start_timeout) {
530+
ssl->dtls_start_timeout = LowResTimer();
531+
}
481532
}
482-
}
483533
#endif /* !NO_ASN_TIME */
484534

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

488-
/* From the RECV(2) man page
489-
* The returned address is truncated if the buffer provided is too small; in
490-
* this case, addrlen will return a value greater than was supplied to the
491-
* call.
492-
*/
493-
if (dtlsCtx->connected) {
494-
/* No need to sanitize the value of peerSz */
495-
}
496-
else if (dtlsCtx->userSet) {
497-
/* Truncate peer size */
498-
if (peerSz > (XSOCKLENT)sizeof(lclPeer))
499-
peerSz = (XSOCKLENT)sizeof(lclPeer);
500-
}
501-
else {
502-
/* Truncate peer size */
503-
if (peerSz > (XSOCKLENT)dtlsCtx->peer.bufSz)
504-
peerSz = (XSOCKLENT)dtlsCtx->peer.bufSz;
505-
}
538+
/* From the RECV(2) man page
539+
* The returned address is truncated if the buffer provided is too
540+
* small; in this case, addrlen will return a value greater than was
541+
* supplied to the call.
542+
*/
543+
if (dtlsCtx->connected) {
544+
/* No need to sanitize the value of peerSz */
545+
}
546+
else if (dtlsCtx->userSet) {
547+
/* Truncate peer size */
548+
if (peerSz > (XSOCKLENT)sizeof(lclPeer))
549+
peerSz = (XSOCKLENT)sizeof(lclPeer);
550+
}
551+
else {
552+
/* Truncate peer size */
553+
if (peerSz > (XSOCKLENT)dtlsCtx->peer.bufSz)
554+
peerSz = (XSOCKLENT)dtlsCtx->peer.bufSz;
555+
}
506556

507-
recvd = TranslateReturnCode(recvd, sd);
557+
recvd = TranslateReturnCode(recvd, sd);
508558

509-
if (recvd < 0) {
510-
WOLFSSL_MSG("Embed Receive From error");
511-
recvd = TranslateIoError(recvd);
512-
if (recvd == WOLFSSL_CBIO_ERR_WANT_READ &&
513-
!wolfSSL_dtls_get_using_nonblock(ssl)) {
514-
recvd = WOLFSSL_CBIO_ERR_TIMEOUT;
559+
if (recvd < 0) {
560+
WOLFSSL_MSG("Embed Receive From error");
561+
recvd = TranslateIoError(recvd);
562+
if (recvd == WOLFSSL_CBIO_ERR_WANT_READ &&
563+
!wolfSSL_dtls_get_using_nonblock(ssl)) {
564+
recvd = WOLFSSL_CBIO_ERR_TIMEOUT;
565+
}
566+
return recvd;
515567
}
516-
return recvd;
517-
}
518-
else if (recvd == 0) {
519-
if (!isDGramSock(sd)) {
520-
/* Closed TCP connection */
521-
recvd = WOLFSSL_CBIO_ERR_CONN_CLOSE;
568+
else if (recvd == 0) {
569+
if (!isDGramSock(sd)) {
570+
/* Closed TCP connection */
571+
recvd = WOLFSSL_CBIO_ERR_CONN_CLOSE;
572+
}
573+
else {
574+
WOLFSSL_MSG("Ignoring 0-length datagram");
575+
continue;
576+
}
577+
return recvd;
522578
}
523-
else {
524-
WOLFSSL_MSG("Ignoring 0-length datagram");
579+
else if (dtlsCtx->connected) {
580+
/* Nothing to do */
581+
}
582+
else if (dtlsCtx->userSet) {
583+
/* Check we received the packet from the correct peer */
584+
if (dtlsCtx->peer.sz > 0 &&
585+
(peerSz != (XSOCKLENT)dtlsCtx->peer.sz ||
586+
!sockAddrEqual(peer, peerSz, (SOCKADDR_S*)dtlsCtx->peer.sa,
587+
dtlsCtx->peer.sz))) {
588+
WOLFSSL_MSG(" Ignored packet from invalid peer");
589+
#if defined(NO_ASN_TIME) && \
590+
!defined(DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER)
591+
if (doDtlsTimeout) {
592+
invalidPeerPackets++;
593+
if (invalidPeerPackets > DTLS_RECEIVEFROM_MAX_INVALID_PEER)
594+
return wolfSSL_dtls_get_using_nonblock(ssl)
595+
? WOLFSSL_CBIO_ERR_WANT_READ
596+
: WOLFSSL_CBIO_ERR_TIMEOUT;
597+
}
598+
#endif /* NO_ASN_TIME && !DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER */
599+
continue;
600+
}
525601
}
526-
return recvd;
527-
}
528-
else if (dtlsCtx->connected) {
529-
/* Nothing to do */
530-
}
531-
else if (dtlsCtx->userSet) {
532-
/* Check we received the packet from the correct peer */
533-
if (dtlsCtx->peer.sz > 0 &&
534-
(peerSz != (XSOCKLENT)dtlsCtx->peer.sz ||
535-
!sockAddrEqual(peer, peerSz, (SOCKADDR_S*)dtlsCtx->peer.sa,
536-
dtlsCtx->peer.sz))) {
537-
WOLFSSL_MSG(" Ignored packet from invalid peer");
538-
return WOLFSSL_CBIO_ERR_WANT_READ;
602+
else {
603+
/* Store size of saved address */
604+
dtlsCtx->peer.sz = peerSz;
539605
}
540-
}
541-
else {
542-
/* Store size of saved address */
543-
dtlsCtx->peer.sz = peerSz;
544-
}
545606
#ifndef NO_ASN_TIME
546-
ssl->dtls_start_timeout = 0;
607+
ssl->dtls_start_timeout = 0;
547608
#endif /* !NO_ASN_TIME */
609+
break;
610+
} while (1);
548611

549612
return recvd;
550613
}
@@ -569,6 +632,12 @@ int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
569632
else if (!dtlsCtx->connected) {
570633
peer = (const SOCKADDR_S*)dtlsCtx->peer.sa;
571634
peerSz = dtlsCtx->peer.sz;
635+
#ifndef WOLFSSL_IPV6
636+
if (PeerIsIpv6(peer, peerSz)) {
637+
WOLFSSL_MSG("ipv6 dtls peer setted but no ipv6 support compiled");
638+
return NOT_COMPILED_IN;
639+
}
640+
#endif
572641
}
573642

574643
sent = (int)DTLS_SENDTO_FUNCTION(sd, buf, sz, ssl->wflags,

0 commit comments

Comments
 (0)