Exemple #1
0
void grpc_do_security_handshake(
    grpc_exec_ctx *exec_ctx, tsi_handshaker *handshaker,
    grpc_security_connector *connector, bool is_client_side,
    grpc_endpoint *nonsecure_endpoint, gpr_slice_buffer *read_buffer,
    gpr_timespec deadline, grpc_security_handshake_done_cb cb,
    void *user_data) {
    grpc_security_connector_handshake_list *handshake_node;
    grpc_security_handshake *h = gpr_malloc(sizeof(grpc_security_handshake));
    memset(h, 0, sizeof(grpc_security_handshake));
    h->handshaker = handshaker;
    h->connector = GRPC_SECURITY_CONNECTOR_REF(connector, "handshake");
    h->is_client_side = is_client_side;
    h->handshake_buffer_size = GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE;
    h->handshake_buffer = gpr_malloc(h->handshake_buffer_size);
    h->wrapped_endpoint = nonsecure_endpoint;
    h->user_data = user_data;
    h->cb = cb;
    gpr_ref_init(&h->refs, 2); /* timer and handshake proper each get a ref */
    grpc_closure_init(&h->on_handshake_data_sent_to_peer,
                      on_handshake_data_sent_to_peer, h);
    grpc_closure_init(&h->on_handshake_data_received_from_peer,
                      on_handshake_data_received_from_peer, h);
    gpr_slice_buffer_init(&h->left_overs);
    gpr_slice_buffer_init(&h->outgoing);
    gpr_slice_buffer_init(&h->incoming);
    if (read_buffer != NULL) {
        gpr_slice_buffer_move_into(read_buffer, &h->incoming);
        gpr_free(read_buffer);
    }
    if (!is_client_side) {
        grpc_server_security_connector *server_connector =
            (grpc_server_security_connector *)connector;
        handshake_node = gpr_malloc(sizeof(grpc_security_connector_handshake_list));
        handshake_node->handshake = h;
        gpr_mu_lock(&server_connector->mu);
        handshake_node->next = server_connector->handshaking_handshakes;
        server_connector->handshaking_handshakes = handshake_node;
        gpr_mu_unlock(&server_connector->mu);
    }
    send_handshake_bytes_to_peer(exec_ctx, h);
    grpc_timer_init(exec_ctx, &h->timer,
                    gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
                    on_timeout, h, gpr_now(GPR_CLOCK_MONOTONIC));
}
void grpc_setup_secure_transport(grpc_security_connector *connector,
                                 grpc_endpoint *nonsecure_endpoint,
                                 grpc_secure_transport_setup_done_cb cb,
                                 void *user_data) {
  grpc_security_status result = GRPC_SECURITY_OK;
  grpc_secure_transport_setup *s =
      gpr_malloc(sizeof(grpc_secure_transport_setup));
  memset(s, 0, sizeof(grpc_secure_transport_setup));
  result = grpc_security_connector_create_handshaker(connector, &s->handshaker);
  if (result != GRPC_SECURITY_OK) {
    secure_transport_setup_done(s, 0);
    return;
  }
  s->connector = grpc_security_connector_ref(connector);
  s->handshake_buffer_size = GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE;
  s->handshake_buffer = gpr_malloc(s->handshake_buffer_size);
  s->endpoint = nonsecure_endpoint;
  s->user_data = user_data;
  s->cb = cb;
  gpr_slice_buffer_init(&s->left_overs);
  send_handshake_bytes_to_peer(s);
}
Exemple #3
0
static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
        void *handshake,
        grpc_error *error) {
    grpc_security_handshake *h = handshake;
    size_t consumed_slice_size = 0;
    tsi_result result = TSI_OK;
    size_t i;
    size_t num_left_overs;
    int has_left_overs_in_current_slice = 0;

    if (error != GRPC_ERROR_NONE) {
        security_handshake_done(
            exec_ctx, h,
            GRPC_ERROR_CREATE_REFERENCING("Handshake read failed", &error, 1));
        return;
    }

    for (i = 0; i < h->incoming.count; i++) {
        consumed_slice_size = GPR_SLICE_LENGTH(h->incoming.slices[i]);
        result = tsi_handshaker_process_bytes_from_peer(
                     h->handshaker, GPR_SLICE_START_PTR(h->incoming.slices[i]),
                     &consumed_slice_size);
        if (!tsi_handshaker_is_in_progress(h->handshaker)) break;
    }

    if (tsi_handshaker_is_in_progress(h->handshaker)) {
        /* We may need more data. */
        if (result == TSI_INCOMPLETE_DATA) {
            grpc_endpoint_read(exec_ctx, h->wrapped_endpoint, &h->incoming,
                               &h->on_handshake_data_received_from_peer);
            return;
        } else {
            send_handshake_bytes_to_peer(exec_ctx, h);
            return;
        }
    }

    if (result != TSI_OK) {
        security_handshake_done(exec_ctx, h,
                                grpc_set_tsi_error_result(
                                    GRPC_ERROR_CREATE("Handshake failed"), result));
        return;
    }

    /* Handshake is done and successful this point. */
    has_left_overs_in_current_slice =
        (consumed_slice_size < GPR_SLICE_LENGTH(h->incoming.slices[i]));
    num_left_overs =
        (has_left_overs_in_current_slice ? 1 : 0) + h->incoming.count - i - 1;
    if (num_left_overs == 0) {
        check_peer(exec_ctx, h);
        return;
    }

    /* Put the leftovers in our buffer (ownership transfered). */
    if (has_left_overs_in_current_slice) {
        gpr_slice_buffer_add(
            &h->left_overs,
            gpr_slice_split_tail(&h->incoming.slices[i], consumed_slice_size));
        gpr_slice_unref(
            h->incoming.slices[i]); /* split_tail above increments refcount. */
    }
    gpr_slice_buffer_addn(
        &h->left_overs, &h->incoming.slices[i + 1],
        num_left_overs - (size_t)has_left_overs_in_current_slice);
    check_peer(exec_ctx, h);
}
static void on_handshake_data_received_from_peer(
    void *setup, gpr_slice *slices, size_t nslices,
    grpc_endpoint_cb_status error) {
  grpc_secure_transport_setup *s = setup;
  size_t consumed_slice_size = 0;
  tsi_result result = TSI_OK;
  size_t i;
  size_t num_left_overs;
  int has_left_overs_in_current_slice = 0;

  if (error != GRPC_ENDPOINT_CB_OK) {
    gpr_log(GPR_ERROR, "Read failed.");
    cleanup_slices(slices, nslices);
    secure_transport_setup_done(s, 0);
    return;
  }

  for (i = 0; i < nslices; i++) {
    consumed_slice_size = GPR_SLICE_LENGTH(slices[i]);
    result = tsi_handshaker_process_bytes_from_peer(
        s->handshaker, GPR_SLICE_START_PTR(slices[i]), &consumed_slice_size);
    if (!tsi_handshaker_is_in_progress(s->handshaker)) break;
  }

  if (tsi_handshaker_is_in_progress(s->handshaker)) {
    /* We may need more data. */
    if (result == TSI_INCOMPLETE_DATA) {
      /* TODO(klempner,jboeuf): This should probably use the client setup
         deadline */
      grpc_endpoint_notify_on_read(s->endpoint,
                                   on_handshake_data_received_from_peer, setup);
      cleanup_slices(slices, nslices);
      return;
    } else {
      send_handshake_bytes_to_peer(s);
      cleanup_slices(slices, nslices);
      return;
    }
  }

  if (result != TSI_OK) {
    gpr_log(GPR_ERROR, "Handshake failed with error %s",
            tsi_result_to_string(result));
    cleanup_slices(slices, nslices);
    secure_transport_setup_done(s, 0);
    return;
  }

  /* Handshake is done and successful this point. */
  has_left_overs_in_current_slice =
      (consumed_slice_size < GPR_SLICE_LENGTH(slices[i]));
  num_left_overs = (has_left_overs_in_current_slice ? 1 : 0) + nslices - i - 1;
  if (num_left_overs == 0) {
    cleanup_slices(slices, nslices);
    check_peer(s);
    return;
  }
  cleanup_slices(slices, nslices - num_left_overs);

  /* Put the leftovers in our buffer (ownership transfered). */
  if (has_left_overs_in_current_slice) {
    gpr_slice_buffer_add(&s->left_overs,
                         gpr_slice_split_tail(&slices[i], consumed_slice_size));
    gpr_slice_unref(slices[i]); /* split_tail above increments refcount. */
  }
  gpr_slice_buffer_addn(&s->left_overs, &slices[i + 1],
                        num_left_overs - has_left_overs_in_current_slice);
  check_peer(s);
}