|
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
|
|
50 | 51 | # define MSG_DONTWAIT 0
|
51 | 52 | #endif
|
52 | 53 |
|
| 54 | +#ifdef HAVE_ARPA_INET_H |
| 55 | +#include <arpa/inet.h> |
| 56 | +#endif |
| 57 | + |
53 | 58 | /* Flags for determining allowed stream crypto methods */
|
54 | 59 | #define STREAM_CRYPTO_IS_CLIENT (1<<0)
|
55 | 60 | #define STREAM_CRYPTO_METHOD_SSLv2 (1<<1)
|
|
125 | 130 | #define PHP_X509_NAME_ENTRY_TO_UTF8(ne, i, out) \
|
126 | 131 | ASN1_STRING_to_UTF8(&out, X509_NAME_ENTRY_get_data(X509_NAME_get_entry(ne, i)))
|
127 | 132 |
|
| 133 | +/* Used for IPv6 Address peer verification */ |
| 134 | +#define EXPAND_IPV6_ADDRESS(_str, _bytes) \ |
| 135 | + do { \ |
| 136 | + snprintf(_str, 40, "%X:%X:%X:%X:%X:%X:%X:%X", \ |
| 137 | + _bytes[0] << 8 | _bytes[1], \ |
| 138 | + _bytes[2] << 8 | _bytes[3], \ |
| 139 | + _bytes[4] << 8 | _bytes[5], \ |
| 140 | + _bytes[6] << 8 | _bytes[7], \ |
| 141 | + _bytes[8] << 8 | _bytes[9], \ |
| 142 | + _bytes[10] << 8 | _bytes[11], \ |
| 143 | + _bytes[12] << 8 | _bytes[13], \ |
| 144 | + _bytes[14] << 8 | _bytes[15] \ |
| 145 | + ); \ |
| 146 | + } while(0) |
| 147 | + |
128 | 148 | #if PHP_OPENSSL_API_VERSION < 0x10100
|
129 | 149 | static RSA *php_openssl_tmp_rsa_cb(SSL *s, int is_export, int keylength);
|
130 | 150 | #endif
|
@@ -436,6 +456,18 @@ static bool php_openssl_matches_san_list(X509 *peer, const char *subject_name) /
|
436 | 456 | GENERAL_NAMES *alt_names = X509_get_ext_d2i(peer, NID_subject_alt_name, 0, 0);
|
437 | 457 | int alt_name_count = sk_GENERAL_NAME_num(alt_names);
|
438 | 458 |
|
| 459 | +#if defined(HAVE_IPV6) && defined(HAVE_INET_PTON) |
| 460 | + /* detect if subject name is an IPv6 address and expand once if required */ |
| 461 | + char subject_name_ipv6_expanded[40]; |
| 462 | + unsigned char ipv6[16]; |
| 463 | + bool subject_name_is_ipv6 = false; |
| 464 | + subject_name_ipv6_expanded[0] = 0; |
| 465 | + if (inet_pton(AF_INET6, subject_name, &ipv6)) { |
| 466 | + EXPAND_IPV6_ADDRESS(subject_name_ipv6_expanded, ipv6); |
| 467 | + subject_name_is_ipv6 = true; |
| 468 | + } |
| 469 | +#endif |
| 470 | + |
439 | 471 | for (i = 0; i < alt_name_count; i++) {
|
440 | 472 | GENERAL_NAME *san = sk_GENERAL_NAME_value(alt_names, i);
|
441 | 473 |
|
@@ -474,10 +506,17 @@ static bool php_openssl_matches_san_list(X509 *peer, const char *subject_name) /
|
474 | 506 | return 1;
|
475 | 507 | }
|
476 | 508 | }
|
477 |
| - /* No, we aren't bothering to check IPv6 addresses. Why? |
478 |
| - * Because IP SAN names are officially deprecated and are |
479 |
| - * not allowed by CAs starting in 2015. Deal with it. |
480 |
| - */ |
| 509 | +#if defined(HAVE_IPV6) && defined(HAVE_INET_PTON) |
| 510 | + else if (san->d.ip->length == 16 && subject_name_is_ipv6) { |
| 511 | + ipbuffer[0] = 0; |
| 512 | + EXPAND_IPV6_ADDRESS(ipbuffer, san->d.iPAddress->data); |
| 513 | + if (strcasecmp((const char*)subject_name_ipv6_expanded, (const char*)ipbuffer) == 0) { |
| 514 | + sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free); |
| 515 | + |
| 516 | + return 1; |
| 517 | + } |
| 518 | + } |
| 519 | +#endif |
481 | 520 | }
|
482 | 521 | }
|
483 | 522 |
|
|
0 commit comments