mirror of https://github.com/wolfSSL/wolfssl.git
WOLFSSL_BIO_SSL BIO should use remaining chain for IO
This is accomplished by passing the next BIO in the chain in to the `wolfSSL_set_bio` API.pull/3824/head
parent
4c1a94a6ad
commit
d7838155e5
30
src/bio.c
30
src/bio.c
|
@ -202,8 +202,9 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len)
|
|||
}
|
||||
}
|
||||
|
||||
/* start at end of list and work backwards */
|
||||
while ((bio != NULL) && (bio->next != NULL)) {
|
||||
/* start at end of list (or a WOLFSSL_BIO_SSL object since it takes care of
|
||||
* the rest of the chain) and work backwards */
|
||||
while (bio != NULL && bio->next != NULL && bio->type != WOLFSSL_BIO_SSL) {
|
||||
bio = bio->next;
|
||||
}
|
||||
|
||||
|
@ -250,6 +251,10 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (bio->type == WOLFSSL_BIO_SOCKET) {
|
||||
ret = wolfIO_Recv(bio->num, (char*)buf, len, 0);
|
||||
}
|
||||
|
||||
/* case where front of list is done */
|
||||
if (bio == front) {
|
||||
break; /* at front of list so be done */
|
||||
|
@ -606,6 +611,8 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len)
|
|||
else {
|
||||
ret = wolfSSL_BIO_SSL_write(bio, data, len, front);
|
||||
}
|
||||
/* Rest of chain is taken care of inside call */
|
||||
break;
|
||||
}
|
||||
|
||||
if (bio->type == WOLFSSL_BIO_MD) {
|
||||
|
@ -615,6 +622,10 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len)
|
|||
}
|
||||
#endif /* WOLFCRYPT_ONLY */
|
||||
|
||||
if (bio->type == WOLFSSL_BIO_SOCKET) {
|
||||
ret = wolfIO_Send(bio->num, (char*)data, len, 0);
|
||||
}
|
||||
|
||||
/* advance to the next bio in list */
|
||||
bio = bio->next;
|
||||
}
|
||||
|
@ -944,6 +955,21 @@ size_t wolfSSL_BIO_wpending(const WOLFSSL_BIO *bio)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Custom wolfSSL API to check if current bio object supports checking
|
||||
* pending state.
|
||||
*/
|
||||
int wolfSSL_BIO_supports_pending(const WOLFSSL_BIO *bio)
|
||||
{
|
||||
while (bio) {
|
||||
if (bio->type == WOLFSSL_BIO_SSL ||
|
||||
bio->type == WOLFSSL_BIO_MEMORY ||
|
||||
bio->type == WOLFSSL_BIO_BIO)
|
||||
return 1;
|
||||
bio = bio->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the number of pending bytes in read and write buffers */
|
||||
size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *bio)
|
||||
{
|
||||
|
|
|
@ -6426,9 +6426,14 @@ void SSL_ResourceFree(WOLFSSL* ssl)
|
|||
#endif /* WOLFSSL_DTLS */
|
||||
#ifdef OPENSSL_EXTRA
|
||||
#ifndef NO_BIO
|
||||
/* Don't free if there was/is a previous element in the chain.
|
||||
* This means that this BIO was part of a chain that will be
|
||||
* free'd separately. */
|
||||
if (ssl->biord != ssl->biowr) /* only free write if different */
|
||||
wolfSSL_BIO_free(ssl->biowr);
|
||||
wolfSSL_BIO_free(ssl->biord); /* always free read bio */
|
||||
if (ssl->biowr != NULL && ssl->biowr->prev == NULL)
|
||||
wolfSSL_BIO_free(ssl->biowr);
|
||||
if (ssl->biord != NULL && ssl->biord->prev == NULL)
|
||||
wolfSSL_BIO_free(ssl->biord);
|
||||
ssl->biowr = NULL;
|
||||
ssl->biord = NULL;
|
||||
#endif
|
||||
|
|
47
src/ssl.c
47
src/ssl.c
|
@ -15136,37 +15136,27 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
|
|||
return;
|
||||
}
|
||||
|
||||
/* if WOLFSSL_BIO is socket type then set WOLFSSL socket to use */
|
||||
if (rd != NULL && rd->type == WOLFSSL_BIO_SOCKET) {
|
||||
wolfSSL_set_rfd(ssl, rd->num);
|
||||
}
|
||||
if (wr != NULL && wr->type == WOLFSSL_BIO_SOCKET) {
|
||||
wolfSSL_set_wfd(ssl, wr->num);
|
||||
}
|
||||
|
||||
/* free any existing WOLFSSL_BIOs in use */
|
||||
/* free any existing WOLFSSL_BIOs in use but don't free those in
|
||||
* a chain */
|
||||
if (ssl->biord != NULL) {
|
||||
if (ssl->biord != ssl->biowr) {
|
||||
if (ssl->biowr != NULL) {
|
||||
if (ssl->biowr != NULL && ssl->biowr->prev != NULL)
|
||||
wolfSSL_BIO_free(ssl->biowr);
|
||||
ssl->biowr = NULL;
|
||||
}
|
||||
ssl->biowr = NULL;
|
||||
}
|
||||
wolfSSL_BIO_free(ssl->biord);
|
||||
if (ssl->biord->prev != NULL)
|
||||
wolfSSL_BIO_free(ssl->biord);
|
||||
ssl->biord = NULL;
|
||||
}
|
||||
|
||||
|
||||
ssl->biord = rd;
|
||||
ssl->biowr = wr;
|
||||
|
||||
/* set SSL to use BIO callbacks instead */
|
||||
if (((ssl->cbioFlag & WOLFSSL_CBIO_RECV) == 0) &&
|
||||
(rd != NULL && rd->type != WOLFSSL_BIO_SOCKET)) {
|
||||
if (((ssl->cbioFlag & WOLFSSL_CBIO_RECV) == 0)) {
|
||||
ssl->CBIORecv = BioReceive;
|
||||
}
|
||||
if (((ssl->cbioFlag & WOLFSSL_CBIO_SEND) == 0) &&
|
||||
(wr != NULL && wr->type != WOLFSSL_BIO_SOCKET)) {
|
||||
if (((ssl->cbioFlag & WOLFSSL_CBIO_SEND) == 0)) {
|
||||
ssl->CBIOSend = BioSend;
|
||||
}
|
||||
|
||||
|
@ -16049,6 +16039,21 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
|
|||
return 0;
|
||||
}
|
||||
|
||||
long wolfSSL_BIO_do_handshake(WOLFSSL_BIO *b)
|
||||
{
|
||||
WOLFSSL_ENTER("wolfSSL_BIO_do_handshake");
|
||||
if (b == NULL) {
|
||||
WOLFSSL_MSG("Bad parameter");
|
||||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
if (b->type == WOLFSSL_BIO_SSL && b->ptr != NULL) {
|
||||
return wolfSSL_negotiate((WOLFSSL*)b->ptr);
|
||||
}
|
||||
else {
|
||||
WOLFSSL_MSG("Not SSL BIO or no SSL object set");
|
||||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
long wolfSSL_BIO_set_ssl(WOLFSSL_BIO* b, WOLFSSL* ssl, int closeF)
|
||||
{
|
||||
|
@ -16059,6 +16064,8 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
|
|||
if (b != NULL) {
|
||||
b->ptr = ssl;
|
||||
b->shutdown = (byte)closeF;
|
||||
if (b->next != NULL)
|
||||
wolfSSL_set_bio(ssl, b->next, b->next);
|
||||
/* add to ssl for bio free if SSL_free called before/instead of free_all? */
|
||||
ret = WOLFSSL_SUCCESS;
|
||||
}
|
||||
|
@ -16280,6 +16287,10 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
|
|||
top->next = append;
|
||||
append->prev = top;
|
||||
|
||||
/* SSL BIO's should use the next object in the chain for IO */
|
||||
if (top->type == WOLFSSL_BIO_SSL && top->ptr)
|
||||
wolfSSL_set_bio((WOLFSSL*)top->ptr, append, append);
|
||||
|
||||
return top;
|
||||
}
|
||||
#endif /* !NO_BIO */
|
||||
|
|
96
src/wolfio.c
96
src/wolfio.c
|
@ -133,31 +133,46 @@ int BioReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx)
|
|||
return WOLFSSL_CBIO_ERR_GENERAL;
|
||||
}
|
||||
|
||||
if (ssl->biord->method && ssl->biord->method->readCb) {
|
||||
WOLFSSL_MSG("Calling custom biord");
|
||||
recvd = ssl->biord->method->readCb(ssl->biord, buf, sz);
|
||||
if (recvd < 0 && recvd != WOLFSSL_CBIO_ERR_WANT_READ)
|
||||
return WOLFSSL_CBIO_ERR_GENERAL;
|
||||
return recvd;
|
||||
if (wolfSSL_BIO_supports_pending(ssl->biord) &&
|
||||
wolfSSL_BIO_ctrl_pending(ssl->biord) == 0) {
|
||||
WOLFSSL_MSG("BIO want read");
|
||||
return WOLFSSL_CBIO_ERR_WANT_READ;
|
||||
}
|
||||
recvd = wolfSSL_BIO_read(ssl->biord, buf, sz);
|
||||
if (recvd <= 0) {
|
||||
if (ssl->biord->type == WOLFSSL_BIO_SOCKET) {
|
||||
int err;
|
||||
|
||||
switch (ssl->biord->type) {
|
||||
case WOLFSSL_BIO_MEMORY:
|
||||
case WOLFSSL_BIO_BIO:
|
||||
if (wolfSSL_BIO_ctrl_pending(ssl->biord) == 0) {
|
||||
WOLFSSL_MSG("BIO want read");
|
||||
return WOLFSSL_CBIO_ERR_WANT_READ;
|
||||
if (recvd == 0) {
|
||||
WOLFSSL_MSG("BioReceive connection closed");
|
||||
return WOLFSSL_CBIO_ERR_CONN_CLOSE;
|
||||
}
|
||||
recvd = wolfSSL_BIO_read(ssl->biord, buf, sz);
|
||||
if (recvd <= 0) {
|
||||
WOLFSSL_MSG("BIO general error");
|
||||
|
||||
err = wolfSSL_LastError(recvd);
|
||||
if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
|
||||
WOLFSSL_MSG("\tWould block");
|
||||
return WOLFSSL_CBIO_ERR_WANT_READ;
|
||||
}
|
||||
else if (err == SOCKET_ECONNRESET) {
|
||||
WOLFSSL_MSG("\tConnection reset");
|
||||
return WOLFSSL_CBIO_ERR_CONN_RST;
|
||||
}
|
||||
else if (err == SOCKET_EINTR) {
|
||||
WOLFSSL_MSG("\tSocket interrupted");
|
||||
return WOLFSSL_CBIO_ERR_ISR;
|
||||
}
|
||||
else if (err == SOCKET_ECONNABORTED) {
|
||||
WOLFSSL_MSG("\tConnection aborted");
|
||||
return WOLFSSL_CBIO_ERR_CONN_CLOSE;
|
||||
}
|
||||
else {
|
||||
WOLFSSL_MSG("\tGeneral error");
|
||||
return WOLFSSL_CBIO_ERR_GENERAL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
WOLFSSL_MSG("This BIO type is unknown / unsupported");
|
||||
return WOLFSSL_CBIO_ERR_GENERAL;
|
||||
WOLFSSL_MSG("BIO general error");
|
||||
return WOLFSSL_CBIO_ERR_GENERAL;
|
||||
}
|
||||
|
||||
(void)ctx;
|
||||
|
@ -186,27 +201,32 @@ int BioSend(WOLFSSL* ssl, char *buf, int sz, void *ctx)
|
|||
return WOLFSSL_CBIO_ERR_GENERAL;
|
||||
}
|
||||
|
||||
if (ssl->biowr->method && ssl->biowr->method->writeCb) {
|
||||
WOLFSSL_MSG("Calling custom biowr");
|
||||
sent = ssl->biowr->method->writeCb(ssl->biowr, buf, sz);
|
||||
if ((sent < 0) && (sent != WOLFSSL_CBIO_ERR_WANT_WRITE)) {
|
||||
return WOLFSSL_CBIO_ERR_GENERAL;
|
||||
}
|
||||
return sent;
|
||||
}
|
||||
|
||||
switch (ssl->biowr->type) {
|
||||
case WOLFSSL_BIO_MEMORY:
|
||||
case WOLFSSL_BIO_BIO:
|
||||
sent = wolfSSL_BIO_write(ssl->biowr, buf, sz);
|
||||
if (sent < 0) {
|
||||
sent = wolfSSL_BIO_write(ssl->biowr, buf, sz);
|
||||
if (sent < 0) {
|
||||
if (ssl->biowr->type == WOLFSSL_BIO_SOCKET) {
|
||||
int err = wolfSSL_LastError(sent);
|
||||
if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
|
||||
WOLFSSL_MSG("\tWould Block");
|
||||
return WOLFSSL_CBIO_ERR_WANT_WRITE;
|
||||
}
|
||||
else if (err == SOCKET_ECONNRESET) {
|
||||
WOLFSSL_MSG("\tConnection reset");
|
||||
return WOLFSSL_CBIO_ERR_CONN_RST;
|
||||
}
|
||||
else if (err == SOCKET_EINTR) {
|
||||
WOLFSSL_MSG("\tSocket interrupted");
|
||||
return WOLFSSL_CBIO_ERR_ISR;
|
||||
}
|
||||
else if (err == SOCKET_EPIPE) {
|
||||
WOLFSSL_MSG("\tSocket EPIPE");
|
||||
return WOLFSSL_CBIO_ERR_CONN_CLOSE;
|
||||
}
|
||||
else {
|
||||
WOLFSSL_MSG("\tGeneral error");
|
||||
return WOLFSSL_CBIO_ERR_GENERAL;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
WOLFSSL_MSG("This BIO type is unknown / unsupported");
|
||||
return WOLFSSL_CBIO_ERR_GENERAL;
|
||||
}
|
||||
return WOLFSSL_CBIO_ERR_GENERAL;
|
||||
}
|
||||
(void)ctx;
|
||||
|
||||
|
|
70
tests/api.c
70
tests/api.c
|
@ -31459,6 +31459,75 @@ static void test_wolfSSL_BIO_should_retry(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void test_wolfSSL_BIO_connect(void)
|
||||
{
|
||||
#if defined(OPENSSL_ALL) && defined(HAVE_IO_TESTS_DEPENDENCIES)
|
||||
tcp_ready ready;
|
||||
func_args server_args;
|
||||
THREAD_TYPE serverThread;
|
||||
BIO *tcp_bio;
|
||||
BIO *ssl_bio;
|
||||
SSL_CTX* ctx;
|
||||
SSL *ssl;
|
||||
char msg[] = "hello wolfssl!";
|
||||
char reply[30];
|
||||
char buff[10] = {0};
|
||||
|
||||
printf(testingFmt, "wolfSSL_BIO_new_connect()");
|
||||
|
||||
/* Setup server */
|
||||
XMEMSET(&server_args, 0, sizeof(func_args));
|
||||
StartTCP();
|
||||
InitTcpReady(&ready);
|
||||
#if defined(USE_WINDOWS_API)
|
||||
/* use RNG to get random port if using windows */
|
||||
ready.port = GetRandomPort();
|
||||
#endif
|
||||
server_args.signal = &ready;
|
||||
start_thread(test_server_nofail, &server_args, &serverThread);
|
||||
wait_tcp_ready(&server_args);
|
||||
AssertIntGT(XSPRINTF(buff, "%d", ready.port), 0);
|
||||
|
||||
/* Start the test proper */
|
||||
/* Setup the TCP BIO */
|
||||
AssertNotNull(tcp_bio = BIO_new_connect(wolfSSLIP));
|
||||
AssertIntEQ(BIO_set_conn_port(tcp_bio, buff), 1);
|
||||
/* Setup the SSL object */
|
||||
AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
|
||||
AssertIntEQ(WOLFSSL_SUCCESS,
|
||||
wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0));
|
||||
AssertIntEQ(WOLFSSL_SUCCESS,
|
||||
wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, SSL_FILETYPE_PEM));
|
||||
AssertIntEQ(WOLFSSL_SUCCESS,
|
||||
wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, SSL_FILETYPE_PEM));
|
||||
AssertNotNull(ssl = SSL_new(ctx));
|
||||
SSL_set_connect_state(ssl);
|
||||
/* Setup the SSL BIO */
|
||||
AssertNotNull(ssl_bio = BIO_new(BIO_f_ssl()));
|
||||
AssertIntEQ(BIO_set_ssl(ssl_bio, ssl, BIO_CLOSE), 1);
|
||||
/* Link BIO's so that ssl_bio uses tcp_bio for IO */
|
||||
AssertPtrEq(BIO_push(ssl_bio, tcp_bio), ssl_bio);
|
||||
/* Do TCP connect */
|
||||
AssertIntEQ(BIO_do_connect(ssl_bio), 1);
|
||||
/* Do TLS handshake */
|
||||
AssertIntEQ(BIO_do_handshake(ssl_bio), 1);
|
||||
/* Test writing */
|
||||
AssertIntEQ(BIO_write(ssl_bio, msg, sizeof(msg)), sizeof(msg));
|
||||
/* Expect length of default wolfSSL reply */
|
||||
AssertIntEQ(BIO_read(ssl_bio, reply, sizeof(reply)), 23);
|
||||
|
||||
/* Clean it all up */
|
||||
BIO_free_all(ssl_bio);
|
||||
SSL_CTX_free(ctx);
|
||||
|
||||
/* Server clean up */
|
||||
join_thread(serverThread);
|
||||
FreeTcpReady(&ready);
|
||||
|
||||
printf(resultFmt, passed);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_wolfSSL_BIO_write(void)
|
||||
{
|
||||
#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_BASE64_ENCODE)
|
||||
|
@ -40621,6 +40690,7 @@ void ApiTest(void)
|
|||
test_wolfSSL_BIO_should_retry();
|
||||
test_wolfSSL_d2i_PUBKEY();
|
||||
test_wolfSSL_BIO_write();
|
||||
test_wolfSSL_BIO_connect();
|
||||
test_wolfSSL_BIO_printf();
|
||||
test_wolfSSL_BIO_f_md();
|
||||
#endif
|
||||
|
|
|
@ -672,11 +672,10 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_
|
|||
#define BIO_set_write_buffer_size wolfSSL_BIO_set_write_buffer_size
|
||||
#define BIO_f_ssl wolfSSL_BIO_f_ssl
|
||||
#define BIO_new_socket wolfSSL_BIO_new_socket
|
||||
#ifndef NO_WOLFSSL_STUB
|
||||
#define BIO_new_connect wolfSSL_BIO_new_connect
|
||||
#define BIO_set_conn_port wolfSSL_BIO_set_conn_port
|
||||
#define BIO_do_connect wolfSSL_BIO_do_connect
|
||||
#endif
|
||||
#define BIO_do_handshake wolfSSL_BIO_do_handshake
|
||||
#define SSL_set_bio wolfSSL_set_bio
|
||||
#define BIO_set_ssl wolfSSL_BIO_set_ssl
|
||||
#define BIO_eof wolfSSL_BIO_eof
|
||||
|
|
|
@ -1325,6 +1325,8 @@ WOLFSSL_API WOLFSSL_BIO *wolfSSL_BIO_new_connect(const char *str);
|
|||
WOLFSSL_API long wolfSSL_BIO_set_conn_port(WOLFSSL_BIO *b, char* port);
|
||||
WOLFSSL_API long wolfSSL_BIO_do_connect(WOLFSSL_BIO *b);
|
||||
|
||||
WOLFSSL_API long wolfSSL_BIO_do_handshake(WOLFSSL_BIO *b);
|
||||
|
||||
WOLFSSL_API long wolfSSL_BIO_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, void *parg);
|
||||
WOLFSSL_API long wolfSSL_BIO_int_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, int iarg);
|
||||
|
||||
|
@ -3549,6 +3551,7 @@ WOLFSSL_API size_t wolfSSL_get_client_random(const WOLFSSL* ssl,
|
|||
|
||||
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
|
||||
WOLFSSL_API size_t wolfSSL_BIO_wpending(const WOLFSSL_BIO *bio);
|
||||
WOLFSSL_API int wolfSSL_BIO_supports_pending(const WOLFSSL_BIO *bio);
|
||||
WOLFSSL_API size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *b);
|
||||
|
||||
WOLFSSL_API int wolfSSL_get_server_tmp_key(const WOLFSSL*, WOLFSSL_EVP_PKEY**);
|
||||
|
|
Loading…
Reference in New Issue