Exemplo n.º 1
0
GPR_EXPORT grpc_channel_credentials *GPR_CALLTYPE
grpcsharp_ssl_credentials_create(const char *pem_root_certs,
                                 const char *key_cert_pair_cert_chain,
                                 const char *key_cert_pair_private_key) {
  grpc_ssl_pem_key_cert_pair key_cert_pair;
  if (key_cert_pair_cert_chain || key_cert_pair_private_key) {
    key_cert_pair.cert_chain = key_cert_pair_cert_chain;
    key_cert_pair.private_key = key_cert_pair_private_key;
    return grpc_ssl_credentials_create(pem_root_certs, &key_cert_pair, NULL);
  } else {
    GPR_ASSERT(!key_cert_pair_cert_chain);
    GPR_ASSERT(!key_cert_pair_private_key);
    return grpc_ssl_credentials_create(pem_root_certs, NULL, NULL);
  }
}
Exemplo n.º 2
0
static void test_ssl_oauth2_iam_composite_creds(void) {
    grpc_credentials *ssl_creds =
        grpc_ssl_credentials_create(test_root_cert, NULL);
    const grpc_credentials_array *creds_array;
    grpc_credentials *oauth2_creds =
        grpc_fake_oauth2_credentials_create(test_oauth2_bearer_token, 0);
    grpc_credentials *aux_creds =
        grpc_composite_credentials_create(ssl_creds, oauth2_creds);
    grpc_credentials *iam_creds = grpc_iam_credentials_create(
                                      test_iam_authorization_token, test_iam_authority_selector);
    grpc_credentials *composite_creds =
        grpc_composite_credentials_create(aux_creds, iam_creds);
    grpc_credentials_unref(ssl_creds);
    grpc_credentials_unref(oauth2_creds);
    grpc_credentials_unref(aux_creds);
    grpc_credentials_unref(iam_creds);
    GPR_ASSERT(strcmp(composite_creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) ==
               0);
    GPR_ASSERT(grpc_credentials_has_request_metadata(composite_creds));
    GPR_ASSERT(!grpc_credentials_has_request_metadata_only(composite_creds));
    creds_array = grpc_composite_credentials_get_credentials(composite_creds);
    GPR_ASSERT(creds_array->num_creds == 3);
    GPR_ASSERT(strcmp(creds_array->creds_array[0]->type,
                      GRPC_CREDENTIALS_TYPE_SSL) == 0);
    GPR_ASSERT(strcmp(creds_array->creds_array[1]->type,
                      GRPC_CREDENTIALS_TYPE_OAUTH2) == 0);
    GPR_ASSERT(strcmp(creds_array->creds_array[2]->type,
                      GRPC_CREDENTIALS_TYPE_IAM) == 0);
    grpc_credentials_get_request_metadata(composite_creds, NULL, test_service_url,
                                          check_ssl_oauth2_iam_composite_metadata,
                                          composite_creds);
}
Exemplo n.º 3
0
GPR_EXPORT grpc_channel_credentials* GPR_CALLTYPE
grpcsharp_ssl_credentials_create(const char* pem_root_certs,
                                 const char* key_cert_pair_cert_chain,
                                 const char* key_cert_pair_private_key,
                                 void* verify_peer_callback_tag) {
  grpc_ssl_pem_key_cert_pair key_cert_pair;
  verify_peer_options verify_options;
  grpc_ssl_pem_key_cert_pair* key_cert_pair_ptr = NULL;
  verify_peer_options* verify_options_ptr = NULL;

  if (key_cert_pair_cert_chain || key_cert_pair_private_key) {
    memset(&key_cert_pair, 0, sizeof(key_cert_pair));
    key_cert_pair.cert_chain = key_cert_pair_cert_chain;
    key_cert_pair.private_key = key_cert_pair_private_key;
    key_cert_pair_ptr = &key_cert_pair;
  } else {
    GPR_ASSERT(!key_cert_pair_cert_chain);
    GPR_ASSERT(!key_cert_pair_private_key);
  }

  if (verify_peer_callback_tag != NULL) {
    memset(&verify_options, 0, sizeof(verify_peer_options));
    verify_options.verify_peer_callback_userdata = verify_peer_callback_tag;
    verify_options.verify_peer_destruct = grpcsharp_verify_peer_destroy_handler;
    verify_options.verify_peer_callback = grpcsharp_verify_peer_handler;
    verify_options_ptr = &verify_options;
  }

  return grpc_ssl_credentials_create(pem_root_certs, key_cert_pair_ptr,
                                     verify_options_ptr, NULL);
}
Exemplo n.º 4
0
grpc_channel_credentials *grpc_google_default_credentials_create(void) {
  grpc_channel_credentials *result = NULL;
  grpc_call_credentials *call_creds = NULL;

  GRPC_API_TRACE("grpc_google_default_credentials_create(void)", 0, ());

  gpr_once_init(&g_once, init_default_credentials);

  gpr_mu_lock(&g_mu);

  if (default_credentials != NULL) {
    result = grpc_channel_credentials_ref(default_credentials);
    goto end;
  }

  /* First, try the environment variable. */
  call_creds = create_default_creds_from_path(
      gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR));
  if (call_creds != NULL) goto end;

  /* Then the well-known file. */
  call_creds = create_default_creds_from_path(
      grpc_get_well_known_google_credentials_file_path());
  if (call_creds != NULL) goto end;

  /* At last try to see if we're on compute engine (do the detection only once
     since it requires a network test). */
  if (!compute_engine_detection_done) {
    int need_compute_engine_creds = is_stack_running_on_compute_engine();
    compute_engine_detection_done = 1;
    if (need_compute_engine_creds) {
      call_creds = grpc_google_compute_engine_credentials_create(NULL);
    }
  }

end:
  if (result == NULL) {
    if (call_creds != NULL) {
      /* Blend with default ssl credentials and add a global reference so that
         it
         can be cached and re-served. */
      grpc_channel_credentials *ssl_creds =
          grpc_ssl_credentials_create(NULL, NULL, NULL);
      default_credentials = grpc_channel_credentials_ref(
          grpc_composite_channel_credentials_create(ssl_creds, call_creds,
                                                    NULL));
      GPR_ASSERT(default_credentials != NULL);
      grpc_channel_credentials_unref(ssl_creds);
      grpc_call_credentials_unref(call_creds);
      result = default_credentials;
    } else {
      gpr_log(GPR_ERROR, "Could not create google default credentials.");
    }
  }
  gpr_mu_unlock(&g_mu);
  return result;
}
Exemplo n.º 5
0
void test_ssl_fake_transport_security_composite_creds_failure(void) {
    grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL);
    grpc_credentials *fake_transport_security_creds =
        grpc_fake_transport_security_credentials_create();

    /* 2 connector credentials: should not work. */
    GPR_ASSERT(grpc_composite_credentials_create(
                   ssl_creds, fake_transport_security_creds) == NULL);
    grpc_credentials_unref(ssl_creds);
    grpc_credentials_unref(fake_transport_security_creds);
}
static void chttp2_init_client_simple_ssl_secure_fullstack(
    grpc_end2end_test_fixture *f, grpc_channel_args *client_args) {
  grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL);
  grpc_arg ssl_name_override = {GRPC_ARG_STRING,
                                GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
                                {"foo.test.google.fr"}};
  grpc_channel_args *new_client_args =
      grpc_channel_args_copy_and_add(client_args, &ssl_name_override, 1);
  chttp2_init_client_secure_fullstack(f, new_client_args, ssl_creds);
  grpc_channel_args_destroy(new_client_args);
}
Exemplo n.º 7
0
/*
  call-seq:
    creds1 = Credentials.new()
    ...
    creds2 = Credentials.new(pem_root_certs)
    ...
    creds3 = Credentials.new(pem_root_certs, pem_private_key,
                             pem_cert_chain)
    pem_root_certs: (optional) PEM encoding of the server root certificate
    pem_private_key: (optional) PEM encoding of the client's private key
    pem_cert_chain: (optional) PEM encoding of the client's cert chain
    Initializes Credential instances. */
static VALUE grpc_rb_channel_credentials_init(int argc, VALUE* argv,
                                              VALUE self) {
  VALUE pem_root_certs = Qnil;
  VALUE pem_private_key = Qnil;
  VALUE pem_cert_chain = Qnil;
  grpc_rb_channel_credentials* wrapper = NULL;
  grpc_channel_credentials* creds = NULL;
  grpc_ssl_pem_key_cert_pair key_cert_pair;
  const char* pem_root_certs_cstr = NULL;
  MEMZERO(&key_cert_pair, grpc_ssl_pem_key_cert_pair, 1);

  /* "03" == no mandatory arg, 3 optional */
  rb_scan_args(argc, argv, "03", &pem_root_certs, &pem_private_key,
               &pem_cert_chain);

  TypedData_Get_Struct(self, grpc_rb_channel_credentials,
                       &grpc_rb_channel_credentials_data_type, wrapper);
  if (pem_root_certs != Qnil) {
    pem_root_certs_cstr = RSTRING_PTR(pem_root_certs);
  }
  if (pem_private_key == Qnil && pem_cert_chain == Qnil) {
    creds = grpc_ssl_credentials_create(pem_root_certs_cstr, NULL, NULL, NULL);
  } else {
    key_cert_pair.private_key = RSTRING_PTR(pem_private_key);
    key_cert_pair.cert_chain = RSTRING_PTR(pem_cert_chain);
    creds = grpc_ssl_credentials_create(pem_root_certs_cstr, &key_cert_pair,
                                        NULL, NULL);
  }
  if (creds == NULL) {
    rb_raise(rb_eRuntimeError, "could not create a credentials, not sure why");
    return Qnil;
  }
  wrapper->wrapped = creds;

  /* Add the input objects as hidden fields to preserve them. */
  rb_ivar_set(self, id_pem_cert_chain, pem_cert_chain);
  rb_ivar_set(self, id_pem_private_key, pem_private_key);
  rb_ivar_set(self, id_pem_root_certs, pem_root_certs);

  return self;
}
Exemplo n.º 8
0
/*
  call-seq:
    creds1 = Credentials.new(pem_root_certs)
    ...
    creds2 = Credentials.new(pem_root_certs, pem_private_key,
                             pem_cert_chain)
    pem_root_certs: (required) PEM encoding of the server root certificate
    pem_private_key: (optional) PEM encoding of the client's private key
    pem_cert_chain: (optional) PEM encoding of the client's cert chain
    Initializes Credential instances. */
static VALUE grpc_rb_credentials_init(int argc, VALUE *argv, VALUE self) {
  VALUE pem_root_certs = Qnil;
  VALUE pem_private_key = Qnil;
  VALUE pem_cert_chain = Qnil;
  grpc_rb_credentials *wrapper = NULL;
  grpc_credentials *creds = NULL;
  grpc_ssl_pem_key_cert_pair key_cert_pair;
  MEMZERO(&key_cert_pair, grpc_ssl_pem_key_cert_pair, 1);
  /* TODO: Remove mandatory arg when we support default roots. */
  /* "12" == 1 mandatory arg, 2 (credentials) is optional */
  rb_scan_args(argc, argv, "12", &pem_root_certs, &pem_private_key,
               &pem_cert_chain);

  Data_Get_Struct(self, grpc_rb_credentials, wrapper);
  if (pem_root_certs == Qnil) {
    rb_raise(rb_eRuntimeError,
             "could not create a credential: nil pem_root_certs");
    return Qnil;
  }
  if (pem_private_key == Qnil && pem_cert_chain == Qnil) {
    creds = grpc_ssl_credentials_create(RSTRING_PTR(pem_root_certs), NULL);
  } else {
    key_cert_pair.private_key = RSTRING_PTR(pem_private_key);
    key_cert_pair.cert_chain = RSTRING_PTR(pem_cert_chain);
    creds = grpc_ssl_credentials_create(
        RSTRING_PTR(pem_root_certs), &key_cert_pair);
  }
  if (creds == NULL) {
    rb_raise(rb_eRuntimeError, "could not create a credentials, not sure why");
    return Qnil;
  }
  wrapper->wrapped = creds;

  /* Add the input objects as hidden fields to preserve them. */
  rb_ivar_set(self, id_pem_cert_chain, pem_cert_chain);
  rb_ivar_set(self, id_pem_private_key, pem_private_key);
  rb_ivar_set(self, id_pem_root_certs, pem_root_certs);

  return self;
}
static grpc_channel *create_proxy_client(const char *target) {
  grpc_channel *channel;
  grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL);
  grpc_arg ssl_name_override = {GRPC_ARG_STRING,
                                GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
                                {"foo.test.google.fr"}};
  grpc_channel_args client_args;
  client_args.num_args = 1;
  client_args.args = &ssl_name_override;
  channel = grpc_secure_channel_create(ssl_creds, target, &client_args);
  grpc_credentials_release(ssl_creds);
  return channel;
}
Exemplo n.º 10
0
static grpc_channel *create_proxy_client(const char *target,
                                         grpc_channel_args *client_args) {
  grpc_channel *channel;
  grpc_channel_credentials *ssl_creds =
      grpc_ssl_credentials_create(NULL, NULL, NULL);
  grpc_arg ssl_name_override = {GRPC_ARG_STRING,
                                GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
                                {"foo.test.google.fr"}};
  grpc_channel_args *new_client_args =
      grpc_channel_args_copy_and_add(client_args, &ssl_name_override, 1);
  channel =
      grpc_secure_channel_create(ssl_creds, target, new_client_args, NULL);
  grpc_channel_credentials_release(ssl_creds);
  grpc_channel_args_destroy(new_client_args);
  return channel;
}
Exemplo n.º 11
0
grpc_credentials *grpc_google_default_credentials_create(void) {
  grpc_credentials *result = NULL;
  int serving_cached_credentials = 0;
  gpr_once_init(&g_once, init_default_credentials);

  gpr_mu_lock(&g_mu);

  if (default_credentials != NULL) {
    result = grpc_credentials_ref(default_credentials);
    serving_cached_credentials = 1;
    goto end;
  }

  /* First, try the environment variable. */
  result =
      create_jwt_creds_from_path(gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR));
  if (result != NULL) goto end;

  /* Then the well-known file. */
  result = create_refresh_token_creds_from_path(
      grpc_get_well_known_google_credentials_file_path());
  if (result != NULL) goto end;

  /* At last try to see if we're on compute engine (do the detection only once
     since it requires a network test). */
  if (!compute_engine_detection_done) {
    int need_compute_engine_creds = is_stack_running_on_compute_engine();
    compute_engine_detection_done = 1;
    if (need_compute_engine_creds) {
      result = grpc_compute_engine_credentials_create();
    }
  }

end:
  if (!serving_cached_credentials && result != NULL) {
    /* Blend with default ssl credentials and add a global reference so that it
       can be cached and re-served. */
    result = grpc_composite_credentials_create(
        grpc_ssl_credentials_create(NULL, NULL), result);
    GPR_ASSERT(result != NULL);
    default_credentials = grpc_credentials_ref(result);
  }
  gpr_mu_unlock(&g_mu);
  return result;
}
static void chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack(
    grpc_end2end_test_fixture *f, grpc_channel_args *client_args) {
  grpc_credentials *ssl_creds =
      grpc_ssl_credentials_create(test_root_cert, NULL);
  grpc_credentials *oauth2_creds =
      grpc_fake_oauth2_credentials_create("Bearer aaslkfjs424535asdf", 1);
  grpc_credentials *ssl_oauth2_creds =
      grpc_composite_credentials_create(ssl_creds, oauth2_creds);
  grpc_arg ssl_name_override = {GRPC_ARG_STRING,
                                GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
                                {"foo.test.google.fr"}};
  grpc_channel_args *new_client_args =
      grpc_channel_args_copy_and_add(client_args, &ssl_name_override);
  chttp2_init_client_secure_fullstack(f, new_client_args, ssl_oauth2_creds);
  grpc_channel_args_destroy(new_client_args);
  grpc_credentials_release(ssl_creds);
  grpc_credentials_release(oauth2_creds);
}
Exemplo n.º 13
0
static void run_test(const char *target, size_t nops) {
    grpc_channel_credentials *ssl_creds =
        grpc_ssl_credentials_create(NULL, NULL, NULL);
    grpc_channel *channel;
    grpc_call *c;

    grpc_metadata_array initial_metadata_recv;
    grpc_metadata_array trailing_metadata_recv;
    char *details = NULL;
    size_t details_capacity = 0;
    grpc_status_code status;
    grpc_call_error error;
    gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5);
    grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
    cq_verifier *cqv = cq_verifier_create(cq);

    grpc_op ops[6];
    grpc_op *op;

    grpc_arg ssl_name_override = {GRPC_ARG_STRING,
                                  GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
    {"foo.test.google.fr"}
                                 };
    grpc_channel_args args;

    args.num_args = 1;
    args.args = &ssl_name_override;

    grpc_metadata_array_init(&initial_metadata_recv);
    grpc_metadata_array_init(&trailing_metadata_recv);

    channel = grpc_secure_channel_create(ssl_creds, target, &args, NULL);
    c = grpc_channel_create_call(channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
                                 "/foo", "foo.test.google.fr:1234", deadline,
                                 NULL);

    op = ops;
    op->op = GRPC_OP_SEND_INITIAL_METADATA;
    op->data.send_initial_metadata.count = 0;
    op->flags = 0;
    op->reserved = NULL;
    op++;
    op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
    op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
    op->data.recv_status_on_client.status = &status;
    op->data.recv_status_on_client.status_details = &details;
    op->data.recv_status_on_client.status_details_capacity = &details_capacity;
    op->flags = 0;
    op->reserved = NULL;
    op++;
    op->op = GRPC_OP_RECV_INITIAL_METADATA;
    op->data.recv_initial_metadata = &initial_metadata_recv;
    op->flags = 0;
    op->reserved = NULL;
    op++;
    op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
    op->flags = 0;
    op->reserved = NULL;
    op++;
    error = grpc_call_start_batch(c, ops, nops, tag(1), NULL);
    GPR_ASSERT(GRPC_CALL_OK == error);

    cq_expect_completion(cqv, tag(1), 1);
    cq_verify(cqv);

    GPR_ASSERT(status != GRPC_STATUS_OK);

    grpc_call_destroy(c);
    gpr_free(details);
    grpc_metadata_array_destroy(&initial_metadata_recv);
    grpc_metadata_array_destroy(&trailing_metadata_recv);

    grpc_channel_destroy(channel);
    grpc_completion_queue_destroy(cq);
    cq_verifier_destroy(cqv);
    grpc_channel_credentials_release(ssl_creds);
}
Exemplo n.º 14
0
grpc_channel_credentials *grpc_google_default_credentials_create(void) {
  grpc_channel_credentials *result = NULL;
  grpc_call_credentials *call_creds = NULL;
  grpc_error *error = GRPC_ERROR_CREATE("Failed to create Google credentials");
  grpc_error *err;
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;

  GRPC_API_TRACE("grpc_google_default_credentials_create(void)", 0, ());

  gpr_once_init(&g_once, init_default_credentials);

  gpr_mu_lock(&g_state_mu);

  if (default_credentials != NULL) {
    result = grpc_channel_credentials_ref(default_credentials);
    goto end;
  }

  /* First, try the environment variable. */
  err = create_default_creds_from_path(
      &exec_ctx, gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR), &call_creds);
  if (err == GRPC_ERROR_NONE) goto end;
  error = grpc_error_add_child(error, err);

  /* Then the well-known file. */
  err = create_default_creds_from_path(
      &exec_ctx, grpc_get_well_known_google_credentials_file_path(),
      &call_creds);
  if (err == GRPC_ERROR_NONE) goto end;
  error = grpc_error_add_child(error, err);

  /* At last try to see if we're on compute engine (do the detection only once
     since it requires a network test). */
  if (!compute_engine_detection_done) {
    int need_compute_engine_creds =
        is_stack_running_on_compute_engine(&exec_ctx);
    compute_engine_detection_done = 1;
    if (need_compute_engine_creds) {
      call_creds = grpc_google_compute_engine_credentials_create(NULL);
      if (call_creds == NULL) {
        error = grpc_error_add_child(
            error, GRPC_ERROR_CREATE("Failed to get credentials from network"));
      }
    }
  }

end:
  if (result == NULL) {
    if (call_creds != NULL) {
      /* Blend with default ssl credentials and add a global reference so that
         it
         can be cached and re-served. */
      grpc_channel_credentials *ssl_creds =
          grpc_ssl_credentials_create(NULL, NULL, NULL);
      default_credentials = grpc_channel_credentials_ref(
          grpc_composite_channel_credentials_create(ssl_creds, call_creds,
                                                    NULL));
      GPR_ASSERT(default_credentials != NULL);
      grpc_channel_credentials_unref(&exec_ctx, ssl_creds);
      grpc_call_credentials_unref(&exec_ctx, call_creds);
      result = default_credentials;
    } else {
      gpr_log(GPR_ERROR, "Could not create google default credentials.");
    }
  }
  gpr_mu_unlock(&g_state_mu);
  if (result == NULL) {
    GRPC_LOG_IF_ERROR("grpc_google_default_credentials_create", error);
  } else {
    GRPC_ERROR_UNREF(error);
  }
  grpc_exec_ctx_finish(&exec_ctx);
  return result;
}
Exemplo n.º 15
0
// This test launches a minimal TLS server on a separate thread and then
// establishes a TLS handshake via the core library to the server. The TLS
// server validates ALPN aspects of the handshake and supplies the protocol
// specified in the server_alpn_preferred argument to the client.
static bool client_ssl_test(char *server_alpn_preferred) {
  bool success = true;

  grpc_init();

  // Find a port we can bind to. Retries added to handle flakes in port server
  // and port picking.
  int port = -1;
  int server_socket = -1;
  int socket_retries = 10;
  while (server_socket == -1 && socket_retries-- > 0) {
    port = grpc_pick_unused_port_or_die();
    server_socket = create_socket(port);
    if (server_socket == -1) {
      sleep(1);
    }
  }
  GPR_ASSERT(server_socket > 0);

  // Launch the TLS server thread.
  gpr_thd_options thdopt = gpr_thd_options_default();
  gpr_thd_id thdid;
  gpr_thd_options_set_joinable(&thdopt);
  server_args args = {.socket = server_socket,
                      .alpn_preferred = server_alpn_preferred};
  GPR_ASSERT(gpr_thd_new(&thdid, server_thread, &args, &thdopt));

  // Load key pair and establish client SSL credentials.
  grpc_ssl_pem_key_cert_pair pem_key_cert_pair;
  gpr_slice ca_slice, cert_slice, key_slice;
  GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
                               grpc_load_file(SSL_CA_PATH, 1, &ca_slice)));
  GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
                               grpc_load_file(SSL_CERT_PATH, 1, &cert_slice)));
  GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
                               grpc_load_file(SSL_KEY_PATH, 1, &key_slice)));
  const char *ca_cert = (const char *)GPR_SLICE_START_PTR(ca_slice);
  pem_key_cert_pair.private_key = (const char *)GPR_SLICE_START_PTR(key_slice);
  pem_key_cert_pair.cert_chain = (const char *)GPR_SLICE_START_PTR(cert_slice);
  grpc_channel_credentials *ssl_creds =
      grpc_ssl_credentials_create(ca_cert, &pem_key_cert_pair, NULL);

  // Establish a channel pointing at the TLS server. Since the gRPC runtime is
  // lazy, this won't necessarily establish a connection yet.
  char *target;
  gpr_asprintf(&target, "127.0.0.1:%d", port);
  grpc_arg ssl_name_override = {GRPC_ARG_STRING,
                                GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
                                {"foo.test.google.fr"}};
  grpc_channel_args grpc_args;
  grpc_args.num_args = 1;
  grpc_args.args = &ssl_name_override;
  grpc_channel *channel =
      grpc_secure_channel_create(ssl_creds, target, &grpc_args, NULL);
  GPR_ASSERT(channel);
  gpr_free(target);

  // Initially the channel will be idle, the
  // grpc_channel_check_connectivity_state triggers an attempt to connect.
  GPR_ASSERT(grpc_channel_check_connectivity_state(
                 channel, 1 /* try_to_connect */) == GRPC_CHANNEL_IDLE);

  // Wait a bounded number of times for the channel to be ready. When the
  // channel is ready, the initial TLS handshake will have successfully
  // completed and we know that the client's ALPN list satisfied the server.
  int retries = 10;
  grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
  grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
  while (state != GRPC_CHANNEL_READY && retries-- > 0) {
    grpc_channel_watch_connectivity_state(
        channel, state, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), cq, NULL);
    gpr_timespec cq_deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5);
    grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, NULL);
    GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
    state =
        grpc_channel_check_connectivity_state(channel, 0 /* try_to_connect */);
  }
  grpc_completion_queue_destroy(cq);
  if (retries < 0) {
    success = false;
  }

  grpc_channel_destroy(channel);
  grpc_channel_credentials_release(ssl_creds);
  gpr_slice_unref(cert_slice);
  gpr_slice_unref(key_slice);
  gpr_slice_unref(ca_slice);

  gpr_thd_join(thdid);

  grpc_shutdown();

  return success;
}