aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/security
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/security')
-rw-r--r--src/core/security/base64.c10
-rw-r--r--src/core/security/client_auth_filter.c113
-rw-r--r--src/core/security/credentials.c315
-rw-r--r--src/core/security/credentials.h36
-rw-r--r--src/core/security/google_default_credentials.c24
-rw-r--r--src/core/security/handshake.c288
-rw-r--r--src/core/security/handshake.h (renamed from src/core/security/secure_transport_setup.h)25
-rw-r--r--src/core/security/jwt_verifier.c33
-rw-r--r--src/core/security/jwt_verifier.h3
-rw-r--r--src/core/security/secure_endpoint.c196
-rw-r--r--src/core/security/secure_transport_setup.c293
-rw-r--r--src/core/security/security_connector.c118
-rw-r--r--src/core/security/security_connector.h30
-rw-r--r--src/core/security/security_context.c50
-rw-r--r--src/core/security/security_context.h11
-rw-r--r--src/core/security/server_auth_filter.c87
-rw-r--r--src/core/security/server_secure_chttp2.c73
17 files changed, 1011 insertions, 694 deletions
diff --git a/src/core/security/base64.c b/src/core/security/base64.c
index 8dfaef846f..5226d2c578 100644
--- a/src/core/security/base64.c
+++ b/src/core/security/base64.c
@@ -125,13 +125,14 @@ gpr_slice grpc_base64_decode(const char *b64, int url_safe) {
static void decode_one_char(const unsigned char *codes, unsigned char *result,
size_t *result_offset) {
- gpr_uint32 packed = (codes[0] << 2) | (codes[1] >> 4);
+ gpr_uint32 packed = ((gpr_uint32)codes[0] << 2) | ((gpr_uint32)codes[1] >> 4);
result[(*result_offset)++] = (unsigned char)packed;
}
static void decode_two_chars(const unsigned char *codes, unsigned char *result,
size_t *result_offset) {
- gpr_uint32 packed = (codes[0] << 10) | (codes[1] << 4) | (codes[2] >> 2);
+ gpr_uint32 packed = ((gpr_uint32)codes[0] << 10) |
+ ((gpr_uint32)codes[1] << 4) | ((gpr_uint32)codes[2] >> 2);
result[(*result_offset)++] = (unsigned char)(packed >> 8);
result[(*result_offset)++] = (unsigned char)(packed);
}
@@ -171,8 +172,9 @@ static int decode_group(const unsigned char *codes, size_t num_codes,
decode_two_chars(codes, result, result_offset);
} else {
/* No padding. */
- gpr_uint32 packed =
- (codes[0] << 18) | (codes[1] << 12) | (codes[2] << 6) | codes[3];
+ gpr_uint32 packed = ((gpr_uint32)codes[0] << 18) |
+ ((gpr_uint32)codes[1] << 12) |
+ ((gpr_uint32)codes[2] << 6) | codes[3];
result[(*result_offset)++] = (unsigned char)(packed >> 16);
result[(*result_offset)++] = (unsigned char)(packed >> 8);
result[(*result_offset)++] = (unsigned char)(packed);
diff --git a/src/core/security/client_auth_filter.c b/src/core/security/client_auth_filter.c
index f3ecfd0e60..635982b252 100644
--- a/src/core/security/client_auth_filter.c
+++ b/src/core/security/client_auth_filter.c
@@ -63,6 +63,7 @@ typedef struct {
int sent_initial_metadata;
gpr_uint8 security_context_set;
grpc_linked_mdelem md_links[MAX_CREDENTIALS_METADATA_COUNT];
+ char *service_url;
} call_data;
/* We can have a per-channel credentials. */
@@ -75,15 +76,22 @@ typedef struct {
grpc_mdstr *status_key;
} channel_data;
-static void bubble_up_error(grpc_call_element *elem, grpc_status_code status,
- const char *error_msg) {
+static void reset_service_url(call_data *calld) {
+ if (calld->service_url != NULL) {
+ gpr_free(calld->service_url);
+ calld->service_url = NULL;
+ }
+}
+
+static void bubble_up_error(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+ grpc_status_code status, const char *error_msg) {
call_data *calld = elem->call_data;
gpr_log(GPR_ERROR, "Client side authentication failure: %s", error_msg);
grpc_transport_stream_op_add_cancellation(&calld->op, status);
- grpc_call_next_op(elem, &calld->op);
+ grpc_call_next_op(exec_ctx, elem, &calld->op);
}
-static void on_credentials_metadata(void *user_data,
+static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data,
grpc_credentials_md *md_elems,
size_t num_md,
grpc_credentials_status status) {
@@ -93,8 +101,9 @@ static void on_credentials_metadata(void *user_data,
grpc_transport_stream_op *op = &calld->op;
grpc_metadata_batch *mdb;
size_t i;
+ reset_service_url(calld);
if (status != GRPC_CREDENTIALS_OK) {
- bubble_up_error(elem, GRPC_STATUS_UNAUTHENTICATED,
+ bubble_up_error(exec_ctx, elem, GRPC_STATUS_UNAUTHENTICATED,
"Credentials failed to get metadata.");
return;
}
@@ -108,11 +117,10 @@ static void on_credentials_metadata(void *user_data,
grpc_mdelem_from_slices(chand->md_ctx, gpr_slice_ref(md_elems[i].key),
gpr_slice_ref(md_elems[i].value)));
}
- grpc_call_next_op(elem, op);
+ grpc_call_next_op(exec_ctx, elem, op);
}
-static char *build_service_url(const char *url_scheme, call_data *calld) {
- char *service_url;
+void build_service_url(const char *url_scheme, call_data *calld) {
char *service = gpr_strdup(grpc_mdstr_as_c_string(calld->method));
char *last_slash = strrchr(service, '/');
if (last_slash == NULL) {
@@ -125,19 +133,19 @@ static char *build_service_url(const char *url_scheme, call_data *calld) {
*last_slash = '\0';
}
if (url_scheme == NULL) url_scheme = "";
- gpr_asprintf(&service_url, "%s://%s%s", url_scheme,
+ reset_service_url(calld);
+ gpr_asprintf(&calld->service_url, "%s://%s%s", url_scheme,
grpc_mdstr_as_c_string(calld->host), service);
gpr_free(service);
- return service_url;
}
-static void send_security_metadata(grpc_call_element *elem,
+static void send_security_metadata(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
grpc_transport_stream_op *op) {
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
grpc_client_security_context *ctx =
(grpc_client_security_context *)op->context[GRPC_CONTEXT_SECURITY].value;
- char *service_url = NULL;
grpc_credentials *channel_creds =
chand->security_connector->request_metadata_creds;
int channel_creds_has_md =
@@ -148,7 +156,7 @@ static void send_security_metadata(grpc_call_element *elem,
if (!channel_creds_has_md && !call_creds_has_md) {
/* Skip sending metadata altogether. */
- grpc_call_next_op(elem, op);
+ grpc_call_next_op(exec_ctx, elem, op);
return;
}
@@ -156,7 +164,7 @@ static void send_security_metadata(grpc_call_element *elem,
calld->creds =
grpc_composite_credentials_create(channel_creds, ctx->creds, NULL);
if (calld->creds == NULL) {
- bubble_up_error(elem, GRPC_STATUS_INVALID_ARGUMENT,
+ bubble_up_error(exec_ctx, elem, GRPC_STATUS_INVALID_ARGUMENT,
"Incompatible credentials set on channel and call.");
return;
}
@@ -165,26 +173,26 @@ static void send_security_metadata(grpc_call_element *elem,
grpc_credentials_ref(call_creds_has_md ? ctx->creds : channel_creds);
}
- service_url =
- build_service_url(chand->security_connector->base.url_scheme, calld);
+ build_service_url(chand->security_connector->base.url_scheme, calld);
calld->op = *op; /* Copy op (originates from the caller's stack). */
GPR_ASSERT(calld->pollset);
- grpc_credentials_get_request_metadata(
- calld->creds, calld->pollset, service_url, on_credentials_metadata, elem);
- gpr_free(service_url);
+ grpc_credentials_get_request_metadata(exec_ctx, calld->creds, calld->pollset,
+ calld->service_url,
+ on_credentials_metadata, elem);
}
-static void on_host_checked(void *user_data, grpc_security_status status) {
+static void on_host_checked(grpc_exec_ctx *exec_ctx, void *user_data,
+ grpc_security_status status) {
grpc_call_element *elem = (grpc_call_element *)user_data;
call_data *calld = elem->call_data;
if (status == GRPC_SECURITY_OK) {
- send_security_metadata(elem, &calld->op);
+ send_security_metadata(exec_ctx, elem, &calld->op);
} else {
char *error_msg;
gpr_asprintf(&error_msg, "Invalid host %s set in :authority metadata.",
grpc_mdstr_as_c_string(calld->host));
- bubble_up_error(elem, GRPC_STATUS_INVALID_ARGUMENT, error_msg);
+ bubble_up_error(exec_ctx, elem, GRPC_STATUS_INVALID_ARGUMENT, error_msg);
gpr_free(error_msg);
}
}
@@ -194,7 +202,8 @@ static void on_host_checked(void *user_data, grpc_security_status status) {
- a network event (or similar) from below, to receive something
op contains type and call direction information, in addition to the data
that is being sent or received. */
-static void auth_start_transport_op(grpc_call_element *elem,
+static void auth_start_transport_op(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
grpc_transport_stream_op *op) {
/* grab pointers to our data from the call element */
call_data *calld = elem->call_data;
@@ -203,7 +212,8 @@ static void auth_start_transport_op(grpc_call_element *elem,
size_t i;
grpc_client_security_context *sec_ctx = NULL;
- if (calld->security_context_set == 0) {
+ if (calld->security_context_set == 0 &&
+ op->cancel_with_status == GRPC_STATUS_OK) {
calld->security_context_set = 1;
GPR_ASSERT(op->context);
if (op->context[GRPC_CONTEXT_SECURITY].value == NULL) {
@@ -218,11 +228,11 @@ static void auth_start_transport_op(grpc_call_element *elem,
chand->security_connector->base.auth_context, "client_auth_filter");
}
- if (op->bind_pollset) {
+ if (op->bind_pollset != NULL) {
calld->pollset = op->bind_pollset;
}
- if (op->send_ops && !calld->sent_initial_metadata) {
+ if (op->send_ops != NULL && !calld->sent_initial_metadata) {
size_t nops = op->send_ops->nops;
grpc_stream_op *ops = op->send_ops->ops;
for (i = 0; i < nops; i++) {
@@ -247,45 +257,42 @@ static void auth_start_transport_op(grpc_call_element *elem,
const char *call_host = grpc_mdstr_as_c_string(calld->host);
calld->op = *op; /* Copy op (originates from the caller's stack). */
status = grpc_channel_security_connector_check_call_host(
- chand->security_connector, call_host, on_host_checked, elem);
+ exec_ctx, chand->security_connector, call_host, on_host_checked,
+ elem);
if (status != GRPC_SECURITY_OK) {
if (status == GRPC_SECURITY_ERROR) {
char *error_msg;
gpr_asprintf(&error_msg,
"Invalid host %s set in :authority metadata.",
call_host);
- bubble_up_error(elem, GRPC_STATUS_INVALID_ARGUMENT, error_msg);
+ bubble_up_error(exec_ctx, elem, GRPC_STATUS_INVALID_ARGUMENT,
+ error_msg);
gpr_free(error_msg);
}
return; /* early exit */
}
}
- send_security_metadata(elem, op);
+ send_security_metadata(exec_ctx, elem, op);
return; /* early exit */
}
}
- /* pass control up or down the stack */
- grpc_call_next_op(elem, op);
+ /* pass control down the stack */
+ grpc_call_next_op(exec_ctx, elem, op);
}
/* Constructor for call_data */
-static void init_call_elem(grpc_call_element *elem,
+static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const void *server_transport_data,
grpc_transport_stream_op *initial_op) {
call_data *calld = elem->call_data;
- calld->creds = NULL;
- calld->host = NULL;
- calld->method = NULL;
- calld->pollset = NULL;
- calld->sent_initial_metadata = 0;
- calld->security_context_set = 0;
-
+ memset(calld, 0, sizeof(*calld));
GPR_ASSERT(!initial_op || !initial_op->send_ops);
}
/* Destructor for call_data */
-static void destroy_call_elem(grpc_call_element *elem) {
+static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem) {
call_data *calld = elem->call_data;
grpc_credentials_unref(calld->creds);
if (calld->host != NULL) {
@@ -294,10 +301,12 @@ static void destroy_call_elem(grpc_call_element *elem) {
if (calld->method != NULL) {
GRPC_MDSTR_UNREF(calld->method);
}
+ reset_service_url(calld);
}
/* Constructor for channel_data */
-static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
+static void init_channel_elem(grpc_exec_ctx *exec_ctx,
+ grpc_channel_element *elem, grpc_channel *master,
const grpc_channel_args *args,
grpc_mdctx *metadata_context, int is_first,
int is_last) {
@@ -317,16 +326,15 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
(grpc_channel_security_connector *)GRPC_SECURITY_CONNECTOR_REF(
sc, "client_auth_filter");
chand->md_ctx = metadata_context;
- chand->authority_string =
- grpc_mdstr_from_string(chand->md_ctx, ":authority", 0);
- chand->path_string = grpc_mdstr_from_string(chand->md_ctx, ":path", 0);
- chand->error_msg_key =
- grpc_mdstr_from_string(chand->md_ctx, "grpc-message", 0);
- chand->status_key = grpc_mdstr_from_string(chand->md_ctx, "grpc-status", 0);
+ chand->authority_string = grpc_mdstr_from_string(chand->md_ctx, ":authority");
+ chand->path_string = grpc_mdstr_from_string(chand->md_ctx, ":path");
+ chand->error_msg_key = grpc_mdstr_from_string(chand->md_ctx, "grpc-message");
+ chand->status_key = grpc_mdstr_from_string(chand->md_ctx, "grpc-status");
}
/* Destructor for channel data */
-static void destroy_channel_elem(grpc_channel_element *elem) {
+static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
+ grpc_channel_element *elem) {
/* grab pointers to our data from the channel element */
channel_data *chand = elem->channel_data;
grpc_channel_security_connector *ctx = chand->security_connector;
@@ -347,8 +355,7 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
}
const grpc_channel_filter grpc_client_auth_filter = {
- auth_start_transport_op, grpc_channel_next_op,
- sizeof(call_data), init_call_elem,
- destroy_call_elem, sizeof(channel_data),
- init_channel_elem, destroy_channel_elem,
- grpc_call_next_get_peer, "client-auth"};
+ auth_start_transport_op, grpc_channel_next_op, sizeof(call_data),
+ init_call_elem, destroy_call_elem, sizeof(channel_data),
+ init_channel_elem, destroy_channel_elem, grpc_call_next_get_peer,
+ "client-auth"};
diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c
index a764413300..5e155d83b9 100644
--- a/src/core/security/credentials.c
+++ b/src/core/security/credentials.c
@@ -41,12 +41,14 @@
#include "src/core/json/json.h"
#include "src/core/httpcli/httpcli.h"
#include "src/core/iomgr/iomgr.h"
+#include "src/core/surface/api_trace.h"
#include "src/core/support/string.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
+#include <grpc/support/thd.h>
#include <grpc/support/time.h>
/* -- Common. -- */
@@ -54,7 +56,6 @@
struct grpc_credentials_metadata_request {
grpc_credentials *creds;
grpc_credentials_metadata_cb cb;
- grpc_iomgr_closure *on_simulated_token_fetch_done_closure;
void *user_data;
};
@@ -66,8 +67,6 @@ grpc_credentials_metadata_request_create(grpc_credentials *creds,
gpr_malloc(sizeof(grpc_credentials_metadata_request));
r->creds = grpc_credentials_ref(creds);
r->cb = cb;
- r->on_simulated_token_fetch_done_closure =
- gpr_malloc(sizeof(grpc_iomgr_closure));
r->user_data = user_data;
return r;
}
@@ -75,7 +74,6 @@ grpc_credentials_metadata_request_create(grpc_credentials *creds,
static void grpc_credentials_metadata_request_destroy(
grpc_credentials_metadata_request *r) {
grpc_credentials_unref(r->creds);
- gpr_free(r->on_simulated_token_fetch_done_closure);
gpr_free(r);
}
@@ -94,6 +92,7 @@ void grpc_credentials_unref(grpc_credentials *creds) {
}
void grpc_credentials_release(grpc_credentials *creds) {
+ GRPC_API_TRACE("grpc_credentials_release(creds=%p)", 1, (creds));
grpc_credentials_unref(creds);
}
@@ -107,19 +106,17 @@ int grpc_credentials_has_request_metadata_only(grpc_credentials *creds) {
return creds->vtable->has_request_metadata_only(creds);
}
-void grpc_credentials_get_request_metadata(grpc_credentials *creds,
- grpc_pollset *pollset,
- const char *service_url,
- grpc_credentials_metadata_cb cb,
- void *user_data) {
+void grpc_credentials_get_request_metadata(
+ grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
+ const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
if (creds == NULL || !grpc_credentials_has_request_metadata(creds) ||
creds->vtable->get_request_metadata == NULL) {
if (cb != NULL) {
- cb(user_data, NULL, 0, GRPC_CREDENTIALS_OK);
+ cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
}
return;
}
- creds->vtable->get_request_metadata(creds, pollset, service_url, cb,
+ creds->vtable->get_request_metadata(exec_ctx, creds, pollset, service_url, cb,
user_data);
}
@@ -157,6 +154,7 @@ void grpc_server_credentials_unref(grpc_server_credentials *creds) {
}
void grpc_server_credentials_release(grpc_server_credentials *creds) {
+ GRPC_API_TRACE("grpc_server_credentials_release(creds=%p)", 1, (creds));
grpc_server_credentials_unref(creds);
}
@@ -171,6 +169,11 @@ grpc_security_status grpc_server_credentials_create_security_connector(
void grpc_server_credentials_set_auth_metadata_processor(
grpc_server_credentials *creds, grpc_auth_metadata_processor processor) {
+ GRPC_API_TRACE(
+ "grpc_server_credentials_set_auth_metadata_processor("
+ "creds=%p, "
+ "processor=grpc_auth_metadata_processor { process: %lx, state: %p })",
+ 3, (creds, (unsigned long)processor.process, processor.state));
if (creds == NULL) return;
if (creds->processor.destroy != NULL && creds->processor.state != NULL) {
creds->processor.destroy(creds->processor.state);
@@ -178,6 +181,48 @@ void grpc_server_credentials_set_auth_metadata_processor(
creds->processor = processor;
}
+static void server_credentials_pointer_arg_destroy(void *p) {
+ grpc_server_credentials_unref(p);
+}
+
+static void *server_credentials_pointer_arg_copy(void *p) {
+ return grpc_server_credentials_ref(p);
+}
+
+grpc_arg grpc_server_credentials_to_arg(grpc_server_credentials *p) {
+ grpc_arg arg;
+ memset(&arg, 0, sizeof(grpc_arg));
+ arg.type = GRPC_ARG_POINTER;
+ arg.key = GRPC_SERVER_CREDENTIALS_ARG;
+ arg.value.pointer.p = p;
+ arg.value.pointer.copy = server_credentials_pointer_arg_copy;
+ arg.value.pointer.destroy = server_credentials_pointer_arg_destroy;
+ return arg;
+}
+
+grpc_server_credentials *grpc_server_credentials_from_arg(
+ const grpc_arg *arg) {
+ if (strcmp(arg->key, GRPC_SERVER_CREDENTIALS_ARG) != 0) return NULL;
+ if (arg->type != GRPC_ARG_POINTER) {
+ gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type,
+ GRPC_SERVER_CREDENTIALS_ARG);
+ return NULL;
+ }
+ return arg->value.pointer.p;
+}
+
+grpc_server_credentials *grpc_find_server_credentials_in_args(
+ const grpc_channel_args *args) {
+ size_t i;
+ if (args == NULL) return NULL;
+ for (i = 0; i < args->num_args; i++) {
+ grpc_server_credentials *p =
+ grpc_server_credentials_from_arg(&args->args[i]);
+ if (p != NULL) return p;
+ }
+ return NULL;
+}
+
/* -- Ssl credentials. -- */
static void ssl_destruct(grpc_credentials *creds) {
@@ -223,7 +268,7 @@ static grpc_security_status ssl_create_security_connector(
grpc_security_status status = GRPC_SECURITY_OK;
size_t i = 0;
const char *overridden_target_name = NULL;
- grpc_arg arg;
+ grpc_arg new_arg;
for (i = 0; args && i < args->num_args; i++) {
grpc_arg *arg = &args->args[i];
@@ -238,10 +283,10 @@ static grpc_security_status ssl_create_security_connector(
if (status != GRPC_SECURITY_OK) {
return status;
}
- arg.type = GRPC_ARG_STRING;
- arg.key = GRPC_ARG_HTTP2_SCHEME;
- arg.value.string = "https";
- *new_args = grpc_channel_args_copy_and_add(args, &arg, 1);
+ new_arg.type = GRPC_ARG_STRING;
+ new_arg.key = GRPC_ARG_HTTP2_SCHEME;
+ new_arg.value.string = "https";
+ *new_args = grpc_channel_args_copy_and_add(args, &new_arg, 1);
return status;
}
@@ -322,6 +367,11 @@ grpc_credentials *grpc_ssl_credentials_create(
const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
void *reserved) {
grpc_ssl_credentials *c = gpr_malloc(sizeof(grpc_ssl_credentials));
+ GRPC_API_TRACE(
+ "grpc_ssl_credentials_create(pem_root_certs=%s, "
+ "pem_key_cert_pair=%p, "
+ "reserved=%p)",
+ 3, (pem_root_certs, pem_key_cert_pair, reserved));
GPR_ASSERT(reserved == NULL);
memset(c, 0, sizeof(grpc_ssl_credentials));
c->base.type = GRPC_CREDENTIALS_TYPE_SSL;
@@ -336,6 +386,12 @@ grpc_server_credentials *grpc_ssl_server_credentials_create(
size_t num_key_cert_pairs, int force_client_auth, void *reserved) {
grpc_ssl_server_credentials *c =
gpr_malloc(sizeof(grpc_ssl_server_credentials));
+ GRPC_API_TRACE(
+ "grpc_ssl_server_credentials_create("
+ "pem_root_certs=%s, pem_key_cert_pairs=%p, num_key_cert_pairs=%lu, "
+ "force_client_auth=%d, reserved=%p)",
+ 5, (pem_root_certs, pem_key_cert_pairs, (unsigned long)num_key_cert_pairs,
+ force_client_auth, reserved));
GPR_ASSERT(reserved == NULL);
memset(c, 0, sizeof(grpc_ssl_server_credentials));
c->base.type = GRPC_CREDENTIALS_TYPE_SSL;
@@ -374,11 +430,9 @@ static int jwt_has_request_metadata_only(const grpc_credentials *creds) {
return 1;
}
-static void jwt_get_request_metadata(grpc_credentials *creds,
- grpc_pollset *pollset,
- const char *service_url,
- grpc_credentials_metadata_cb cb,
- void *user_data) {
+static void jwt_get_request_metadata(
+ grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
+ const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
grpc_service_account_jwt_access_credentials *c =
(grpc_service_account_jwt_access_credentials *)creds;
gpr_timespec refresh_threshold = gpr_time_from_seconds(
@@ -422,10 +476,11 @@ static void jwt_get_request_metadata(grpc_credentials *creds,
}
if (jwt_md != NULL) {
- cb(user_data, jwt_md->entries, jwt_md->num_entries, GRPC_CREDENTIALS_OK);
+ cb(exec_ctx, user_data, jwt_md->entries, jwt_md->num_entries,
+ GRPC_CREDENTIALS_OK);
grpc_credentials_md_store_unref(jwt_md);
} else {
- cb(user_data, NULL, 0, GRPC_CREDENTIALS_ERROR);
+ cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_ERROR);
}
}
@@ -455,6 +510,14 @@ grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
grpc_credentials *grpc_service_account_jwt_access_credentials_create(
const char *json_key, gpr_timespec token_lifetime, void *reserved) {
+ GRPC_API_TRACE(
+ "grpc_service_account_jwt_access_credentials_create("
+ "json_key=%s, "
+ "token_lifetime="
+ "gpr_timespec { tv_sec: %ld, tv_nsec: %d, clock_type: %d }, "
+ "reserved=%p)",
+ 5, (json_key, (long)token_lifetime.tv_sec, token_lifetime.tv_nsec,
+ (int)token_lifetime.clock_type, reserved));
GPR_ASSERT(reserved == NULL);
return grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
grpc_auth_json_key_create_from_string(json_key), token_lifetime);
@@ -571,7 +634,8 @@ end:
}
static void on_oauth2_token_fetcher_http_response(
- void *user_data, const grpc_httpcli_response *response) {
+ grpc_exec_ctx *exec_ctx, void *user_data,
+ const grpc_httpcli_response *response) {
grpc_credentials_metadata_request *r =
(grpc_credentials_metadata_request *)user_data;
grpc_oauth2_token_fetcher_credentials *c =
@@ -585,19 +649,19 @@ static void on_oauth2_token_fetcher_http_response(
if (status == GRPC_CREDENTIALS_OK) {
c->token_expiration =
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), token_lifetime);
- r->cb(r->user_data, c->access_token_md->entries,
+ r->cb(exec_ctx, r->user_data, c->access_token_md->entries,
c->access_token_md->num_entries, status);
} else {
c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
- r->cb(r->user_data, NULL, 0, status);
+ r->cb(exec_ctx, r->user_data, NULL, 0, status);
}
gpr_mu_unlock(&c->mu);
grpc_credentials_metadata_request_destroy(r);
}
static void oauth2_token_fetcher_get_request_metadata(
- grpc_credentials *creds, grpc_pollset *pollset, const char *service_url,
- grpc_credentials_metadata_cb cb, void *user_data) {
+ grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
+ const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
grpc_oauth2_token_fetcher_credentials *c =
(grpc_oauth2_token_fetcher_credentials *)creds;
gpr_timespec refresh_threshold = gpr_time_from_seconds(
@@ -615,11 +679,12 @@ static void oauth2_token_fetcher_get_request_metadata(
gpr_mu_unlock(&c->mu);
}
if (cached_access_token_md != NULL) {
- cb(user_data, cached_access_token_md->entries,
+ cb(exec_ctx, user_data, cached_access_token_md->entries,
cached_access_token_md->num_entries, GRPC_CREDENTIALS_OK);
grpc_credentials_md_store_unref(cached_access_token_md);
} else {
c->fetch_func(
+ exec_ctx,
grpc_credentials_metadata_request_create(creds, cb, user_data),
&c->httpcli_context, pollset, on_oauth2_token_fetcher_http_response,
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), refresh_threshold));
@@ -645,7 +710,7 @@ static grpc_credentials_vtable compute_engine_vtable = {
oauth2_token_fetcher_get_request_metadata, NULL};
static void compute_engine_fetch_oauth2(
- grpc_credentials_metadata_request *metadata_req,
+ grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req,
grpc_httpcli_context *httpcli_context, grpc_pollset *pollset,
grpc_httpcli_response_cb response_cb, gpr_timespec deadline) {
grpc_httpcli_header header = {"Metadata-Flavor", "Google"};
@@ -655,14 +720,16 @@ static void compute_engine_fetch_oauth2(
request.path = GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH;
request.hdr_count = 1;
request.hdrs = &header;
- grpc_httpcli_get(httpcli_context, pollset, &request, deadline, response_cb,
- metadata_req);
+ grpc_httpcli_get(exec_ctx, httpcli_context, pollset, &request, deadline,
+ response_cb, metadata_req);
}
grpc_credentials *grpc_google_compute_engine_credentials_create(
void *reserved) {
grpc_oauth2_token_fetcher_credentials *c =
gpr_malloc(sizeof(grpc_oauth2_token_fetcher_credentials));
+ GRPC_API_TRACE("grpc_compute_engine_credentials_create(reserved=%p)", 1,
+ (reserved));
GPR_ASSERT(reserved == NULL);
init_oauth2_token_fetcher(c, compute_engine_fetch_oauth2);
c->base.vtable = &compute_engine_vtable;
@@ -684,7 +751,7 @@ static grpc_credentials_vtable refresh_token_vtable = {
oauth2_token_fetcher_get_request_metadata, NULL};
static void refresh_token_fetch_oauth2(
- grpc_credentials_metadata_request *metadata_req,
+ grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req,
grpc_httpcli_context *httpcli_context, grpc_pollset *pollset,
grpc_httpcli_response_cb response_cb, gpr_timespec deadline) {
grpc_google_refresh_token_credentials *c =
@@ -702,13 +769,12 @@ static void refresh_token_fetch_oauth2(
request.hdr_count = 1;
request.hdrs = &header;
request.handshaker = &grpc_httpcli_ssl;
- grpc_httpcli_post(httpcli_context, pollset, &request, body, strlen(body),
- deadline, response_cb, metadata_req);
+ grpc_httpcli_post(exec_ctx, httpcli_context, pollset, &request, body,
+ strlen(body), deadline, response_cb, metadata_req);
gpr_free(body);
}
-grpc_credentials *
-grpc_refresh_token_credentials_create_from_auth_refresh_token(
+grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token(
grpc_auth_refresh_token refresh_token) {
grpc_google_refresh_token_credentials *c;
if (!grpc_auth_refresh_token_is_valid(&refresh_token)) {
@@ -725,6 +791,10 @@ grpc_refresh_token_credentials_create_from_auth_refresh_token(
grpc_credentials *grpc_google_refresh_token_credentials_create(
const char *json_refresh_token, void *reserved) {
+ GRPC_API_TRACE(
+ "grpc_refresh_token_credentials_create(json_refresh_token=%s, "
+ "reserved=%p)",
+ 2, (json_refresh_token, reserved));
GPR_ASSERT(reserved == NULL);
return grpc_refresh_token_credentials_create_from_auth_refresh_token(
grpc_auth_refresh_token_create_from_string(json_refresh_token));
@@ -746,31 +816,29 @@ static int md_only_test_has_request_metadata_only(
return 1;
}
-void on_simulated_token_fetch_done(void *user_data, int success) {
+static void on_simulated_token_fetch_done(void *user_data) {
grpc_credentials_metadata_request *r =
(grpc_credentials_metadata_request *)user_data;
grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)r->creds;
- GPR_ASSERT(success);
- r->cb(r->user_data, c->md_store->entries, c->md_store->num_entries,
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ r->cb(&exec_ctx, r->user_data, c->md_store->entries, c->md_store->num_entries,
GRPC_CREDENTIALS_OK);
grpc_credentials_metadata_request_destroy(r);
+ grpc_exec_ctx_finish(&exec_ctx);
}
-static void md_only_test_get_request_metadata(grpc_credentials *creds,
- grpc_pollset *pollset,
- const char *service_url,
- grpc_credentials_metadata_cb cb,
- void *user_data) {
+static void md_only_test_get_request_metadata(
+ grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
+ const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
if (c->is_async) {
+ gpr_thd_id thd_id;
grpc_credentials_metadata_request *cb_arg =
grpc_credentials_metadata_request_create(creds, cb, user_data);
- grpc_iomgr_closure_init(cb_arg->on_simulated_token_fetch_done_closure,
- on_simulated_token_fetch_done, cb_arg);
- grpc_iomgr_add_callback(cb_arg->on_simulated_token_fetch_done_closure);
+ gpr_thd_new(&thd_id, on_simulated_token_fetch_done, cb_arg, NULL);
} else {
- cb(user_data, c->md_store->entries, 1, GRPC_CREDENTIALS_OK);
+ cb(exec_ctx, user_data, c->md_store->entries, 1, GRPC_CREDENTIALS_OK);
}
}
@@ -810,13 +878,11 @@ static int access_token_has_request_metadata_only(
return 1;
}
-static void access_token_get_request_metadata(grpc_credentials *creds,
- grpc_pollset *pollset,
- const char *service_url,
- grpc_credentials_metadata_cb cb,
- void *user_data) {
+static void access_token_get_request_metadata(
+ grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
+ const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
- cb(user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK);
+ cb(exec_ctx, user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK);
}
static grpc_credentials_vtable access_token_vtable = {
@@ -829,6 +895,10 @@ grpc_credentials *grpc_access_token_credentials_create(const char *access_token,
grpc_access_token_credentials *c =
gpr_malloc(sizeof(grpc_access_token_credentials));
char *token_md_value;
+ GRPC_API_TRACE(
+ "grpc_access_token_credentials_create(access_token=%s, "
+ "reserved=%p)",
+ 2, (access_token, reserved));
GPR_ASSERT(reserved == NULL);
memset(c, 0, sizeof(grpc_access_token_credentials));
c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2;
@@ -961,13 +1031,13 @@ static void composite_md_context_destroy(
gpr_free(ctx);
}
-static void composite_metadata_cb(void *user_data,
+static void composite_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data,
grpc_credentials_md *md_elems, size_t num_md,
grpc_credentials_status status) {
grpc_composite_credentials_metadata_context *ctx =
(grpc_composite_credentials_metadata_context *)user_data;
if (status != GRPC_CREDENTIALS_OK) {
- ctx->cb(ctx->user_data, NULL, 0, status);
+ ctx->cb(exec_ctx, ctx->user_data, NULL, 0, status);
return;
}
@@ -985,7 +1055,7 @@ static void composite_metadata_cb(void *user_data,
grpc_credentials *inner_creds =
ctx->composite_creds->inner.creds_array[ctx->creds_index++];
if (grpc_credentials_has_request_metadata(inner_creds)) {
- grpc_credentials_get_request_metadata(inner_creds, ctx->pollset,
+ grpc_credentials_get_request_metadata(exec_ctx, inner_creds, ctx->pollset,
ctx->service_url,
composite_metadata_cb, ctx);
return;
@@ -993,20 +1063,18 @@ static void composite_metadata_cb(void *user_data,
}
/* We're done!. */
- ctx->cb(ctx->user_data, ctx->md_elems->entries, ctx->md_elems->num_entries,
- GRPC_CREDENTIALS_OK);
+ ctx->cb(exec_ctx, ctx->user_data, ctx->md_elems->entries,
+ ctx->md_elems->num_entries, GRPC_CREDENTIALS_OK);
composite_md_context_destroy(ctx);
}
-static void composite_get_request_metadata(grpc_credentials *creds,
- grpc_pollset *pollset,
- const char *service_url,
- grpc_credentials_metadata_cb cb,
- void *user_data) {
+static void composite_get_request_metadata(
+ grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
+ const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
grpc_composite_credentials *c = (grpc_composite_credentials *)creds;
grpc_composite_credentials_metadata_context *ctx;
if (!grpc_credentials_has_request_metadata(creds)) {
- cb(user_data, NULL, 0, GRPC_CREDENTIALS_OK);
+ cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
return;
}
ctx = gpr_malloc(sizeof(grpc_composite_credentials_metadata_context));
@@ -1020,8 +1088,9 @@ static void composite_get_request_metadata(grpc_credentials *creds,
while (ctx->creds_index < c->inner.num_creds) {
grpc_credentials *inner_creds = c->inner.creds_array[ctx->creds_index++];
if (grpc_credentials_has_request_metadata(inner_creds)) {
- grpc_credentials_get_request_metadata(inner_creds, pollset, service_url,
- composite_metadata_cb, ctx);
+ grpc_credentials_get_request_metadata(exec_ctx, inner_creds, pollset,
+ service_url, composite_metadata_cb,
+ ctx);
return;
}
}
@@ -1066,6 +1135,10 @@ grpc_credentials *grpc_composite_credentials_create(grpc_credentials *creds1,
grpc_credentials_array creds1_array;
grpc_credentials_array creds2_array;
grpc_composite_credentials *c;
+ GRPC_API_TRACE(
+ "grpc_composite_credentials_create(creds1=%p, creds2=%p, "
+ "reserved=%p)",
+ 3, (creds1, creds2, reserved));
GPR_ASSERT(reserved == NULL);
GPR_ASSERT(creds1 != NULL);
GPR_ASSERT(creds2 != NULL);
@@ -1153,13 +1226,11 @@ static int iam_has_request_metadata_only(const grpc_credentials *creds) {
return 1;
}
-static void iam_get_request_metadata(grpc_credentials *creds,
- grpc_pollset *pollset,
- const char *service_url,
- grpc_credentials_metadata_cb cb,
- void *user_data) {
+static void iam_get_request_metadata(
+ grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
+ const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
- cb(user_data, c->iam_md->entries, c->iam_md->num_entries,
+ cb(exec_ctx, user_data, c->iam_md->entries, c->iam_md->num_entries,
GRPC_CREDENTIALS_OK);
}
@@ -1170,6 +1241,10 @@ static grpc_credentials_vtable iam_vtable = {
grpc_credentials *grpc_google_iam_credentials_create(
const char *token, const char *authority_selector, void *reserved) {
grpc_google_iam_credentials *c;
+ GRPC_API_TRACE(
+ "grpc_iam_credentials_create(token=%s, authority_selector=%s, "
+ "reserved=%p)",
+ 3, (token, authority_selector, reserved));
GPR_ASSERT(reserved == NULL);
GPR_ASSERT(token != NULL);
GPR_ASSERT(authority_selector != NULL);
@@ -1185,3 +1260,95 @@ grpc_credentials *grpc_google_iam_credentials_create(
c->iam_md, GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, authority_selector);
return &c->base;
}
+
+/* -- Plugin credentials. -- */
+
+typedef struct {
+ void *user_data;
+ grpc_credentials_metadata_cb cb;
+} grpc_metadata_plugin_request;
+
+static void plugin_destruct(grpc_credentials *creds) {
+ grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
+ if (c->plugin.state != NULL && c->plugin.destroy != NULL) {
+ c->plugin.destroy(c->plugin.state);
+ }
+}
+
+static int plugin_has_request_metadata(const grpc_credentials *creds) {
+ return 1;
+}
+
+static int plugin_has_request_metadata_only(const grpc_credentials *creds) {
+ return 1;
+}
+
+static void plugin_md_request_metadata_ready(void *request,
+ const grpc_metadata *md,
+ size_t num_md,
+ grpc_status_code status,
+ const char *error_details) {
+ /* called from application code */
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_metadata_plugin_request *r = (grpc_metadata_plugin_request *)request;
+ if (status != GRPC_STATUS_OK) {
+ if (error_details != NULL) {
+ gpr_log(GPR_ERROR, "Getting metadata from plugin failed with error: %s",
+ error_details);
+ }
+ r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR);
+ } else {
+ size_t i;
+ grpc_credentials_md *md_array = NULL;
+ if (num_md > 0) {
+ md_array = gpr_malloc(num_md * sizeof(grpc_credentials_md));
+ for (i = 0; i < num_md; i++) {
+ md_array[i].key = gpr_slice_from_copied_string(md[i].key);
+ md_array[i].value =
+ gpr_slice_from_copied_buffer(md[i].value, md[i].value_length);
+ }
+ }
+ r->cb(&exec_ctx, r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK);
+ if (md_array != NULL) {
+ for (i = 0; i < num_md; i++) {
+ gpr_slice_unref(md_array[i].key);
+ gpr_slice_unref(md_array[i].value);
+ }
+ gpr_free(md_array);
+ }
+ }
+ gpr_free(r);
+ grpc_exec_ctx_finish(&exec_ctx);
+}
+
+static void plugin_get_request_metadata(
+ grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
+ const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
+ grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
+ if (c->plugin.get_metadata != NULL) {
+ grpc_metadata_plugin_request *request = gpr_malloc(sizeof(*request));
+ memset(request, 0, sizeof(*request));
+ request->user_data = user_data;
+ request->cb = cb;
+ c->plugin.get_metadata(c->plugin.state, service_url,
+ plugin_md_request_metadata_ready, request);
+ } else {
+ cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
+ }
+}
+
+static grpc_credentials_vtable plugin_vtable = {
+ plugin_destruct, plugin_has_request_metadata,
+ plugin_has_request_metadata_only, plugin_get_request_metadata, NULL};
+
+grpc_credentials *grpc_metadata_credentials_create_from_plugin(
+ grpc_metadata_credentials_plugin plugin, void *reserved) {
+ grpc_plugin_credentials *c = gpr_malloc(sizeof(*c));
+ GPR_ASSERT(reserved == NULL);
+ memset(c, 0, sizeof(*c));
+ c->base.type = GRPC_CREDENTIALS_TYPE_METADATA_PLUGIN;
+ c->base.vtable = &plugin_vtable;
+ gpr_ref_init(&c->base.refcount, 1);
+ c->plugin = plugin;
+ return &c->base;
+}
diff --git a/src/core/security/credentials.h b/src/core/security/credentials.h
index 8e4fed7615..01203b08f1 100644
--- a/src/core/security/credentials.h
+++ b/src/core/security/credentials.h
@@ -56,6 +56,7 @@ typedef enum {
#define GRPC_CREDENTIALS_TYPE_SSL "Ssl"
#define GRPC_CREDENTIALS_TYPE_OAUTH2 "Oauth2"
+#define GRPC_CREDENTIALS_TYPE_METADATA_PLUGIN "Plugin"
#define GRPC_CREDENTIALS_TYPE_JWT "Jwt"
#define GRPC_CREDENTIALS_TYPE_IAM "Iam"
#define GRPC_CREDENTIALS_TYPE_COMPOSITE "Composite"
@@ -123,7 +124,8 @@ grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
/* It is the caller's responsibility to gpr_free the result if not NULL. */
char *grpc_get_well_known_google_credentials_file_path(void);
-typedef void (*grpc_credentials_metadata_cb)(void *user_data,
+typedef void (*grpc_credentials_metadata_cb)(grpc_exec_ctx *exec_ctx,
+ void *user_data,
grpc_credentials_md *md_elems,
size_t num_md,
grpc_credentials_status status);
@@ -132,8 +134,8 @@ typedef struct {
void (*destruct)(grpc_credentials *c);
int (*has_request_metadata)(const grpc_credentials *c);
int (*has_request_metadata_only)(const grpc_credentials *c);
- void (*get_request_metadata)(grpc_credentials *c, grpc_pollset *pollset,
- const char *service_url,
+ void (*get_request_metadata)(grpc_exec_ctx *exec_ctx, grpc_credentials *c,
+ grpc_pollset *pollset, const char *service_url,
grpc_credentials_metadata_cb cb,
void *user_data);
grpc_security_status (*create_security_connector)(
@@ -152,11 +154,9 @@ grpc_credentials *grpc_credentials_ref(grpc_credentials *creds);
void grpc_credentials_unref(grpc_credentials *creds);
int grpc_credentials_has_request_metadata(grpc_credentials *creds);
int grpc_credentials_has_request_metadata_only(grpc_credentials *creds);
-void grpc_credentials_get_request_metadata(grpc_credentials *creds,
- grpc_pollset *pollset,
- const char *service_url,
- grpc_credentials_metadata_cb cb,
- void *user_data);
+void grpc_credentials_get_request_metadata(
+ grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
+ const char *service_url, grpc_credentials_metadata_cb cb, void *user_data);
/* Creates a security connector for the channel. May also create new channel
args for the channel to be used in place of the passed in const args if
@@ -215,8 +215,6 @@ typedef struct {
grpc_server_credentials *c, grpc_security_connector **sc);
} grpc_server_credentials_vtable;
-
-/* TODO(jboeuf): Add a refcount. */
struct grpc_server_credentials {
const grpc_server_credentials_vtable *vtable;
const char *type;
@@ -232,6 +230,13 @@ grpc_server_credentials *grpc_server_credentials_ref(
void grpc_server_credentials_unref(grpc_server_credentials *creds);
+#define GRPC_SERVER_CREDENTIALS_ARG "grpc.server_credentials"
+
+grpc_arg grpc_server_credentials_to_arg(grpc_server_credentials *c);
+grpc_server_credentials *grpc_server_credentials_from_arg(const grpc_arg *arg);
+grpc_server_credentials *grpc_find_server_credentials_in_args(
+ const grpc_channel_args *args);
+
/* -- Ssl credentials. -- */
typedef struct {
@@ -270,7 +275,8 @@ typedef struct {
typedef struct grpc_credentials_metadata_request
grpc_credentials_metadata_request;
-typedef void (*grpc_fetch_oauth2_func)(grpc_credentials_metadata_request *req,
+typedef void (*grpc_fetch_oauth2_func)(grpc_exec_ctx *exec_ctx,
+ grpc_credentials_metadata_request *req,
grpc_httpcli_context *http_context,
grpc_pollset *pollset,
grpc_httpcli_response_cb response_cb,
@@ -322,4 +328,12 @@ typedef struct {
grpc_credentials *connector_creds;
} grpc_composite_credentials;
+/* -- Plugin credentials. -- */
+
+typedef struct {
+ grpc_credentials base;
+ grpc_metadata_credentials_plugin plugin;
+ grpc_credentials_md_store *plugin_md;
+} grpc_plugin_credentials;
+
#endif /* GRPC_INTERNAL_CORE_SECURITY_CREDENTIALS_H */
diff --git a/src/core/security/google_default_credentials.c b/src/core/security/google_default_credentials.c
index 874dd59e84..45135305b2 100644
--- a/src/core/security/google_default_credentials.c
+++ b/src/core/security/google_default_credentials.c
@@ -42,6 +42,7 @@
#include "src/core/httpcli/httpcli.h"
#include "src/core/support/env.h"
#include "src/core/support/file.h"
+#include "src/core/surface/api_trace.h"
/* -- Constants. -- */
@@ -63,7 +64,8 @@ typedef struct {
} compute_engine_detector;
static void on_compute_engine_detection_http_response(
- void *user_data, const grpc_httpcli_response *response) {
+ grpc_exec_ctx *exec_ctx, void *user_data,
+ const grpc_httpcli_response *response) {
compute_engine_detector *detector = (compute_engine_detector *)user_data;
if (response != NULL && response->status == 200 && response->hdr_count > 0) {
/* Internet providers can return a generic response to all requests, so
@@ -84,12 +86,16 @@ static void on_compute_engine_detection_http_response(
gpr_mu_unlock(GRPC_POLLSET_MU(&detector->pollset));
}
-static void destroy_pollset(void *p) { grpc_pollset_destroy(p); }
+static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, int s) {
+ grpc_pollset_destroy(p);
+}
static int is_stack_running_on_compute_engine(void) {
compute_engine_detector detector;
grpc_httpcli_request request;
grpc_httpcli_context context;
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_closure destroy_closure;
/* The http call is local. If it takes more than one sec, it is for sure not
on compute engine. */
@@ -106,22 +112,27 @@ static int is_stack_running_on_compute_engine(void) {
grpc_httpcli_context_init(&context);
grpc_httpcli_get(
- &context, &detector.pollset, &request,
+ &exec_ctx, &context, &detector.pollset, &request,
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), max_detection_delay),
on_compute_engine_detection_http_response, &detector);
+ grpc_exec_ctx_finish(&exec_ctx);
+
/* Block until we get the response. This is not ideal but this should only be
called once for the lifetime of the process by the default credentials. */
gpr_mu_lock(GRPC_POLLSET_MU(&detector.pollset));
while (!detector.is_done) {
grpc_pollset_worker worker;
- grpc_pollset_work(&detector.pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC),
+ grpc_pollset_work(&exec_ctx, &detector.pollset, &worker,
+ gpr_now(GPR_CLOCK_MONOTONIC),
gpr_inf_future(GPR_CLOCK_MONOTONIC));
}
gpr_mu_unlock(GRPC_POLLSET_MU(&detector.pollset));
grpc_httpcli_context_destroy(&context);
- grpc_pollset_shutdown(&detector.pollset, destroy_pollset, &detector.pollset);
+ grpc_closure_init(&destroy_closure, destroy_pollset, &detector.pollset);
+ grpc_pollset_shutdown(&exec_ctx, &detector.pollset, &destroy_closure);
+ grpc_exec_ctx_finish(&exec_ctx);
return detector.success;
}
@@ -168,6 +179,9 @@ end:
grpc_credentials *grpc_google_default_credentials_create(void) {
grpc_credentials *result = NULL;
int serving_cached_credentials = 0;
+
+ GRPC_API_TRACE("grpc_google_default_credentials_create(void)", 0, ());
+
gpr_once_init(&g_once, init_default_credentials);
gpr_mu_lock(&g_mu);
diff --git a/src/core/security/handshake.c b/src/core/security/handshake.c
new file mode 100644
index 0000000000..adbdd0b40e
--- /dev/null
+++ b/src/core/security/handshake.c
@@ -0,0 +1,288 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/security/handshake.h"
+
+#include <string.h>
+
+#include "src/core/security/secure_endpoint.h"
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/slice_buffer.h>
+
+#define GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE 256
+
+typedef struct {
+ grpc_security_connector *connector;
+ tsi_handshaker *handshaker;
+ unsigned char *handshake_buffer;
+ size_t handshake_buffer_size;
+ grpc_endpoint *wrapped_endpoint;
+ grpc_endpoint *secure_endpoint;
+ gpr_slice_buffer left_overs;
+ gpr_slice_buffer incoming;
+ gpr_slice_buffer outgoing;
+ grpc_security_handshake_done_cb cb;
+ void *user_data;
+ grpc_closure on_handshake_data_sent_to_peer;
+ grpc_closure on_handshake_data_received_from_peer;
+} grpc_security_handshake;
+
+static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
+ void *setup, int success);
+
+static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *setup,
+ int success);
+
+static void security_handshake_done(grpc_exec_ctx *exec_ctx,
+ grpc_security_handshake *h,
+ int is_success) {
+ if (is_success) {
+ h->cb(exec_ctx, h->user_data, GRPC_SECURITY_OK, h->wrapped_endpoint,
+ h->secure_endpoint);
+ } else {
+ if (h->secure_endpoint != NULL) {
+ grpc_endpoint_shutdown(exec_ctx, h->secure_endpoint);
+ grpc_endpoint_destroy(exec_ctx, h->secure_endpoint);
+ } else {
+ grpc_endpoint_destroy(exec_ctx, h->wrapped_endpoint);
+ }
+ h->cb(exec_ctx, h->user_data, GRPC_SECURITY_ERROR, h->wrapped_endpoint,
+ NULL);
+ }
+ if (h->handshaker != NULL) tsi_handshaker_destroy(h->handshaker);
+ if (h->handshake_buffer != NULL) gpr_free(h->handshake_buffer);
+ gpr_slice_buffer_destroy(&h->left_overs);
+ gpr_slice_buffer_destroy(&h->outgoing);
+ gpr_slice_buffer_destroy(&h->incoming);
+ GRPC_SECURITY_CONNECTOR_UNREF(h->connector, "handshake");
+ gpr_free(h);
+}
+
+static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *user_data,
+ grpc_security_status status) {
+ grpc_security_handshake *h = user_data;
+ tsi_frame_protector *protector;
+ tsi_result result;
+ if (status != GRPC_SECURITY_OK) {
+ gpr_log(GPR_ERROR, "Error checking peer.");
+ security_handshake_done(exec_ctx, h, 0);
+ return;
+ }
+ result =
+ tsi_handshaker_create_frame_protector(h->handshaker, NULL, &protector);
+ if (result != TSI_OK) {
+ gpr_log(GPR_ERROR, "Frame protector creation failed with error %s.",
+ tsi_result_to_string(result));
+ security_handshake_done(exec_ctx, h, 0);
+ return;
+ }
+ h->secure_endpoint =
+ grpc_secure_endpoint_create(protector, h->wrapped_endpoint,
+ h->left_overs.slices, h->left_overs.count);
+ h->left_overs.count = 0;
+ h->left_overs.length = 0;
+ security_handshake_done(exec_ctx, h, 1);
+ return;
+}
+
+static void check_peer(grpc_exec_ctx *exec_ctx, grpc_security_handshake *h) {
+ grpc_security_status peer_status;
+ tsi_peer peer;
+ tsi_result result = tsi_handshaker_extract_peer(h->handshaker, &peer);
+
+ if (result != TSI_OK) {
+ gpr_log(GPR_ERROR, "Peer extraction failed with error %s",
+ tsi_result_to_string(result));
+ security_handshake_done(exec_ctx, h, 0);
+ return;
+ }
+ peer_status = grpc_security_connector_check_peer(h->connector, peer,
+ on_peer_checked, h);
+ if (peer_status == GRPC_SECURITY_ERROR) {
+ gpr_log(GPR_ERROR, "Peer check failed.");
+ security_handshake_done(exec_ctx, h, 0);
+ return;
+ } else if (peer_status == GRPC_SECURITY_OK) {
+ on_peer_checked(exec_ctx, h, peer_status);
+ }
+}
+
+static void send_handshake_bytes_to_peer(grpc_exec_ctx *exec_ctx,
+ grpc_security_handshake *h) {
+ size_t offset = 0;
+ tsi_result result = TSI_OK;
+ gpr_slice to_send;
+
+ do {
+ size_t to_send_size = h->handshake_buffer_size - offset;
+ result = tsi_handshaker_get_bytes_to_send_to_peer(
+ h->handshaker, h->handshake_buffer + offset, &to_send_size);
+ offset += to_send_size;
+ if (result == TSI_INCOMPLETE_DATA) {
+ h->handshake_buffer_size *= 2;
+ h->handshake_buffer =
+ gpr_realloc(h->handshake_buffer, h->handshake_buffer_size);
+ }
+ } while (result == TSI_INCOMPLETE_DATA);
+
+ if (result != TSI_OK) {
+ gpr_log(GPR_ERROR, "Handshake failed with error %s",
+ tsi_result_to_string(result));
+ security_handshake_done(exec_ctx, h, 0);
+ return;
+ }
+
+ to_send =
+ gpr_slice_from_copied_buffer((const char *)h->handshake_buffer, offset);
+ gpr_slice_buffer_reset_and_unref(&h->outgoing);
+ gpr_slice_buffer_add(&h->outgoing, to_send);
+ /* TODO(klempner,jboeuf): This should probably use the client setup
+ deadline */
+ grpc_endpoint_write(exec_ctx, h->wrapped_endpoint, &h->outgoing,
+ &h->on_handshake_data_sent_to_peer);
+}
+
+static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
+ void *handshake, int success) {
+ 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 (!success) {
+ gpr_log(GPR_ERROR, "Read failed.");
+ security_handshake_done(exec_ctx, h, 0);
+ 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) {
+ gpr_log(GPR_ERROR, "Handshake failed with error %s",
+ tsi_result_to_string(result));
+ security_handshake_done(exec_ctx, h, 0);
+ 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);
+}
+
+/* If handshake is NULL, the handshake is done. */
+static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx,
+ void *handshake, int success) {
+ grpc_security_handshake *h = handshake;
+
+ /* Make sure that write is OK. */
+ if (!success) {
+ gpr_log(GPR_ERROR, "Write failed.");
+ if (handshake != NULL) security_handshake_done(exec_ctx, h, 0);
+ return;
+ }
+
+ /* We may be done. */
+ if (tsi_handshaker_is_in_progress(h->handshaker)) {
+ /* TODO(klempner,jboeuf): This should probably use the client setup
+ deadline */
+ grpc_endpoint_read(exec_ctx, h->wrapped_endpoint, &h->incoming,
+ &h->on_handshake_data_received_from_peer);
+ } else {
+ check_peer(exec_ctx, h);
+ }
+}
+
+void grpc_do_security_handshake(grpc_exec_ctx *exec_ctx,
+ tsi_handshaker *handshaker,
+ grpc_security_connector *connector,
+ grpc_endpoint *nonsecure_endpoint,
+ grpc_security_handshake_done_cb cb,
+ void *user_data) {
+ 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->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;
+ 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);
+ send_handshake_bytes_to_peer(exec_ctx, h);
+}
diff --git a/src/core/security/secure_transport_setup.h b/src/core/security/handshake.h
index d9b802556d..28eaa79dc3 100644
--- a/src/core/security/secure_transport_setup.h
+++ b/src/core/security/handshake.h
@@ -31,23 +31,18 @@
*
*/
-#ifndef GRPC_INTERNAL_CORE_SECURITY_SECURE_TRANSPORT_SETUP_H
-#define GRPC_INTERNAL_CORE_SECURITY_SECURE_TRANSPORT_SETUP_H
+#ifndef GRPC_INTERNAL_CORE_SECURITY_HANDSHAKE_H
+#define GRPC_INTERNAL_CORE_SECURITY_HANDSHAKE_H
#include "src/core/iomgr/endpoint.h"
#include "src/core/security/security_connector.h"
-/* --- Secure transport setup --- */
+/* Calls the callback upon completion. Takes owership of handshaker. */
+void grpc_do_security_handshake(grpc_exec_ctx *exec_ctx,
+ tsi_handshaker *handshaker,
+ grpc_security_connector *connector,
+ grpc_endpoint *nonsecure_endpoint,
+ grpc_security_handshake_done_cb cb,
+ void *user_data);
-/* Ownership of the secure_endpoint is transfered. */
-typedef void (*grpc_secure_transport_setup_done_cb)(
- void *user_data, grpc_security_status status,
- grpc_endpoint *wrapped_endpoint, grpc_endpoint *secure_endpoint);
-
-/* Calls the callback upon completion. */
-void grpc_setup_secure_transport(grpc_security_connector *connector,
- grpc_endpoint *nonsecure_endpoint,
- grpc_secure_transport_setup_done_cb cb,
- void *user_data);
-
-#endif /* GRPC_INTERNAL_CORE_SECURITY_SECURE_TRANSPORT_SETUP_H */
+#endif /* GRPC_INTERNAL_CORE_SECURITY_HANDSHAKE_H */
diff --git a/src/core/security/jwt_verifier.c b/src/core/security/jwt_verifier.c
index 38ad134a6a..9de8482025 100644
--- a/src/core/security/jwt_verifier.c
+++ b/src/core/security/jwt_verifier.c
@@ -33,6 +33,7 @@
#include "src/core/security/jwt_verifier.h"
+#include <limits.h>
#include <string.h>
#include "src/core/httpcli/httpcli.h"
@@ -144,7 +145,7 @@ static jose_header *jose_header_from_json(grpc_json *json, gpr_slice buffer) {
/* We only support RSA-1.5 signatures for now.
Beware of this if we add HMAC support:
https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/
- */
+ */
if (cur->type != GRPC_JSON_STRING || strncmp(cur->value, "RS", 2) ||
evp_md_from_alg(cur->value) == NULL) {
gpr_log(GPR_ERROR, "Invalid alg field [%s]", cur->value);
@@ -412,7 +413,9 @@ static EVP_PKEY *extract_pkey_from_x509(const char *x509_str) {
X509 *x509 = NULL;
EVP_PKEY *result = NULL;
BIO *bio = BIO_new(BIO_s_mem());
- BIO_write(bio, x509_str, strlen(x509_str));
+ size_t len = strlen(x509_str);
+ GPR_ASSERT(len < INT_MAX);
+ BIO_write(bio, x509_str, (int)len);
x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
if (x509 == NULL) {
gpr_log(GPR_ERROR, "Unable to parse x509 cert.");
@@ -439,7 +442,8 @@ static BIGNUM *bignum_from_base64(const char *b64) {
gpr_log(GPR_ERROR, "Invalid base64 for big num.");
return NULL;
}
- result = BN_bin2bn(GPR_SLICE_START_PTR(bin), GPR_SLICE_LENGTH(bin), NULL);
+ result =
+ BN_bin2bn(GPR_SLICE_START_PTR(bin), (int)GPR_SLICE_LENGTH(bin), NULL);
gpr_slice_unref(bin);
return result;
}
@@ -490,7 +494,7 @@ static EVP_PKEY *find_verification_key(const grpc_json *json,
jwk_keys = find_property_by_name(json, "keys");
if (jwk_keys == NULL) {
/* Use the google proprietary format which is:
- { <kid1>: <x5091>, <kid2>: <x5092>, ... } */
+ { <kid1>: <x5091>, <kid2>: <x5092>, ... } */
const grpc_json *cur = find_property_by_name(json, header_kid);
if (cur == NULL) return NULL;
return extract_pkey_from_x509(cur->value);
@@ -565,7 +569,7 @@ end:
return result;
}
-static void on_keys_retrieved(void *user_data,
+static void on_keys_retrieved(grpc_exec_ctx *exec_ctx, void *user_data,
const grpc_httpcli_response *response) {
grpc_json *json = json_from_http(response);
verifier_cb_ctx *ctx = (verifier_cb_ctx *)user_data;
@@ -606,7 +610,7 @@ end:
verifier_cb_ctx_destroy(ctx);
}
-static void on_openid_config_retrieved(void *user_data,
+static void on_openid_config_retrieved(grpc_exec_ctx *exec_ctx, void *user_data,
const grpc_httpcli_response *response) {
const grpc_json *cur;
grpc_json *json = json_from_http(response);
@@ -614,7 +618,7 @@ static void on_openid_config_retrieved(void *user_data,
grpc_httpcli_request req;
const char *jwks_uri;
- /* TODO(jboeuf): Cache the jwks_uri in order to avoid this hop next time.*/
+ /* TODO(jboeuf): Cache the jwks_uri in order to avoid this hop next time. */
if (json == NULL) goto error;
cur = find_property_by_name(json, "jwks_uri");
if (cur == NULL) {
@@ -637,7 +641,7 @@ static void on_openid_config_retrieved(void *user_data,
*(req.host + (req.path - jwks_uri)) = '\0';
}
grpc_httpcli_get(
- &ctx->verifier->http_ctx, ctx->pollset, &req,
+ exec_ctx, &ctx->verifier->http_ctx, ctx->pollset, &req,
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay),
on_keys_retrieved, ctx);
grpc_json_destroy(json);
@@ -678,7 +682,8 @@ static void verifier_put_mapping(grpc_jwt_verifier *v, const char *email_domain,
}
/* Takes ownership of ctx. */
-static void retrieve_key_and_verify(verifier_cb_ctx *ctx) {
+static void retrieve_key_and_verify(grpc_exec_ctx *exec_ctx,
+ verifier_cb_ctx *ctx) {
const char *at_sign;
grpc_httpcli_response_cb http_cb;
char *path_prefix = NULL;
@@ -739,7 +744,7 @@ static void retrieve_key_and_verify(verifier_cb_ctx *ctx) {
}
grpc_httpcli_get(
- &ctx->verifier->http_ctx, ctx->pollset, &req,
+ exec_ctx, &ctx->verifier->http_ctx, ctx->pollset, &req,
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay),
http_cb, ctx);
gpr_free(req.host);
@@ -751,7 +756,8 @@ error:
verifier_cb_ctx_destroy(ctx);
}
-void grpc_jwt_verifier_verify(grpc_jwt_verifier *verifier,
+void grpc_jwt_verifier_verify(grpc_exec_ctx *exec_ctx,
+ grpc_jwt_verifier *verifier,
grpc_pollset *pollset, const char *jwt,
const char *audience,
grpc_jwt_verification_done_cb cb,
@@ -769,7 +775,7 @@ void grpc_jwt_verifier_verify(grpc_jwt_verifier *verifier,
GPR_ASSERT(verifier != NULL && jwt != NULL && audience != NULL && cb != NULL);
dot = strchr(cur, '.');
if (dot == NULL) goto error;
- json = parse_json_part_from_jwt(cur, dot - cur, &header_buffer);
+ json = parse_json_part_from_jwt(cur, (size_t)(dot - cur), &header_buffer);
if (json == NULL) goto error;
header = jose_header_from_json(json, header_buffer);
if (header == NULL) goto error;
@@ -777,7 +783,7 @@ void grpc_jwt_verifier_verify(grpc_jwt_verifier *verifier,
cur = dot + 1;
dot = strchr(cur, '.');
if (dot == NULL) goto error;
- json = parse_json_part_from_jwt(cur, dot - cur, &claims_buffer);
+ json = parse_json_part_from_jwt(cur, (size_t)(dot - cur), &claims_buffer);
if (json == NULL) goto error;
claims = grpc_jwt_claims_from_json(json, claims_buffer);
if (claims == NULL) goto error;
@@ -787,6 +793,7 @@ void grpc_jwt_verifier_verify(grpc_jwt_verifier *verifier,
signature = grpc_base64_decode(cur, 1);
if (GPR_SLICE_IS_EMPTY(signature)) goto error;
retrieve_key_and_verify(
+ exec_ctx,
verifier_cb_ctx_create(verifier, pollset, header, claims, audience,
signature, jwt, signed_jwt_len, user_data, cb));
return;
diff --git a/src/core/security/jwt_verifier.h b/src/core/security/jwt_verifier.h
index 7a32debfcb..51ea036e4a 100644
--- a/src/core/security/jwt_verifier.h
+++ b/src/core/security/jwt_verifier.h
@@ -120,7 +120,8 @@ typedef void (*grpc_jwt_verification_done_cb)(void *user_data,
grpc_jwt_claims *claims);
/* Verifies for the JWT for the given expected audience. */
-void grpc_jwt_verifier_verify(grpc_jwt_verifier *verifier,
+void grpc_jwt_verifier_verify(grpc_exec_ctx *exec_ctx,
+ grpc_jwt_verifier *verifier,
grpc_pollset *pollset, const char *jwt,
const char *audience,
grpc_jwt_verification_done_cb cb,
diff --git a/src/core/security/secure_endpoint.c b/src/core/security/secure_endpoint.c
index 81b3e33cb2..fd50abb773 100644
--- a/src/core/security/secure_endpoint.c
+++ b/src/core/security/secure_endpoint.c
@@ -49,15 +49,15 @@ typedef struct {
struct tsi_frame_protector *protector;
gpr_mu protector_mu;
/* saved upper level callbacks and user_data. */
- grpc_endpoint_read_cb read_cb;
- void *read_user_data;
- grpc_endpoint_write_cb write_cb;
- void *write_user_data;
+ grpc_closure *read_cb;
+ grpc_closure *write_cb;
+ grpc_closure on_read;
+ gpr_slice_buffer *read_buffer;
+ gpr_slice_buffer source_buffer;
/* saved handshaker leftover data to unprotect. */
gpr_slice_buffer leftover_bytes;
/* buffers for read and write */
gpr_slice read_staging_buffer;
- gpr_slice_buffer input_buffer;
gpr_slice write_staging_buffer;
gpr_slice_buffer output_buffer;
@@ -67,62 +67,97 @@ typedef struct {
int grpc_trace_secure_endpoint = 0;
-static void secure_endpoint_ref(secure_endpoint *ep) { gpr_ref(&ep->ref); }
-
-static void destroy(secure_endpoint *secure_ep) {
+static void destroy(grpc_exec_ctx *exec_ctx, secure_endpoint *secure_ep) {
secure_endpoint *ep = secure_ep;
- grpc_endpoint_destroy(ep->wrapped_ep);
+ grpc_endpoint_destroy(exec_ctx, ep->wrapped_ep);
tsi_frame_protector_destroy(ep->protector);
gpr_slice_buffer_destroy(&ep->leftover_bytes);
gpr_slice_unref(ep->read_staging_buffer);
- gpr_slice_buffer_destroy(&ep->input_buffer);
gpr_slice_unref(ep->write_staging_buffer);
gpr_slice_buffer_destroy(&ep->output_buffer);
+ gpr_slice_buffer_destroy(&ep->source_buffer);
gpr_mu_destroy(&ep->protector_mu);
gpr_free(ep);
}
-static void secure_endpoint_unref(secure_endpoint *ep) {
+/*#define GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG*/
+#ifdef GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG
+#define SECURE_ENDPOINT_UNREF(exec_ctx, ep, reason) \
+ secure_endpoint_unref((exec_ctx), (ep), (reason), __FILE__, __LINE__)
+#define SECURE_ENDPOINT_REF(ep, reason) \
+ secure_endpoint_ref((ep), (reason), __FILE__, __LINE__)
+static void secure_endpoint_unref(secure_endpoint *ep,
+ grpc_closure_list *closure_list,
+ const char *reason, const char *file,
+ int line) {
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP unref %p : %s %d -> %d",
+ ep, reason, ep->ref.count, ep->ref.count - 1);
if (gpr_unref(&ep->ref)) {
- destroy(ep);
+ destroy(exec_ctx, ep);
}
}
+static void secure_endpoint_ref(secure_endpoint *ep, const char *reason,
+ const char *file, int line) {
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP ref %p : %s %d -> %d",
+ ep, reason, ep->ref.count, ep->ref.count + 1);
+ gpr_ref(&ep->ref);
+}
+#else
+#define SECURE_ENDPOINT_UNREF(exec_ctx, ep, reason) \
+ secure_endpoint_unref((exec_ctx), (ep))
+#define SECURE_ENDPOINT_REF(ep, reason) secure_endpoint_ref((ep))
+static void secure_endpoint_unref(grpc_exec_ctx *exec_ctx,
+ secure_endpoint *ep) {
+ if (gpr_unref(&ep->ref)) {
+ destroy(exec_ctx, ep);
+ }
+}
+
+static void secure_endpoint_ref(secure_endpoint *ep) { gpr_ref(&ep->ref); }
+#endif
+
static void flush_read_staging_buffer(secure_endpoint *ep, gpr_uint8 **cur,
gpr_uint8 **end) {
- gpr_slice_buffer_add(&ep->input_buffer, ep->read_staging_buffer);
+ gpr_slice_buffer_add(ep->read_buffer, ep->read_staging_buffer);
ep->read_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE);
*cur = GPR_SLICE_START_PTR(ep->read_staging_buffer);
*end = GPR_SLICE_END_PTR(ep->read_staging_buffer);
}
-static void call_read_cb(secure_endpoint *ep, gpr_slice *slices, size_t nslices,
- grpc_endpoint_cb_status error) {
+static void call_read_cb(grpc_exec_ctx *exec_ctx, secure_endpoint *ep,
+ int success) {
if (grpc_trace_secure_endpoint) {
size_t i;
- for (i = 0; i < nslices; i++) {
- char *data = gpr_dump_slice(slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
+ for (i = 0; i < ep->read_buffer->count; i++) {
+ char *data = gpr_dump_slice(ep->read_buffer->slices[i],
+ GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_DEBUG, "READ %p: %s", ep, data);
gpr_free(data);
}
}
- ep->read_cb(ep->read_user_data, slices, nslices, error);
- secure_endpoint_unref(ep);
+ ep->read_buffer = NULL;
+ grpc_exec_ctx_enqueue(exec_ctx, ep->read_cb, success);
+ SECURE_ENDPOINT_UNREF(exec_ctx, ep, "read");
}
-static void on_read(void *user_data, gpr_slice *slices, size_t nslices,
- grpc_endpoint_cb_status error) {
+static void on_read(grpc_exec_ctx *exec_ctx, void *user_data, int success) {
unsigned i;
gpr_uint8 keep_looping = 0;
- size_t input_buffer_count = 0;
tsi_result result = TSI_OK;
secure_endpoint *ep = (secure_endpoint *)user_data;
gpr_uint8 *cur = GPR_SLICE_START_PTR(ep->read_staging_buffer);
gpr_uint8 *end = GPR_SLICE_END_PTR(ep->read_staging_buffer);
+ if (!success) {
+ gpr_slice_buffer_reset_and_unref(ep->read_buffer);
+ call_read_cb(exec_ctx, ep, 0);
+ return;
+ }
+
/* TODO(yangg) check error, maybe bail out early */
- for (i = 0; i < nslices; i++) {
- gpr_slice encrypted = slices[i];
+ for (i = 0; i < ep->source_buffer.count; i++) {
+ gpr_slice encrypted = ep->source_buffer.slices[i];
gpr_uint8 *message_bytes = GPR_SLICE_START_PTR(encrypted);
size_t message_size = GPR_SLICE_LENGTH(encrypted);
@@ -161,7 +196,7 @@ static void on_read(void *user_data, gpr_slice *slices, size_t nslices,
if (cur != GPR_SLICE_START_PTR(ep->read_staging_buffer)) {
gpr_slice_buffer_add(
- &ep->input_buffer,
+ ep->read_buffer,
gpr_slice_split_head(
&ep->read_staging_buffer,
(size_t)(cur - GPR_SLICE_START_PTR(ep->read_staging_buffer))));
@@ -169,38 +204,34 @@ static void on_read(void *user_data, gpr_slice *slices, size_t nslices,
/* TODO(yangg) experiment with moving this block after read_cb to see if it
helps latency */
- for (i = 0; i < nslices; i++) {
- gpr_slice_unref(slices[i]);
- }
+ gpr_slice_buffer_reset_and_unref(&ep->source_buffer);
if (result != TSI_OK) {
- gpr_slice_buffer_reset_and_unref(&ep->input_buffer);
- call_read_cb(ep, NULL, 0, GRPC_ENDPOINT_CB_ERROR);
+ gpr_slice_buffer_reset_and_unref(ep->read_buffer);
+ call_read_cb(exec_ctx, ep, 0);
return;
}
- /* The upper level will unref the slices. */
- input_buffer_count = ep->input_buffer.count;
- ep->input_buffer.count = 0;
- call_read_cb(ep, ep->input_buffer.slices, input_buffer_count, error);
+
+ call_read_cb(exec_ctx, ep, 1);
}
-static void endpoint_notify_on_read(grpc_endpoint *secure_ep,
- grpc_endpoint_read_cb cb, void *user_data) {
+static void endpoint_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep,
+ gpr_slice_buffer *slices, grpc_closure *cb) {
secure_endpoint *ep = (secure_endpoint *)secure_ep;
ep->read_cb = cb;
- ep->read_user_data = user_data;
-
- secure_endpoint_ref(ep);
+ ep->read_buffer = slices;
+ gpr_slice_buffer_reset_and_unref(ep->read_buffer);
+ SECURE_ENDPOINT_REF(ep, "read");
if (ep->leftover_bytes.count) {
- size_t leftover_nslices = ep->leftover_bytes.count;
- ep->leftover_bytes.count = 0;
- on_read(ep, ep->leftover_bytes.slices, leftover_nslices,
- GRPC_ENDPOINT_CB_OK);
+ gpr_slice_buffer_swap(&ep->leftover_bytes, &ep->source_buffer);
+ GPR_ASSERT(ep->leftover_bytes.count == 0);
+ on_read(exec_ctx, ep, 1);
return;
}
- grpc_endpoint_notify_on_read(ep->wrapped_ep, on_read, ep);
+ grpc_endpoint_read(exec_ctx, ep->wrapped_ep, &ep->source_buffer,
+ &ep->on_read);
}
static void flush_write_staging_buffer(secure_endpoint *ep, gpr_uint8 **cur,
@@ -211,36 +242,27 @@ static void flush_write_staging_buffer(secure_endpoint *ep, gpr_uint8 **cur,
*end = GPR_SLICE_END_PTR(ep->write_staging_buffer);
}
-static void on_write(void *data, grpc_endpoint_cb_status error) {
- secure_endpoint *ep = data;
- ep->write_cb(ep->write_user_data, error);
- secure_endpoint_unref(ep);
-}
-
-static grpc_endpoint_write_status endpoint_write(grpc_endpoint *secure_ep,
- gpr_slice *slices,
- size_t nslices,
- grpc_endpoint_write_cb cb,
- void *user_data) {
+static void endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep,
+ gpr_slice_buffer *slices, grpc_closure *cb) {
unsigned i;
- size_t output_buffer_count = 0;
tsi_result result = TSI_OK;
secure_endpoint *ep = (secure_endpoint *)secure_ep;
gpr_uint8 *cur = GPR_SLICE_START_PTR(ep->write_staging_buffer);
gpr_uint8 *end = GPR_SLICE_END_PTR(ep->write_staging_buffer);
- grpc_endpoint_write_status status;
- GPR_ASSERT(ep->output_buffer.count == 0);
+
+ gpr_slice_buffer_reset_and_unref(&ep->output_buffer);
if (grpc_trace_secure_endpoint) {
- for (i = 0; i < nslices; i++) {
- char *data = gpr_dump_slice(slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
+ for (i = 0; i < slices->count; i++) {
+ char *data =
+ gpr_dump_slice(slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_DEBUG, "WRITE %p: %s", ep, data);
gpr_free(data);
}
}
- for (i = 0; i < nslices; i++) {
- gpr_slice plain = slices[i];
+ for (i = 0; i < slices->count; i++) {
+ gpr_slice plain = slices->slices[i];
gpr_uint8 *message_bytes = GPR_SLICE_START_PTR(plain);
size_t message_size = GPR_SLICE_LENGTH(plain);
while (message_size > 0) {
@@ -290,51 +312,40 @@ static grpc_endpoint_write_status endpoint_write(grpc_endpoint *secure_ep,
}
}
- for (i = 0; i < nslices; i++) {
- gpr_slice_unref(slices[i]);
- }
-
if (result != TSI_OK) {
/* TODO(yangg) do different things according to the error type? */
gpr_slice_buffer_reset_and_unref(&ep->output_buffer);
- return GRPC_ENDPOINT_WRITE_ERROR;
+ grpc_exec_ctx_enqueue(exec_ctx, cb, 0);
+ return;
}
- /* clear output_buffer and let the lower level handle its slices. */
- output_buffer_count = ep->output_buffer.count;
- ep->output_buffer.count = 0;
- ep->write_cb = cb;
- ep->write_user_data = user_data;
- /* Need to keep the endpoint alive across a transport */
- secure_endpoint_ref(ep);
- status = grpc_endpoint_write(ep->wrapped_ep, ep->output_buffer.slices,
- output_buffer_count, on_write, ep);
- if (status != GRPC_ENDPOINT_WRITE_PENDING) {
- secure_endpoint_unref(ep);
- }
- return status;
+ grpc_endpoint_write(exec_ctx, ep->wrapped_ep, &ep->output_buffer, cb);
}
-static void endpoint_shutdown(grpc_endpoint *secure_ep) {
+static void endpoint_shutdown(grpc_exec_ctx *exec_ctx,
+ grpc_endpoint *secure_ep) {
secure_endpoint *ep = (secure_endpoint *)secure_ep;
- grpc_endpoint_shutdown(ep->wrapped_ep);
+ grpc_endpoint_shutdown(exec_ctx, ep->wrapped_ep);
}
-static void endpoint_unref(grpc_endpoint *secure_ep) {
+static void endpoint_destroy(grpc_exec_ctx *exec_ctx,
+ grpc_endpoint *secure_ep) {
secure_endpoint *ep = (secure_endpoint *)secure_ep;
- secure_endpoint_unref(ep);
+ SECURE_ENDPOINT_UNREF(exec_ctx, ep, "destroy");
}
-static void endpoint_add_to_pollset(grpc_endpoint *secure_ep,
+static void endpoint_add_to_pollset(grpc_exec_ctx *exec_ctx,
+ grpc_endpoint *secure_ep,
grpc_pollset *pollset) {
secure_endpoint *ep = (secure_endpoint *)secure_ep;
- grpc_endpoint_add_to_pollset(ep->wrapped_ep, pollset);
+ grpc_endpoint_add_to_pollset(exec_ctx, ep->wrapped_ep, pollset);
}
-static void endpoint_add_to_pollset_set(grpc_endpoint *secure_ep,
+static void endpoint_add_to_pollset_set(grpc_exec_ctx *exec_ctx,
+ grpc_endpoint *secure_ep,
grpc_pollset_set *pollset_set) {
secure_endpoint *ep = (secure_endpoint *)secure_ep;
- grpc_endpoint_add_to_pollset_set(ep->wrapped_ep, pollset_set);
+ grpc_endpoint_add_to_pollset_set(exec_ctx, ep->wrapped_ep, pollset_set);
}
static char *endpoint_get_peer(grpc_endpoint *secure_ep) {
@@ -343,9 +354,8 @@ static char *endpoint_get_peer(grpc_endpoint *secure_ep) {
}
static const grpc_endpoint_vtable vtable = {
- endpoint_notify_on_read, endpoint_write,
- endpoint_add_to_pollset, endpoint_add_to_pollset_set,
- endpoint_shutdown, endpoint_unref,
+ endpoint_read, endpoint_write, endpoint_add_to_pollset,
+ endpoint_add_to_pollset_set, endpoint_shutdown, endpoint_destroy,
endpoint_get_peer};
grpc_endpoint *grpc_secure_endpoint_create(
@@ -363,8 +373,10 @@ grpc_endpoint *grpc_secure_endpoint_create(
}
ep->write_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE);
ep->read_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE);
- gpr_slice_buffer_init(&ep->input_buffer);
gpr_slice_buffer_init(&ep->output_buffer);
+ gpr_slice_buffer_init(&ep->source_buffer);
+ ep->read_buffer = NULL;
+ grpc_closure_init(&ep->on_read, on_read, ep);
gpr_mu_init(&ep->protector_mu);
gpr_ref_init(&ep->ref, 1);
return &ep->base;
diff --git a/src/core/security/secure_transport_setup.c b/src/core/security/secure_transport_setup.c
deleted file mode 100644
index 0c3572b53c..0000000000
--- a/src/core/security/secure_transport_setup.c
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "src/core/security/secure_transport_setup.h"
-
-#include <string.h>
-
-#include "src/core/security/secure_endpoint.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/slice_buffer.h>
-
-#define GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE 256
-
-typedef struct {
- grpc_security_connector *connector;
- tsi_handshaker *handshaker;
- unsigned char *handshake_buffer;
- size_t handshake_buffer_size;
- grpc_endpoint *wrapped_endpoint;
- grpc_endpoint *secure_endpoint;
- gpr_slice_buffer left_overs;
- grpc_secure_transport_setup_done_cb cb;
- void *user_data;
-} grpc_secure_transport_setup;
-
-static void on_handshake_data_received_from_peer(void *setup, gpr_slice *slices,
- size_t nslices,
- grpc_endpoint_cb_status error);
-
-static void on_handshake_data_sent_to_peer(void *setup,
- grpc_endpoint_cb_status error);
-
-static void secure_transport_setup_done(grpc_secure_transport_setup *s,
- int is_success) {
- if (is_success) {
- s->cb(s->user_data, GRPC_SECURITY_OK, s->wrapped_endpoint,
- s->secure_endpoint);
- } else {
- if (s->secure_endpoint != NULL) {
- grpc_endpoint_shutdown(s->secure_endpoint);
- grpc_endpoint_destroy(s->secure_endpoint);
- } else {
- grpc_endpoint_destroy(s->wrapped_endpoint);
- }
- s->cb(s->user_data, GRPC_SECURITY_ERROR, s->wrapped_endpoint, NULL);
- }
- if (s->handshaker != NULL) tsi_handshaker_destroy(s->handshaker);
- if (s->handshake_buffer != NULL) gpr_free(s->handshake_buffer);
- gpr_slice_buffer_destroy(&s->left_overs);
- GRPC_SECURITY_CONNECTOR_UNREF(s->connector, "secure_transport_setup");
- gpr_free(s);
-}
-
-static void on_peer_checked(void *user_data, grpc_security_status status) {
- grpc_secure_transport_setup *s = user_data;
- tsi_frame_protector *protector;
- tsi_result result;
- if (status != GRPC_SECURITY_OK) {
- gpr_log(GPR_ERROR, "Error checking peer.");
- secure_transport_setup_done(s, 0);
- return;
- }
- result =
- tsi_handshaker_create_frame_protector(s->handshaker, NULL, &protector);
- if (result != TSI_OK) {
- gpr_log(GPR_ERROR, "Frame protector creation failed with error %s.",
- tsi_result_to_string(result));
- secure_transport_setup_done(s, 0);
- return;
- }
- s->secure_endpoint =
- grpc_secure_endpoint_create(protector, s->wrapped_endpoint,
- s->left_overs.slices, s->left_overs.count);
- secure_transport_setup_done(s, 1);
- return;
-}
-
-static void check_peer(grpc_secure_transport_setup *s) {
- grpc_security_status peer_status;
- tsi_peer peer;
- tsi_result result = tsi_handshaker_extract_peer(s->handshaker, &peer);
-
- if (result != TSI_OK) {
- gpr_log(GPR_ERROR, "Peer extraction failed with error %s",
- tsi_result_to_string(result));
- secure_transport_setup_done(s, 0);
- return;
- }
- peer_status = grpc_security_connector_check_peer(s->connector, peer,
- on_peer_checked, s);
- if (peer_status == GRPC_SECURITY_ERROR) {
- gpr_log(GPR_ERROR, "Peer check failed.");
- secure_transport_setup_done(s, 0);
- return;
- } else if (peer_status == GRPC_SECURITY_OK) {
- on_peer_checked(s, peer_status);
- }
-}
-
-static void send_handshake_bytes_to_peer(grpc_secure_transport_setup *s) {
- size_t offset = 0;
- tsi_result result = TSI_OK;
- gpr_slice to_send;
- grpc_endpoint_write_status write_status;
-
- do {
- size_t to_send_size = s->handshake_buffer_size - offset;
- result = tsi_handshaker_get_bytes_to_send_to_peer(
- s->handshaker, s->handshake_buffer + offset, &to_send_size);
- offset += to_send_size;
- if (result == TSI_INCOMPLETE_DATA) {
- s->handshake_buffer_size *= 2;
- s->handshake_buffer =
- gpr_realloc(s->handshake_buffer, s->handshake_buffer_size);
- }
- } while (result == TSI_INCOMPLETE_DATA);
-
- if (result != TSI_OK) {
- gpr_log(GPR_ERROR, "Handshake failed with error %s",
- tsi_result_to_string(result));
- secure_transport_setup_done(s, 0);
- return;
- }
-
- to_send =
- gpr_slice_from_copied_buffer((const char *)s->handshake_buffer, offset);
- /* TODO(klempner,jboeuf): This should probably use the client setup
- deadline */
- write_status = grpc_endpoint_write(s->wrapped_endpoint, &to_send, 1,
- on_handshake_data_sent_to_peer, s);
- if (write_status == GRPC_ENDPOINT_WRITE_ERROR) {
- gpr_log(GPR_ERROR, "Could not send handshake data to peer.");
- secure_transport_setup_done(s, 0);
- } else if (write_status == GRPC_ENDPOINT_WRITE_DONE) {
- on_handshake_data_sent_to_peer(s, GRPC_ENDPOINT_CB_OK);
- }
-}
-
-static void cleanup_slices(gpr_slice *slices, size_t num_slices) {
- size_t i;
- for (i = 0; i < num_slices; i++) {
- gpr_slice_unref(slices[i]);
- }
-}
-
-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->wrapped_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 - (size_t)has_left_overs_in_current_slice);
- check_peer(s);
-}
-
-/* If setup is NULL, the setup is done. */
-static void on_handshake_data_sent_to_peer(void *setup,
- grpc_endpoint_cb_status error) {
- grpc_secure_transport_setup *s = setup;
-
- /* Make sure that write is OK. */
- if (error != GRPC_ENDPOINT_CB_OK) {
- gpr_log(GPR_ERROR, "Write failed with error %d.", error);
- if (setup != NULL) secure_transport_setup_done(s, 0);
- return;
- }
-
- /* We may be done. */
- if (tsi_handshaker_is_in_progress(s->handshaker)) {
- /* TODO(klempner,jboeuf): This should probably use the client setup
- deadline */
- grpc_endpoint_notify_on_read(s->wrapped_endpoint,
- on_handshake_data_received_from_peer, setup);
- } else {
- check_peer(s);
- }
-}
-
-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, "secure_transport_setup");
- s->handshake_buffer_size = GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE;
- s->handshake_buffer = gpr_malloc(s->handshake_buffer_size);
- s->wrapped_endpoint = nonsecure_endpoint;
- s->user_data = user_data;
- s->cb = cb;
- gpr_slice_buffer_init(&s->left_overs);
- send_handshake_bytes_to_peer(s);
-}
diff --git a/src/core/security/security_connector.c b/src/core/security/security_connector.c
index ba9ac68c5f..7c4cf6f04d 100644
--- a/src/core/security/security_connector.c
+++ b/src/core/security/security_connector.c
@@ -36,6 +36,7 @@
#include <string.h>
#include "src/core/security/credentials.h"
+#include "src/core/security/handshake.h"
#include "src/core/security/secure_endpoint.h"
#include "src/core/security/security_context.h"
#include "src/core/support/env.h"
@@ -101,10 +102,16 @@ const tsi_peer_property *tsi_peer_get_property_by_name(const tsi_peer *peer,
return NULL;
}
-grpc_security_status grpc_security_connector_create_handshaker(
- grpc_security_connector *sc, tsi_handshaker **handshaker) {
- if (sc == NULL || handshaker == NULL) return GRPC_SECURITY_ERROR;
- return sc->vtable->create_handshaker(sc, handshaker);
+void grpc_security_connector_do_handshake(grpc_exec_ctx *exec_ctx,
+ grpc_security_connector *sc,
+ grpc_endpoint *nonsecure_endpoint,
+ grpc_security_handshake_done_cb cb,
+ void *user_data) {
+ if (sc == NULL || nonsecure_endpoint == NULL) {
+ cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, nonsecure_endpoint, NULL);
+ } else {
+ sc->vtable->do_handshake(exec_ctx, sc, nonsecure_endpoint, cb, user_data);
+ }
}
grpc_security_status grpc_security_connector_check_peer(
@@ -118,10 +125,10 @@ grpc_security_status grpc_security_connector_check_peer(
}
grpc_security_status grpc_channel_security_connector_check_call_host(
- grpc_channel_security_connector *sc, const char *host,
- grpc_security_check_cb cb, void *user_data) {
+ grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
+ const char *host, grpc_security_check_cb cb, void *user_data) {
if (sc == NULL || sc->check_call_host == NULL) return GRPC_SECURITY_ERROR;
- return sc->check_call_host(sc, host, cb, user_data);
+ return sc->check_call_host(exec_ctx, sc, host, cb, user_data);
}
#ifdef GRPC_SECURITY_CONNECTOR_REFCOUNT_DEBUG
@@ -225,18 +232,6 @@ static void fake_server_destroy(grpc_security_connector *sc) {
gpr_free(sc);
}
-static grpc_security_status fake_channel_create_handshaker(
- grpc_security_connector *sc, tsi_handshaker **handshaker) {
- *handshaker = tsi_create_fake_handshaker(1);
- return GRPC_SECURITY_OK;
-}
-
-static grpc_security_status fake_server_create_handshaker(
- grpc_security_connector *sc, tsi_handshaker **handshaker) {
- *handshaker = tsi_create_fake_handshaker(0);
- return GRPC_SECURITY_OK;
-}
-
static grpc_security_status fake_check_peer(grpc_security_connector *sc,
tsi_peer peer,
grpc_security_check_cb cb,
@@ -274,23 +269,41 @@ end:
}
static grpc_security_status fake_channel_check_call_host(
- grpc_channel_security_connector *sc, const char *host,
- grpc_security_check_cb cb, void *user_data) {
+ grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
+ const char *host, grpc_security_check_cb cb, void *user_data) {
grpc_fake_channel_security_connector *c =
(grpc_fake_channel_security_connector *)sc;
if (c->call_host_check_is_async) {
- cb(user_data, GRPC_SECURITY_OK);
+ cb(exec_ctx, user_data, GRPC_SECURITY_OK);
return GRPC_SECURITY_PENDING;
} else {
return GRPC_SECURITY_OK;
}
}
+static void fake_channel_do_handshake(grpc_exec_ctx *exec_ctx,
+ grpc_security_connector *sc,
+ grpc_endpoint *nonsecure_endpoint,
+ grpc_security_handshake_done_cb cb,
+ void *user_data) {
+ grpc_do_security_handshake(exec_ctx, tsi_create_fake_handshaker(1), sc,
+ nonsecure_endpoint, cb, user_data);
+}
+
+static void fake_server_do_handshake(grpc_exec_ctx *exec_ctx,
+ grpc_security_connector *sc,
+ grpc_endpoint *nonsecure_endpoint,
+ grpc_security_handshake_done_cb cb,
+ void *user_data) {
+ grpc_do_security_handshake(exec_ctx, tsi_create_fake_handshaker(0), sc,
+ nonsecure_endpoint, cb, user_data);
+}
+
static grpc_security_connector_vtable fake_channel_vtable = {
- fake_channel_destroy, fake_channel_create_handshaker, fake_check_peer};
+ fake_channel_destroy, fake_channel_do_handshake, fake_check_peer};
static grpc_security_connector_vtable fake_server_vtable = {
- fake_server_destroy, fake_server_create_handshaker, fake_check_peer};
+ fake_server_destroy, fake_server_do_handshake, fake_check_peer};
grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
grpc_credentials *request_metadata_creds, int call_host_check_is_async) {
@@ -372,22 +385,43 @@ static grpc_security_status ssl_create_handshaker(
return GRPC_SECURITY_OK;
}
-static grpc_security_status ssl_channel_create_handshaker(
- grpc_security_connector *sc, tsi_handshaker **handshaker) {
+static void ssl_channel_do_handshake(grpc_exec_ctx *exec_ctx,
+ grpc_security_connector *sc,
+ grpc_endpoint *nonsecure_endpoint,
+ grpc_security_handshake_done_cb cb,
+ void *user_data) {
grpc_ssl_channel_security_connector *c =
(grpc_ssl_channel_security_connector *)sc;
- return ssl_create_handshaker(c->handshaker_factory, 1,
- c->overridden_target_name != NULL
- ? c->overridden_target_name
- : c->target_name,
- handshaker);
+ tsi_handshaker *handshaker;
+ grpc_security_status status = ssl_create_handshaker(
+ c->handshaker_factory, 1,
+ c->overridden_target_name != NULL ? c->overridden_target_name
+ : c->target_name,
+ &handshaker);
+ if (status != GRPC_SECURITY_OK) {
+ cb(exec_ctx, user_data, status, nonsecure_endpoint, NULL);
+ } else {
+ grpc_do_security_handshake(exec_ctx, handshaker, sc, nonsecure_endpoint, cb,
+ user_data);
+ }
}
-static grpc_security_status ssl_server_create_handshaker(
- grpc_security_connector *sc, tsi_handshaker **handshaker) {
+static void ssl_server_do_handshake(grpc_exec_ctx *exec_ctx,
+ grpc_security_connector *sc,
+ grpc_endpoint *nonsecure_endpoint,
+ grpc_security_handshake_done_cb cb,
+ void *user_data) {
grpc_ssl_server_security_connector *c =
(grpc_ssl_server_security_connector *)sc;
- return ssl_create_handshaker(c->handshaker_factory, 0, NULL, handshaker);
+ tsi_handshaker *handshaker;
+ grpc_security_status status =
+ ssl_create_handshaker(c->handshaker_factory, 0, NULL, &handshaker);
+ if (status != GRPC_SECURITY_OK) {
+ cb(exec_ctx, user_data, status, nonsecure_endpoint, NULL);
+ } else {
+ grpc_do_security_handshake(exec_ctx, handshaker, sc, nonsecure_endpoint, cb,
+ user_data);
+ }
}
static int ssl_host_matches_name(const tsi_peer *peer, const char *peer_name) {
@@ -494,8 +528,8 @@ static grpc_security_status ssl_server_check_peer(grpc_security_connector *sc,
}
static grpc_security_status ssl_channel_check_call_host(
- grpc_channel_security_connector *sc, const char *host,
- grpc_security_check_cb cb, void *user_data) {
+ grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
+ const char *host, grpc_security_check_cb cb, void *user_data) {
grpc_ssl_channel_security_connector *c =
(grpc_ssl_channel_security_connector *)sc;
@@ -512,10 +546,10 @@ static grpc_security_status ssl_channel_check_call_host(
}
static grpc_security_connector_vtable ssl_channel_vtable = {
- ssl_channel_destroy, ssl_channel_create_handshaker, ssl_channel_check_peer};
+ ssl_channel_destroy, ssl_channel_do_handshake, ssl_channel_check_peer};
static grpc_security_connector_vtable ssl_server_vtable = {
- ssl_server_destroy, ssl_server_create_handshaker, ssl_server_check_peer};
+ ssl_server_destroy, ssl_server_do_handshake, ssl_server_check_peer};
static gpr_slice default_pem_root_certs;
@@ -614,12 +648,12 @@ grpc_security_status grpc_ssl_channel_security_connector_create(
goto error;
}
*sc = &c->base;
- gpr_free(alpn_protocol_strings);
+ gpr_free((void *)alpn_protocol_strings);
gpr_free(alpn_protocol_string_lengths);
return GRPC_SECURITY_OK;
error:
- gpr_free(alpn_protocol_strings);
+ gpr_free((void *)alpn_protocol_strings);
gpr_free(alpn_protocol_string_lengths);
return GRPC_SECURITY_ERROR;
}
@@ -669,12 +703,12 @@ grpc_security_status grpc_ssl_server_security_connector_create(
goto error;
}
*sc = &c->base;
- gpr_free(alpn_protocol_strings);
+ gpr_free((void *)alpn_protocol_strings);
gpr_free(alpn_protocol_string_lengths);
return GRPC_SECURITY_OK;
error:
- gpr_free(alpn_protocol_strings);
+ gpr_free((void *)alpn_protocol_strings);
gpr_free(alpn_protocol_string_lengths);
return GRPC_SECURITY_ERROR;
}
diff --git a/src/core/security/security_connector.h b/src/core/security/security_connector.h
index 2c9aa1c5a4..9218a3caab 100644
--- a/src/core/security/security_connector.h
+++ b/src/core/security/security_connector.h
@@ -60,13 +60,21 @@ typedef struct grpc_security_connector grpc_security_connector;
#define GRPC_SECURITY_CONNECTOR_ARG "grpc.security_connector"
-typedef void (*grpc_security_check_cb)(void *user_data,
+typedef void (*grpc_security_check_cb)(grpc_exec_ctx *exec_ctx, void *user_data,
grpc_security_status status);
+/* Ownership of the secure_endpoint is transfered. */
+typedef void (*grpc_security_handshake_done_cb)(grpc_exec_ctx *exec_ctx,
+ void *user_data,
+ grpc_security_status status,
+ grpc_endpoint *wrapped_endpoint,
+ grpc_endpoint *secure_endpoint);
+
typedef struct {
void (*destroy)(grpc_security_connector *sc);
- grpc_security_status (*create_handshaker)(grpc_security_connector *sc,
- tsi_handshaker **handshaker);
+ void (*do_handshake)(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc,
+ grpc_endpoint *nonsecure_endpoint,
+ grpc_security_handshake_done_cb cb, void *user_data);
grpc_security_status (*check_peer)(grpc_security_connector *sc, tsi_peer peer,
grpc_security_check_cb cb,
void *user_data);
@@ -100,9 +108,12 @@ grpc_security_connector *grpc_security_connector_ref(
void grpc_security_connector_unref(grpc_security_connector *policy);
#endif
-/* Handshake creation. */
-grpc_security_status grpc_security_connector_create_handshaker(
- grpc_security_connector *sc, tsi_handshaker **handshaker);
+/* Handshake. */
+void grpc_security_connector_do_handshake(grpc_exec_ctx *exec_ctx,
+ grpc_security_connector *connector,
+ grpc_endpoint *nonsecure_endpoint,
+ grpc_security_handshake_done_cb cb,
+ void *user_data);
/* Check the peer.
Implementations can choose to check the peer either synchronously or
@@ -135,7 +146,8 @@ typedef struct grpc_channel_security_connector grpc_channel_security_connector;
struct grpc_channel_security_connector {
grpc_security_connector base; /* requires is_client_side to be non 0. */
grpc_credentials *request_metadata_creds;
- grpc_security_status (*check_call_host)(grpc_channel_security_connector *sc,
+ grpc_security_status (*check_call_host)(grpc_exec_ctx *exec_ctx,
+ grpc_channel_security_connector *sc,
const char *host,
grpc_security_check_cb cb,
void *user_data);
@@ -147,8 +159,8 @@ struct grpc_channel_security_connector {
GRPC_SECURITY_OK. In the asynchronous case, the call will return
GRPC_SECURITY_PENDING unless an error is detected early on. */
grpc_security_status grpc_channel_security_connector_check_call_host(
- grpc_channel_security_connector *sc, const char *host,
- grpc_security_check_cb cb, void *user_data);
+ grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
+ const char *host, grpc_security_check_cb cb, void *user_data);
/* --- Creation security connectors. --- */
diff --git a/src/core/security/security_context.c b/src/core/security/security_context.c
index 95d80ba122..f544c1d943 100644
--- a/src/core/security/security_context.c
+++ b/src/core/security/security_context.c
@@ -34,6 +34,7 @@
#include <string.h>
#include "src/core/security/security_context.h"
+#include "src/core/surface/api_trace.h"
#include "src/core/surface/call.h"
#include "src/core/support/string.h"
@@ -47,6 +48,8 @@
grpc_call_error grpc_call_set_credentials(grpc_call *call,
grpc_credentials *creds) {
grpc_client_security_context *ctx = NULL;
+ GRPC_API_TRACE("grpc_call_set_credentials(call=%p, creds=%p)", 2,
+ (call, creds));
if (!grpc_call_is_client(call)) {
gpr_log(GPR_ERROR, "Method is client-side only.");
return GRPC_CALL_ERROR_NOT_ON_SERVER;
@@ -71,6 +74,7 @@ grpc_call_error grpc_call_set_credentials(grpc_call *call,
grpc_auth_context *grpc_call_auth_context(grpc_call *call) {
void *sec_ctx = grpc_call_context_get(call, GRPC_CONTEXT_SECURITY);
+ GRPC_API_TRACE("grpc_call_auth_context(call=%p)", 1, (call));
if (sec_ctx == NULL) return NULL;
return grpc_call_is_client(call)
? GRPC_AUTH_CONTEXT_REF(
@@ -82,6 +86,7 @@ grpc_auth_context *grpc_call_auth_context(grpc_call *call) {
}
void grpc_auth_context_release(grpc_auth_context *context) {
+ GRPC_API_TRACE("grpc_auth_context_release(context=%p)", 1, (context));
GRPC_AUTH_CONTEXT_UNREF(context, "grpc_auth_context_unref");
}
@@ -174,6 +179,8 @@ void grpc_auth_context_unref(grpc_auth_context *ctx) {
const char *grpc_auth_context_peer_identity_property_name(
const grpc_auth_context *ctx) {
+ GRPC_API_TRACE("grpc_auth_context_peer_identity_property_name(ctx=%p)", 1,
+ (ctx));
return ctx->peer_identity_property_name;
}
@@ -182,6 +189,9 @@ int grpc_auth_context_set_peer_identity_property_name(grpc_auth_context *ctx,
grpc_auth_property_iterator it =
grpc_auth_context_find_properties_by_name(ctx, name);
const grpc_auth_property *prop = grpc_auth_property_iterator_next(&it);
+ GRPC_API_TRACE(
+ "grpc_auth_context_set_peer_identity_property_name(ctx=%p, name=%s)", 2,
+ (ctx, name));
if (prop == NULL) {
gpr_log(GPR_ERROR, "Property name %s not found in auth context.",
name != NULL ? name : "NULL");
@@ -192,12 +202,14 @@ int grpc_auth_context_set_peer_identity_property_name(grpc_auth_context *ctx,
}
int grpc_auth_context_peer_is_authenticated(const grpc_auth_context *ctx) {
+ GRPC_API_TRACE("grpc_auth_context_peer_is_authenticated(ctx=%p)", 1, (ctx));
return ctx->peer_identity_property_name == NULL ? 0 : 1;
}
grpc_auth_property_iterator grpc_auth_context_property_iterator(
const grpc_auth_context *ctx) {
grpc_auth_property_iterator it = empty_iterator;
+ GRPC_API_TRACE("grpc_auth_context_property_iterator(ctx=%p)", 1, (ctx));
if (ctx == NULL) return it;
it.ctx = ctx;
return it;
@@ -205,6 +217,7 @@ grpc_auth_property_iterator grpc_auth_context_property_iterator(
const grpc_auth_property *grpc_auth_property_iterator_next(
grpc_auth_property_iterator *it) {
+ GRPC_API_TRACE("grpc_auth_property_iterator_next(it=%p)", 1, (it));
if (it == NULL || it->ctx == NULL) return NULL;
while (it->index == it->ctx->properties.count) {
if (it->ctx->chained == NULL) return NULL;
@@ -229,6 +242,8 @@ const grpc_auth_property *grpc_auth_property_iterator_next(
grpc_auth_property_iterator grpc_auth_context_find_properties_by_name(
const grpc_auth_context *ctx, const char *name) {
grpc_auth_property_iterator it = empty_iterator;
+ GRPC_API_TRACE("grpc_auth_context_find_properties_by_name(ctx=%p, name=%s)",
+ 2, (ctx, name));
if (ctx == NULL || name == NULL) return empty_iterator;
it.ctx = ctx;
it.name = name;
@@ -237,6 +252,7 @@ grpc_auth_property_iterator grpc_auth_context_find_properties_by_name(
grpc_auth_property_iterator grpc_auth_context_peer_identity(
const grpc_auth_context *ctx) {
+ GRPC_API_TRACE("grpc_auth_context_peer_identity(ctx=%p)", 1, (ctx));
if (ctx == NULL) return empty_iterator;
return grpc_auth_context_find_properties_by_name(
ctx, ctx->peer_identity_property_name);
@@ -255,6 +271,11 @@ static void ensure_auth_context_capacity(grpc_auth_context *ctx) {
void grpc_auth_context_add_property(grpc_auth_context *ctx, const char *name,
const char *value, size_t value_length) {
grpc_auth_property *prop;
+ GRPC_API_TRACE(
+ "grpc_auth_context_add_property(ctx=%p, name=%s, value=%*.*s, "
+ "value_length=%lu)",
+ 6, (ctx, name, (int)value_length, (int)value_length, value,
+ (unsigned long)value_length));
ensure_auth_context_capacity(ctx);
prop = &ctx->properties.array[ctx->properties.count++];
prop->name = gpr_strdup(name);
@@ -268,6 +289,9 @@ void grpc_auth_context_add_cstring_property(grpc_auth_context *ctx,
const char *name,
const char *value) {
grpc_auth_property *prop;
+ GRPC_API_TRACE(
+ "grpc_auth_context_add_cstring_property(ctx=%p, name=%s, value=%s)", 3,
+ (ctx, name, value));
ensure_auth_context_capacity(ctx);
prop = &ctx->properties.array[ctx->properties.count++];
prop->name = gpr_strdup(name);
@@ -281,33 +305,43 @@ void grpc_auth_property_reset(grpc_auth_property *property) {
memset(property, 0, sizeof(grpc_auth_property));
}
-grpc_arg grpc_auth_metadata_processor_to_arg(grpc_auth_metadata_processor *p) {
+static void auth_context_pointer_arg_destroy(void *p) {
+ GRPC_AUTH_CONTEXT_UNREF(p, "auth_context_pointer_arg");
+}
+
+static void *auth_context_pointer_arg_copy(void *p) {
+ return GRPC_AUTH_CONTEXT_REF(p, "auth_context_pointer_arg");
+}
+
+grpc_arg grpc_auth_context_to_arg(grpc_auth_context *p) {
grpc_arg arg;
memset(&arg, 0, sizeof(grpc_arg));
arg.type = GRPC_ARG_POINTER;
- arg.key = GRPC_AUTH_METADATA_PROCESSOR_ARG;
+ arg.key = GRPC_AUTH_CONTEXT_ARG;
arg.value.pointer.p = p;
+ arg.value.pointer.copy = auth_context_pointer_arg_copy;
+ arg.value.pointer.destroy = auth_context_pointer_arg_destroy;
return arg;
}
-grpc_auth_metadata_processor *grpc_auth_metadata_processor_from_arg(
+grpc_auth_context *grpc_auth_context_from_arg(
const grpc_arg *arg) {
- if (strcmp(arg->key, GRPC_AUTH_METADATA_PROCESSOR_ARG) != 0) return NULL;
+ if (strcmp(arg->key, GRPC_AUTH_CONTEXT_ARG) != 0) return NULL;
if (arg->type != GRPC_ARG_POINTER) {
gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type,
- GRPC_AUTH_METADATA_PROCESSOR_ARG);
+ GRPC_AUTH_CONTEXT_ARG);
return NULL;
}
return arg->value.pointer.p;
}
-grpc_auth_metadata_processor *grpc_find_auth_metadata_processor_in_args(
+grpc_auth_context *grpc_find_auth_context_in_args(
const grpc_channel_args *args) {
size_t i;
if (args == NULL) return NULL;
for (i = 0; i < args->num_args; i++) {
- grpc_auth_metadata_processor *p =
- grpc_auth_metadata_processor_from_arg(&args->args[i]);
+ grpc_auth_context *p =
+ grpc_auth_context_from_arg(&args->args[i]);
if (p != NULL) return p;
}
return NULL;
diff --git a/src/core/security/security_context.h b/src/core/security/security_context.h
index a9a0306410..2bbdc4be97 100644
--- a/src/core/security/security_context.h
+++ b/src/core/security/security_context.h
@@ -103,13 +103,12 @@ typedef struct {
grpc_server_security_context *grpc_server_security_context_create(void);
void grpc_server_security_context_destroy(void *ctx);
-/* --- Auth metadata processing. --- */
-#define GRPC_AUTH_METADATA_PROCESSOR_ARG "grpc.auth_metadata_processor"
+/* --- Channel args for auth context --- */
+#define GRPC_AUTH_CONTEXT_ARG "grpc.auth_context"
-grpc_arg grpc_auth_metadata_processor_to_arg(grpc_auth_metadata_processor *p);
-grpc_auth_metadata_processor *grpc_auth_metadata_processor_from_arg(
- const grpc_arg *arg);
-grpc_auth_metadata_processor *grpc_find_auth_metadata_processor_in_args(
+grpc_arg grpc_auth_context_to_arg(grpc_auth_context *c);
+grpc_auth_context *grpc_auth_context_from_arg(const grpc_arg *arg);
+grpc_auth_context *grpc_find_auth_context_in_args(
const grpc_channel_args *args);
#endif /* GRPC_INTERNAL_CORE_SECURITY_SECURITY_CONTEXT_H */
diff --git a/src/core/security/server_auth_filter.c b/src/core/security/server_auth_filter.c
index b767f85498..2e18369fe8 100644
--- a/src/core/security/server_auth_filter.c
+++ b/src/core/security/server_auth_filter.c
@@ -34,7 +34,7 @@
#include <string.h>
#include "src/core/security/auth_filters.h"
-#include "src/core/security/security_connector.h"
+#include "src/core/security/credentials.h"
#include "src/core/security/security_context.h"
#include <grpc/support/alloc.h>
@@ -44,11 +44,11 @@ typedef struct call_data {
gpr_uint8 got_client_metadata;
grpc_stream_op_buffer *recv_ops;
/* Closure to call when finished with the auth_on_recv hook. */
- grpc_iomgr_closure *on_done_recv;
+ grpc_closure *on_done_recv;
/* Receive closures are chained: we inject this closure as the on_done_recv
up-call on transport_op, and remember to call our on_done_recv member after
handling it. */
- grpc_iomgr_closure auth_on_recv;
+ grpc_closure auth_on_recv;
grpc_transport_stream_op transport_op;
grpc_metadata_array md;
const grpc_metadata *consumed_md;
@@ -58,8 +58,8 @@ typedef struct call_data {
} call_data;
typedef struct channel_data {
- grpc_security_connector *security_connector;
- grpc_auth_metadata_processor processor;
+ grpc_auth_context *auth_context;
+ grpc_server_credentials *creds;
grpc_mdctx *mdctx;
} channel_data;
@@ -109,12 +109,14 @@ static grpc_mdelem *remove_consumed_md(void *user_data, grpc_mdelem *md) {
return md;
}
+/* called from application code */
static void on_md_processing_done(
void *user_data, const grpc_metadata *consumed_md, size_t num_consumed_md,
const grpc_metadata *response_md, size_t num_response_md,
grpc_status_code status, const char *error_details) {
grpc_call_element *elem = user_data;
call_data *calld = elem->call_data;
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
/* TODO(jboeuf): Implement support for response_md. */
if (response_md != NULL && num_response_md > 0) {
@@ -128,21 +130,25 @@ static void on_md_processing_done(
calld->num_consumed_md = num_consumed_md;
grpc_metadata_batch_filter(&calld->md_op->data.metadata, remove_consumed_md,
elem);
- calld->on_done_recv->cb(calld->on_done_recv->cb_arg, 1);
+ grpc_metadata_array_destroy(&calld->md);
+ calld->on_done_recv->cb(&exec_ctx, calld->on_done_recv->cb_arg, 1);
} else {
gpr_slice message;
+ grpc_metadata_array_destroy(&calld->md);
error_details = error_details != NULL
- ? error_details
- : "Authentication metadata processing failed.";
+ ? error_details
+ : "Authentication metadata processing failed.";
message = gpr_slice_from_copied_string(error_details);
grpc_sopb_reset(calld->recv_ops);
grpc_transport_stream_op_add_close(&calld->transport_op, status, &message);
- grpc_call_next_op(elem, &calld->transport_op);
+ grpc_call_next_op(&exec_ctx, elem, &calld->transport_op);
}
- grpc_metadata_array_destroy(&calld->md);
+
+ grpc_exec_ctx_finish(&exec_ctx);
}
-static void auth_on_recv(void *user_data, int success) {
+static void auth_on_recv(grpc_exec_ctx *exec_ctx, void *user_data,
+ int success) {
grpc_call_element *elem = user_data;
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
@@ -154,16 +160,16 @@ static void auth_on_recv(void *user_data, int success) {
grpc_stream_op *op = &ops[i];
if (op->type != GRPC_OP_METADATA || calld->got_client_metadata) continue;
calld->got_client_metadata = 1;
- if (chand->processor.process == NULL) continue;
+ if (chand->creds->processor.process == NULL) continue;
calld->md_op = op;
calld->md = metadata_batch_to_md_array(&op->data.metadata);
- chand->processor.process(chand->processor.state, calld->auth_context,
- calld->md.metadata, calld->md.count,
- on_md_processing_done, elem);
+ chand->creds->processor.process(
+ chand->creds->processor.state, calld->auth_context,
+ calld->md.metadata, calld->md.count, on_md_processing_done, elem);
return;
}
}
- calld->on_done_recv->cb(calld->on_done_recv->cb_arg, success);
+ calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, success);
}
static void set_recv_ops_md_callbacks(grpc_call_element *elem,
@@ -184,14 +190,15 @@ static void set_recv_ops_md_callbacks(grpc_call_element *elem,
- a network event (or similar) from below, to receive something
op contains type and call direction information, in addition to the data
that is being sent or received. */
-static void auth_start_transport_op(grpc_call_element *elem,
+static void auth_start_transport_op(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
grpc_transport_stream_op *op) {
set_recv_ops_md_callbacks(elem, op);
- grpc_call_next_op(elem, op);
+ grpc_call_next_op(exec_ctx, elem, op);
}
/* Constructor for call_data */
-static void init_call_elem(grpc_call_element *elem,
+static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const void *server_transport_data,
grpc_transport_stream_op *initial_op) {
/* grab pointers to our data from the call element */
@@ -201,7 +208,7 @@ static void init_call_elem(grpc_call_element *elem,
/* initialize members */
memset(calld, 0, sizeof(*calld));
- grpc_iomgr_closure_init(&calld->auth_on_recv, auth_on_recv, elem);
+ grpc_closure_init(&calld->auth_on_recv, auth_on_recv, elem);
GPR_ASSERT(initial_op && initial_op->context != NULL &&
initial_op->context[GRPC_CONTEXT_SECURITY].value == NULL);
@@ -214,7 +221,7 @@ static void init_call_elem(grpc_call_element *elem,
}
server_ctx = grpc_server_security_context_create();
server_ctx->auth_context =
- grpc_auth_context_create(chand->security_connector->auth_context);
+ grpc_auth_context_create(chand->auth_context);
server_ctx->auth_context->pollset = initial_op->bind_pollset;
initial_op->context[GRPC_CONTEXT_SECURITY].value = server_ctx;
initial_op->context[GRPC_CONTEXT_SECURITY].destroy =
@@ -226,15 +233,16 @@ static void init_call_elem(grpc_call_element *elem,
}
/* Destructor for call_data */
-static void destroy_call_elem(grpc_call_element *elem) {}
+static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem) {}
/* Constructor for channel_data */
-static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
+static void init_channel_elem(grpc_exec_ctx *exec_ctx,
+ grpc_channel_element *elem, grpc_channel *master,
const grpc_channel_args *args, grpc_mdctx *mdctx,
int is_first, int is_last) {
- grpc_security_connector *sc = grpc_find_security_connector_in_args(args);
- grpc_auth_metadata_processor *processor =
- grpc_find_auth_metadata_processor_in_args(args);
+ grpc_auth_context *auth_context = grpc_find_auth_context_in_args(args);
+ grpc_server_credentials *creds = grpc_find_server_credentials_in_args(args);
/* grab pointers to our data from the channel element */
channel_data *chand = elem->channel_data;
@@ -243,28 +251,27 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
path */
GPR_ASSERT(!is_first);
GPR_ASSERT(!is_last);
- GPR_ASSERT(sc != NULL);
- GPR_ASSERT(processor != NULL);
+ GPR_ASSERT(auth_context != NULL);
+ GPR_ASSERT(creds != NULL);
/* initialize members */
- GPR_ASSERT(!sc->is_client_side);
- chand->security_connector =
- GRPC_SECURITY_CONNECTOR_REF(sc, "server_auth_filter");
+ chand->auth_context =
+ GRPC_AUTH_CONTEXT_REF(auth_context, "server_auth_filter");
+ chand->creds = grpc_server_credentials_ref(creds);
chand->mdctx = mdctx;
- chand->processor = *processor;
}
/* Destructor for channel data */
-static void destroy_channel_elem(grpc_channel_element *elem) {
+static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
+ grpc_channel_element *elem) {
/* grab pointers to our data from the channel element */
channel_data *chand = elem->channel_data;
- GRPC_SECURITY_CONNECTOR_UNREF(chand->security_connector,
- "server_auth_filter");
+ GRPC_AUTH_CONTEXT_UNREF(chand->auth_context, "server_auth_filter");
+ grpc_server_credentials_unref(chand->creds);
}
const grpc_channel_filter grpc_server_auth_filter = {
- auth_start_transport_op, grpc_channel_next_op,
- sizeof(call_data), init_call_elem,
- destroy_call_elem, sizeof(channel_data),
- init_channel_elem, destroy_channel_elem,
- grpc_call_next_get_peer, "server-auth"};
+ auth_start_transport_op, grpc_channel_next_op, sizeof(call_data),
+ init_call_elem, destroy_call_elem, sizeof(channel_data),
+ init_channel_elem, destroy_channel_elem, grpc_call_next_get_peer,
+ "server-auth"};
diff --git a/src/core/security/server_secure_chttp2.c b/src/core/security/server_secure_chttp2.c
index 4749f5f516..82c639e830 100644
--- a/src/core/security/server_secure_chttp2.c
+++ b/src/core/security/server_secure_chttp2.c
@@ -44,7 +44,7 @@
#include "src/core/security/credentials.h"
#include "src/core/security/security_connector.h"
#include "src/core/security/security_context.h"
-#include "src/core/security/secure_transport_setup.h"
+#include "src/core/surface/api_trace.h"
#include "src/core/surface/server.h"
#include "src/core/transport/chttp2_transport.h"
#include <grpc/support/alloc.h>
@@ -66,6 +66,8 @@ typedef struct grpc_server_secure_state {
int is_shutdown;
gpr_mu mu;
gpr_refcount refcount;
+ grpc_closure destroy_closure;
+ grpc_closure *destroy_callback;
} grpc_server_secure_state;
static void state_ref(grpc_server_secure_state *state) {
@@ -84,20 +86,20 @@ static void state_unref(grpc_server_secure_state *state) {
}
}
-static void setup_transport(void *statep, grpc_transport *transport,
- grpc_mdctx *mdctx) {
+static void setup_transport(grpc_exec_ctx *exec_ctx, void *statep,
+ grpc_transport *transport, grpc_mdctx *mdctx) {
static grpc_channel_filter const *extra_filters[] = {
&grpc_server_auth_filter, &grpc_http_server_filter};
grpc_server_secure_state *state = statep;
grpc_channel_args *args_copy;
grpc_arg args_to_add[2];
- args_to_add[0] = grpc_security_connector_to_arg(state->sc);
+ args_to_add[0] = grpc_server_credentials_to_arg(state->creds);
args_to_add[1] =
- grpc_auth_metadata_processor_to_arg(&state->creds->processor);
+ grpc_auth_context_to_arg(state->sc->auth_context);
args_copy = grpc_channel_args_copy_and_add(
grpc_server_get_channel_args(state->server), args_to_add,
GPR_ARRAY_SIZE(args_to_add));
- grpc_server_setup_transport(state->server, transport, extra_filters,
+ grpc_server_setup_transport(exec_ctx, state->server, transport, extra_filters,
GPR_ARRAY_SIZE(extra_filters), mdctx, args_copy);
grpc_channel_args_destroy(args_copy);
}
@@ -123,10 +125,10 @@ static int remove_tcp_from_list_locked(grpc_server_secure_state *state,
return -1;
}
-static void on_secure_transport_setup_done(void *statep,
- grpc_security_status status,
- grpc_endpoint *wrapped_endpoint,
- grpc_endpoint *secure_endpoint) {
+static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *statep,
+ grpc_security_status status,
+ grpc_endpoint *wrapped_endpoint,
+ grpc_endpoint *secure_endpoint) {
grpc_server_secure_state *state = statep;
grpc_transport *transport;
grpc_mdctx *mdctx;
@@ -136,14 +138,14 @@ static void on_secure_transport_setup_done(void *statep,
if (!state->is_shutdown) {
mdctx = grpc_mdctx_create();
transport = grpc_create_chttp2_transport(
- grpc_server_get_channel_args(state->server), secure_endpoint, mdctx,
- 0);
- setup_transport(state, transport, mdctx);
- grpc_chttp2_transport_start_reading(transport, NULL, 0);
+ exec_ctx, grpc_server_get_channel_args(state->server),
+ secure_endpoint, mdctx, 0);
+ setup_transport(exec_ctx, state, transport, mdctx);
+ grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL, 0);
} else {
/* We need to consume this here, because the server may already have gone
* away. */
- grpc_endpoint_destroy(secure_endpoint);
+ grpc_endpoint_destroy(exec_ctx, secure_endpoint);
}
gpr_mu_unlock(&state->mu);
} else {
@@ -155,7 +157,8 @@ static void on_secure_transport_setup_done(void *statep,
state_unref(state);
}
-static void on_accept(void *statep, grpc_endpoint *tcp) {
+static void on_accept(grpc_exec_ctx *exec_ctx, void *statep,
+ grpc_endpoint *tcp) {
grpc_server_secure_state *state = statep;
tcp_endpoint_list *node;
state_ref(state);
@@ -165,23 +168,26 @@ static void on_accept(void *statep, grpc_endpoint *tcp) {
node->next = state->handshaking_tcp_endpoints;
state->handshaking_tcp_endpoints = node;
gpr_mu_unlock(&state->mu);
- grpc_setup_secure_transport(state->sc, tcp, on_secure_transport_setup_done,
- state);
+ grpc_security_connector_do_handshake(exec_ctx, state->sc, tcp,
+ on_secure_handshake_done, state);
}
/* Server callback: start listening on our ports */
-static void start(grpc_server *server, void *statep, grpc_pollset **pollsets,
- size_t pollset_count) {
+static void start(grpc_exec_ctx *exec_ctx, grpc_server *server, void *statep,
+ grpc_pollset **pollsets, size_t pollset_count) {
grpc_server_secure_state *state = statep;
- grpc_tcp_server_start(state->tcp, pollsets, pollset_count, on_accept, state);
+ grpc_tcp_server_start(exec_ctx, state->tcp, pollsets, pollset_count,
+ on_accept, state);
}
-static void destroy_done(void *statep) {
+static void destroy_done(grpc_exec_ctx *exec_ctx, void *statep, int success) {
grpc_server_secure_state *state = statep;
- grpc_server_listener_destroy_done(state->server);
+ state->destroy_callback->cb(exec_ctx, state->destroy_callback->cb_arg,
+ success);
gpr_mu_lock(&state->mu);
while (state->handshaking_tcp_endpoints != NULL) {
- grpc_endpoint_shutdown(state->handshaking_tcp_endpoints->tcp_endpoint);
+ grpc_endpoint_shutdown(exec_ctx,
+ state->handshaking_tcp_endpoints->tcp_endpoint);
remove_tcp_from_list_locked(state,
state->handshaking_tcp_endpoints->tcp_endpoint);
}
@@ -191,14 +197,17 @@ static void destroy_done(void *statep) {
/* Server callback: destroy the tcp listener (so we don't generate further
callbacks) */
-static void destroy(grpc_server *server, void *statep) {
+static void destroy(grpc_exec_ctx *exec_ctx, grpc_server *server, void *statep,
+ grpc_closure *callback) {
grpc_server_secure_state *state = statep;
grpc_tcp_server *tcp;
gpr_mu_lock(&state->mu);
state->is_shutdown = 1;
+ state->destroy_callback = callback;
tcp = state->tcp;
gpr_mu_unlock(&state->mu);
- grpc_tcp_server_destroy(tcp, destroy_done, state);
+ grpc_closure_init(&state->destroy_closure, destroy_done, state);
+ grpc_tcp_server_destroy(exec_ctx, tcp, &state->destroy_closure);
}
int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
@@ -212,6 +221,12 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
int port_temp;
grpc_security_status status = GRPC_SECURITY_ERROR;
grpc_security_connector *sc = NULL;
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+ GRPC_API_TRACE(
+ "grpc_server_add_secure_http2_port("
+ "server=%p, addr=%s, creds=%p)",
+ 3, (server, addr, creds));
/* create security context */
if (creds == NULL) goto error;
@@ -272,8 +287,9 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
gpr_ref_init(&state->refcount, 1);
/* Register with the server only upon success */
- grpc_server_add_listener(server, state, start, destroy);
+ grpc_server_add_listener(&exec_ctx, server, state, start, destroy);
+ grpc_exec_ctx_finish(&exec_ctx);
return port_num;
/* Error path: cleanup and return */
@@ -285,10 +301,11 @@ error:
grpc_resolved_addresses_destroy(resolved);
}
if (tcp) {
- grpc_tcp_server_destroy(tcp, NULL, NULL);
+ grpc_tcp_server_destroy(&exec_ctx, tcp, NULL);
}
if (state) {
gpr_free(state);
}
+ grpc_exec_ctx_finish(&exec_ctx);
return 0;
}