remove XSNPRINTF

add a full BIO client/server test
This commit is contained in:
Ludovic FLAMENT 2016-05-17 17:49:30 +02:00
parent 4017e0f8dd
commit 9fe6ca3130
5 changed files with 443 additions and 56 deletions

View File

@ -666,8 +666,13 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_bio(void* args)
wc_BioSetFd(bio, clientfd, BIO_NOCLOSE);
read_again:
idx = wc_BioRead(bio, input, sizeof(input)-1);
if (idx <= 0) {
if (wc_BioShouldRetry(bio)) {
printf("Retry read\n");
goto read_again;
}
printf("wc_BioWrite failed\n");
goto done;
}
@ -704,7 +709,6 @@ done:
#endif
}
static void test_client_bio(void* args)
{
WOLFCRYPT_BIO* bio = 0;
@ -756,8 +760,13 @@ static void test_client_bio(void* args)
goto done2;
}
read_again:
input = wc_BioRead(bio, reply, sizeof(reply)-1);
if (input <= 0) {
if (wc_BioShouldRetry(bio)) {
printf("Retry read\n");
goto read_again;
}
printf("wc_BioRead failed");
goto done2;
}
@ -774,10 +783,206 @@ done2:
#ifdef WOLFSSL_TIRTOS
fdCloseSession(Task_self());
#endif
return;
}
#ifndef TEST_IPV6
static THREAD_RETURN WOLFSSL_THREAD test_server_full_bio(void* args)
{
WOLFCRYPT_BIO *abio = 0, *cbio = 0;
char buf[256];
char msg[] = "I hear you fa shizzle!";
int r;
#ifdef WOLFSSL_TIRTOS
fdOpenSession(Task_self());
#endif
((func_args*)args)->return_code = TEST_FAIL;
abio = wc_BioNew(wc_Bio_s_accept());
if (abio == NULL) {
printf("wc_Bio_s_accept failed\n");
goto done;
}
snprintf(buf, sizeof(buf), "%s:%d", wolfSSLIP, wolfSSLPort);
if (wc_BioSetAcceptPort(abio, buf) <= 0) {
printf("wc_BioSetAcceptPort failed\n");
goto done;
}
XMEMSET(buf, 0, sizeof(buf));
/* force SO_REUSEADDR */
wc_BioSetBindMode(abio, BIO_BIND_REUSEADDR);
/* force NO_SIGPIPE and TCP_NODELAY */
wc_BioSetSocketOptions(abio, BIO_OPT_TCP_NO_DELAY|BIO_OPT_IGN_SIGPIPE);
/* First call to wc_BioAccept() sets up accept BIO */
if (wc_BioDoAccept(abio) <= 0) {
printf("Error setting up accept\n");
goto done;
}
/* activate Thread */
tcp_set_ready(args, wolfSSLPort, 0);
/* Wait for incoming connection */
if (wc_BioDoAccept(abio) <= 0) {
printf("Error accepting connection\n");
goto done;
}
/* Retrieve BIO for connection */
cbio = wc_BioPop(abio);
wc_BioPuts(cbio, msg);
/* Close accept BIO to refuse further connections */
wc_BioFree(abio);
abio = 0;
/* Read msg, send ack */
do {
XMEMSET(buf, 0, sizeof(buf));
r = wc_BioRead(cbio, buf, sizeof(buf));
if (r <= 0) {
if (wc_BioShouldRetry(cbio)) {
printf("Retry read\n");
continue;
}
printf("wc_BioRead failed\n");
break;
}
if (r >= 3 && !XSTRNCMP("end", buf, 3)) {
printf("BioFullSrv, Client close connection\n");
break;
}
buf[r] = 0;
printf("BioFullSrv, Client sent: %s\n", buf);
wc_BioPuts(cbio, "Server ACK");
} while (1);
done:
if (abio != 0)
wc_BioFree(abio);
if (cbio != 0)
wc_BioFree(cbio);
((func_args*)args)->return_code = TEST_SUCCESS;
#ifdef WOLFSSL_TIRTOS
fdCloseSession(Task_self());
#endif
#ifndef WOLFSSL_TIRTOS
return 0;
#endif
}
static void test_client_full_bio(void* args)
{
WOLFCRYPT_BIO* bio = 0;
char msg[64] = "Hello wolfssl!";
char reply[1024];
#ifdef TEST_IPV6
SOCKET_T sockfd = 0;
#else
char ip[] = {127, 0, 0, 1};
#endif
int input, port;
int msgSz = (int)strlen(msg);
printf("client\n");
#ifdef WOLFSSL_TIRTOS
fdOpenSession(Task_self());
#endif
((func_args*)args)->return_code = TEST_FAIL;
#ifdef TEST_IPV6
bio = wc_BioNew(wc_Bio_s_socket());
#else
bio = wc_BioNew(wc_Bio_s_connect());
#endif
if (bio == NULL) {
printf("wc_BioNew failed\n");
goto done2;
}
port = ((func_args*)args)->signal->port;
#ifdef TEST_IPV6
tcp_connect(&sockfd, wolfSSLIP, port, 0, NULL);
wc_BioSetFd(bio, sockfd, BIO_NOCLOSE);
#else
wc_BioSetConnIp(bio, ip);
wc_BioSetConnIntPort(bio, &port);
printf("client do connect\n");
/* start connection */
input = (int)wc_BioDoConnect(bio);
if (input <= 0) {
printf("wc_BioDoConnect failed : %d\n", input);
goto done2;
}
printf("done\n");
#endif
read_again:
input = wc_BioRead(bio, reply, sizeof(reply)-1);
if (input <= 0) {
if (wc_BioShouldRetry(bio)) {
printf("Retry read\n");
goto read_again;
}
printf("wc_BioRead failed");
goto done2;
}
reply[input] = 0;
printf("BioFullCli, Server sent: %s\n", reply);
if (wc_BioWrite(bio, msg, msgSz) != msgSz) {
printf("wc_BioWrite failed");
goto done2;
}
read_again2:
input = wc_BioRead(bio, reply, sizeof(reply)-1);
if (input <= 0) {
if (wc_BioShouldRetry(bio)) {
printf("Retry read\n");
goto read_again2;
}
printf("wc_BioRead failed");
goto done2;
}
reply[input] = 0;
printf("BioFullCli, Server response: %s\n", reply);
/* close */
if (wc_BioWrite(bio, "end", 3) != 3) {
printf("wc_BioWrite failed");
goto done2;
}
done2:
if (bio != 0)
wc_BioFreeAll(bio);
((func_args*)args)->return_code = TEST_SUCCESS;
#ifdef WOLFSSL_TIRTOS
fdCloseSession(Task_self());
#endif
}
#endif /* TEST_IPV6 */
/* BIO SSL test */
static THREAD_RETURN WOLFSSL_THREAD test_server_bio_ssl(void* args)
{
@ -863,8 +1068,13 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_bio_ssl(void* args)
goto done;
}
read_again:
idx = wc_BioRead(ssl_bio, input, sizeof(input)-1);
if (idx <= 0) {
if (wc_BioShouldRetry(ssl_bio)) {
printf("Retry read\n");
goto read_again;
}
printf("wc_BioWrite failed\n");
goto done;
}
@ -977,8 +1187,13 @@ static void test_client_bio_ssl(void* args)
goto done2;
}
read_again:
input = wc_BioRead(ssl_bio, reply, sizeof(reply)-1);
if (input <= 0) {
if (wc_BioShouldRetry(ssl_bio)) {
printf("Retry read\n");
goto read_again;
}
printf("wc_BioRead failed");
goto done2;
}
@ -1294,6 +1509,64 @@ static void test_wolfSSL_read_write_bio(void)
#endif
}
static void test_wolfSSL_read_write_bio_full(void)
{
#ifdef TEST_IPV6
/* nothing to do */
#else
#ifdef HAVE_IO_TESTS_DEPENDENCIES
/* The unit testing for read and write shall happen simutaneously, since
* one can't do anything with one without the other. (Except for a failure
* test case.) This function will call all the others that will set up,
* execute, and report their test findings.
*
* Set up the success case first. This function will become the template
* for the other tests. This should eventually be renamed
*
* The success case isn't interesting, how can this fail?
* - Do not give the client context a CA certificate. The connect should
* fail. Do not need server for this?
* - Using NULL for the ssl object on server. Do not need client for this.
* - Using NULL for the ssl object on client. Do not need server for this.
* - Good ssl objects for client and server. Client write() without server
* read().
* - Good ssl objects for client and server. Server write() without client
* read().
* - Forgetting the password callback?
*/
tcp_ready ready;
func_args client_args;
func_args server_args;
THREAD_TYPE serverThread;
#ifdef WOLFSSL_TIRTOS
fdOpenSession(Task_self());
#endif
StartTCP();
InitTcpReady(&ready);
server_args.signal = &ready;
client_args.signal = &ready;
start_thread(test_server_full_bio, &server_args, &serverThread);
wait_tcp_ready(&server_args);
test_client_full_bio(&client_args);
join_thread(serverThread);
AssertTrue(client_args.return_code);
AssertTrue(server_args.return_code);
FreeTcpReady(&ready);
#ifdef WOLFSSL_TIRTOS
fdOpenSession(Task_self());
#endif
#endif /* HAVE_IO_TESTS_DEPENDENCIES */
#endif /* TEST_IPV6 */
}
static void test_wolfSSL_read_write_bio_ssl(void)
{
#ifdef HAVE_IO_TESTS_DEPENDENCIES
@ -1345,7 +1618,7 @@ static void test_wolfSSL_read_write_bio_ssl(void)
fdOpenSession(Task_self());
#endif
#endif
#endif /* HAVE_IO_TESTS_DEPENDENCIES */
}
#endif /* OPENSSL_EXTRA */
@ -2089,6 +2362,7 @@ void ApiTest(void)
test_wolfSSL_read_write();
#if defined(OPENSSL_EXTRA)
test_wolfSSL_read_write_bio_full();
test_wolfSSL_read_write_bio();
test_wolfSSL_read_write_bio_ssl();
#endif

View File

@ -66,6 +66,35 @@
#include <wolfssl/wolfcrypt/coding.h>
#include <wolfssl/wolfcrypt/bio.h>
static int wc_BioIntToStr(int i, char *str, int strSz){
char const digit[] = "0123456789";
int shift, count = 0;
if (i < 0)
return -1;
shift = i;
do {
++str;
shift = shift/10;
count++;
} while(shift);
/* check size */
if (strSz <= count)
return -1;
*str = '\0';
do {
*--str = digit[i%10];
i = i/10;
} while(i);
return count;
}
WOLFCRYPT_BIO *wc_BioNew(WOLFCRYPT_BIO_METHOD *method)
{
WOLFCRYPT_BIO *bio;
@ -3008,7 +3037,7 @@ err:
int wc_BioAccept(int sock, char **addr)
{
int dsock = WOLFSSL_SOCKET_INVALID;
int dsock = WOLFSSL_SOCKET_INVALID, idx, ret;
unsigned long l;
struct {
@ -3031,6 +3060,7 @@ int wc_BioAccept(int sock, char **addr)
if (sizeof(sa.len.i) != sizeof(sa.len.s) && !sa.len.i) {
if (sa.len.s > sizeof(sa.from)) {
WOLFSSL_ERROR(MEMORY_E);
dsock = WOLFSSL_SOCKET_INVALID;
goto end;
}
@ -3057,11 +3087,45 @@ int wc_BioAccept(int sock, char **addr)
l = ntohl(sa.from.sa_in.sin_addr.s_addr);
XSNPRINTF(*addr, 24, "%d.%d.%d.%d:%d",
(unsigned char)(l >> 24L) & 0xff,
(unsigned char)(l >> 16L) & 0xff,
(unsigned char)(l >> 8L) & 0xff,
(unsigned char)(l) & 0xff, ntohs(sa.from.sa_in.sin_port));
ret = wc_BioIntToStr((unsigned char)(l >> 24L) & 0xff, *addr, 24);
if (ret <= 0) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
dsock = WOLFSSL_SOCKET_INVALID;
goto end;
}
idx = ret;
*(*addr+(idx++)) = '.';
ret = wc_BioIntToStr((unsigned char)(l >> 16L) & 0xff, *addr+idx, 24-idx);
if (ret <= 0) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
dsock = WOLFSSL_SOCKET_INVALID;
goto end;
}
idx += ret;
*(*addr+(idx++)) = '.';
ret = wc_BioIntToStr((unsigned char)(l >> 8L) & 0xff, *addr+idx, 24-idx);
if (ret <= 0) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
dsock = WOLFSSL_SOCKET_INVALID;
goto end;
}
idx += ret;
*(*addr+(idx++)) = '.';
ret = wc_BioIntToStr((unsigned char)(l) & 0xff, *addr+idx, 24-idx);
if (ret <= 0) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
dsock = WOLFSSL_SOCKET_INVALID;
goto end;
}
idx += ret;
*(*addr+(idx++)) = ':';
ret = wc_BioIntToStr(ntohs(sa.from.sa_in.sin_port), *addr+idx, 24-idx);
if (ret <= 0) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
dsock = WOLFSSL_SOCKET_INVALID;
goto end;
}
end:
return dsock;
}
@ -3304,7 +3368,7 @@ again:
}
/* TCP NO DELAY */
if (baccept->options & 1) {
if (baccept->options & BIO_OPT_TCP_NO_DELAY) {
if (!wc_BioSetTcpNdelay(s, 1)) {
#ifdef USE_WINDOWS_API
closesocket(s);
@ -3317,7 +3381,7 @@ again:
}
/* IGNORE SIGPIPE */
if (baccept->options & 2) {
if (baccept->options & BIO_OPT_IGN_SIGPIPE) {
if (!wc_BioSetTcpNsigpipe(s, 1)) {
#ifdef USE_WINDOWS_API
closesocket(s);
@ -4078,9 +4142,38 @@ static long wc_BioConn_ctrl(WOLFCRYPT_BIO *bio, int cmd, long num, void *ptr)
else if (num == 2) {
char buf[16];
unsigned char *p = ptr;
int idx, res;
XSNPRINTF(buf, sizeof(buf), "%d.%d.%d.%d",
p[0], p[1], p[2], p[3]);
res = wc_BioIntToStr(p[0], buf, sizeof(buf));
if (res <= 0) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
ret = -1;
break;
}
idx = res;
buf[idx++] = '.';
res = wc_BioIntToStr(p[1], buf+idx, sizeof(buf)-idx);
if (res <= 0) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
ret = -1;
break;
}
idx += res;
buf[idx++] = '.';
res = wc_BioIntToStr(p[2], buf+idx, sizeof(buf)-idx);
if (res <= 0) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
ret = -1;
break;
}
idx += res;
buf[idx++] = '.';
res = wc_BioIntToStr(p[3], buf+idx, sizeof(buf)-idx);
if (res <= 0) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
ret = -1;
break;
}
if (conn->pHostname != NULL)
XFREE(conn->pHostname, 0, DYNAMIC_TYPE_OPENSSL);
@ -4097,8 +4190,15 @@ static long wc_BioConn_ctrl(WOLFCRYPT_BIO *bio, int cmd, long num, void *ptr)
}
else if (num == 3) {
char buf[6];
int res;
res = wc_BioIntToStr(*(int *)ptr, buf, sizeof(buf));
if (res <= 0) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
ret = -1;
break;
}
XSNPRINTF(buf, sizeof(buf), "%d", *(int *)ptr);
if (conn->pPort != NULL)
XFREE(conn->pPort, 0, DYNAMIC_TYPE_OPENSSL);

View File

@ -828,6 +828,54 @@ static INLINE void udp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd,
*clientfd = *sockfd;
}
static INLINE void tcp_set_ready(func_args* args, word16 port, int ready_file)
{
#if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER) && !defined(__MINGW32__)
/* signal ready to tcp_accept */
{
tcp_ready* ready = args->signal;
if (ready) {
pthread_mutex_lock(&ready->mutex);
ready->ready = 1;
ready->port = port;
pthread_cond_signal(&ready->cond);
pthread_mutex_unlock(&ready->mutex);
}
}
#elif defined (WOLFSSL_TIRTOS)
/* Need mutex? */
tcp_ready* ready = args->signal;
ready->ready = 1;
ready->port = port;
#endif
if (ready_file) {
#ifndef NO_FILESYSTEM
FILE* srf = NULL;
tcp_ready* ready = args ? args->signal : NULL;
if (ready) {
srf = fopen(ready->srfName, "w");
if (srf) {
/* let's write port sever is listening on to ready file
external monitor can then do ephemeral ports by passing
-p 0 to server on supported platforms with -R ready_file
client can then wait for existence of ready_file and see
which port the server is listening on. */
fprintf(srf, "%d\n", (int)port);
fclose(srf);
}
}
#endif
}
(void)port;
(void)ready_file;
(void)args;
}
static INLINE void tcp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd,
func_args* args, word16 port, int useAnyAddr,
int udp, int ready_file, int do_listen)
@ -843,45 +891,7 @@ static INLINE void tcp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd,
if(do_listen) {
tcp_listen(sockfd, &port, useAnyAddr, udp);
#if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER) && !defined(__MINGW32__)
/* signal ready to tcp_accept */
{
tcp_ready* ready = args->signal;
if (ready) {
pthread_mutex_lock(&ready->mutex);
ready->ready = 1;
ready->port = port;
pthread_cond_signal(&ready->cond);
pthread_mutex_unlock(&ready->mutex);
}
}
#elif defined (WOLFSSL_TIRTOS)
/* Need mutex? */
tcp_ready* ready = args->signal;
ready->ready = 1;
ready->port = port;
#endif
if (ready_file) {
#ifndef NO_FILESYSTEM
FILE* srf = NULL;
tcp_ready* ready = args ? args->signal : NULL;
if (ready) {
srf = fopen(ready->srfName, "w");
if (srf) {
/* let's write port sever is listening on to ready file
external monitor can then do ephemeral ports by passing
-p 0 to server on supported platforms with -R ready_file
client can then wait for existence of ready_file and see
which port the server is listening on. */
fprintf(srf, "%d\n", (int)port);
fclose(srf);
}
}
#endif
}
tcp_set_ready(args, port, ready_file);
}
*clientfd = accept(*sockfd, (struct sockaddr*)&client,
@ -891,7 +901,6 @@ static INLINE void tcp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd,
}
}
static INLINE void tcp_set_nonblocking(SOCKET_T* sockfd)
{
#ifdef USE_WINDOWS_API

View File

@ -277,6 +277,12 @@ enum WS_BIO_BIND {
BIO_BIND_REUSEADDR = 2,
};
enum WC_BIO_OPT {
BIO_OPT_NONE = 0,
BIO_OPT_TCP_NO_DELAY = 1,
BIO_OPT_IGN_SIGPIPE = 2,
};
WOLFSSL_API WOLFCRYPT_BIO *wc_BioNew(WOLFCRYPT_BIO_METHOD *method);
WOLFSSL_API int wc_BioFree(WOLFCRYPT_BIO *bio);
WOLFSSL_API void wc_BioFreeAll(WOLFCRYPT_BIO *bio);

View File

@ -212,10 +212,8 @@
#define XSTRNCAT(s1,s2,n) strncat((s1),(s2),(n))
#ifndef USE_WINDOWS_API
#define XSTRNCASECMP(s1,s2,n) strncasecmp((s1),(s2),(n))
#define XSNPRINTF snprintf
#else
#define XSTRNCASECMP(s1,s2,n) _strnicmp((s1),(s2),(n))
#define XSNPRINTF _snprintf
#endif
#if defined(WOLFSSL_CERT_EXT) || defined(HAVE_ALPN)