mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-07-31 19:24:42 +02:00
ALPN : add option to continue in case of client/server protocol mismatch (like OpenSSL)
This commit is contained in:
@@ -194,7 +194,7 @@ static void Usage(void)
|
|||||||
printf("-C Disable CRL\n");
|
printf("-C Disable CRL\n");
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_ALPN
|
#ifdef HAVE_ALPN
|
||||||
printf("-n <str> Application-Layer Protocole Name\n");
|
printf("-n <str> Application-Layer Protocole Name ({C,F}:<list>)\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,6 +247,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
|||||||
int overrideDateErrors = 0;
|
int overrideDateErrors = 0;
|
||||||
int minDhKeyBits = DEFAULT_MIN_DHKEY_BITS;
|
int minDhKeyBits = DEFAULT_MIN_DHKEY_BITS;
|
||||||
char* alpnList = NULL;
|
char* alpnList = NULL;
|
||||||
|
unsigned char alpn_opt = 0;
|
||||||
char* cipherList = NULL;
|
char* cipherList = NULL;
|
||||||
const char* verifyCert = caCert;
|
const char* verifyCert = caCert;
|
||||||
const char* ourCert = cliCert;
|
const char* ourCert = cliCert;
|
||||||
@@ -294,6 +295,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
|||||||
(void)disableCRL;
|
(void)disableCRL;
|
||||||
(void)minDhKeyBits;
|
(void)minDhKeyBits;
|
||||||
(void)alpnList;
|
(void)alpnList;
|
||||||
|
(void)alpn_opt;
|
||||||
|
|
||||||
StackTrap();
|
StackTrap();
|
||||||
|
|
||||||
@@ -500,6 +502,18 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
|||||||
case 'n' :
|
case 'n' :
|
||||||
#ifdef HAVE_ALPN
|
#ifdef HAVE_ALPN
|
||||||
alpnList = myoptarg;
|
alpnList = myoptarg;
|
||||||
|
|
||||||
|
if (alpnList[0] == 'C' && alpnList[1] == ':')
|
||||||
|
alpn_opt = WOLFSSL_ALPN_CONTINUE_ON_MISMATCH;
|
||||||
|
else if (alpnList[0] == 'F' && alpnList[1] == ':')
|
||||||
|
alpn_opt = WOLFSSL_ALPN_FAILED_ON_MISMATCH;
|
||||||
|
else {
|
||||||
|
Usage();
|
||||||
|
exit(MY_EX_USAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
alpnList += 2;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -812,7 +826,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
|||||||
#ifdef HAVE_ALPN
|
#ifdef HAVE_ALPN
|
||||||
if (alpnList != NULL) {
|
if (alpnList != NULL) {
|
||||||
printf("ALPN accepted protocols list : %s\n", alpnList);
|
printf("ALPN accepted protocols list : %s\n", alpnList);
|
||||||
wolfSSL_UseALPN(ssl, alpnList, (word32)XSTRLEN(alpnList));
|
wolfSSL_UseALPN(ssl, alpnList, (word32)XSTRLEN(alpnList), alpn_opt);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -885,16 +899,19 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
|||||||
showPeer(ssl);
|
showPeer(ssl);
|
||||||
|
|
||||||
#ifdef HAVE_ALPN
|
#ifdef HAVE_ALPN
|
||||||
{
|
if (alpnList != NULL) {
|
||||||
|
int err;
|
||||||
char *protocol_name = NULL;
|
char *protocol_name = NULL;
|
||||||
word16 protocol_nameSz = 0;
|
word16 protocol_nameSz = 0;
|
||||||
|
|
||||||
if (wolfSSL_ALPN_GetProtocol(ssl, &protocol_name,
|
err = wolfSSL_ALPN_GetProtocol(ssl, &protocol_name, &protocol_nameSz);
|
||||||
&protocol_nameSz) != SSL_SUCCESS)
|
if (err == SSL_SUCCESS)
|
||||||
printf("Getting ALPN protocol name failed\n");
|
|
||||||
else
|
|
||||||
printf("Received ALPN protocol : %s (%d)\n",
|
printf("Received ALPN protocol : %s (%d)\n",
|
||||||
protocol_name, protocol_nameSz);
|
protocol_name, protocol_nameSz);
|
||||||
|
else if (err == SSL_ALPN_NOT_FOUND)
|
||||||
|
printf("Not received ALPN response (no match with server)\n");
|
||||||
|
else
|
||||||
|
printf("Getting ALPN protocol name failed\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -988,7 +1005,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
|||||||
#ifdef HAVE_ALPN
|
#ifdef HAVE_ALPN
|
||||||
if (alpnList != NULL) {
|
if (alpnList != NULL) {
|
||||||
printf("ALPN accepted protocols list : %s\n", alpnList);
|
printf("ALPN accepted protocols list : %s\n", alpnList);
|
||||||
wolfSSL_UseALPN(sslResume, alpnList, (word32)XSTRLEN(alpnList));
|
wolfSSL_UseALPN(sslResume, alpnList, (word32)XSTRLEN(alpnList),
|
||||||
|
alpn_opt);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_SECURE_RENEGOTIATION
|
#ifdef HAVE_SECURE_RENEGOTIATION
|
||||||
@@ -1024,17 +1042,21 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
|||||||
printf("didn't reuse session id!!!\n");
|
printf("didn't reuse session id!!!\n");
|
||||||
|
|
||||||
#ifdef HAVE_ALPN
|
#ifdef HAVE_ALPN
|
||||||
{
|
if (alpnList != NULL) {
|
||||||
|
int err;
|
||||||
char *protocol_name = NULL;
|
char *protocol_name = NULL;
|
||||||
word16 protocol_nameSz = 0;
|
word16 protocol_nameSz = 0;
|
||||||
|
|
||||||
printf("Sending ALPN accepted list : %s\n", alpnList);
|
printf("Sending ALPN accepted list : %s\n", alpnList);
|
||||||
if (wolfSSL_ALPN_GetProtocol(sslResume, &protocol_name,
|
err = wolfSSL_ALPN_GetProtocol(sslResume, &protocol_name,
|
||||||
&protocol_nameSz) != SSL_SUCCESS)
|
&protocol_nameSz);
|
||||||
printf("Getting ALPN protocol name failed\n");
|
if (err == SSL_SUCCESS)
|
||||||
else
|
|
||||||
printf("Received ALPN protocol : %s (%d)\n",
|
printf("Received ALPN protocol : %s (%d)\n",
|
||||||
protocol_name, protocol_nameSz);
|
protocol_name, protocol_nameSz);
|
||||||
|
else if (err == SSL_ALPN_NOT_FOUND)
|
||||||
|
printf("Not received ALPN response (no match with server)\n");
|
||||||
|
else
|
||||||
|
printf("Getting ALPN protocol name failed\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (wolfSSL_write(sslResume, resumeMsg, resumeSz) != resumeSz)
|
if (wolfSSL_write(sslResume, resumeMsg, resumeSz) != resumeSz)
|
||||||
|
@@ -162,7 +162,7 @@ static void Usage(void)
|
|||||||
printf("-I Do not send PSK identity hint\n");
|
printf("-I Do not send PSK identity hint\n");
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_ALPN
|
#ifdef HAVE_ALPN
|
||||||
printf("-L <str> Application-Layer Protocole Name\n");
|
printf("-L <str> Application-Layer Protocole Name ({C,F}:<list>)\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,6 +198,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
|
|||||||
int minDhKeyBits = DEFAULT_MIN_DHKEY_BITS;
|
int minDhKeyBits = DEFAULT_MIN_DHKEY_BITS;
|
||||||
int ret;
|
int ret;
|
||||||
char* alpnList = NULL;
|
char* alpnList = NULL;
|
||||||
|
unsigned char alpn_opt = 0;
|
||||||
char* cipherList = NULL;
|
char* cipherList = NULL;
|
||||||
const char* verifyCert = cliCert;
|
const char* verifyCert = cliCert;
|
||||||
const char* ourCert = svrCert;
|
const char* ourCert = svrCert;
|
||||||
@@ -237,6 +238,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
|
|||||||
(void)doCliCertCheck;
|
(void)doCliCertCheck;
|
||||||
(void)minDhKeyBits;
|
(void)minDhKeyBits;
|
||||||
(void)alpnList;
|
(void)alpnList;
|
||||||
|
(void)alpn_opt;
|
||||||
|
|
||||||
#ifdef CYASSL_TIRTOS
|
#ifdef CYASSL_TIRTOS
|
||||||
fdOpenSession(Task_self());
|
fdOpenSession(Task_self());
|
||||||
@@ -384,6 +386,18 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
|
|||||||
case 'L' :
|
case 'L' :
|
||||||
#ifdef HAVE_ALPN
|
#ifdef HAVE_ALPN
|
||||||
alpnList = myoptarg;
|
alpnList = myoptarg;
|
||||||
|
|
||||||
|
if (alpnList[0] == 'C' && alpnList[1] == ':')
|
||||||
|
alpn_opt = WOLFSSL_ALPN_CONTINUE_ON_MISMATCH;
|
||||||
|
else if (alpnList[0] == 'F' && alpnList[1] == ':')
|
||||||
|
alpn_opt = WOLFSSL_ALPN_FAILED_ON_MISMATCH;
|
||||||
|
else {
|
||||||
|
Usage();
|
||||||
|
exit(MY_EX_USAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
alpnList += 2;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -636,7 +650,7 @@ while (1) { /* allow resume option */
|
|||||||
#ifdef HAVE_ALPN
|
#ifdef HAVE_ALPN
|
||||||
if (alpnList != NULL) {
|
if (alpnList != NULL) {
|
||||||
printf("ALPN accepted protocols list : %s\n", alpnList);
|
printf("ALPN accepted protocols list : %s\n", alpnList);
|
||||||
wolfSSL_UseALPN(ssl, alpnList, (word32)XSTRLEN(alpnList));
|
wolfSSL_UseALPN(ssl, alpnList, (word32)XSTRLEN(alpnList), alpn_opt);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -683,16 +697,19 @@ while (1) { /* allow resume option */
|
|||||||
showPeer(ssl);
|
showPeer(ssl);
|
||||||
|
|
||||||
#ifdef HAVE_ALPN
|
#ifdef HAVE_ALPN
|
||||||
{
|
if (alpnList != NULL) {
|
||||||
|
int err;
|
||||||
char *protocol_name = NULL;
|
char *protocol_name = NULL;
|
||||||
word16 protocol_nameSz = 0;
|
word16 protocol_nameSz = 0;
|
||||||
|
|
||||||
if (wolfSSL_ALPN_GetProtocol(ssl, &protocol_name,
|
err = wolfSSL_ALPN_GetProtocol(ssl, &protocol_name, &protocol_nameSz);
|
||||||
&protocol_nameSz) != SSL_SUCCESS)
|
if (err == SSL_SUCCESS)
|
||||||
printf("Getting ALPN protocol name failed\n");
|
|
||||||
else
|
|
||||||
printf("Send ALPN protocol : %s (%d)\n",
|
printf("Send ALPN protocol : %s (%d)\n",
|
||||||
protocol_name, protocol_nameSz);
|
protocol_name, protocol_nameSz);
|
||||||
|
else if (err == SSL_ALPN_NOT_FOUND)
|
||||||
|
printf("Not send ALPN response (no match with server)\n");
|
||||||
|
else
|
||||||
|
printf("Getting ALPN protocol name failed\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
13
src/ssl.c
13
src/ssl.c
@@ -889,7 +889,7 @@ int wolfSSL_UseSupportedQSH(WOLFSSL* ssl, word16 name)
|
|||||||
#ifdef HAVE_ALPN
|
#ifdef HAVE_ALPN
|
||||||
|
|
||||||
int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list,
|
int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list,
|
||||||
word32 protocol_name_listSz)
|
word32 protocol_name_listSz, byte options)
|
||||||
{
|
{
|
||||||
char *list, *ptr, *token[10];
|
char *list, *ptr, *token[10];
|
||||||
word16 len;
|
word16 len;
|
||||||
@@ -904,10 +904,17 @@ int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list,
|
|||||||
if (protocol_name_listSz > (WOLFSSL_MAX_ALPN_NUMBER *
|
if (protocol_name_listSz > (WOLFSSL_MAX_ALPN_NUMBER *
|
||||||
WOLFSSL_MAX_ALPN_PROTO_NAME_LEN +
|
WOLFSSL_MAX_ALPN_PROTO_NAME_LEN +
|
||||||
WOLFSSL_MAX_ALPN_NUMBER)) {
|
WOLFSSL_MAX_ALPN_NUMBER)) {
|
||||||
WOLFSSL_MSG("Invalid arguments, procolt name list too long");
|
WOLFSSL_MSG("Invalid arguments, protocol name list too long");
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(options & WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) &&
|
||||||
|
!(options & WOLFSSL_ALPN_FAILED_ON_MISMATCH)) {
|
||||||
|
WOLFSSL_MSG("Invalid arguments, options not supported");
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
list = (char *)XMALLOC(protocol_name_listSz+1, NULL,
|
list = (char *)XMALLOC(protocol_name_listSz+1, NULL,
|
||||||
DYNAMIC_TYPE_TMP_BUFFER);
|
DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
if (list == NULL) {
|
if (list == NULL) {
|
||||||
@@ -927,7 +934,7 @@ int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list,
|
|||||||
while ((idx--) > 0) {
|
while ((idx--) > 0) {
|
||||||
len = (word16)XSTRLEN(token[idx]);
|
len = (word16)XSTRLEN(token[idx]);
|
||||||
|
|
||||||
ret = TLSX_UseALPN(&ssl->extensions, token[idx], len);
|
ret = TLSX_UseALPN(&ssl->extensions, token[idx], len, options);
|
||||||
if (ret != SSL_SUCCESS) {
|
if (ret != SSL_SUCCESS) {
|
||||||
WOLFSSL_MSG("TLSX_UseALPN failure");
|
WOLFSSL_MSG("TLSX_UseALPN failure");
|
||||||
break;
|
break;
|
||||||
|
45
src/tls.c
45
src/tls.c
@@ -867,6 +867,8 @@ static ALPN* TLSX_ALPN_New(char *protocol_name, word16 protocol_nameSz)
|
|||||||
}
|
}
|
||||||
|
|
||||||
alpn->next = NULL;
|
alpn->next = NULL;
|
||||||
|
alpn->negociated = 0;
|
||||||
|
alpn->options = 0;
|
||||||
|
|
||||||
alpn->protocol_name = XMALLOC(protocol_nameSz + 1, 0, DYNAMIC_TYPE_TLSX);
|
alpn->protocol_name = XMALLOC(protocol_nameSz + 1, 0, DYNAMIC_TYPE_TLSX);
|
||||||
if (alpn->protocol_name == NULL) {
|
if (alpn->protocol_name == NULL) {
|
||||||
@@ -977,6 +979,8 @@ static int TLSX_SetALPN(TLSX** extensions, const void* data, word16 size)
|
|||||||
return MEMORY_E;
|
return MEMORY_E;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
alpn->negociated = 1;
|
||||||
|
|
||||||
ret = TLSX_Push(extensions, WOLFSSL_ALPN, (void*)alpn);
|
ret = TLSX_Push(extensions, WOLFSSL_ALPN, (void*)alpn);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
TLSX_ALPN_Free(alpn);
|
TLSX_ALPN_Free(alpn);
|
||||||
@@ -995,7 +999,7 @@ static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length,
|
|||||||
word16 offset = 0;
|
word16 offset = 0;
|
||||||
int r = BUFFER_ERROR;
|
int r = BUFFER_ERROR;
|
||||||
TLSX *extension;
|
TLSX *extension;
|
||||||
ALPN *alpn = NULL;
|
ALPN *alpn = NULL, *list;
|
||||||
|
|
||||||
extension = TLSX_Find(ssl->extensions, WOLFSSL_ALPN);
|
extension = TLSX_Find(ssl->extensions, WOLFSSL_ALPN);
|
||||||
if (extension == NULL)
|
if (extension == NULL)
|
||||||
@@ -1017,14 +1021,15 @@ static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length,
|
|||||||
if (length != OPAQUE16_LEN + size)
|
if (length != OPAQUE16_LEN + size)
|
||||||
return BUFFER_ERROR;
|
return BUFFER_ERROR;
|
||||||
|
|
||||||
|
list = (ALPN*)extension->data;
|
||||||
|
|
||||||
for (size = 0; offset < length; offset += size) {
|
for (size = 0; offset < length; offset += size) {
|
||||||
|
|
||||||
size = input[offset++];
|
size = input[offset++];
|
||||||
if (offset + size > length)
|
if (offset + size > length)
|
||||||
return BUFFER_ERROR;
|
return BUFFER_ERROR;
|
||||||
|
|
||||||
alpn = TLSX_ALPN_Find((ALPN*)extension->data,
|
alpn = TLSX_ALPN_Find(list, (char*)input + offset, size);
|
||||||
(char*)input + offset, size);
|
|
||||||
if (alpn != NULL) {
|
if (alpn != NULL) {
|
||||||
WOLFSSL_MSG("ALPN protocol match");
|
WOLFSSL_MSG("ALPN protocol match");
|
||||||
break;
|
break;
|
||||||
@@ -1034,13 +1039,21 @@ static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length,
|
|||||||
if (alpn == NULL) {
|
if (alpn == NULL) {
|
||||||
WOLFSSL_MSG("No ALPN protocol 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;
|
||||||
|
}
|
||||||
|
|
||||||
SendAlert(ssl, alert_fatal, no_application_protocol);
|
SendAlert(ssl, alert_fatal, no_application_protocol);
|
||||||
return UNKNOWN_ALPN_PROTOCOL_NAME_E;
|
return UNKNOWN_ALPN_PROTOCOL_NAME_E;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the matching negociated protocol */
|
/* set the matching negociated protocol */
|
||||||
r = TLSX_SetALPN(&ssl->extensions,
|
r = TLSX_SetALPN(&ssl->extensions,
|
||||||
alpn->protocol_name, (word16)XSTRLEN(alpn->protocol_name));
|
alpn->protocol_name,
|
||||||
|
(word16)XSTRLEN(alpn->protocol_name));
|
||||||
if (r != SSL_SUCCESS) {
|
if (r != SSL_SUCCESS) {
|
||||||
WOLFSSL_MSG("TLSX_UseALPN failed");
|
WOLFSSL_MSG("TLSX_UseALPN failed");
|
||||||
return BUFFER_ERROR;
|
return BUFFER_ERROR;
|
||||||
@@ -1057,7 +1070,7 @@ static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Add a protocol name to the list of accepted usable ones */
|
/** Add a protocol name to the list of accepted usable ones */
|
||||||
int TLSX_UseALPN(TLSX** extensions, const void* data, word16 size)
|
int TLSX_UseALPN(TLSX** extensions, const void* data, word16 size, byte options)
|
||||||
{
|
{
|
||||||
ALPN *alpn;
|
ALPN *alpn;
|
||||||
TLSX *extension;
|
TLSX *extension;
|
||||||
@@ -1072,6 +1085,9 @@ int TLSX_UseALPN(TLSX** extensions, const void* data, word16 size)
|
|||||||
return MEMORY_E;
|
return MEMORY_E;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set Options of ALPN */
|
||||||
|
alpn->options = options;
|
||||||
|
|
||||||
extension = TLSX_Find(*extensions, WOLFSSL_ALPN);
|
extension = TLSX_Find(*extensions, WOLFSSL_ALPN);
|
||||||
if (extension == NULL) {
|
if (extension == NULL) {
|
||||||
ret = TLSX_Push(extensions, WOLFSSL_ALPN, (void*)alpn);
|
ret = TLSX_Push(extensions, WOLFSSL_ALPN, (void*)alpn);
|
||||||
@@ -1101,13 +1117,28 @@ int TLSX_ALPN_GetRequest(TLSX* extensions, void** data, word16 *dataSz)
|
|||||||
extension = TLSX_Find(extensions, WOLFSSL_ALPN);
|
extension = TLSX_Find(extensions, WOLFSSL_ALPN);
|
||||||
if (extension == NULL) {
|
if (extension == NULL) {
|
||||||
WOLFSSL_MSG("TLS extension not found");
|
WOLFSSL_MSG("TLS extension not found");
|
||||||
return SSL_FATAL_ERROR;
|
return SSL_ALPN_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
alpn = (ALPN *)extension->data;
|
alpn = (ALPN *)extension->data;
|
||||||
if (alpn == NULL) {
|
if (alpn == NULL) {
|
||||||
WOLFSSL_MSG("ALPN extension not found");
|
WOLFSSL_MSG("ALPN extension not found");
|
||||||
return WOLFSSL_ALPN_NO_MATCH;
|
*data = NULL;
|
||||||
|
*dataSz = 0;
|
||||||
|
return SSL_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alpn->negociated != 1) {
|
||||||
|
|
||||||
|
/* consider as an error */
|
||||||
|
if (alpn->options & WOLFSSL_ALPN_FAILED_ON_MISMATCH) {
|
||||||
|
WOLFSSL_MSG("No protocol match with peer -> Failed");
|
||||||
|
return SSL_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* continue without negociated protocol */
|
||||||
|
WOLFSSL_MSG("No protocol match with peer -> Continue");
|
||||||
|
return SSL_ALPN_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (alpn->next != NULL) {
|
if (alpn->next != NULL) {
|
||||||
|
74
tests/api.c
74
tests/api.c
@@ -1215,7 +1215,19 @@ static void use_ALPN_all(WOLFSSL* ssl)
|
|||||||
0x73, 0x70, 0x64, 0x79, 0x2f, 0x31, 0x2c,
|
0x73, 0x70, 0x64, 0x79, 0x2f, 0x31, 0x2c,
|
||||||
0x73, 0x70, 0x64, 0x79, 0x2f, 0x32, 0x2c,
|
0x73, 0x70, 0x64, 0x79, 0x2f, 0x32, 0x2c,
|
||||||
0x73, 0x70, 0x64, 0x79, 0x2f, 0x33};
|
0x73, 0x70, 0x64, 0x79, 0x2f, 0x33};
|
||||||
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, alpn_list, sizeof(alpn_list)));
|
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, alpn_list, sizeof(alpn_list),
|
||||||
|
WOLFSSL_ALPN_FAILED_ON_MISMATCH));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void use_ALPN_all_continue(WOLFSSL* ssl)
|
||||||
|
{
|
||||||
|
/* http/1.1,spdy/1,spdy/2,spdy/3 */
|
||||||
|
char alpn_list[] = {0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31, 0x2c,
|
||||||
|
0x73, 0x70, 0x64, 0x79, 0x2f, 0x31, 0x2c,
|
||||||
|
0x73, 0x70, 0x64, 0x79, 0x2f, 0x32, 0x2c,
|
||||||
|
0x73, 0x70, 0x64, 0x79, 0x2f, 0x33};
|
||||||
|
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, alpn_list, sizeof(alpn_list),
|
||||||
|
WOLFSSL_ALPN_CONTINUE_ON_MISMATCH));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void use_ALPN_one(WOLFSSL* ssl)
|
static void use_ALPN_one(WOLFSSL* ssl)
|
||||||
@@ -1223,7 +1235,8 @@ static void use_ALPN_one(WOLFSSL* ssl)
|
|||||||
/* spdy/2 */
|
/* spdy/2 */
|
||||||
char proto[] = {0x73, 0x70, 0x64, 0x79, 0x2f, 0x32};
|
char proto[] = {0x73, 0x70, 0x64, 0x79, 0x2f, 0x32};
|
||||||
|
|
||||||
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, proto, sizeof(proto)));
|
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, proto, sizeof(proto),
|
||||||
|
WOLFSSL_ALPN_FAILED_ON_MISMATCH));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void use_ALPN_unknown(WOLFSSL* ssl)
|
static void use_ALPN_unknown(WOLFSSL* ssl)
|
||||||
@@ -1231,7 +1244,17 @@ static void use_ALPN_unknown(WOLFSSL* ssl)
|
|||||||
/* http/2.0 */
|
/* http/2.0 */
|
||||||
char proto[] = {0x68, 0x74, 0x74, 0x70, 0x2f, 0x32, 0x2e, 0x30};
|
char proto[] = {0x68, 0x74, 0x74, 0x70, 0x2f, 0x32, 0x2e, 0x30};
|
||||||
|
|
||||||
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, proto, sizeof(proto)));
|
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, proto, sizeof(proto),
|
||||||
|
WOLFSSL_ALPN_FAILED_ON_MISMATCH));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void use_ALPN_unknown_continue(WOLFSSL* ssl)
|
||||||
|
{
|
||||||
|
/* http/2.0 */
|
||||||
|
char proto[] = {0x68, 0x74, 0x74, 0x70, 0x2f, 0x32, 0x2e, 0x30};
|
||||||
|
|
||||||
|
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, proto, sizeof(proto),
|
||||||
|
WOLFSSL_ALPN_CONTINUE_ON_MISMATCH));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void verify_ALPN_not_matching_spdy3(WOLFSSL* ssl)
|
static void verify_ALPN_not_matching_spdy3(WOLFSSL* ssl)
|
||||||
@@ -1242,9 +1265,6 @@ static void verify_ALPN_not_matching_spdy3(WOLFSSL* ssl)
|
|||||||
char *proto;
|
char *proto;
|
||||||
word16 protoSz = 0;
|
word16 protoSz = 0;
|
||||||
|
|
||||||
printf("verify_ALPN_not_matching GetProtocol(ssl) = %d\n",
|
|
||||||
wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz));
|
|
||||||
|
|
||||||
AssertIntEQ(SSL_SUCCESS, wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz));
|
AssertIntEQ(SSL_SUCCESS, wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz));
|
||||||
|
|
||||||
/* check value */
|
/* check value */
|
||||||
@@ -1252,6 +1272,19 @@ static void verify_ALPN_not_matching_spdy3(WOLFSSL* ssl)
|
|||||||
AssertIntNE(0, XMEMCMP(nego_proto, proto, sizeof(nego_proto)));
|
AssertIntNE(0, XMEMCMP(nego_proto, proto, sizeof(nego_proto)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void verify_ALPN_not_matching_continue(WOLFSSL* ssl)
|
||||||
|
{
|
||||||
|
char *proto = NULL;
|
||||||
|
word16 protoSz = 0;
|
||||||
|
|
||||||
|
AssertIntEQ(SSL_ALPN_NOT_FOUND,
|
||||||
|
wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz));
|
||||||
|
|
||||||
|
/* check value */
|
||||||
|
AssertIntEQ(1, 0 == protoSz);
|
||||||
|
AssertIntEQ(1, NULL == proto);
|
||||||
|
}
|
||||||
|
|
||||||
static void verify_ALPN_matching_http1(WOLFSSL* ssl)
|
static void verify_ALPN_matching_http1(WOLFSSL* ssl)
|
||||||
{
|
{
|
||||||
/* http/1.1 */
|
/* http/1.1 */
|
||||||
@@ -1259,9 +1292,6 @@ static void verify_ALPN_matching_http1(WOLFSSL* ssl)
|
|||||||
char *proto;
|
char *proto;
|
||||||
word16 protoSz = 0;
|
word16 protoSz = 0;
|
||||||
|
|
||||||
printf("verify_ALPN_matching GetProtocol(ssl) = %d\n",
|
|
||||||
wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz));
|
|
||||||
|
|
||||||
AssertIntEQ(SSL_SUCCESS, wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz));
|
AssertIntEQ(SSL_SUCCESS, wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz));
|
||||||
|
|
||||||
/* check value */
|
/* check value */
|
||||||
@@ -1276,9 +1306,6 @@ static void verify_ALPN_matching_spdy2(WOLFSSL* ssl)
|
|||||||
char *proto;
|
char *proto;
|
||||||
word16 protoSz = 0;
|
word16 protoSz = 0;
|
||||||
|
|
||||||
printf("verify_ALPN_matching GetProtocol(ssl) = %d\n",
|
|
||||||
wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz));
|
|
||||||
|
|
||||||
AssertIntEQ(SSL_SUCCESS, wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz));
|
AssertIntEQ(SSL_SUCCESS, wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz));
|
||||||
|
|
||||||
/* check value */
|
/* check value */
|
||||||
@@ -1286,7 +1313,6 @@ static void verify_ALPN_matching_spdy2(WOLFSSL* ssl)
|
|||||||
AssertIntEQ(0, XMEMCMP(nego_proto, proto, protoSz));
|
AssertIntEQ(0, XMEMCMP(nego_proto, proto, protoSz));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void test_wolfSSL_UseALPN_connection(void)
|
static void test_wolfSSL_UseALPN_connection(void)
|
||||||
{
|
{
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
@@ -1307,6 +1333,10 @@ static void test_wolfSSL_UseALPN_connection(void)
|
|||||||
{0, 0, 0, 0},
|
{0, 0, 0, 0},
|
||||||
{0, 0, use_ALPN_all, 0},
|
{0, 0, use_ALPN_all, 0},
|
||||||
|
|
||||||
|
/* success case missmatch behavior but option 'continue' set */
|
||||||
|
{0, 0, use_ALPN_all_continue, verify_ALPN_not_matching_continue},
|
||||||
|
{0, 0, use_ALPN_unknown_continue, 0},
|
||||||
|
|
||||||
/* missmatch behavior with same list
|
/* missmatch behavior with same list
|
||||||
* the first and only this one must be taken */
|
* the first and only this one must be taken */
|
||||||
{0, 0, use_ALPN_all, 0},
|
{0, 0, use_ALPN_all, 0},
|
||||||
@@ -1345,13 +1375,16 @@ static void test_wolfSSL_UseALPN_params(void)
|
|||||||
|
|
||||||
/* error cases */
|
/* error cases */
|
||||||
AssertIntNE(SSL_SUCCESS,
|
AssertIntNE(SSL_SUCCESS,
|
||||||
wolfSSL_UseALPN(NULL, http1, sizeof(http1)));
|
wolfSSL_UseALPN(NULL, http1, sizeof(http1),
|
||||||
AssertIntNE(SSL_SUCCESS, wolfSSL_UseALPN(ssl, NULL, 0));
|
WOLFSSL_ALPN_FAILED_ON_MISMATCH));
|
||||||
|
AssertIntNE(SSL_SUCCESS, wolfSSL_UseALPN(ssl, NULL, 0,
|
||||||
|
WOLFSSL_ALPN_FAILED_ON_MISMATCH));
|
||||||
|
|
||||||
/* success case */
|
/* success case */
|
||||||
/* http1 only */
|
/* http1 only */
|
||||||
AssertIntEQ(SSL_SUCCESS,
|
AssertIntEQ(SSL_SUCCESS,
|
||||||
wolfSSL_UseALPN(ssl, http1, sizeof(http1)));
|
wolfSSL_UseALPN(ssl, http1, sizeof(http1),
|
||||||
|
WOLFSSL_ALPN_FAILED_ON_MISMATCH));
|
||||||
|
|
||||||
/* http1, spdy1 */
|
/* http1, spdy1 */
|
||||||
memcpy(buff, http1, sizeof(http1));
|
memcpy(buff, http1, sizeof(http1));
|
||||||
@@ -1359,7 +1392,8 @@ static void test_wolfSSL_UseALPN_params(void)
|
|||||||
buff[idx++] = ',';
|
buff[idx++] = ',';
|
||||||
memcpy(buff+idx, spdy1, sizeof(spdy1));
|
memcpy(buff+idx, spdy1, sizeof(spdy1));
|
||||||
idx += sizeof(spdy1);
|
idx += sizeof(spdy1);
|
||||||
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx));
|
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx,
|
||||||
|
WOLFSSL_ALPN_FAILED_ON_MISMATCH));
|
||||||
|
|
||||||
/* http1, spdy2, spdy1 */
|
/* http1, spdy2, spdy1 */
|
||||||
memcpy(buff, http1, sizeof(http1));
|
memcpy(buff, http1, sizeof(http1));
|
||||||
@@ -1370,7 +1404,8 @@ static void test_wolfSSL_UseALPN_params(void)
|
|||||||
buff[idx++] = ',';
|
buff[idx++] = ',';
|
||||||
memcpy(buff+idx, spdy1, sizeof(spdy1));
|
memcpy(buff+idx, spdy1, sizeof(spdy1));
|
||||||
idx += sizeof(spdy1);
|
idx += sizeof(spdy1);
|
||||||
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx));
|
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx,
|
||||||
|
WOLFSSL_ALPN_FAILED_ON_MISMATCH));
|
||||||
|
|
||||||
/* spdy3, http1, spdy2, spdy1 */
|
/* spdy3, http1, spdy2, spdy1 */
|
||||||
memcpy(buff, spdy3, sizeof(spdy3));
|
memcpy(buff, spdy3, sizeof(spdy3));
|
||||||
@@ -1384,7 +1419,8 @@ static void test_wolfSSL_UseALPN_params(void)
|
|||||||
buff[idx++] = ',';
|
buff[idx++] = ',';
|
||||||
memcpy(buff+idx, spdy1, sizeof(spdy1));
|
memcpy(buff+idx, spdy1, sizeof(spdy1));
|
||||||
idx += sizeof(spdy1);
|
idx += sizeof(spdy1);
|
||||||
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx));
|
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx,
|
||||||
|
WOLFSSL_ALPN_CONTINUE_ON_MISMATCH));
|
||||||
|
|
||||||
wolfSSL_free(ssl);
|
wolfSSL_free(ssl);
|
||||||
wolfSSL_CTX_free(ctx);
|
wolfSSL_CTX_free(ctx);
|
||||||
|
@@ -1540,13 +1540,17 @@ WOLFSSL_LOCAL int TLSX_SNI_GetFromBuffer(const byte* buffer, word32 bufferSz,
|
|||||||
typedef struct ALPN {
|
typedef struct ALPN {
|
||||||
char* protocol_name; /* ALPN protocol name */
|
char* protocol_name; /* ALPN protocol name */
|
||||||
struct ALPN* next; /* List Behavior */
|
struct ALPN* next; /* List Behavior */
|
||||||
|
byte options; /* Behaviour options */
|
||||||
|
byte negociated; /* ALPN protocol negociated or not */
|
||||||
} ALPN;
|
} ALPN;
|
||||||
|
|
||||||
WOLFSSL_LOCAL int TLSX_ALPN_GetRequest(TLSX* extensions,
|
WOLFSSL_LOCAL int TLSX_ALPN_GetRequest(TLSX* extensions,
|
||||||
void** data, word16 *dataSz);
|
void** data, word16 *dataSz);
|
||||||
|
|
||||||
WOLFSSL_LOCAL int TLSX_UseALPN(TLSX** extensions, const void* data,
|
WOLFSSL_LOCAL int TLSX_UseALPN(TLSX** extensions, const void* data,
|
||||||
word16 size);
|
word16 size, byte options);
|
||||||
|
|
||||||
|
WOLFSSL_LOCAL int TLSX_ALPN_SetOptions(TLSX** extensions, const byte option);
|
||||||
#endif /* HAVE_ALPN */
|
#endif /* HAVE_ALPN */
|
||||||
|
|
||||||
/* Maximum Fragment Length */
|
/* Maximum Fragment Length */
|
||||||
|
@@ -674,6 +674,7 @@ enum { /* ssl Constants */
|
|||||||
SSL_SUCCESS = 1,
|
SSL_SUCCESS = 1,
|
||||||
SSL_SHUTDOWN_NOT_DONE = 2, /* call wolfSSL_shutdown again to complete */
|
SSL_SHUTDOWN_NOT_DONE = 2, /* call wolfSSL_shutdown again to complete */
|
||||||
|
|
||||||
|
SSL_ALPN_NOT_FOUND = -9,
|
||||||
SSL_BAD_CERTTYPE = -8,
|
SSL_BAD_CERTTYPE = -8,
|
||||||
SSL_BAD_STAT = -7,
|
SSL_BAD_STAT = -7,
|
||||||
SSL_BAD_PATH = -6,
|
SSL_BAD_PATH = -6,
|
||||||
@@ -1354,7 +1355,9 @@ WOLFSSL_API int wolfSSL_SNI_GetFromBuffer(
|
|||||||
/* ALPN status code */
|
/* ALPN status code */
|
||||||
enum {
|
enum {
|
||||||
WOLFSSL_ALPN_NO_MATCH = 0,
|
WOLFSSL_ALPN_NO_MATCH = 0,
|
||||||
WOLFSSL_ALPN_MATCH = 1
|
WOLFSSL_ALPN_MATCH = 1,
|
||||||
|
WOLFSSL_ALPN_CONTINUE_ON_MISMATCH = 2,
|
||||||
|
WOLFSSL_ALPN_FAILED_ON_MISMATCH = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -1363,7 +1366,8 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
WOLFSSL_API int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list,
|
WOLFSSL_API int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list,
|
||||||
unsigned int protocol_name_listSz);
|
unsigned int protocol_name_listSz,
|
||||||
|
unsigned char options);
|
||||||
|
|
||||||
WOLFSSL_API int wolfSSL_ALPN_GetProtocol(WOLFSSL* ssl, char **protocol_name,
|
WOLFSSL_API int wolfSSL_ALPN_GetProtocol(WOLFSSL* ssl, char **protocol_name,
|
||||||
unsigned short *size);
|
unsigned short *size);
|
||||||
|
Reference in New Issue
Block a user