diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/libssl/ssl_lib.c | 83 |
1 files changed, 54 insertions, 29 deletions
diff --git a/src/lib/libssl/ssl_lib.c b/src/lib/libssl/ssl_lib.c index d1b552d94f..406567b535 100644 --- a/src/lib/libssl/ssl_lib.c +++ b/src/lib/libssl/ssl_lib.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssl_lib.c,v 1.323 2024/04/15 16:00:05 tb Exp $ */ | 1 | /* $OpenBSD: ssl_lib.c,v 1.324 2024/06/28 14:46:19 tb Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -1785,45 +1785,70 @@ LSSL_ALIAS(SSL_get_servername_type); | |||
1785 | * It returns either: | 1785 | * It returns either: |
1786 | * OPENSSL_NPN_NEGOTIATED if a common protocol was found, or | 1786 | * OPENSSL_NPN_NEGOTIATED if a common protocol was found, or |
1787 | * OPENSSL_NPN_NO_OVERLAP if the fallback case was reached. | 1787 | * OPENSSL_NPN_NO_OVERLAP if the fallback case was reached. |
1788 | * | ||
1789 | * XXX - the out argument points into server_list or client list and should | ||
1790 | * therefore really be const. We can't fix that without breaking the callers. | ||
1788 | */ | 1791 | */ |
1789 | int | 1792 | int |
1790 | SSL_select_next_proto(unsigned char **out, unsigned char *outlen, | 1793 | SSL_select_next_proto(unsigned char **out, unsigned char *outlen, |
1791 | const unsigned char *server, unsigned int server_len, | 1794 | const unsigned char *server_list, unsigned int server_list_len, |
1792 | const unsigned char *client, unsigned int client_len) | 1795 | const unsigned char *client_list, unsigned int client_list_len) |
1793 | { | 1796 | { |
1794 | unsigned int i, j; | 1797 | CBS client, client_proto, server, server_proto; |
1795 | const unsigned char *result; | 1798 | |
1796 | int status = OPENSSL_NPN_UNSUPPORTED; | 1799 | *out = NULL; |
1800 | *outlen = 0; | ||
1801 | |||
1802 | /* First check that the client list is well-formed. */ | ||
1803 | CBS_init(&client, client_list, client_list_len); | ||
1804 | if (!tlsext_alpn_check_format(&client)) | ||
1805 | goto err; | ||
1806 | |||
1807 | /* | ||
1808 | * Use first client protocol as fallback. This is one way of doing NPN's | ||
1809 | * "opportunistic" protocol selection (see security considerations in | ||
1810 | * draft-agl-tls-nextprotoneg-04), and it is the documented behavior of | ||
1811 | * this API. For ALPN it's the callback's responsibility to fail on | ||
1812 | * OPENSSL_NPN_NO_OVERLAP. | ||
1813 | */ | ||
1814 | |||
1815 | if (!CBS_get_u8_length_prefixed(&client, &client_proto)) | ||
1816 | goto err; | ||
1817 | |||
1818 | *out = (unsigned char *)CBS_data(&client_proto); | ||
1819 | *outlen = CBS_len(&client_proto); | ||
1820 | |||
1821 | /* Now check that the server list is well-formed. */ | ||
1822 | CBS_init(&server, server_list, server_list_len); | ||
1823 | if (!tlsext_alpn_check_format(&server)) | ||
1824 | goto err; | ||
1797 | 1825 | ||
1798 | /* | 1826 | /* |
1799 | * For each protocol in server preference order, | 1827 | * Walk the server list and select the first protocol that appears in |
1800 | * see if we support it. | 1828 | * the client list. |
1801 | */ | 1829 | */ |
1802 | for (i = 0; i < server_len; ) { | 1830 | while (CBS_len(&server) > 0) { |
1803 | for (j = 0; j < client_len; ) { | 1831 | if (!CBS_get_u8_length_prefixed(&server, &server_proto)) |
1804 | if (server[i] == client[j] && | 1832 | goto err; |
1805 | memcmp(&server[i + 1], | 1833 | |
1806 | &client[j + 1], server[i]) == 0) { | 1834 | CBS_init(&client, client_list, client_list_len); |
1807 | /* We found a match */ | 1835 | |
1808 | result = &server[i]; | 1836 | while (CBS_len(&client) > 0) { |
1809 | status = OPENSSL_NPN_NEGOTIATED; | 1837 | if (!CBS_get_u8_length_prefixed(&client, &client_proto)) |
1810 | goto found; | 1838 | goto err; |
1839 | |||
1840 | if (CBS_mem_equal(&client_proto, | ||
1841 | CBS_data(&server_proto), CBS_len(&server_proto))) { | ||
1842 | *out = (unsigned char *)CBS_data(&server_proto); | ||
1843 | *outlen = CBS_len(&server_proto); | ||
1844 | |||
1845 | return OPENSSL_NPN_NEGOTIATED; | ||
1811 | } | 1846 | } |
1812 | j += client[j]; | ||
1813 | j++; | ||
1814 | } | 1847 | } |
1815 | i += server[i]; | ||
1816 | i++; | ||
1817 | } | 1848 | } |
1818 | 1849 | ||
1819 | /* There's no overlap between our protocols and the server's list. */ | 1850 | err: |
1820 | result = client; | 1851 | return OPENSSL_NPN_NO_OVERLAP; |
1821 | status = OPENSSL_NPN_NO_OVERLAP; | ||
1822 | |||
1823 | found: | ||
1824 | *out = (unsigned char *) result + 1; | ||
1825 | *outlen = result[0]; | ||
1826 | return (status); | ||
1827 | } | 1852 | } |
1828 | LSSL_ALIAS(SSL_select_next_proto); | 1853 | LSSL_ALIAS(SSL_select_next_proto); |
1829 | 1854 | ||