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