|  | @@ -69,12 +69,22 @@ grpc_security_status grpc_security_context_create_handshaker(
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  grpc_security_status grpc_security_context_check_peer(
 | 
	
		
			
				|  |  | -    grpc_security_context *ctx, const tsi_peer *peer,
 | 
	
		
			
				|  |  | -    grpc_security_check_peer_cb cb, void *user_data) {
 | 
	
		
			
				|  |  | -  if (ctx == NULL) return GRPC_SECURITY_ERROR;
 | 
	
		
			
				|  |  | +    grpc_security_context *ctx, tsi_peer peer, grpc_security_check_cb cb,
 | 
	
		
			
				|  |  | +    void *user_data) {
 | 
	
		
			
				|  |  | +  if (ctx == NULL) {
 | 
	
		
			
				|  |  | +    tsi_peer_destruct(&peer);
 | 
	
		
			
				|  |  | +    return GRPC_SECURITY_ERROR;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |    return ctx->vtable->check_peer(ctx, peer, cb, user_data);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +grpc_security_status grpc_channel_security_context_check_call_host(
 | 
	
		
			
				|  |  | +    grpc_channel_security_context *ctx, const char *host,
 | 
	
		
			
				|  |  | +    grpc_security_check_cb cb, void *user_data) {
 | 
	
		
			
				|  |  | +  if (ctx == NULL || ctx->check_call_host == NULL) return GRPC_SECURITY_ERROR;
 | 
	
		
			
				|  |  | +  return ctx->check_call_host(ctx, host, cb, user_data);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  void grpc_security_context_unref(grpc_security_context *ctx) {
 | 
	
		
			
				|  |  |    if (ctx == NULL) return;
 | 
	
		
			
				|  |  |    if (gpr_unref(&ctx->refcount)) ctx->vtable->destroy(ctx);
 | 
	
	
		
			
				|  | @@ -137,6 +147,11 @@ static int check_request_metadata_creds(grpc_credentials *creds) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /* -- Fake implementation. -- */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +typedef struct {
 | 
	
		
			
				|  |  | +  grpc_channel_security_context base;
 | 
	
		
			
				|  |  | +  int call_host_check_is_async;
 | 
	
		
			
				|  |  | +} grpc_fake_channel_security_context;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void fake_channel_destroy(grpc_security_context *ctx) {
 | 
	
		
			
				|  |  |    grpc_channel_security_context *c = (grpc_channel_security_context *)ctx;
 | 
	
		
			
				|  |  |    grpc_credentials_unref(c->request_metadata_creds);
 | 
	
	
		
			
				|  | @@ -158,31 +173,51 @@ static grpc_security_status fake_server_create_handshaker(
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static grpc_security_status fake_check_peer(grpc_security_context *ctx,
 | 
	
		
			
				|  |  | -                                            const tsi_peer *peer,
 | 
	
		
			
				|  |  | -                                            grpc_security_check_peer_cb cb,
 | 
	
		
			
				|  |  | +                                            tsi_peer peer,
 | 
	
		
			
				|  |  | +                                            grpc_security_check_cb cb,
 | 
	
		
			
				|  |  |                                              void *user_data) {
 | 
	
		
			
				|  |  |    const char *prop_name;
 | 
	
		
			
				|  |  | -  if (peer->property_count != 1) {
 | 
	
		
			
				|  |  | +  grpc_security_status status = GRPC_SECURITY_OK;
 | 
	
		
			
				|  |  | +  if (peer.property_count != 1) {
 | 
	
		
			
				|  |  |      gpr_log(GPR_ERROR, "Fake peers should only have 1 property.");
 | 
	
		
			
				|  |  | -    return GRPC_SECURITY_ERROR;
 | 
	
		
			
				|  |  | +    status = GRPC_SECURITY_ERROR;
 | 
	
		
			
				|  |  | +    goto end;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  prop_name = peer->properties[0].name;
 | 
	
		
			
				|  |  | +  prop_name = peer.properties[0].name;
 | 
	
		
			
				|  |  |    if (prop_name == NULL ||
 | 
	
		
			
				|  |  |        strcmp(prop_name, TSI_CERTIFICATE_TYPE_PEER_PROPERTY)) {
 | 
	
		
			
				|  |  |      gpr_log(GPR_ERROR, "Unexpected property in fake peer: %s.",
 | 
	
		
			
				|  |  |              prop_name == NULL ? "<EMPTY>" : prop_name);
 | 
	
		
			
				|  |  | -    return GRPC_SECURITY_ERROR;
 | 
	
		
			
				|  |  | +    status = GRPC_SECURITY_ERROR;
 | 
	
		
			
				|  |  | +    goto end;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  if (peer->properties[0].type != TSI_PEER_PROPERTY_TYPE_STRING) {
 | 
	
		
			
				|  |  | +  if (peer.properties[0].type != TSI_PEER_PROPERTY_TYPE_STRING) {
 | 
	
		
			
				|  |  |      gpr_log(GPR_ERROR, "Invalid type of cert type property.");
 | 
	
		
			
				|  |  | -    return GRPC_SECURITY_ERROR;
 | 
	
		
			
				|  |  | +    status = GRPC_SECURITY_ERROR;
 | 
	
		
			
				|  |  | +    goto end;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  if (strncmp(peer->properties[0].value.string.data, TSI_FAKE_CERTIFICATE_TYPE,
 | 
	
		
			
				|  |  | -              peer->properties[0].value.string.length)) {
 | 
	
		
			
				|  |  | +  if (strncmp(peer.properties[0].value.string.data, TSI_FAKE_CERTIFICATE_TYPE,
 | 
	
		
			
				|  |  | +              peer.properties[0].value.string.length)) {
 | 
	
		
			
				|  |  |      gpr_log(GPR_ERROR, "Invalid value for cert type property.");
 | 
	
		
			
				|  |  | -    return GRPC_SECURITY_ERROR;
 | 
	
		
			
				|  |  | +    status = GRPC_SECURITY_ERROR;
 | 
	
		
			
				|  |  | +    goto end;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +end:
 | 
	
		
			
				|  |  | +  tsi_peer_destruct(&peer);
 | 
	
		
			
				|  |  | +  return status;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static grpc_security_status fake_channel_check_call_host(
 | 
	
		
			
				|  |  | +    grpc_channel_security_context *ctx, const char *host,
 | 
	
		
			
				|  |  | +    grpc_security_check_cb cb, void *user_data) {
 | 
	
		
			
				|  |  | +  grpc_fake_channel_security_context *c =
 | 
	
		
			
				|  |  | +      (grpc_fake_channel_security_context *)ctx;
 | 
	
		
			
				|  |  | +  if (c->call_host_check_is_async) {
 | 
	
		
			
				|  |  | +    cb(user_data, GRPC_SECURITY_OK);
 | 
	
		
			
				|  |  | +    return GRPC_SECURITY_PENDING;
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    return GRPC_SECURITY_OK;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  return GRPC_SECURITY_OK;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static grpc_security_context_vtable fake_channel_vtable = {
 | 
	
	
		
			
				|  | @@ -192,15 +227,17 @@ static grpc_security_context_vtable fake_server_vtable = {
 | 
	
		
			
				|  |  |      fake_server_destroy, fake_server_create_handshaker, fake_check_peer};
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  grpc_channel_security_context *grpc_fake_channel_security_context_create(
 | 
	
		
			
				|  |  | -    grpc_credentials *request_metadata_creds) {
 | 
	
		
			
				|  |  | -  grpc_channel_security_context *c =
 | 
	
		
			
				|  |  | -      gpr_malloc(sizeof(grpc_channel_security_context));
 | 
	
		
			
				|  |  | -  gpr_ref_init(&c->base.refcount, 1);
 | 
	
		
			
				|  |  | -  c->base.is_client_side = 1;
 | 
	
		
			
				|  |  | -  c->base.vtable = &fake_channel_vtable;
 | 
	
		
			
				|  |  | +    grpc_credentials *request_metadata_creds, int call_host_check_is_async) {
 | 
	
		
			
				|  |  | +  grpc_fake_channel_security_context *c =
 | 
	
		
			
				|  |  | +      gpr_malloc(sizeof(grpc_fake_channel_security_context));
 | 
	
		
			
				|  |  | +  gpr_ref_init(&c->base.base.refcount, 1);
 | 
	
		
			
				|  |  | +  c->base.base.is_client_side = 1;
 | 
	
		
			
				|  |  | +  c->base.base.vtable = &fake_channel_vtable;
 | 
	
		
			
				|  |  |    GPR_ASSERT(check_request_metadata_creds(request_metadata_creds));
 | 
	
		
			
				|  |  | -  c->request_metadata_creds = grpc_credentials_ref(request_metadata_creds);
 | 
	
		
			
				|  |  | -  return c;
 | 
	
		
			
				|  |  | +  c->base.request_metadata_creds = grpc_credentials_ref(request_metadata_creds);
 | 
	
		
			
				|  |  | +  c->base.check_call_host = fake_channel_check_call_host;
 | 
	
		
			
				|  |  | +  c->call_host_check_is_async = call_host_check_is_async;
 | 
	
		
			
				|  |  | +  return &c->base;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  grpc_security_context *grpc_fake_server_security_context_create(void) {
 | 
	
	
		
			
				|  | @@ -215,7 +252,9 @@ grpc_security_context *grpc_fake_server_security_context_create(void) {
 | 
	
		
			
				|  |  |  typedef struct {
 | 
	
		
			
				|  |  |    grpc_channel_security_context base;
 | 
	
		
			
				|  |  |    tsi_ssl_handshaker_factory *handshaker_factory;
 | 
	
		
			
				|  |  | -  char *secure_peer_name;
 | 
	
		
			
				|  |  | +  char *target_name;
 | 
	
		
			
				|  |  | +  char *overridden_target_name;
 | 
	
		
			
				|  |  | +  tsi_peer peer;
 | 
	
		
			
				|  |  |  } grpc_ssl_channel_security_context;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  typedef struct {
 | 
	
	
		
			
				|  | @@ -230,7 +269,9 @@ static void ssl_channel_destroy(grpc_security_context *ctx) {
 | 
	
		
			
				|  |  |    if (c->handshaker_factory != NULL) {
 | 
	
		
			
				|  |  |      tsi_ssl_handshaker_factory_destroy(c->handshaker_factory);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  if (c->secure_peer_name != NULL) gpr_free(c->secure_peer_name);
 | 
	
		
			
				|  |  | +  if (c->target_name != NULL) gpr_free(c->target_name);
 | 
	
		
			
				|  |  | +  if (c->overridden_target_name != NULL) gpr_free(c->overridden_target_name);
 | 
	
		
			
				|  |  | +  tsi_peer_destruct(&c->peer);
 | 
	
		
			
				|  |  |    gpr_free(ctx);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -244,11 +285,11 @@ static void ssl_server_destroy(grpc_security_context *ctx) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static grpc_security_status ssl_create_handshaker(
 | 
	
		
			
				|  |  |      tsi_ssl_handshaker_factory *handshaker_factory, int is_client,
 | 
	
		
			
				|  |  | -    const char *secure_peer_name, tsi_handshaker **handshaker) {
 | 
	
		
			
				|  |  | +    const char *peer_name, tsi_handshaker **handshaker) {
 | 
	
		
			
				|  |  |    tsi_result result = TSI_OK;
 | 
	
		
			
				|  |  |    if (handshaker_factory == NULL) return GRPC_SECURITY_ERROR;
 | 
	
		
			
				|  |  |    result = tsi_ssl_handshaker_factory_create_handshaker(
 | 
	
		
			
				|  |  | -      handshaker_factory, is_client ? secure_peer_name : NULL, handshaker);
 | 
	
		
			
				|  |  | +      handshaker_factory, is_client ? peer_name : NULL, handshaker);
 | 
	
		
			
				|  |  |    if (result != TSI_OK) {
 | 
	
		
			
				|  |  |      gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
 | 
	
		
			
				|  |  |              tsi_result_to_string(result));
 | 
	
	
		
			
				|  | @@ -261,7 +302,10 @@ static grpc_security_status ssl_channel_create_handshaker(
 | 
	
		
			
				|  |  |      grpc_security_context *ctx, tsi_handshaker **handshaker) {
 | 
	
		
			
				|  |  |    grpc_ssl_channel_security_context *c =
 | 
	
		
			
				|  |  |        (grpc_ssl_channel_security_context *)ctx;
 | 
	
		
			
				|  |  | -  return ssl_create_handshaker(c->handshaker_factory, 1, c->secure_peer_name,
 | 
	
		
			
				|  |  | +  return ssl_create_handshaker(c->handshaker_factory, 1,
 | 
	
		
			
				|  |  | +                               c->overridden_target_name != NULL
 | 
	
		
			
				|  |  | +                                   ? c->overridden_target_name
 | 
	
		
			
				|  |  | +                                   : c->target_name,
 | 
	
		
			
				|  |  |                                 handshaker);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -271,7 +315,7 @@ static grpc_security_status ssl_server_create_handshaker(
 | 
	
		
			
				|  |  |    return ssl_create_handshaker(c->handshaker_factory, 0, NULL, handshaker);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static grpc_security_status ssl_check_peer(const char *secure_peer_name,
 | 
	
		
			
				|  |  | +static grpc_security_status ssl_check_peer(const char *peer_name,
 | 
	
		
			
				|  |  |                                             const tsi_peer *peer) {
 | 
	
		
			
				|  |  |    /* Check the ALPN. */
 | 
	
		
			
				|  |  |    const tsi_peer_property *p =
 | 
	
	
		
			
				|  | @@ -291,28 +335,54 @@ static grpc_security_status ssl_check_peer(const char *secure_peer_name,
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* Check the peer name if specified. */
 | 
	
		
			
				|  |  | -  if (secure_peer_name != NULL &&
 | 
	
		
			
				|  |  | -      !tsi_ssl_peer_matches_name(peer, secure_peer_name)) {
 | 
	
		
			
				|  |  | -    gpr_log(GPR_ERROR, "Peer name %s is not in peer certificate",
 | 
	
		
			
				|  |  | -            secure_peer_name);
 | 
	
		
			
				|  |  | +  if (peer_name != NULL &&
 | 
	
		
			
				|  |  | +      !tsi_ssl_peer_matches_name(peer, peer_name)) {
 | 
	
		
			
				|  |  | +    gpr_log(GPR_ERROR, "Peer name %s is not in peer certificate", peer_name);
 | 
	
		
			
				|  |  |      return GRPC_SECURITY_ERROR;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    return GRPC_SECURITY_OK;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static grpc_security_status ssl_channel_check_peer(
 | 
	
		
			
				|  |  | -    grpc_security_context *ctx, const tsi_peer *peer,
 | 
	
		
			
				|  |  | -    grpc_security_check_peer_cb cb, void *user_data) {
 | 
	
		
			
				|  |  | +static grpc_security_status ssl_channel_check_peer(grpc_security_context *ctx,
 | 
	
		
			
				|  |  | +                                                   tsi_peer peer,
 | 
	
		
			
				|  |  | +                                                   grpc_security_check_cb cb,
 | 
	
		
			
				|  |  | +                                                   void *user_data) {
 | 
	
		
			
				|  |  |    grpc_ssl_channel_security_context *c =
 | 
	
		
			
				|  |  |        (grpc_ssl_channel_security_context *)ctx;
 | 
	
		
			
				|  |  | -  return ssl_check_peer(c->secure_peer_name, peer);
 | 
	
		
			
				|  |  | +  grpc_security_status status = ssl_check_peer(c->overridden_target_name != NULL
 | 
	
		
			
				|  |  | +                                                   ? c->overridden_target_name
 | 
	
		
			
				|  |  | +                                                   : c->target_name,
 | 
	
		
			
				|  |  | +                                               &peer);
 | 
	
		
			
				|  |  | +  c->peer = peer;
 | 
	
		
			
				|  |  | +  return status;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static grpc_security_status ssl_server_check_peer(grpc_security_context *ctx,
 | 
	
		
			
				|  |  | +                                                  tsi_peer peer,
 | 
	
		
			
				|  |  | +                                                  grpc_security_check_cb cb,
 | 
	
		
			
				|  |  | +                                                  void *user_data) {
 | 
	
		
			
				|  |  | +  /* TODO(jboeuf): Find a way to expose the peer to the authorization layer. */
 | 
	
		
			
				|  |  | +  grpc_security_status status = ssl_check_peer(NULL, &peer);
 | 
	
		
			
				|  |  | +  tsi_peer_destruct(&peer);
 | 
	
		
			
				|  |  | +  return status;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static grpc_security_status ssl_server_check_peer(
 | 
	
		
			
				|  |  | -    grpc_security_context *ctx, const tsi_peer *peer,
 | 
	
		
			
				|  |  | -    grpc_security_check_peer_cb cb, void *user_data) {
 | 
	
		
			
				|  |  | -  /* TODO(jboeuf): Find a way to expose the peer to the authorization layer. */
 | 
	
		
			
				|  |  | -  return ssl_check_peer(NULL, peer);
 | 
	
		
			
				|  |  | +static grpc_security_status ssl_channel_check_call_host(
 | 
	
		
			
				|  |  | +    grpc_channel_security_context *ctx, const char *host,
 | 
	
		
			
				|  |  | +    grpc_security_check_cb cb, void *user_data) {
 | 
	
		
			
				|  |  | +  grpc_ssl_channel_security_context *c =
 | 
	
		
			
				|  |  | +      (grpc_ssl_channel_security_context *)ctx;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  if (tsi_ssl_peer_matches_name(&c->peer, host)) return 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. */
 | 
	
		
			
				|  |  | +  if (c->overridden_target_name != NULL && !strcmp(host, c->target_name)) {
 | 
	
		
			
				|  |  | +    return GRPC_SECURITY_OK;
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    return GRPC_SECURITY_ERROR;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static grpc_security_context_vtable ssl_channel_vtable = {
 | 
	
	
		
			
				|  | @@ -345,7 +415,8 @@ static size_t get_default_pem_roots(const unsigned char **pem_root_certs) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  grpc_security_status grpc_ssl_channel_security_context_create(
 | 
	
		
			
				|  |  |      grpc_credentials *request_metadata_creds, const grpc_ssl_config *config,
 | 
	
		
			
				|  |  | -    const char *secure_peer_name, grpc_channel_security_context **ctx) {
 | 
	
		
			
				|  |  | +    const char *target_name, const char *overridden_target_name,
 | 
	
		
			
				|  |  | +    grpc_channel_security_context **ctx) {
 | 
	
		
			
				|  |  |    size_t num_alpn_protocols = grpc_chttp2_num_alpn_versions();
 | 
	
		
			
				|  |  |    const unsigned char **alpn_protocol_strings =
 | 
	
		
			
				|  |  |        gpr_malloc(sizeof(const char *) * num_alpn_protocols);
 | 
	
	
		
			
				|  | @@ -364,8 +435,8 @@ grpc_security_status grpc_ssl_channel_security_context_create(
 | 
	
		
			
				|  |  |          strlen(grpc_chttp2_get_alpn_version_index(i));
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  if (config == NULL || secure_peer_name == NULL) {
 | 
	
		
			
				|  |  | -    gpr_log(GPR_ERROR, "An ssl channel needs a config and a secure name.");
 | 
	
		
			
				|  |  | +  if (config == NULL || target_name == NULL) {
 | 
	
		
			
				|  |  | +    gpr_log(GPR_ERROR, "An ssl channel needs a config and a target name.");
 | 
	
		
			
				|  |  |      goto error;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    if (!check_request_metadata_creds(request_metadata_creds)) {
 | 
	
	
		
			
				|  | @@ -379,8 +450,12 @@ grpc_security_status grpc_ssl_channel_security_context_create(
 | 
	
		
			
				|  |  |    c->base.base.vtable = &ssl_channel_vtable;
 | 
	
		
			
				|  |  |    c->base.base.is_client_side = 1;
 | 
	
		
			
				|  |  |    c->base.request_metadata_creds = grpc_credentials_ref(request_metadata_creds);
 | 
	
		
			
				|  |  | -  if (secure_peer_name != NULL) {
 | 
	
		
			
				|  |  | -    c->secure_peer_name = gpr_strdup(secure_peer_name);
 | 
	
		
			
				|  |  | +  c->base.check_call_host = ssl_channel_check_call_host;
 | 
	
		
			
				|  |  | +  if (target_name != NULL) {
 | 
	
		
			
				|  |  | +    c->target_name = gpr_strdup(target_name);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  if (overridden_target_name != NULL) {
 | 
	
		
			
				|  |  | +    c->overridden_target_name = gpr_strdup(overridden_target_name);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    if (config->pem_root_certs == NULL) {
 | 
	
		
			
				|  |  |      pem_root_certs_size = get_default_pem_roots(&pem_root_certs);
 | 
	
	
		
			
				|  | @@ -478,7 +553,7 @@ grpc_channel *grpc_ssl_channel_create(grpc_credentials *ssl_creds,
 | 
	
		
			
				|  |  |    grpc_channel *channel = NULL;
 | 
	
		
			
				|  |  |    grpc_security_status status = GRPC_SECURITY_OK;
 | 
	
		
			
				|  |  |    size_t i = 0;
 | 
	
		
			
				|  |  | -  const char *secure_peer_name = target;
 | 
	
		
			
				|  |  | +  const char *overridden_target_name = NULL;
 | 
	
		
			
				|  |  |    grpc_arg arg;
 | 
	
		
			
				|  |  |    grpc_channel_args *new_args;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -486,13 +561,13 @@ grpc_channel *grpc_ssl_channel_create(grpc_credentials *ssl_creds,
 | 
	
		
			
				|  |  |      grpc_arg *arg = &args->args[i];
 | 
	
		
			
				|  |  |      if (!strcmp(arg->key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG) &&
 | 
	
		
			
				|  |  |          arg->type == GRPC_ARG_STRING) {
 | 
	
		
			
				|  |  | -      secure_peer_name = arg->value.string;
 | 
	
		
			
				|  |  | +      overridden_target_name = arg->value.string;
 | 
	
		
			
				|  |  |        break;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    status = grpc_ssl_channel_security_context_create(
 | 
	
		
			
				|  |  |        request_metadata_creds, grpc_ssl_credentials_get_config(ssl_creds),
 | 
	
		
			
				|  |  | -      secure_peer_name, &ctx);
 | 
	
		
			
				|  |  | +      target, overridden_target_name, &ctx);
 | 
	
		
			
				|  |  |    if (status != GRPC_SECURITY_OK) {
 | 
	
		
			
				|  |  |      return grpc_lame_client_channel_create();
 | 
	
		
			
				|  |  |    }
 | 
	
	
		
			
				|  | @@ -510,7 +585,7 @@ grpc_channel *grpc_fake_transport_security_channel_create(
 | 
	
		
			
				|  |  |      grpc_credentials *fake_creds, grpc_credentials *request_metadata_creds,
 | 
	
		
			
				|  |  |      const char *target, const grpc_channel_args *args) {
 | 
	
		
			
				|  |  |    grpc_channel_security_context *ctx =
 | 
	
		
			
				|  |  | -      grpc_fake_channel_security_context_create(request_metadata_creds);
 | 
	
		
			
				|  |  | +      grpc_fake_channel_security_context_create(request_metadata_creds, 1);
 | 
	
		
			
				|  |  |    grpc_channel *channel =
 | 
	
		
			
				|  |  |        grpc_secure_channel_create_internal(target, args, ctx);
 | 
	
		
			
				|  |  |    grpc_security_context_unref(&ctx->base);
 |