From 046b987324bd318f1343b1efc67879e87efe0f1f Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Thu, 2 Jun 2016 09:23:12 -0600 Subject: [PATCH] callbacks for setting and getting peer ip/port/family --- src/internal.c | 141 ++++++++++++++---------------------------- src/io.c | 150 +++++++++++++++++++++++++++++++++++++++++++++ wolfssl/internal.h | 4 ++ wolfssl/ssl.h | 48 +++++---------- 4 files changed, 216 insertions(+), 127 deletions(-) diff --git a/src/internal.c b/src/internal.c index c1d367dcd..762658041 100755 --- a/src/internal.c +++ b/src/internal.c @@ -1001,8 +1001,10 @@ static int dtls_export_load(WOLFSSL* ssl, byte* exp, word32 len, byte ver) static int ExportPeerInfo(WOLFSSL* ssl, byte* exp, word32 len, byte ver) { - int idx = 0; - word16 fam = 0; + int idx = 0; + int ipSz = DTLS_EXPORT_IP; /* start as max size */ + int fam = 0; + word16 port = 0; char ip[DTLS_EXPORT_IP]; if (ver != 1) { @@ -1010,57 +1012,29 @@ static int ExportPeerInfo(WOLFSSL* ssl, byte* exp, word32 len, byte ver) return BAD_FUNC_ARG; } - if (exp == NULL || len < sizeof(ip) + 3 * DTLS_EXPORT_LEN) { + if (ssl == NULL || exp == NULL || len < sizeof(ip) + 3 * DTLS_EXPORT_LEN) { return BAD_FUNC_ARG; } - fam = ((SOCKADDR_S*)ssl->buffers.dtlsCtx.peer.sa)->ss_family; - c16toa(fam, exp + idx); idx += DTLS_EXPORT_LEN; - - switch (fam) { - case WOLFSSL_IP4: - if (XINET_NTOP(fam, - &(((SOCKADDR_IN*)ssl->buffers.dtlsCtx.peer.sa)->sin_addr), - ip, sizeof(ip)) == NULL) { - WOLFSSL_MSG("XINET_NTOP error"); - return SOCKET_ERROR_E; - } - break; - - case WOLFSSL_IP6: - if (XINET_NTOP(fam, - &(((SOCKADDR_IN6*)ssl->buffers.dtlsCtx.peer.sa)->sin6_addr), - ip, sizeof(ip)) == NULL) { - WOLFSSL_MSG("XINET_NTOP error"); - return SOCKET_ERROR_E; - } - break; - - default: - WOLFSSL_MSG("Unknown family type"); - return SOCKET_ERROR_E; + if (ssl->ctx->CBGetPeer == NULL) { + WOLFSSL_MSG("No get peer call back set"); + return BAD_FUNC_ARG; } - ip[sizeof(ip)-1] = '\0'; /* make sure has terminator */ - c16toa((word16)XSTRLEN(ip), exp + idx); - idx += DTLS_EXPORT_LEN; - XMEMCPY(exp + idx, ip, XSTRLEN(ip)); - idx += (word16)XSTRLEN(ip); - - switch (fam) { - case WOLFSSL_IP4: - c16toa(XNTOHS(((SOCKADDR_IN*)ssl->buffers.dtlsCtx.peer.sa)->sin_port), - exp + idx); - break; - case WOLFSSL_IP6: - c16toa(XNTOHS(((SOCKADDR_IN6*)ssl->buffers.dtlsCtx.peer.sa)->sin6_port), - exp + idx); - break; - - default: - WOLFSSL_MSG("Unknown address family"); - return SOCKET_ERROR_E; + if (ssl->ctx->CBGetPeer(ssl, ip, &ipSz, &port, &fam) != SSL_SUCCESS) { + WOLFSSL_MSG("Get peer callback error"); + return SOCKET_ERROR_E; } - idx += DTLS_EXPORT_LEN; + + /* check that ipSz/fam is not negative or too large since user can set cb */ + if (ipSz < 0 || ipSz > DTLS_EXPORT_IP || fam < 0) { + WOLFSSL_MSG("Bad ipSz or fam returned from get peer callback"); + return SOCKET_ERROR_E; + } + + c16toa((word16)fam, exp + idx); idx += DTLS_EXPORT_LEN; + c16toa((word16)ipSz, exp + idx); idx += DTLS_EXPORT_LEN; + XMEMCPY(exp + idx, ip, ipSz); idx += ipSz; + c16toa(port, exp + idx); idx += DTLS_EXPORT_LEN; return idx; } @@ -1068,75 +1042,48 @@ static int ExportPeerInfo(WOLFSSL* ssl, byte* exp, word32 len, byte ver) static int ImportPeerInfo(WOLFSSL* ssl, byte* buf, word32 len, byte ver) { - int ret; word16 idx = 0; - word16 value; + word16 ipSz; + word16 fam; + word16 port; char ip[DTLS_EXPORT_IP]; - SOCKADDR_S addr; if (ver != 1) { WOLFSSL_MSG("Export version not supported"); return BAD_FUNC_ARG; } - if (buf == NULL || len < 3 * DTLS_EXPORT_LEN) { + if (ssl == NULL || buf == NULL || len < 3 * DTLS_EXPORT_LEN) { return BAD_FUNC_ARG; } /* import sin family */ - ato16(buf + idx, &value); idx += DTLS_EXPORT_LEN; - addr.ss_family = value; + ato16(buf + idx, &fam); idx += DTLS_EXPORT_LEN; - /* import ip address idx, and value or unsigned but cast for enum */ - ato16(buf + idx, &value); idx += DTLS_EXPORT_LEN; - if (value > sizeof(ip) || (word16)(idx + value + DTLS_EXPORT_LEN) > len) { + /* import ip address idx, and ipSz are unsigned but cast for enum */ + ato16(buf + idx, &ipSz); idx += DTLS_EXPORT_LEN; + if (ipSz > sizeof(ip) || (word16)(idx + ipSz + DTLS_EXPORT_LEN) > len) { return BUFFER_E; } XMEMSET(ip, 0, sizeof(ip)); - XMEMCPY(ip, buf + idx, value); idx += value; - ip[value] = '\0'; - ato16(buf + idx, &value); idx += DTLS_EXPORT_LEN; - switch (addr.ss_family) { - case WOLFSSL_IP4: - if (XINET_PTON(addr.ss_family, ip, - &(((SOCKADDR_IN*)&addr)->sin_addr)) <= 0) { - WOLFSSL_MSG("XINET_PTON error"); - return SOCKET_ERROR_E; - } - ((SOCKADDR_IN*)&addr)->sin_port = XHTONS(value); + XMEMCPY(ip, buf + idx, ipSz); idx += ipSz; + ip[ipSz] = '\0'; + ato16(buf + idx, &port); idx += DTLS_EXPORT_LEN; - /* peer sa is free'd in SSL_ResourceFree */ - if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN*)&addr, - sizeof(SOCKADDR_IN)))!= SSL_SUCCESS) { - WOLFSSL_MSG("Import DTLS peer info error"); - return ret; - } - break; - - case WOLFSSL_IP6: - if (XINET_PTON(addr.ss_family, ip, - &(((SOCKADDR_IN6*)&addr)->sin6_addr)) <= 0) { - WOLFSSL_MSG("XINET_PTON error"); - return SOCKET_ERROR_E; - } - ((SOCKADDR_IN6*)&addr)->sin6_port = XHTONS(value); - - /* peer sa is free'd in SSL_ResourceFree */ - if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN6*)&addr, - sizeof(SOCKADDR_IN6)))!= SSL_SUCCESS) { - WOLFSSL_MSG("Import DTLS peer info error"); - return ret; - } - break; - - default: - WOLFSSL_MSG("Unknown address family"); - return BUFFER_E; + /* sanity check for a function to call, then use it to import peer info */ + if (ssl->ctx->CBSetPeer == NULL) { + WOLFSSL_MSG("No set peer function"); + return BAD_FUNC_ARG; + } + if (ssl->ctx->CBSetPeer(ssl, ip, ipSz, port, fam) != SSL_SUCCESS) { + WOLFSSL_MSG("Error setting peer info"); + return SOCKET_ERROR_E; } return idx; } + /* WOLFSSL_LOCAL function that serializes the current WOLFSSL session * buf is used to hold the serialized WOLFSSL struct and sz is the size of buf * passed in. @@ -1454,6 +1401,10 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method) ctx->CBIORecv = EmbedReceiveFrom; ctx->CBIOSend = EmbedSendTo; } + #ifdef WOLFSSL_SESSION_EXPORT + ctx->CBGetPeer = EmbedGetPeer; + ctx->CBSetPeer = EmbedSetPeer; + #endif #endif #endif /* WOLFSSL_USER_IO */ diff --git a/src/io.c b/src/io.c index c971951f5..3ca5b6ed2 100644 --- a/src/io.c +++ b/src/io.c @@ -550,6 +550,142 @@ int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) return sz; } +#ifdef WOLFSSL_SESSION_EXPORT + #ifndef XINET_NTOP + #define XINET_NTOP(a,b,c,d) inet_ntop((a),(b),(c),(d)) + #endif + #ifndef XINET_PTON + #define XINET_PTON(a,b,c) inet_pton((a),(b),(c)) + #endif + #ifndef XHTONS + #define XHTONS(a) htons((a)) + #endif + #ifndef XNTOHS + #define XNTOHS(a) ntohs((a)) + #endif + + #ifndef WOLFSSL_IP4 + #define WOLFSSL_IP4 AF_INET + #endif + #ifndef WOLFSSL_IP6 + #define WOLFSSL_IP6 AF_INET6 + #endif + + typedef struct sockaddr_storage SOCKADDR_S; + typedef struct sockaddr_in SOCKADDR_IN; + typedef struct sockaddr_in6 SOCKADDR_IN6; + + /* get the peer information in human readable form (ip, port, family) + * default function assumes BSD sockets + * can be overriden with wolfSSL_CTX_SetIOGetPeer + */ + int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz, + unsigned short* port, int* fam) + { + SOCKADDR_S peer; + word32 peerSz; + int ret; + + if (ssl == NULL || ip == NULL || ipSz == NULL || + port == NULL || fam == NULL) { + return BAD_FUNC_ARG; + } + + /* get peer information stored in ssl struct */ + peerSz = sizeof(SOCKADDR_S); + if ((ret = wolfSSL_dtls_get_peer(ssl, (void*)&peer, &peerSz)) + != SSL_SUCCESS) { + return ret; + } + + /* extract family, ip, and port */ + *fam = ((SOCKADDR_S*)&peer)->ss_family; + switch (*fam) { + case WOLFSSL_IP4: + if (XINET_NTOP(*fam, &(((SOCKADDR_IN*)&peer)->sin_addr), + ip, *ipSz) == NULL) { + WOLFSSL_MSG("XINET_NTOP error"); + return SOCKET_ERROR_E; + } + *port = XNTOHS(((SOCKADDR_IN*)&peer)->sin_port); + break; + + case WOLFSSL_IP6: + if (XINET_NTOP(*fam, &(((SOCKADDR_IN6*)&peer)->sin6_addr), + ip, *ipSz) == NULL) { + WOLFSSL_MSG("XINET_NTOP error"); + return SOCKET_ERROR_E; + } + *port = XNTOHS(((SOCKADDR_IN6*)&peer)->sin6_port); + break; + + default: + WOLFSSL_MSG("Unknown family type"); + return SOCKET_ERROR_E; + } + ip[*ipSz - 1] = '\0'; /* make sure has terminator */ + *ipSz = (word16)XSTRLEN(ip); + + return SSL_SUCCESS; + } + + /* set the peer information in human readable form (ip, port, family) + * default function assumes BSD sockets + * can be overriden with wolfSSL_CTX_SetIOSetPeer + */ + int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz, + unsigned short port, int fam) + { + int ret; + SOCKADDR_S addr; + + /* sanity checks on arguments */ + if (ssl == NULL || ip == NULL || ipSz < 0 || ipSz > DTLS_EXPORT_IP) { + return BAD_FUNC_ARG; + } + + addr.ss_family = fam; + switch (addr.ss_family) { + case WOLFSSL_IP4: + if (XINET_PTON(addr.ss_family, ip, + &(((SOCKADDR_IN*)&addr)->sin_addr)) <= 0) { + WOLFSSL_MSG("XINET_PTON error"); + return SOCKET_ERROR_E; + } + ((SOCKADDR_IN*)&addr)->sin_port = XHTONS(port); + + /* peer sa is free'd in SSL_ResourceFree */ + if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN*)&addr, + sizeof(SOCKADDR_IN)))!= SSL_SUCCESS) { + WOLFSSL_MSG("Import DTLS peer info error"); + return ret; + } + break; + + case WOLFSSL_IP6: + if (XINET_PTON(addr.ss_family, ip, + &(((SOCKADDR_IN6*)&addr)->sin6_addr)) <= 0) { + WOLFSSL_MSG("XINET_PTON error"); + return SOCKET_ERROR_E; + } + ((SOCKADDR_IN6*)&addr)->sin6_port = XHTONS(port); + + /* peer sa is free'd in SSL_ResourceFree */ + if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN6*)&addr, + sizeof(SOCKADDR_IN6)))!= SSL_SUCCESS) { + WOLFSSL_MSG("Import DTLS peer info error"); + return ret; + } + break; + + default: + WOLFSSL_MSG("Unknown address family"); + return BUFFER_E; + } + + return SSL_SUCCESS; + } +#endif /* WOLFSSL_SESSION_EXPORT */ #endif /* WOLFSSL_DTLS */ #ifdef HAVE_OCSP @@ -1066,6 +1202,20 @@ WOLFSSL_API void* wolfSSL_GetCookieCtx(WOLFSSL* ssl) return NULL; } +#ifdef WOLFSSL_SESSION_EXPORT + +WOLFSSL_API void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX* ctx, CallbackGetPeer cb) +{ + ctx->CBGetPeer = cb; +} + + +WOLFSSL_API void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX* ctx, CallbackSetPeer cb) +{ + ctx->CBSetPeer = cb; +} + +#endif /* WOLFSSL_SESSION_EXPORT */ #endif /* WOLFSSL_DTLS */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 76d67be9b..5efe933ce 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1960,7 +1960,11 @@ struct WOLFSSL_CTX { #ifdef WOLFSSL_DTLS CallbackGenCookie CBIOCookie; /* gen cookie callback */ wc_dtls_export dtls_export; /* export function for DTLS session */ +#ifdef WOLFSSL_SESSION_EXPORT + CallbackGetPeer CBGetPeer; + CallbackSetPeer CBSetPeer; #endif +#endif /* WOLFSSL_DTLS */ VerifyCallback verifyCallback; /* cert verification callback */ word32 timeout; /* session timeout */ #ifdef HAVE_ECC diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index b2cd3622a..862596d7d 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -31,37 +31,6 @@ #include #include -#ifdef WOLFSSL_SESSION_EXPORT - #include - #include - - #ifndef XINET_NTOP - #define XINET_NTOP(a,b,c,d) inet_ntop((a),(b),(c),(d)) - #endif - #ifndef XINET_PTON - #define XINET_PTON(a,b,c) inet_pton((a),(b),(c)) - #endif - #ifndef XHTONS - #define XHTONS(a) htons((a)) - #endif - #ifndef XNTOHS - #define XNTOHS(a) ntohs((a)) - #endif - - #ifndef WOLFSSL_IP4 - #define WOLFSSL_IP4 AF_INET - #endif - #ifndef WOLFSSL_IP6 - #define WOLFSSL_IP6 AF_INET6 - #endif - - typedef struct sockaddr_storage SOCKADDR_S; - typedef struct sockaddr_in SOCKADDR_IN; - typedef struct sockaddr_in6 SOCKADDR_IN6; - -#endif - - #ifndef NO_FILESYSTEM #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) #if MQX_USE_IO_OLD @@ -1097,7 +1066,6 @@ WOLFSSL_API void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl); WOLFSSL_API void wolfSSL_SetIOReadFlags( WOLFSSL* ssl, int flags); WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags); - #ifndef WOLFSSL_USER_IO /* default IO callbacks */ WOLFSSL_API int EmbedReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx); @@ -1114,6 +1082,22 @@ WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags); WOLFSSL_API int EmbedSendTo(WOLFSSL* ssl, char* buf, int sz, void* ctx); WOLFSSL_API int EmbedGenerateCookie(WOLFSSL* ssl, unsigned char* buf, int sz, void*); + #ifdef WOLFSSL_SESSION_EXPORT + WOLFSSL_API int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz, + unsigned short* port, int* fam); + WOLFSSL_API int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz, + unsigned short port, int fam); + + typedef int (*CallbackGetPeer)(WOLFSSL* ssl, char* ip, int* ipSz, + unsigned short* port, int* fam); + typedef int (*CallbackSetPeer)(WOLFSSL* ssl, char* ip, int ipSz, + unsigned short port, int fam); + + WOLFSSL_API void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX*, + CallbackGetPeer); + WOLFSSL_API void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX*, + CallbackSetPeer); + #endif /* WOLFSSL_SESSION_EXPORT */ #endif /* WOLFSSL_DTLS */ #endif /* WOLFSSL_USER_IO */