ALPN : add option to continue in case of client/server protocol mismatch (like OpenSSL)

This commit is contained in:
Ludovic FLAMENT
2015-10-13 09:38:40 +02:00
parent 266936db93
commit 10f5154389
7 changed files with 173 additions and 52 deletions

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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) {

View File

@ -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);

View File

@ -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 */

View File

@ -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);