diff --git a/src/ssl.c b/src/ssl.c index 4b678e767..c37a8a40e 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -3112,14 +3112,19 @@ int wolfSSL_ALPN_GetPeerProtocol(WOLFSSL* ssl, char **list, word16 *listSz) char *p; byte *s; - if (list == NULL || listSz == NULL) + if (ssl == NULL || list == NULL || listSz == NULL) return BAD_FUNC_ARG; if (ssl->alpn_peer_requested == NULL || ssl->alpn_peer_requested_length == 0) return BUFFER_ERROR; - *listSz = ssl->alpn_peer_requested_length -1; + /* 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) diff --git a/src/tls.c b/src/tls.c index 837a2341f..9bfc7dbdb 100644 --- a/src/tls.c +++ b/src/tls.c @@ -1585,7 +1585,6 @@ static int ALPN_find_match(WOLFSSL *ssl, TLSX **pextension, { TLSX *extension; ALPN *alpn, *list; - int r = 0; const byte *sel = NULL, *s; byte sel_len = 0, wlen; @@ -1595,10 +1594,8 @@ static int ALPN_find_match(WOLFSSL *ssl, TLSX **pextension, TLSX_APPLICATION_LAYER_PROTOCOL); /* No ALPN configured here */ - if (extension == NULL || extension->data == NULL) { - extension = NULL; - goto cleanup; - } + if (extension == NULL || extension->data == NULL) + return 0; list = (ALPN*)extension->data; for (s = alpn_val, wlen = 0; @@ -1621,20 +1618,18 @@ static int ALPN_find_match(WOLFSSL *ssl, TLSX **pextension, is set to continue (like OpenSSL) */ if (list->options & WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) { WOLFSSL_MSG("Continue on mismatch"); - goto cleanup; } - - SendAlert(ssl, alert_fatal, no_application_protocol); - WOLFSSL_ERROR_VERBOSE(UNKNOWN_ALPN_PROTOCOL_NAME_E); - r = UNKNOWN_ALPN_PROTOCOL_NAME_E; - goto cleanup; + else { + SendAlert(ssl, alert_fatal, no_application_protocol); + WOLFSSL_ERROR_VERBOSE(UNKNOWN_ALPN_PROTOCOL_NAME_E); + return UNKNOWN_ALPN_PROTOCOL_NAME_E; + } } -cleanup: *pextension = extension; *psel = sel; *psel_len = sel_len; - return r; + return 0; } int ALPN_Select(WOLFSSL *ssl) @@ -1645,9 +1640,8 @@ int ALPN_Select(WOLFSSL *ssl) int r = 0; WOLFSSL_ENTER("ALPN_Select"); - if (ssl->alpn_peer_requested == NULL) { - goto cleanup; - } + 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) { @@ -1668,7 +1662,7 @@ int ALPN_Select(WOLFSSL *ssl) ssl->alpn_peer_requested, ssl->alpn_peer_requested_length); if (r != 0) - goto cleanup; + return r; } if (sel != NULL) { @@ -1676,19 +1670,14 @@ int ALPN_Select(WOLFSSL *ssl) r = TLSX_SetALPN(&ssl->extensions, sel, sel_len, ssl->heap); if (r != WOLFSSL_SUCCESS) { WOLFSSL_MSG("TLSX_SetALPN failed"); - r = BUFFER_ERROR; - goto cleanup; + return BUFFER_ERROR; } /* reply to ALPN extension sent from peer */ #ifndef NO_WOLFSSL_SERVER TLSX_SetResponse(ssl, TLSX_APPLICATION_LAYER_PROTOCOL); #endif } - r = 0; - -cleanup: - WOLFSSL_LEAVE("ALPN_Select", r); - return r; + return 0; } /** Parses a buffer of ALPN extensions and set the first one matching @@ -1702,19 +1691,20 @@ static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, const byte *input, word16 length, const byte *s; if (OPAQUE16_LEN > length) - goto cleanup; + return BUFFER_ERROR; ato16(input, &size); offset += OPAQUE16_LEN; /* validating alpn list length */ if (size == 0 || length != OPAQUE16_LEN + size) - goto cleanup; + return BUFFER_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) - goto cleanup; + return BUFFER_ERROR; } if (isRequest) { @@ -1726,8 +1716,7 @@ static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, const byte *input, word16 length, ssl->alpn_peer_requested = (byte *)XMALLOC(size, ssl->heap, DYNAMIC_TYPE_ALPN); if (ssl->alpn_peer_requested == NULL) { - r = MEMORY_ERROR; - goto cleanup; + return MEMORY_ERROR; } ssl->alpn_peer_requested_length = size; XMEMCPY(ssl->alpn_peer_requested, (char*)input + offset, size); @@ -1739,30 +1728,24 @@ static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, const byte *input, word16 length, r = ALPN_find_match(ssl, &extension, &sel, &sel_len, input + offset, size); if (r != 0) - goto cleanup; + 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"); - r = BUFFER_ERROR; - goto cleanup; + return BUFFER_ERROR; } } /* If we had nothing configured, the response is unexpected */ else if (extension == NULL) { r = TLSX_HandleUnsupportedExtension(ssl); - goto cleanup; - } - else { - /* have sth configured, but did not match. no error returned - * means we accepted that. */ + if (r != 0) + return r; } } - r = 0; -cleanup: - return r; + return 0; } /** Add a protocol name to the list of accepted usable ones */