forked from wolfSSL/wolfssl
Merge pull request #5717 from icing/sni-alpn-order
Changing ALPN selection to a deterministic point in the handshake.
This commit is contained in:
@ -6829,7 +6829,8 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
|
||||
ssl->max_fragment = MAX_RECORD_SIZE;
|
||||
#endif
|
||||
#ifdef HAVE_ALPN
|
||||
ssl->alpn_client_list = NULL;
|
||||
ssl->alpn_peer_requested = NULL;
|
||||
ssl->alpn_peer_requested_length = 0;
|
||||
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
|
||||
ssl->alpnSelect = ctx->alpnSelect;
|
||||
ssl->alpnSelectArg = ctx->alpnSelectArg;
|
||||
@ -7659,9 +7660,10 @@ void SSL_ResourceFree(WOLFSSL* ssl)
|
||||
TLSX_FreeAll(ssl->extensions, ssl->heap);
|
||||
#endif /* !NO_TLS */
|
||||
#ifdef HAVE_ALPN
|
||||
if (ssl->alpn_client_list != NULL) {
|
||||
XFREE(ssl->alpn_client_list, ssl->heap, DYNAMIC_TYPE_ALPN);
|
||||
ssl->alpn_client_list = NULL;
|
||||
if (ssl->alpn_peer_requested != NULL) {
|
||||
XFREE(ssl->alpn_peer_requested, ssl->heap, DYNAMIC_TYPE_ALPN);
|
||||
ssl->alpn_peer_requested = NULL;
|
||||
ssl->alpn_peer_requested_length = 0;
|
||||
}
|
||||
#endif
|
||||
#endif /* HAVE_TLS_EXTENSIONS */
|
||||
@ -33305,6 +33307,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||
if((ret=SNI_Callback(ssl)))
|
||||
goto out;
|
||||
#endif
|
||||
#ifdef HAVE_ALPN
|
||||
if((ret=ALPN_Select(ssl)))
|
||||
goto out;
|
||||
#endif
|
||||
|
||||
i += totalExtSz;
|
||||
#else
|
||||
|
35
src/ssl.c
35
src/ssl.c
@ -3108,22 +3108,37 @@ int wolfSSL_ALPN_GetProtocol(WOLFSSL* ssl, char **protocol_name, word16 *size)
|
||||
|
||||
int wolfSSL_ALPN_GetPeerProtocol(WOLFSSL* ssl, char **list, word16 *listSz)
|
||||
{
|
||||
if (list == NULL || listSz == NULL)
|
||||
int i, len;
|
||||
char *p;
|
||||
byte *s;
|
||||
|
||||
if (ssl == NULL || list == NULL || listSz == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (ssl->alpn_client_list == NULL)
|
||||
if (ssl->alpn_peer_requested == NULL
|
||||
|| ssl->alpn_peer_requested_length == 0)
|
||||
return BUFFER_ERROR;
|
||||
|
||||
*listSz = (word16)XSTRLEN(ssl->alpn_client_list);
|
||||
if (*listSz == 0)
|
||||
return BUFFER_ERROR;
|
||||
|
||||
*list = (char *)XMALLOC((*listSz)+1, ssl->heap, DYNAMIC_TYPE_TLSX);
|
||||
if (*list == NULL)
|
||||
/* ssl->alpn_peer_requested are the original bytes sent in a ClientHello,
|
||||
* formatted as (len-byte chars+)+. To turn n protocols into a
|
||||
* comma-separated C string, one needs (n-1) commas and a final 0 byte
|
||||
* which has the same length as the original.
|
||||
* The returned length is the strlen() of the C string, so -1 of that. */
|
||||
*listSz = ssl->alpn_peer_requested_length-1;
|
||||
*list = p = (char *)XMALLOC(ssl->alpn_peer_requested_length, ssl->heap,
|
||||
DYNAMIC_TYPE_TLSX);
|
||||
if (p == NULL)
|
||||
return MEMORY_ERROR;
|
||||
|
||||
XSTRNCPY(*list, ssl->alpn_client_list, (*listSz)+1);
|
||||
(*list)[*listSz] = 0;
|
||||
for (i = 0, s = ssl->alpn_peer_requested, len = 0;
|
||||
i < ssl->alpn_peer_requested_length;
|
||||
p += len, i += len) {
|
||||
if (i)
|
||||
*p++ = ',';
|
||||
len = s[i++];
|
||||
XSTRNCPY(p, (char *)(s + i), len);
|
||||
}
|
||||
*p = 0;
|
||||
|
||||
return WOLFSSL_SUCCESS;
|
||||
}
|
||||
|
242
src/tls.c
242
src/tls.c
@ -1579,16 +1579,116 @@ static int TLSX_SetALPN(TLSX** extensions, const void* data, word16 size,
|
||||
return WOLFSSL_SUCCESS;
|
||||
}
|
||||
|
||||
static int ALPN_find_match(WOLFSSL *ssl, TLSX **pextension,
|
||||
const byte **psel, byte *psel_len,
|
||||
const byte *alpn_val, word16 alpn_val_len)
|
||||
{
|
||||
TLSX *extension;
|
||||
ALPN *alpn, *list;
|
||||
const byte *sel = NULL, *s;
|
||||
byte sel_len = 0, wlen;
|
||||
|
||||
extension = TLSX_Find(ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL);
|
||||
if (extension == NULL)
|
||||
extension = TLSX_Find(ssl->ctx->extensions,
|
||||
TLSX_APPLICATION_LAYER_PROTOCOL);
|
||||
|
||||
/* No ALPN configured here */
|
||||
if (extension == NULL || extension->data == NULL)
|
||||
return 0;
|
||||
|
||||
list = (ALPN*)extension->data;
|
||||
for (s = alpn_val, wlen = 0;
|
||||
(s - alpn_val) < alpn_val_len;
|
||||
s += wlen) {
|
||||
wlen = *s++; /* bounds already checked on save */
|
||||
alpn = TLSX_ALPN_Find(list, (char*)s, wlen);
|
||||
if (alpn != NULL) {
|
||||
WOLFSSL_MSG("ALPN protocol match");
|
||||
sel = s,
|
||||
sel_len = wlen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sel == NULL) {
|
||||
WOLFSSL_MSG("No ALPN protocol match");
|
||||
|
||||
/* do nothing if no protocol match between client and server and option
|
||||
is set to continue (like OpenSSL) */
|
||||
if (list->options & WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) {
|
||||
WOLFSSL_MSG("Continue on mismatch");
|
||||
}
|
||||
else {
|
||||
SendAlert(ssl, alert_fatal, no_application_protocol);
|
||||
WOLFSSL_ERROR_VERBOSE(UNKNOWN_ALPN_PROTOCOL_NAME_E);
|
||||
return UNKNOWN_ALPN_PROTOCOL_NAME_E;
|
||||
}
|
||||
}
|
||||
|
||||
*pextension = extension;
|
||||
*psel = sel;
|
||||
*psel_len = sel_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ALPN_Select(WOLFSSL *ssl)
|
||||
{
|
||||
TLSX *extension;
|
||||
const byte *sel = NULL;
|
||||
byte sel_len = 0;
|
||||
int r = 0;
|
||||
|
||||
WOLFSSL_ENTER("ALPN_Select");
|
||||
if (ssl->alpn_peer_requested == NULL)
|
||||
return 0;
|
||||
|
||||
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
|
||||
if (ssl->alpnSelect != NULL && ssl->options.side == WOLFSSL_SERVER_END) {
|
||||
if (ssl->alpnSelect(ssl, &sel, &sel_len, ssl->alpn_peer_requested,
|
||||
ssl->alpn_peer_requested_length,
|
||||
ssl->alpnSelectArg) == 0) {
|
||||
WOLFSSL_MSG_EX("ALPN protocol match");
|
||||
}
|
||||
else {
|
||||
sel = NULL;
|
||||
sel_len = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sel == NULL) {
|
||||
r = ALPN_find_match(ssl, &extension, &sel, &sel_len,
|
||||
ssl->alpn_peer_requested,
|
||||
ssl->alpn_peer_requested_length);
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (sel != NULL) {
|
||||
/* set the matching negotiated protocol */
|
||||
r = TLSX_SetALPN(&ssl->extensions, sel, sel_len, ssl->heap);
|
||||
if (r != WOLFSSL_SUCCESS) {
|
||||
WOLFSSL_MSG("TLSX_SetALPN failed");
|
||||
return BUFFER_ERROR;
|
||||
}
|
||||
/* reply to ALPN extension sent from peer */
|
||||
#ifndef NO_WOLFSSL_SERVER
|
||||
TLSX_SetResponse(ssl, TLSX_APPLICATION_LAYER_PROTOCOL);
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Parses a buffer of ALPN extensions and set the first one matching
|
||||
* client and server requirements */
|
||||
static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, const byte *input, word16 length,
|
||||
byte isRequest)
|
||||
{
|
||||
word16 size = 0, offset = 0, idx = 0;
|
||||
word16 size = 0, offset = 0, wlen;
|
||||
int r = BUFFER_ERROR;
|
||||
byte match = 0;
|
||||
TLSX *extension;
|
||||
ALPN *alpn = NULL, *list;
|
||||
const byte *s;
|
||||
|
||||
if (OPAQUE16_LEN > length)
|
||||
return BUFFER_ERROR;
|
||||
@ -1596,116 +1696,56 @@ static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, const byte *input, word16 length,
|
||||
ato16(input, &size);
|
||||
offset += OPAQUE16_LEN;
|
||||
|
||||
if (size == 0)
|
||||
return BUFFER_ERROR;
|
||||
|
||||
extension = TLSX_Find(ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL);
|
||||
if (extension == NULL)
|
||||
extension = TLSX_Find(ssl->ctx->extensions,
|
||||
TLSX_APPLICATION_LAYER_PROTOCOL);
|
||||
|
||||
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
|
||||
if (ssl->alpnSelect != NULL && ssl->options.side == WOLFSSL_SERVER_END) {
|
||||
const byte* out;
|
||||
unsigned char outLen;
|
||||
|
||||
if (ssl->alpnSelect(ssl, &out, &outLen, input + offset, size,
|
||||
ssl->alpnSelectArg) == 0) {
|
||||
WOLFSSL_MSG("ALPN protocol match");
|
||||
/* clears out all current ALPN extensions set */
|
||||
TLSX_Remove(&ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL, ssl->heap);
|
||||
extension = NULL;
|
||||
if (TLSX_UseALPN(&ssl->extensions, (char*)out, outLen, 0, ssl->heap)
|
||||
== WOLFSSL_SUCCESS) {
|
||||
extension = TLSX_Find(ssl->extensions,
|
||||
TLSX_APPLICATION_LAYER_PROTOCOL);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (extension == NULL || extension->data == NULL) {
|
||||
return isRequest ? 0
|
||||
: TLSX_HandleUnsupportedExtension(ssl);
|
||||
}
|
||||
|
||||
/* validating alpn list length */
|
||||
if (length != OPAQUE16_LEN + size)
|
||||
if (size == 0 || length != OPAQUE16_LEN + size)
|
||||
return BUFFER_ERROR;
|
||||
|
||||
list = (ALPN*)extension->data;
|
||||
|
||||
/* keep the list sent by client */
|
||||
if (isRequest) {
|
||||
if (ssl->alpn_client_list != NULL)
|
||||
XFREE(ssl->alpn_client_list, ssl->heap, DYNAMIC_TYPE_ALPN);
|
||||
|
||||
ssl->alpn_client_list = (char *)XMALLOC(size, ssl->heap,
|
||||
DYNAMIC_TYPE_ALPN);
|
||||
if (ssl->alpn_client_list == NULL)
|
||||
return MEMORY_ERROR;
|
||||
/* validating length of entries before accepting */
|
||||
for (s = input + offset, wlen = 0; (s - input) < size; s += wlen) {
|
||||
wlen = *s++;
|
||||
if (wlen == 0 || (s + wlen - input) > length)
|
||||
return BUFFER_ERROR;
|
||||
}
|
||||
|
||||
for (size = 0; offset < length; offset += size) {
|
||||
|
||||
size = input[offset++];
|
||||
if (offset + size > length || size == 0)
|
||||
return BUFFER_ERROR;
|
||||
|
||||
if (isRequest) {
|
||||
XMEMCPY(ssl->alpn_client_list+idx, (char*)input + offset, size);
|
||||
idx += size;
|
||||
ssl->alpn_client_list[idx++] = ',';
|
||||
if (isRequest) {
|
||||
/* keep the list sent by peer, if this is from a request. We
|
||||
* use it later in ALPN_Select() for evaluation. */
|
||||
if (ssl->alpn_peer_requested != NULL) {
|
||||
XFREE(ssl->alpn_peer_requested, ssl->heap, DYNAMIC_TYPE_ALPN);
|
||||
ssl->alpn_peer_requested_length = 0;
|
||||
}
|
||||
ssl->alpn_peer_requested = (byte *)XMALLOC(size, ssl->heap,
|
||||
DYNAMIC_TYPE_ALPN);
|
||||
if (ssl->alpn_peer_requested == NULL) {
|
||||
return MEMORY_ERROR;
|
||||
}
|
||||
ssl->alpn_peer_requested_length = size;
|
||||
XMEMCPY(ssl->alpn_peer_requested, (char*)input + offset, size);
|
||||
}
|
||||
else {
|
||||
/* a response, we should find the value in our config */
|
||||
const byte *sel = NULL;
|
||||
byte sel_len = 0;
|
||||
|
||||
if (!match) {
|
||||
alpn = TLSX_ALPN_Find(list, (char*)input + offset, size);
|
||||
if (alpn != NULL) {
|
||||
WOLFSSL_MSG("ALPN protocol match");
|
||||
match = 1;
|
||||
r = ALPN_find_match(ssl, &extension, &sel, &sel_len, input + offset, size);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
/* skip reading other values if not required */
|
||||
if (!isRequest)
|
||||
break;
|
||||
if (sel != NULL) {
|
||||
/* set the matching negotiated protocol */
|
||||
r = TLSX_SetALPN(&ssl->extensions, sel, sel_len, ssl->heap);
|
||||
if (r != WOLFSSL_SUCCESS) {
|
||||
WOLFSSL_MSG("TLSX_SetALPN failed");
|
||||
return BUFFER_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isRequest)
|
||||
ssl->alpn_client_list[idx-1] = 0;
|
||||
|
||||
if (!match) {
|
||||
WOLFSSL_MSG("No ALPN protocol match");
|
||||
|
||||
/* do nothing if no protocol match between client and server and option
|
||||
is set to continue (like OpenSSL) */
|
||||
if (list->options & WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) {
|
||||
WOLFSSL_MSG("Continue on mismatch");
|
||||
return 0;
|
||||
/* If we had nothing configured, the response is unexpected */
|
||||
else if (extension == NULL) {
|
||||
r = TLSX_HandleUnsupportedExtension(ssl);
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
SendAlert(ssl, alert_fatal, no_application_protocol);
|
||||
WOLFSSL_ERROR_VERBOSE(UNKNOWN_ALPN_PROTOCOL_NAME_E);
|
||||
return UNKNOWN_ALPN_PROTOCOL_NAME_E;
|
||||
}
|
||||
|
||||
/* set the matching negotiated protocol */
|
||||
r = TLSX_SetALPN(&ssl->extensions,
|
||||
alpn->protocol_name,
|
||||
(word16)XSTRLEN(alpn->protocol_name),
|
||||
ssl->heap);
|
||||
if (r != WOLFSSL_SUCCESS) {
|
||||
WOLFSSL_MSG("TLSX_SetALPN failed");
|
||||
return BUFFER_ERROR;
|
||||
}
|
||||
|
||||
/* reply to ALPN extension sent from client */
|
||||
if (isRequest) {
|
||||
#ifndef NO_WOLFSSL_SERVER
|
||||
TLSX_SetResponse(ssl, TLSX_APPLICATION_LAYER_PROTOCOL);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -5863,7 +5863,7 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||
|
||||
#ifdef HAVE_SNI
|
||||
if ((ret = SNI_Callback(ssl)) != 0)
|
||||
return ret;
|
||||
goto exit_dch;
|
||||
ssl->options.side = WOLFSSL_SERVER_END;
|
||||
#endif
|
||||
|
||||
@ -5950,6 +5950,12 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_ALPN
|
||||
/* With PSK and all other things validated, it's time to
|
||||
* select the ALPN protocol, if so requested */
|
||||
if ((ret = ALPN_Select(ssl)) != 0)
|
||||
goto exit_dch;
|
||||
#endif
|
||||
/* Advance state and proceed */
|
||||
ssl->options.asyncState = TLS_ASYNC_BUILD;
|
||||
} /* case TLS_ASYNC_BEGIN */
|
||||
|
95
tests/quic.c
95
tests/quic.c
@ -1174,6 +1174,98 @@ static int test_quic_server_hello(int verbose) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* This has gotten a bit out of hand. */
|
||||
#if (defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && \
|
||||
(defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
|
||||
defined(HAVE_LIGHTY) || defined(WOLFSSL_HAPROXY) || \
|
||||
defined(WOLFSSL_OPENSSH) || defined(HAVE_SBLIM_SFCB)))) \
|
||||
&& defined(HAVE_ALPN) && defined(HAVE_SNI)
|
||||
#define REALLY_HAVE_ALPN_AND_SNI
|
||||
#else
|
||||
#undef REALLY_HAVE_ALPN_AND_SNI
|
||||
#endif
|
||||
|
||||
#ifdef REALLY_HAVE_ALPN_AND_SNI
|
||||
static int inspect_SNI(WOLFSSL *ssl, int *ad, void *baton)
|
||||
{
|
||||
char *stripe = baton;
|
||||
|
||||
(void)ssl;
|
||||
*ad = 0;
|
||||
strcat(stripe, "S");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int select_ALPN(WOLFSSL *ssl,
|
||||
const unsigned char **out,
|
||||
unsigned char *outlen,
|
||||
const unsigned char *in,
|
||||
unsigned int inlen,
|
||||
void *baton)
|
||||
{
|
||||
char *stripe = baton;
|
||||
|
||||
(void)ssl;
|
||||
(void)inlen;
|
||||
/* just select the first */
|
||||
*out = in + 1;
|
||||
*outlen = in[0];
|
||||
strcat(stripe, "A");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_quic_alpn(int verbose) {
|
||||
WOLFSSL_CTX *ctx_c, *ctx_s;
|
||||
int ret = 0;
|
||||
QuicTestContext tclient, tserver;
|
||||
QuicConversation conv;
|
||||
char stripe[256];
|
||||
unsigned char alpn_protos[256];
|
||||
|
||||
AssertNotNull(ctx_c = wolfSSL_CTX_new(wolfTLSv1_3_client_method()));
|
||||
AssertNotNull(ctx_s = wolfSSL_CTX_new(wolfTLSv1_3_server_method()));
|
||||
AssertTrue(wolfSSL_CTX_use_certificate_file(ctx_s, svrCertFile, WOLFSSL_FILETYPE_PEM));
|
||||
AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx_s, svrKeyFile, WOLFSSL_FILETYPE_PEM));
|
||||
|
||||
stripe[0] = '\0';
|
||||
wolfSSL_CTX_set_servername_callback(ctx_s, inspect_SNI);
|
||||
wolfSSL_CTX_set_servername_arg(ctx_s, stripe);
|
||||
wolfSSL_CTX_set_alpn_select_cb(ctx_s, select_ALPN, stripe);
|
||||
|
||||
/* setup ssls */
|
||||
QuicTestContext_init(&tclient, ctx_c, "client", verbose);
|
||||
QuicTestContext_init(&tserver, ctx_s, "server", verbose);
|
||||
|
||||
/* set SNI and ALPN callbacks on server side,
|
||||
* provide values on client side */
|
||||
wolfSSL_UseSNI(tclient.ssl, WOLFSSL_SNI_HOST_NAME,
|
||||
"wolfssl.com", sizeof("wolfssl.com")-1);
|
||||
/* connect */
|
||||
QuicConversation_init(&conv, &tclient, &tserver);
|
||||
|
||||
strcpy((char*)(alpn_protos + 1), "test");
|
||||
alpn_protos[0] = 4;
|
||||
wolfSSL_set_alpn_protos(tclient.ssl, alpn_protos, 5);
|
||||
|
||||
QuicConversation_do(&conv);
|
||||
AssertIntEQ(tclient.output.len, 0);
|
||||
AssertIntEQ(tserver.output.len, 0);
|
||||
|
||||
/* SNI callback needs to be called before ALPN callback */
|
||||
AssertStrEQ(stripe, "SA");
|
||||
|
||||
QuicTestContext_free(&tclient);
|
||||
QuicTestContext_free(&tserver);
|
||||
|
||||
wolfSSL_CTX_free(ctx_c);
|
||||
wolfSSL_CTX_free(ctx_s);
|
||||
printf(" test_quic_alpn: %s\n", (ret == 0)? passed : failed);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* REALLY_HAVE_ALPN_AND_SNI */
|
||||
|
||||
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
|
||||
static int test_quic_key_share(int verbose) {
|
||||
@ -1536,6 +1628,9 @@ int QuicTest(void)
|
||||
if ((ret = test_quic_crypt()) != 0) goto leave;
|
||||
if ((ret = test_quic_client_hello(verbose)) != 0) goto leave;
|
||||
if ((ret = test_quic_server_hello(verbose)) != 0) goto leave;
|
||||
#ifdef REALLY_HAVE_ALPN_AND_SNI
|
||||
if ((ret = test_quic_alpn(verbose)) != 0) goto leave;
|
||||
#endif /* REALLY_HAVE_ALPN_AND_SNI */
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
if ((ret = test_quic_key_share(verbose)) != 0) goto leave;
|
||||
if ((ret = test_quic_resumption(verbose)) != 0) goto leave;
|
||||
|
@ -1975,6 +1975,10 @@ WOLFSSL_LOCAL int SNI_Callback(WOLFSSL* ssl);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ALPN
|
||||
WOLFSSL_LOCAL int ALPN_Select(WOLFSSL* ssl);
|
||||
#endif
|
||||
|
||||
WOLFSSL_LOCAL int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input,
|
||||
word16 sz); /* needed by sniffer */
|
||||
|
||||
@ -5084,7 +5088,9 @@ struct WOLFSSL {
|
||||
SecureRenegotiation* secure_renegotiation; /* valid pointer indicates */
|
||||
#endif /* user turned on */
|
||||
#ifdef HAVE_ALPN
|
||||
char* alpn_client_list; /* keep the client's list */
|
||||
byte *alpn_peer_requested; /* the ALPN bytes requested by peer, sequence
|
||||
* of length byte + chars */
|
||||
word16 alpn_peer_requested_length; /* number of bytes total */
|
||||
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \
|
||||
defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_QUIC)
|
||||
CallbackALPNSelect alpnSelect;
|
||||
|
Reference in New Issue
Block a user