mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-01-29 14:12:11 +01:00
add wolfSSL_write_dup(), creates write_only WOLFSSL to allow concurrent access
This commit is contained in:
190
src/internal.c
190
src/internal.c
@@ -3187,8 +3187,14 @@ int DhAgree(WOLFSSL* ssl,
|
||||
/* This function inherits a WOLFSSL_CTX's fields into an SSL object.
|
||||
It is used during initialization and to switch an ssl's CTX with
|
||||
wolfSSL_Set_SSL_CTX. Requires ssl->suites alloc and ssl-arrays with PSK
|
||||
unless writeDup is on.
|
||||
|
||||
ssl object to initialize
|
||||
ctx parent factory
|
||||
writeDup flag indicating this is a write dup only
|
||||
|
||||
SSL_SUCCESS return value on success */
|
||||
int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
|
||||
int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
|
||||
{
|
||||
byte havePSK = 0;
|
||||
byte haveAnon = 0;
|
||||
@@ -3196,13 +3202,16 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
|
||||
byte haveRSA = 0;
|
||||
(void) haveAnon; /* Squash unused var warnings */
|
||||
|
||||
if(!ssl || !ctx || ssl->suites == NULL)
|
||||
if (!ssl || !ctx)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (ssl->suites == NULL && !writeDup)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
newSSL = ssl->ctx == NULL; /* Assign after null check */
|
||||
|
||||
#ifndef NO_PSK
|
||||
if (ctx->server_hint[0] && ssl->arrays == NULL) {
|
||||
if (ctx->server_hint[0] && ssl->arrays == NULL && !writeDup) {
|
||||
return BAD_FUNC_ARG; /* needed for copy below */
|
||||
}
|
||||
#endif
|
||||
@@ -3307,41 +3316,45 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
|
||||
ssl->devId = ctx->devId;
|
||||
#endif
|
||||
|
||||
if (writeDup == 0) {
|
||||
|
||||
#ifndef NO_PSK
|
||||
if (ctx->server_hint[0]) { /* set in CTX */
|
||||
XSTRNCPY(ssl->arrays->server_hint, ctx->server_hint, MAX_PSK_ID_LEN);
|
||||
ssl->arrays->server_hint[MAX_PSK_ID_LEN - 1] = '\0';
|
||||
}
|
||||
if (ctx->server_hint[0]) { /* set in CTX */
|
||||
XSTRNCPY(ssl->arrays->server_hint, ctx->server_hint,MAX_PSK_ID_LEN);
|
||||
ssl->arrays->server_hint[MAX_PSK_ID_LEN - 1] = '\0';
|
||||
}
|
||||
#endif /* NO_PSK */
|
||||
|
||||
if (ctx->suites)
|
||||
*ssl->suites = *ctx->suites;
|
||||
else
|
||||
XMEMSET(ssl->suites, 0, sizeof(Suites));
|
||||
if (ctx->suites)
|
||||
*ssl->suites = *ctx->suites;
|
||||
else
|
||||
XMEMSET(ssl->suites, 0, sizeof(Suites));
|
||||
|
||||
/* make sure server has DH parms, and add PSK if there, add NTRU too */
|
||||
if (ssl->options.side == WOLFSSL_SERVER_END)
|
||||
InitSuites(ssl->suites, ssl->version, haveRSA, havePSK,
|
||||
/* make sure server has DH parms, and add PSK if there, add NTRU too */
|
||||
if (ssl->options.side == WOLFSSL_SERVER_END)
|
||||
InitSuites(ssl->suites, ssl->version, haveRSA, havePSK,
|
||||
ssl->options.haveDH, ssl->options.haveNTRU,
|
||||
ssl->options.haveECDSAsig, ssl->options.haveECC,
|
||||
ssl->options.haveStaticECC, ssl->options.side);
|
||||
else
|
||||
InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, TRUE,
|
||||
else
|
||||
InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, TRUE,
|
||||
ssl->options.haveNTRU, ssl->options.haveECDSAsig,
|
||||
ssl->options.haveECC, ssl->options.haveStaticECC,
|
||||
ssl->options.side);
|
||||
|
||||
#if !defined(NO_CERTS) && !defined(WOLFSSL_SESSION_EXPORT)
|
||||
/* make sure server has cert and key unless using PSK or Anon
|
||||
* This should be true even if just switching ssl ctx */
|
||||
if (ssl->options.side == WOLFSSL_SERVER_END && !havePSK && !haveAnon)
|
||||
if (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer ||
|
||||
!ssl->buffers.key || !ssl->buffers.key->buffer) {
|
||||
WOLFSSL_MSG("Server missing certificate and/or private key");
|
||||
return NO_PRIVATE_KEY;
|
||||
}
|
||||
/* make sure server has cert and key unless using PSK or Anon
|
||||
* This should be true even if just switching ssl ctx */
|
||||
if (ssl->options.side == WOLFSSL_SERVER_END && !havePSK && !haveAnon)
|
||||
if (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer
|
||||
|| !ssl->buffers.key || !ssl->buffers.key->buffer) {
|
||||
WOLFSSL_MSG("Server missing certificate and/or private key");
|
||||
return NO_PRIVATE_KEY;
|
||||
}
|
||||
#endif
|
||||
|
||||
} /* writeDup check */
|
||||
|
||||
#ifdef WOLFSSL_SESSION_EXPORT
|
||||
#ifdef WOLFSSL_DTLS
|
||||
ssl->dtls_export = ctx->dtls_export; /* export function for session */
|
||||
@@ -3358,8 +3371,13 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
|
||||
|
||||
/* init everything to 0, NULL, default values before calling anything that may
|
||||
fail so that destructor has a "good" state to cleanup
|
||||
|
||||
ssl object to initialize
|
||||
ctx parent factory
|
||||
writeDup flag indicating this is a write dup only
|
||||
|
||||
0 on success */
|
||||
int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
|
||||
int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -3542,30 +3560,65 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
|
||||
|
||||
/* all done with init, now can return errors, call other stuff */
|
||||
|
||||
/* arrays */
|
||||
ssl->arrays = (Arrays*)XMALLOC(sizeof(Arrays), ssl->heap,
|
||||
if (!writeDup) {
|
||||
/* arrays */
|
||||
ssl->arrays = (Arrays*)XMALLOC(sizeof(Arrays), ssl->heap,
|
||||
DYNAMIC_TYPE_ARRAYS);
|
||||
if (ssl->arrays == NULL) {
|
||||
WOLFSSL_MSG("Arrays Memory error");
|
||||
return MEMORY_E;
|
||||
}
|
||||
XMEMSET(ssl->arrays, 0, sizeof(Arrays));
|
||||
if (ssl->arrays == NULL) {
|
||||
WOLFSSL_MSG("Arrays Memory error");
|
||||
return MEMORY_E;
|
||||
}
|
||||
XMEMSET(ssl->arrays, 0, sizeof(Arrays));
|
||||
|
||||
/* suites */
|
||||
ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap,
|
||||
/* suites */
|
||||
ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap,
|
||||
DYNAMIC_TYPE_SUITES);
|
||||
if (ssl->suites == NULL) {
|
||||
WOLFSSL_MSG("Suites Memory error");
|
||||
return MEMORY_E;
|
||||
if (ssl->suites == NULL) {
|
||||
WOLFSSL_MSG("Suites Memory error");
|
||||
return MEMORY_E;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize SSL with the appropriate fields from it's ctx */
|
||||
/* requires valid arrays and suites */
|
||||
if((ret = SetSSL_CTX(ssl, ctx)) != SSL_SUCCESS)
|
||||
/* requires valid arrays and suites unless writeDup ing */
|
||||
if ((ret = SetSSL_CTX(ssl, ctx, writeDup)) != SSL_SUCCESS)
|
||||
return ret;
|
||||
|
||||
ssl->options.dtls = ssl->version.major == DTLS_MAJOR;
|
||||
|
||||
#ifdef SINGLE_THREADED
|
||||
ssl->rng = ctx->rng; /* CTX may have one, if so use it */
|
||||
#endif
|
||||
|
||||
if (ssl->rng == NULL) {
|
||||
/* RNG */
|
||||
ssl->rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), ssl->heap,DYNAMIC_TYPE_RNG);
|
||||
if (ssl->rng == NULL) {
|
||||
WOLFSSL_MSG("RNG Memory error");
|
||||
return MEMORY_E;
|
||||
}
|
||||
XMEMSET(ssl->rng, 0, sizeof(WC_RNG));
|
||||
ssl->options.weOwnRng = 1;
|
||||
|
||||
/* FIPS RNG API does not accept a heap hint */
|
||||
#ifndef HAVE_FIPS
|
||||
if ( (ret = wc_InitRng_ex(ssl->rng, ssl->heap)) != 0) {
|
||||
WOLFSSL_MSG("RNG Init error");
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
if ( (ret = wc_InitRng(ssl->rng)) != 0) {
|
||||
WOLFSSL_MSG("RNG Init error");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (writeDup) {
|
||||
/* all done */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* hsHashes */
|
||||
ssl->hsHashes = (HS_Hashes*)XMALLOC(sizeof(HS_Hashes), ssl->heap,
|
||||
DYNAMIC_TYPE_HASHES);
|
||||
@@ -3604,34 +3657,6 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SINGLE_THREADED
|
||||
ssl->rng = ctx->rng; /* CTX may have one, if so use it */
|
||||
#endif
|
||||
|
||||
if (ssl->rng == NULL) {
|
||||
/* RNG */
|
||||
ssl->rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), ssl->heap,DYNAMIC_TYPE_RNG);
|
||||
if (ssl->rng == NULL) {
|
||||
WOLFSSL_MSG("RNG Memory error");
|
||||
return MEMORY_E;
|
||||
}
|
||||
XMEMSET(ssl->rng, 0, sizeof(WC_RNG));
|
||||
ssl->options.weOwnRng = 1;
|
||||
|
||||
/* FIPS RNG API does not accept a heap hint */
|
||||
#ifndef HAVE_FIPS
|
||||
if ( (ret = wc_InitRng_ex(ssl->rng, ssl->heap)) != 0) {
|
||||
WOLFSSL_MSG("RNG Init error");
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
if ( (ret = wc_InitRng(ssl->rng)) != 0) {
|
||||
WOLFSSL_MSG("RNG Init error");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
|
||||
if (ssl->options.dtls && ssl->options.side == WOLFSSL_SERVER_END) {
|
||||
ret = wolfSSL_DTLS_SetCookieSecret(ssl, NULL, 0);
|
||||
@@ -3842,6 +3867,11 @@ void SSL_ResourceFree(WOLFSSL* ssl)
|
||||
#ifdef HAVE_EXT_CACHE
|
||||
wolfSSL_SESSION_free(ssl->extSession);
|
||||
#endif
|
||||
#ifdef HAVE_WRITE_DUP
|
||||
if (ssl->dupWrite) {
|
||||
FreeWriteDup(ssl);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_STATIC_MEMORY
|
||||
/* check if using fixed io buffers and free them */
|
||||
@@ -11588,6 +11618,26 @@ int SendAlert(WOLFSSL* ssl, int severity, int type)
|
||||
int outputSz;
|
||||
int dtlsExtra = 0;
|
||||
|
||||
#ifdef HAVE_WRITE_DUP
|
||||
if (ssl->dupWrite && ssl->dupSide == READ_DUP_SIDE) {
|
||||
int notifyErr = 0;
|
||||
|
||||
WOLFSSL_MSG("Read dup side cannot write alerts, notifying sibling");
|
||||
|
||||
if (type == close_notify) {
|
||||
notifyErr = ZERO_RETURN;
|
||||
} else if (severity == alert_fatal) {
|
||||
notifyErr = FATAL_ERROR;
|
||||
}
|
||||
|
||||
if (notifyErr != 0) {
|
||||
return NotifyWriteSide(ssl, notifyErr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* if sendalert is called again for nonblocking */
|
||||
if (ssl->options.sendAlertState != 0) {
|
||||
ret = SendBuffered(ssl);
|
||||
@@ -12024,6 +12074,12 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
|
||||
case DECODE_E:
|
||||
return "Decode handshake message error";
|
||||
|
||||
case WRITE_DUP_READ_E:
|
||||
return "Write dup write side can't read error";
|
||||
|
||||
case WRITE_DUP_WRITE_E:
|
||||
return "Write dup read side can't write error";
|
||||
|
||||
default :
|
||||
return "unknown error number";
|
||||
}
|
||||
|
||||
212
src/ssl.c
212
src/ssl.c
@@ -372,7 +372,7 @@ WOLFSSL* wolfSSL_new(WOLFSSL_CTX* ctx)
|
||||
|
||||
ssl = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), ctx->heap, DYNAMIC_TYPE_SSL);
|
||||
if (ssl)
|
||||
if ( (ret = InitSSL(ssl, ctx)) < 0) {
|
||||
if ( (ret = InitSSL(ssl, ctx, 0)) < 0) {
|
||||
FreeSSL(ssl, ctx->heap);
|
||||
ssl = 0;
|
||||
}
|
||||
@@ -390,6 +390,162 @@ void wolfSSL_free(WOLFSSL* ssl)
|
||||
WOLFSSL_LEAVE("SSL_free", 0);
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_WRITE_DUP
|
||||
|
||||
/*
|
||||
* Release resources around WriteDup object
|
||||
*
|
||||
* ssl WOLFSSL object
|
||||
*
|
||||
* no return, destruction so make best attempt
|
||||
*/
|
||||
void FreeWriteDup(WOLFSSL* ssl)
|
||||
{
|
||||
int doFree = 0;
|
||||
|
||||
WOLFSSL_ENTER("FreeWriteDup");
|
||||
|
||||
if (ssl->dupWrite) {
|
||||
if (wc_LockMutex(&ssl->dupWrite->dupMutex) == 0) {
|
||||
ssl->dupWrite->dupCount--;
|
||||
if (ssl->dupWrite->dupCount == 0) {
|
||||
doFree = 1;
|
||||
} else {
|
||||
WOLFSSL_MSG("WriteDup count not zero, no full free");
|
||||
}
|
||||
wc_UnLockMutex(&ssl->dupWrite->dupMutex);
|
||||
}
|
||||
}
|
||||
|
||||
if (doFree) {
|
||||
WOLFSSL_MSG("Doing WriteDup full free, count to zero");
|
||||
wc_FreeMutex(&ssl->dupWrite->dupMutex);
|
||||
XFREE(ssl->dupWrite, ssl->heap, DYNAMIC_TYPE_WRITEDUP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* duplicate existing ssl members into dup needed for writing
|
||||
*
|
||||
* dup write only WOLFSSL
|
||||
* ssl exisiting WOLFSSL
|
||||
*
|
||||
* 0 on success
|
||||
*/
|
||||
static int DupSSL(WOLFSSL* dup, WOLFSSL* ssl)
|
||||
{
|
||||
/* shared dupWrite setup */
|
||||
ssl->dupWrite = (WriteDup*)XMALLOC(sizeof(WriteDup), ssl->heap,
|
||||
DYNAMIC_TYPE_WRITEDUP);
|
||||
if (ssl->dupWrite == NULL) {
|
||||
return MEMORY_E;
|
||||
}
|
||||
XMEMSET(ssl->dupWrite, 0, sizeof(WriteDup));
|
||||
|
||||
if (wc_InitMutex(&ssl->dupWrite->dupMutex) != 0) {
|
||||
XFREE(ssl->dupWrite, ssl->heap, DYNAMIC_TYPE_WRITEDUP);
|
||||
ssl->dupWrite = NULL;
|
||||
return BAD_MUTEX_E;
|
||||
}
|
||||
ssl->dupWrite->dupCount = 2; /* both sides have a count to start */
|
||||
dup->dupWrite = ssl->dupWrite ; /* each side uses */
|
||||
|
||||
/* copy write parts over to dup writer */
|
||||
XMEMCPY(&dup->specs, &ssl->specs, sizeof(CipherSpecs));
|
||||
XMEMCPY(&dup->options, &ssl->options, sizeof(Options));
|
||||
XMEMCPY(&dup->keys, &ssl->keys, sizeof(Keys));
|
||||
XMEMCPY(&dup->encrypt, &ssl->encrypt, sizeof(Ciphers));
|
||||
/* dup side now owns encrypt/write ciphers */
|
||||
XMEMSET(&ssl->encrypt, 0, sizeof(Ciphers));
|
||||
|
||||
dup->IOCB_WriteCtx = ssl->IOCB_WriteCtx;
|
||||
dup->wfd = ssl->wfd;
|
||||
dup->wflags = ssl->wflags;
|
||||
dup->hmac = ssl->hmac;
|
||||
#ifdef HAVE_TRUNCATED_HMAC
|
||||
dup->truncated_hmac = ssl->truncated_hmac;
|
||||
#endif
|
||||
|
||||
/* unique side dup setup */
|
||||
dup->dupSide = WRITE_DUP_SIDE;
|
||||
ssl->dupSide = READ_DUP_SIDE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* duplicate a WOLFSSL object post handshake for writing only
|
||||
* turn exisitng object into read only. Allows concurrent access from two
|
||||
* different threads.
|
||||
*
|
||||
* ssl exisiting WOLFSSL object
|
||||
*
|
||||
* return dup'd WOLFSSL object on success
|
||||
*/
|
||||
WOLFSSL* wolfSSL_write_dup(WOLFSSL* ssl)
|
||||
{
|
||||
WOLFSSL* dup = NULL;
|
||||
int ret = 0;
|
||||
|
||||
(void)ret;
|
||||
WOLFSSL_ENTER("wolfSSL_write_dup");
|
||||
|
||||
if (ssl == NULL) {
|
||||
return ssl;
|
||||
}
|
||||
|
||||
if (ssl->options.handShakeDone == 0) {
|
||||
WOLFSSL_MSG("wolfSSL_write_dup called before handshake complete");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dup = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), ssl->ctx->heap, DYNAMIC_TYPE_SSL);
|
||||
if (dup) {
|
||||
if ( (ret = InitSSL(dup, ssl->ctx, 1)) < 0) {
|
||||
FreeSSL(dup, ssl->ctx->heap);
|
||||
dup = NULL;
|
||||
} else if ( (ret = DupSSL(dup, ssl) < 0)) {
|
||||
FreeSSL(dup, ssl->ctx->heap);
|
||||
dup = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
WOLFSSL_LEAVE("wolfSSL_write_dup", ret);
|
||||
|
||||
return dup;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Notify write dup side of fatal error or close notify
|
||||
*
|
||||
* ssl WOLFSSL object
|
||||
* err Notify err
|
||||
*
|
||||
* 0 on success
|
||||
*/
|
||||
int NotifyWriteSide(WOLFSSL* ssl, int err)
|
||||
{
|
||||
int ret;
|
||||
|
||||
WOLFSSL_ENTER("NotifyWriteSide");
|
||||
|
||||
ret = wc_LockMutex(&ssl->dupWrite->dupMutex);
|
||||
if (ret == 0) {
|
||||
ssl->dupWrite->dupErr = err;
|
||||
ret = wc_UnLockMutex(&ssl->dupWrite->dupMutex);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#endif /* HAVE_WRITE_DUP */
|
||||
|
||||
|
||||
#ifdef HAVE_POLY1305
|
||||
/* set if to use old poly 1 for yes 0 to use new poly */
|
||||
int wolfSSL_use_old_poly(WOLFSSL* ssl, int value)
|
||||
@@ -1114,6 +1270,36 @@ int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz)
|
||||
if (ssl == NULL || data == NULL || sz < 0)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
#ifdef HAVE_WRITE_DUP
|
||||
{ /* local variable scope */
|
||||
int dupErr = 0; /* local copy */
|
||||
|
||||
ret = 0;
|
||||
|
||||
if (ssl->dupWrite && ssl->dupSide == READ_DUP_SIDE) {
|
||||
WOLFSSL_MSG("Read dup side cannot write");
|
||||
return WRITE_DUP_WRITE_E;
|
||||
}
|
||||
if (ssl->dupWrite) {
|
||||
if (wc_LockMutex(&ssl->dupWrite->dupMutex) != 0) {
|
||||
return BAD_MUTEX_E;
|
||||
}
|
||||
dupErr = ssl->dupWrite->dupErr;
|
||||
ret = wc_UnLockMutex(&ssl->dupWrite->dupMutex);
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
ssl->error = ret; /* high priority fatal error */
|
||||
return SSL_FATAL_ERROR;
|
||||
}
|
||||
if (dupErr != 0) {
|
||||
WOLFSSL_MSG("Write dup error from other side");
|
||||
ssl->error = dupErr;
|
||||
return SSL_FATAL_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
errno = 0;
|
||||
#endif
|
||||
@@ -1138,6 +1324,13 @@ static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek)
|
||||
if (ssl == NULL || data == NULL || sz < 0)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
#ifdef HAVE_WRITE_DUP
|
||||
if (ssl->dupWrite && ssl->dupSide == WRITE_DUP_SIDE) {
|
||||
WOLFSSL_MSG("Write dup side cannot read");
|
||||
return WRITE_DUP_READ_E;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
errno = 0;
|
||||
#endif
|
||||
@@ -1158,6 +1351,21 @@ static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek)
|
||||
#endif
|
||||
ret = ReceiveData(ssl, (byte*)data, sz, peek);
|
||||
|
||||
#ifdef HAVE_WRITE_DUP
|
||||
if (ssl->dupWrite) {
|
||||
if (ssl->error != 0 && ssl->error != WANT_READ &&
|
||||
ssl->error != WC_PENDING_E) {
|
||||
int notifyErr;
|
||||
|
||||
WOLFSSL_MSG("Notifying write side of fatal read error");
|
||||
notifyErr = NotifyWriteSide(ssl, ssl->error);
|
||||
if (notifyErr < 0) {
|
||||
ret = ssl->error = notifyErr;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
WOLFSSL_LEAVE("wolfSSL_read_internal()", ret);
|
||||
|
||||
if (ret < 0)
|
||||
@@ -22603,7 +22811,7 @@ const char * wolfSSL_get_servername(WOLFSSL* ssl, byte type)
|
||||
|
||||
WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
|
||||
{
|
||||
if (ssl && ctx && SetSSL_CTX(ssl, ctx) == SSL_SUCCESS)
|
||||
if (ssl && ctx && SetSSL_CTX(ssl, ctx, 0) == SSL_SUCCESS)
|
||||
return ssl->ctx;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user