Merge pull request #14387 from dcow/zone-id

gRPC core: strip zone-id from IPv6 hosts before TLS verification
pull/15214/head
Mark D. Roth 7 years ago committed by GitHub
commit 198d0f56ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 23
      src/core/lib/security/security_connector/security_connector.cc
  2. 1
      src/core/lib/security/security_connector/security_connector.h
  3. 21
      test/core/security/security_connector_test.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. */

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

@ -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();

Loading…
Cancel
Save