|
39 | 39 | #ifdef PHP_WIN32
|
40 | 40 | #include "win32/winutil.h"
|
41 | 41 | #include "win32/time.h"
|
| 42 | +#include <Ws2tcpip.h> |
42 | 43 | #include <Wincrypt.h>
|
43 | 44 | /* These are from Wincrypt.h, they conflict with OpenSSL */
|
44 | 45 | #undef X509_NAME
|
45 | 46 | #undef X509_CERT_PAIR
|
46 | 47 | #undef X509_EXTENSIONS
|
47 | 48 | #endif
|
48 | 49 |
|
| 50 | +#ifdef HAVE_ARPA_INET_H |
| 51 | +#include <arpa/inet.h> |
| 52 | +#endif |
| 53 | + |
49 | 54 | /* Flags for determining allowed stream crypto methods */
|
50 | 55 | #define STREAM_CRYPTO_IS_CLIENT (1<<0)
|
51 | 56 | #define STREAM_CRYPTO_METHOD_SSLv2 (1<<1)
|
|
110 | 115 | #define PHP_X509_NAME_ENTRY_TO_UTF8(ne, i, out) \
|
111 | 116 | ASN1_STRING_to_UTF8(&out, X509_NAME_ENTRY_get_data(X509_NAME_get_entry(ne, i)))
|
112 | 117 |
|
| 118 | +/* Used for IPv6 Address peer verification */ |
| 119 | +#define EXPAND_IPV6_ADDRESS(_str, _bytes) \ |
| 120 | + do { \ |
| 121 | + snprintf(_str, 40, "%X:%X:%X:%X:%X:%X:%X:%X", \ |
| 122 | + _bytes[0] << 8 | _bytes[1], \ |
| 123 | + _bytes[2] << 8 | _bytes[3], \ |
| 124 | + _bytes[4] << 8 | _bytes[5], \ |
| 125 | + _bytes[6] << 8 | _bytes[7], \ |
| 126 | + _bytes[8] << 8 | _bytes[9], \ |
| 127 | + _bytes[10] << 8 | _bytes[11], \ |
| 128 | + _bytes[12] << 8 | _bytes[13], \ |
| 129 | + _bytes[14] << 8 | _bytes[15] \ |
| 130 | + ); \ |
| 131 | + } while(0) |
| 132 | + |
113 | 133 | #if PHP_OPENSSL_API_VERSION < 0x10100
|
114 | 134 | static RSA *php_openssl_tmp_rsa_cb(SSL *s, int is_export, int keylength);
|
115 | 135 | #endif
|
@@ -421,6 +441,18 @@ static bool php_openssl_matches_san_list(X509 *peer, const char *subject_name) /
|
421 | 441 | GENERAL_NAMES *alt_names = X509_get_ext_d2i(peer, NID_subject_alt_name, 0, 0);
|
422 | 442 | int alt_name_count = sk_GENERAL_NAME_num(alt_names);
|
423 | 443 |
|
| 444 | +#if defined(HAVE_IPV6) && defined(HAVE_INET_PTON) |
| 445 | + /* detect if subject name is an IPv6 address and expand once if required */ |
| 446 | + char subject_name_ipv6_expanded[40]; |
| 447 | + unsigned char ipv6[16]; |
| 448 | + bool subject_name_is_ipv6 = false; |
| 449 | + subject_name_ipv6_expanded[0] = 0; |
| 450 | + if (inet_pton(AF_INET6, subject_name, &ipv6)) { |
| 451 | + EXPAND_IPV6_ADDRESS(subject_name_ipv6_expanded, ipv6); |
| 452 | + subject_name_is_ipv6 = true; |
| 453 | + } |
| 454 | +#endif |
| 455 | + |
424 | 456 | for (i = 0; i < alt_name_count; i++) {
|
425 | 457 | GENERAL_NAME *san = sk_GENERAL_NAME_value(alt_names, i);
|
426 | 458 |
|
@@ -459,10 +491,17 @@ static bool php_openssl_matches_san_list(X509 *peer, const char *subject_name) /
|
459 | 491 | return 1;
|
460 | 492 | }
|
461 | 493 | }
|
462 |
| - /* No, we aren't bothering to check IPv6 addresses. Why? |
463 |
| - * Because IP SAN names are officially deprecated and are |
464 |
| - * not allowed by CAs starting in 2015. Deal with it. |
465 |
| - */ |
| 494 | +#if defined(HAVE_IPV6) && defined(HAVE_INET_PTON) |
| 495 | + else if (san->d.ip->length == 16 && subject_name_is_ipv6) { |
| 496 | + ipbuffer[0] = 0; |
| 497 | + EXPAND_IPV6_ADDRESS(ipbuffer, san->d.iPAddress->data); |
| 498 | + if (strcasecmp((const char*)subject_name_ipv6_expanded, (const char*)ipbuffer) == 0) { |
| 499 | + sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free); |
| 500 | + |
| 501 | + return 1; |
| 502 | + } |
| 503 | + } |
| 504 | +#endif |
466 | 505 | }
|
467 | 506 | }
|
468 | 507 |
|
|
0 commit comments