DTLS to use recvfrom and sendto in embed recv and send callbacks. Added support for storing dtls peer address.
This commit is contained in:
parent
bd849ea9d7
commit
6d1e485ef4
@ -220,7 +220,8 @@ enum {
|
||||
DYNAMIC_TYPE_CIPHER = 31,
|
||||
DYNAMIC_TYPE_RNG = 32,
|
||||
DYNAMIC_TYPE_ARRAYS = 33,
|
||||
DYNAMIC_TYPE_DTLS_POOL = 34
|
||||
DYNAMIC_TYPE_DTLS_POOL = 34,
|
||||
DYNAMIC_TYPE_SOCKADDR = 35
|
||||
};
|
||||
|
||||
/* stack protection */
|
||||
|
@ -671,6 +671,10 @@ int SetCipherList(Suites*, const char* list);
|
||||
#endif
|
||||
|
||||
#ifdef CYASSL_DTLS
|
||||
CYASSL_LOCAL
|
||||
int EmbedReceiveFrom(CYASSL *ssl, char *buf, int sz, void *ctx);
|
||||
CYASSL_LOCAL
|
||||
int EmbedSendTo(CYASSL *ssl, char *buf, int sz, void *ctx);
|
||||
CYASSL_LOCAL
|
||||
int EmbedGenerateCookie(byte *buf, int sz, void *ctx);
|
||||
CYASSL_LOCAL
|
||||
@ -789,6 +793,18 @@ struct CYASSL_CERT_MANAGER {
|
||||
};
|
||||
|
||||
|
||||
/* CyaSSL Sock Addr */
|
||||
struct CYASSL_SOCKADDR {
|
||||
unsigned int sz; /* sockaddr size */
|
||||
void* sa; /* pointer to the sockaddr_in or sockaddr_in6 */
|
||||
};
|
||||
|
||||
typedef struct CYASSL_DTLS_CTX {
|
||||
CYASSL_SOCKADDR peer;
|
||||
int fd;
|
||||
} CYASSL_DTLS_CTX;
|
||||
|
||||
|
||||
/* CyaSSL context type */
|
||||
struct CYASSL_CTX {
|
||||
CYASSL_METHOD* method;
|
||||
@ -1113,6 +1129,7 @@ typedef struct Buffers {
|
||||
buffer dtlsHandshake; /* DTLS handshake defragment buf */
|
||||
word32 dtlsUsed; /* DTLS bytes used in buffer */
|
||||
byte dtlsType; /* DTLS handshake frag type */
|
||||
CYASSL_DTLS_CTX dtlsCtx; /* DTLS connection context */
|
||||
#endif
|
||||
} Buffers;
|
||||
|
||||
|
@ -66,6 +66,7 @@ typedef struct CYASSL_X509_NAME CYASSL_X509_NAME;
|
||||
typedef struct CYASSL_X509_CHAIN CYASSL_X509_CHAIN;
|
||||
|
||||
typedef struct CYASSL_CERT_MANAGER CYASSL_CERT_MANAGER;
|
||||
typedef struct CYASSL_SOCKADDR CYASSL_SOCKADDR;
|
||||
|
||||
/* redeclare guard */
|
||||
#define CYASSL_TYPES_DEFINED
|
||||
@ -222,6 +223,9 @@ CYASSL_API int CyaSSL_dtls_get_current_timeout(CYASSL* ssl);
|
||||
CYASSL_API int CyaSSL_dtls_got_timeout(CYASSL* ssl);
|
||||
CYASSL_API int CyaSSL_dtls(CYASSL* ssl);
|
||||
|
||||
CYASSL_API int CyaSSL_dtls_set_peer(CYASSL*, void*, unsigned int);
|
||||
CYASSL_API int CyaSSL_dtls_get_peer(CYASSL*, void*, unsigned int*);
|
||||
|
||||
CYASSL_API int CyaSSL_ERR_GET_REASON(int err);
|
||||
CYASSL_API char* CyaSSL_ERR_error_string(unsigned long,char*);
|
||||
CYASSL_API void CyaSSL_ERR_error_string_n(unsigned long e, char* buf,
|
||||
|
@ -304,8 +304,8 @@ static INLINE void showPeer(CYASSL* ssl)
|
||||
}
|
||||
|
||||
|
||||
static INLINE void tcp_socket(SOCKET_T* sockfd, SOCKADDR_IN_T* addr,
|
||||
const char* peer, word16 port, int udp)
|
||||
static INLINE void build_addr(SOCKADDR_IN_T* addr,
|
||||
const char* peer, word16 port)
|
||||
{
|
||||
#ifndef TEST_IPV6
|
||||
const char* host = peer;
|
||||
@ -326,10 +326,6 @@ static INLINE void tcp_socket(SOCKET_T* sockfd, SOCKADDR_IN_T* addr,
|
||||
}
|
||||
#endif
|
||||
|
||||
if (udp)
|
||||
*sockfd = socket(AF_INET_V, SOCK_DGRAM, 0);
|
||||
else
|
||||
*sockfd = socket(AF_INET_V, SOCK_STREAM, 0);
|
||||
memset(addr, 0, sizeof(SOCKADDR_IN_T));
|
||||
|
||||
#ifndef TEST_IPV6
|
||||
@ -344,6 +340,15 @@ static INLINE void tcp_socket(SOCKET_T* sockfd, SOCKADDR_IN_T* addr,
|
||||
addr->sin6_port = htons(port);
|
||||
addr->sin6_addr = in6addr_loopback;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static INLINE void tcp_socket(SOCKET_T* sockfd, int udp)
|
||||
{
|
||||
if (udp)
|
||||
*sockfd = socket(AF_INET_V, SOCK_DGRAM, 0);
|
||||
else
|
||||
*sockfd = socket(AF_INET_V, SOCK_STREAM, 0);
|
||||
|
||||
#ifndef USE_WINDOWS_API
|
||||
#ifdef SO_NOSIGPIPE
|
||||
@ -374,9 +379,19 @@ static INLINE void tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port,
|
||||
int udp)
|
||||
{
|
||||
SOCKADDR_IN_T addr;
|
||||
tcp_socket(sockfd, &addr, ip, port, udp);
|
||||
build_addr(&addr, ip, port);
|
||||
tcp_socket(sockfd, udp);
|
||||
|
||||
if (connect(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0)
|
||||
if (!udp) {
|
||||
if (connect(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0)
|
||||
err_sys("tcp connect failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static INLINE void udp_connect(SOCKET_T* sockfd, void* addr, int addrSz)
|
||||
{
|
||||
if (connect(*sockfd, (const struct sockaddr*)addr, addrSz) != 0)
|
||||
err_sys("tcp connect failed");
|
||||
}
|
||||
|
||||
@ -388,10 +403,8 @@ static INLINE void tcp_listen(SOCKET_T* sockfd, int port, int useAnyAddr,
|
||||
|
||||
/* don't use INADDR_ANY by default, firewall may block, make user switch
|
||||
on */
|
||||
if (useAnyAddr)
|
||||
tcp_socket(sockfd, &addr, INADDR_ANY, port, udp);
|
||||
else
|
||||
tcp_socket(sockfd, &addr, yasslIP, port, udp);
|
||||
build_addr(&addr, (useAnyAddr ? INADDR_ANY : yasslIP), port);
|
||||
tcp_socket(sockfd, udp);
|
||||
|
||||
#ifndef USE_WINDOWS_API
|
||||
{
|
||||
@ -434,8 +447,9 @@ static INLINE void udp_accept(SOCKET_T* sockfd, int* clientfd, func_args* args)
|
||||
{
|
||||
SOCKADDR_IN_T addr;
|
||||
|
||||
(void)args;
|
||||
tcp_socket(sockfd, &addr, yasslIP, yasslPort, 1);
|
||||
(void)args;
|
||||
build_addr(&addr, yasslIP, yasslPort);
|
||||
tcp_socket(sockfd, 1);
|
||||
|
||||
|
||||
#ifndef USE_WINDOWS_API
|
||||
|
@ -342,10 +342,18 @@ void client_test(void* args)
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
tcp_connect(&sockfd, host, port, doDTLS);
|
||||
ssl = CyaSSL_new(ctx);
|
||||
if (ssl == NULL)
|
||||
err_sys("unable to get SSL object");
|
||||
if (doDTLS) {
|
||||
SOCKADDR_IN_T addr;
|
||||
build_addr(&addr, host, port);
|
||||
CyaSSL_dtls_set_peer(ssl, &addr, sizeof(addr));
|
||||
tcp_socket(&sockfd, 1);
|
||||
}
|
||||
else {
|
||||
tcp_connect(&sockfd, host, port, 0);
|
||||
}
|
||||
CyaSSL_set_fd(ssl, sockfd);
|
||||
#ifdef HAVE_CRL
|
||||
if (CyaSSL_EnableCRL(ssl, CYASSL_CRL_CHECKALL) != SSL_SUCCESS)
|
||||
|
@ -70,8 +70,6 @@ void echoclient_test(void* args)
|
||||
doDTLS = 1;
|
||||
#endif
|
||||
|
||||
tcp_connect(&sockfd, yasslIP, yasslPort, doDTLS);
|
||||
|
||||
#if defined(CYASSL_DTLS)
|
||||
method = DTLSv1_client_method();
|
||||
#elif !defined(NO_TLS)
|
||||
@ -102,6 +100,16 @@ void echoclient_test(void* args)
|
||||
#endif
|
||||
ssl = SSL_new(ctx);
|
||||
|
||||
if (doDTLS) {
|
||||
SOCKADDR_IN_T addr;
|
||||
build_addr(&addr, yasslIP, yasslPort);
|
||||
CyaSSL_dtls_set_peer(ssl, &addr, sizeof(addr));
|
||||
tcp_socket(&sockfd, 1);
|
||||
}
|
||||
else {
|
||||
tcp_connect(&sockfd, yasslIP, yasslPort, 0);
|
||||
}
|
||||
|
||||
SSL_set_fd(ssl, sockfd);
|
||||
#if defined(USE_WINDOWS_API) && defined(CYASSL_DTLS) && defined(NO_MAIN_DRIVER)
|
||||
/* let echoserver bind first, TODO: add Windows signal like pthreads does */
|
||||
|
@ -344,6 +344,13 @@ int InitSSL_Ctx(CYASSL_CTX* ctx, CYASSL_METHOD* method)
|
||||
#ifndef CYASSL_USER_IO
|
||||
ctx->CBIORecv = EmbedReceive;
|
||||
ctx->CBIOSend = EmbedSend;
|
||||
#ifdef CYASSL_DTLS
|
||||
if (method->version.major == DTLS_MAJOR
|
||||
&& method->version.minor == DTLS_MINOR) {
|
||||
ctx->CBIORecv = EmbedReceiveFrom;
|
||||
ctx->CBIOSend = EmbedSendTo;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
/* user will set */
|
||||
ctx->CBIORecv = NULL;
|
||||
@ -1000,7 +1007,10 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx)
|
||||
ssl->heap = ctx->heap; /* defaults to self */
|
||||
ssl->options.tls = 0;
|
||||
ssl->options.tls1_1 = 0;
|
||||
ssl->options.dtls = 0;
|
||||
if (ssl->version.major == DTLS_MAJOR && ssl->version.minor == DTLS_MINOR)
|
||||
ssl->options.dtls = 1;
|
||||
else
|
||||
ssl->options.dtls = 0;
|
||||
ssl->options.partialWrite = ctx->partialWrite;
|
||||
ssl->options.quietShutdown = ctx->quietShutdown;
|
||||
ssl->options.certOnly = 0;
|
||||
@ -1024,6 +1034,9 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx)
|
||||
ssl->buffers.dtlsHandshake.length = 0;
|
||||
ssl->buffers.dtlsHandshake.buffer = NULL;
|
||||
ssl->buffers.dtlsType = 0;
|
||||
ssl->buffers.dtlsCtx.fd = -1;
|
||||
ssl->buffers.dtlsCtx.peer.sa = NULL;
|
||||
ssl->buffers.dtlsCtx.peer.sz = 0;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSSL_EXTRA
|
||||
@ -1181,6 +1194,8 @@ void SSL_ResourceFree(CYASSL* ssl)
|
||||
DtlsPoolReset(ssl);
|
||||
XFREE(ssl->dtls_pool, ssl->heap, DYNAMIC_TYPE_NONE);
|
||||
}
|
||||
XFREE(ssl->buffers.dtlsCtx.peer.sa, ssl->heap, DYNAMIC_TYPE_SOCKADDR);
|
||||
ssl->buffers.dtlsCtx.peer.sa = NULL;
|
||||
#endif
|
||||
#if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS)
|
||||
XFREE(ssl->peerCert.derCert.buffer, ssl->heap, DYNAMIC_TYPE_CERT);
|
||||
|
124
src/io.c
124
src/io.c
@ -86,7 +86,7 @@
|
||||
#define WSAEPIPE -12345
|
||||
#endif
|
||||
#define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK
|
||||
#define SOCKET_EAGAIN WSAEWOULDBLOCK
|
||||
#define SOCKET_EAGAIN WSAETIMEDOUT
|
||||
#define SOCKET_ECONNRESET WSAECONNRESET
|
||||
#define SOCKET_EINTR WSAEINTR
|
||||
#define SOCKET_EPIPE WSAEPIPE
|
||||
@ -255,6 +255,128 @@ int EmbedSend(CYASSL* ssl, char *buf, int sz, void *ctx)
|
||||
#define XSOCKLENT socklen_t
|
||||
#endif
|
||||
|
||||
#define SENDTO_FUNCTION sendto
|
||||
#define RECVFROM_FUNCTION recvfrom
|
||||
|
||||
|
||||
/* The receive embedded callback
|
||||
* return : nb bytes read, or error
|
||||
*/
|
||||
int EmbedReceiveFrom(CYASSL *ssl, char *buf, int sz, void *ctx)
|
||||
{
|
||||
CYASSL_DTLS_CTX* dtlsCtx = (CYASSL_DTLS_CTX*)ctx;
|
||||
int recvd;
|
||||
int err;
|
||||
int sd = dtlsCtx->fd;
|
||||
int dtls_timeout = CyaSSL_dtls_get_current_timeout(ssl);
|
||||
struct sockaddr_in peer;
|
||||
XSOCKLENT peerSz = sizeof(peer);
|
||||
|
||||
CYASSL_ENTER("EmbedReceiveFrom()");
|
||||
if (!CyaSSL_get_using_nonblock(ssl) && dtls_timeout != 0) {
|
||||
#ifdef USE_WINDOWS_API
|
||||
DWORD timeout = dtls_timeout;
|
||||
#else
|
||||
struct timeval timeout = {dtls_timeout, 0};
|
||||
#endif
|
||||
setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO,
|
||||
(char*)&timeout, sizeof(timeout));
|
||||
}
|
||||
|
||||
recvd = RECVFROM_FUNCTION(sd, (char *)buf, sz, 0,
|
||||
(struct sockaddr*)&peer, &peerSz);
|
||||
|
||||
if (recvd < 0) {
|
||||
err = LastError();
|
||||
CYASSL_MSG("Embed Receive From error");
|
||||
|
||||
if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
|
||||
if (CyaSSL_get_using_nonblock(ssl)) {
|
||||
CYASSL_MSG(" Would block");
|
||||
return IO_ERR_WANT_READ;
|
||||
}
|
||||
else {
|
||||
CYASSL_MSG(" Socket timeout");
|
||||
return IO_ERR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
else if (err == SOCKET_ECONNRESET) {
|
||||
CYASSL_MSG(" Connection reset");
|
||||
return IO_ERR_CONN_RST;
|
||||
}
|
||||
else if (err == SOCKET_EINTR) {
|
||||
CYASSL_MSG(" Socket interrupted");
|
||||
return IO_ERR_ISR;
|
||||
}
|
||||
else if (err == SOCKET_ECONNREFUSED) {
|
||||
CYASSL_MSG(" Connection refused");
|
||||
return IO_ERR_WANT_READ;
|
||||
}
|
||||
else {
|
||||
CYASSL_MSG(" General error");
|
||||
return IO_ERR_GENERAL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (dtlsCtx != NULL
|
||||
&& dtlsCtx->peer.sz > 0
|
||||
&& peerSz != dtlsCtx->peer.sz
|
||||
&& memcmp(&peer, dtlsCtx->peer.sa, peerSz) != 0) {
|
||||
CYASSL_MSG(" Ignored packet from invalid peer");
|
||||
return IO_ERR_WANT_READ;
|
||||
}
|
||||
}
|
||||
|
||||
return recvd;
|
||||
}
|
||||
|
||||
|
||||
/* The send embedded callback
|
||||
* return : nb bytes sent, or error
|
||||
*/
|
||||
int EmbedSendTo(CYASSL* ssl, char *buf, int sz, void *ctx)
|
||||
{
|
||||
CYASSL_DTLS_CTX* dtlsCtx = (CYASSL_DTLS_CTX*)ctx;
|
||||
int sd = dtlsCtx->fd;
|
||||
int sent;
|
||||
int len = sz;
|
||||
int err;
|
||||
|
||||
(void)ssl;
|
||||
|
||||
CYASSL_ENTER("EmbedSendTo()");
|
||||
sent = SENDTO_FUNCTION(sd, &buf[sz - len], len, 0,
|
||||
dtlsCtx->peer.sa, dtlsCtx->peer.sz);
|
||||
|
||||
if (sent < 0) {
|
||||
err = LastError();
|
||||
CYASSL_MSG("Embed Send To error");
|
||||
|
||||
if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
|
||||
CYASSL_MSG(" Would Block");
|
||||
return IO_ERR_WANT_WRITE;
|
||||
}
|
||||
else if (err == SOCKET_ECONNRESET) {
|
||||
CYASSL_MSG(" Connection reset");
|
||||
return IO_ERR_CONN_RST;
|
||||
}
|
||||
else if (err == SOCKET_EINTR) {
|
||||
CYASSL_MSG(" Socket interrupted");
|
||||
return IO_ERR_ISR;
|
||||
}
|
||||
else if (err == SOCKET_EPIPE) {
|
||||
CYASSL_MSG(" Socket EPIPE");
|
||||
return IO_ERR_CONN_CLOSE;
|
||||
}
|
||||
else {
|
||||
CYASSL_MSG(" General error");
|
||||
return IO_ERR_GENERAL;
|
||||
}
|
||||
}
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
|
||||
/* The DTLS Generate Cookie callback
|
||||
* return : number of bytes copied into buf, or error
|
||||
|
46
src/ssl.c
46
src/ssl.c
@ -172,6 +172,14 @@ int CyaSSL_set_fd(CYASSL* ssl, int fd)
|
||||
ssl->IOCB_ReadCtx = &ssl->rfd;
|
||||
ssl->IOCB_WriteCtx = &ssl->wfd;
|
||||
|
||||
#ifdef CYASSL_DTLS
|
||||
if (ssl->options.dtls) {
|
||||
ssl->IOCB_ReadCtx = &ssl->buffers.dtlsCtx;
|
||||
ssl->IOCB_WriteCtx = &ssl->buffers.dtlsCtx;
|
||||
ssl->buffers.dtlsCtx.fd = fd;
|
||||
}
|
||||
#endif
|
||||
|
||||
CYASSL_LEAVE("SSL_set_fd", SSL_SUCCESS);
|
||||
return SSL_SUCCESS;
|
||||
}
|
||||
@ -206,6 +214,44 @@ int CyaSSL_dtls(CYASSL* ssl)
|
||||
}
|
||||
|
||||
|
||||
int CyaSSL_dtls_set_peer(CYASSL* ssl, void* peer, unsigned int peerSz)
|
||||
{
|
||||
#ifdef CYASSL_DTLS
|
||||
void* sa = (void*)XMALLOC(peerSz, ssl->heap, DYNAMIC_TYPE_SOCKADDR);
|
||||
if (sa != NULL) {
|
||||
XMEMCPY(sa, peer, peerSz);
|
||||
ssl->buffers.dtlsCtx.peer.sa = sa;
|
||||
ssl->buffers.dtlsCtx.peer.sz = peerSz;
|
||||
return SSL_SUCCESS;
|
||||
}
|
||||
return SSL_FAILURE;
|
||||
#else
|
||||
(void)ssl;
|
||||
(void)peer;
|
||||
(void)peerSz;
|
||||
return SSL_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
int CyaSSL_dtls_get_peer(CYASSL* ssl, void* peer, unsigned int* peerSz)
|
||||
{
|
||||
#ifdef CYASSL_DTLS
|
||||
if (peer != NULL && peerSz != NULL
|
||||
&& *peerSz >= ssl->buffers.dtlsCtx.peer.sz) {
|
||||
*peerSz = ssl->buffers.dtlsCtx.peer.sz;
|
||||
XMEMCPY(peer, ssl->buffers.dtlsCtx.peer.sa, *peerSz);
|
||||
return SSL_SUCCESS;
|
||||
}
|
||||
return SSL_FAILURE;
|
||||
#else
|
||||
(void)ssl;
|
||||
(void)peer;
|
||||
(void)peerSz;
|
||||
return SSL_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int CyaSSL_negotiate(CYASSL* ssl)
|
||||
{
|
||||
int err = SSL_FATAL_ERROR;
|
||||
|
Loading…
Reference in New Issue
Block a user