diff options
3 files changed, 35 insertions, 10 deletions
diff --git a/src/core/lib/security/security_connector/security_connector.cc b/src/core/lib/security/security_connector/security_connector.cc index 3551061aa4..b6c8d1e497 100644 --- a/src/core/lib/security/security_connector/security_connector.cc +++ b/src/core/lib/security/security_connector/security_connector.cc @@ -786,17 +786,20 @@ static void ssl_server_add_handshakers(grpc_server_security_connector* sc, tsi_create_adapter_handshaker(tsi_hs), &sc->base)); } -static int ssl_host_matches_name(const tsi_peer* peer, const char* peer_name) { +int grpc_ssl_host_matches_name(const tsi_peer* peer, const char* peer_name) { char* allocated_name = nullptr; int r; - if (strchr(peer_name, ':') != nullptr) { - char* ignored_port; - gpr_split_host_port(peer_name, &allocated_name, &ignored_port); - gpr_free(ignored_port); - peer_name = allocated_name; - if (!peer_name) return 0; - } + char* ignored_port; + gpr_split_host_port(peer_name, &allocated_name, &ignored_port); + gpr_free(ignored_port); + peer_name = allocated_name; + if (!peer_name) return 0; + + // IPv6 zone-id should not be included in comparisons. + char* const zone_id = strchr(allocated_name, '%'); + if (zone_id != nullptr) *zone_id = '\0'; + r = tsi_ssl_peer_matches_name(peer, peer_name); gpr_free(allocated_name); return r; @@ -859,7 +862,7 @@ static grpc_error* ssl_check_peer(grpc_security_connector* sc, } /* Check the peer name if specified. */ - if (peer_name != nullptr && !ssl_host_matches_name(peer, peer_name)) { + if (peer_name != nullptr && !grpc_ssl_host_matches_name(peer, peer_name)) { char* msg; gpr_asprintf(&msg, "Peer name %s is not in peer certificate", peer_name); grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); @@ -968,7 +971,7 @@ static bool ssl_channel_check_call_host(grpc_channel_security_connector* sc, reinterpret_cast<grpc_ssl_channel_security_connector*>(sc); grpc_security_status status = GRPC_SECURITY_ERROR; tsi_peer peer = tsi_shallow_peer_from_ssl_auth_context(auth_context); - if (ssl_host_matches_name(&peer, host)) status = GRPC_SECURITY_OK; + if (grpc_ssl_host_matches_name(&peer, host)) status = GRPC_SECURITY_OK; /* If the target name was overridden, then the original target_name was 'checked' transitively during the previous peer check at the end of the handshake. */ diff --git a/src/core/lib/security/security_connector/security_connector.h b/src/core/lib/security/security_connector/security_connector.h index c4cc19db81..f2d94d6f1c 100644 --- a/src/core/lib/security/security_connector/security_connector.h +++ b/src/core/lib/security/security_connector/security_connector.h @@ -243,6 +243,7 @@ grpc_auth_context* tsi_ssl_peer_to_auth_context(const tsi_peer* peer); tsi_peer tsi_shallow_peer_from_ssl_auth_context( const grpc_auth_context* auth_context); void tsi_shallow_peer_destruct(tsi_peer* peer); +int grpc_ssl_host_matches_name(const tsi_peer* peer, const char* peer_name); /* --- Default SSL Root Store. --- */ namespace grpc_core { diff --git a/test/core/security/security_connector_test.cc b/test/core/security/security_connector_test.cc index f03f4ccdbd..c78d2ae41f 100644 --- a/test/core/security/security_connector_test.cc +++ b/test/core/security/security_connector_test.cc @@ -340,6 +340,26 @@ static grpc_ssl_roots_override_result override_roots_permanent_failure( return GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY; } +static void test_ipv6_address_san(void) { + const char* addresses[] = { + "2001:db8::1", "fe80::abcd:ef65:4321%em0", "fd11:feed:beef:0:cafe::4", + "128.10.0.1:8888", "[2001:db8::1]:8080", "[2001:db8::1%em1]:8080", + }; + const char* san_ips[] = { + "2001:db8::1", "fe80::abcd:ef65:4321", "fd11:feed:beef:0:cafe::4", + "128.10.0.1", "2001:db8::1", "2001:db8::1", + }; + tsi_peer peer; + GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK); + for (size_t i = 0; i < GPR_ARRAY_SIZE(addresses); i++) { + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, san_ips[i], + &peer.properties[0]) == TSI_OK); + GPR_ASSERT(grpc_ssl_host_matches_name(&peer, addresses[i])); + tsi_peer_property_destruct(&peer.properties[0]); + } + tsi_peer_destruct(&peer); +} namespace grpc_core { namespace { @@ -416,6 +436,7 @@ int main(int argc, char** argv) { test_cn_and_one_san_ssl_peer_to_auth_context(); test_cn_and_multiple_sans_ssl_peer_to_auth_context(); test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context(); + test_ipv6_address_san(); test_default_ssl_roots(); grpc_shutdown(); |