aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/lib/security
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/lib/security')
-rw-r--r--src/core/lib/security/context/security_context.c10
-rw-r--r--src/core/lib/security/credentials/composite/composite_credentials.c31
-rw-r--r--src/core/lib/security/credentials/credentials.c55
-rw-r--r--src/core/lib/security/credentials/credentials.h39
-rw-r--r--src/core/lib/security/credentials/credentials_metadata.c13
-rw-r--r--src/core/lib/security/credentials/fake/fake_credentials.c24
-rw-r--r--src/core/lib/security/credentials/google_default/google_default_credentials.c46
-rw-r--r--src/core/lib/security/credentials/iam/iam_credentials.c5
-rw-r--r--src/core/lib/security/credentials/jwt/jwt_credentials.c28
-rw-r--r--src/core/lib/security/credentials/jwt/jwt_credentials.h3
-rw-r--r--src/core/lib/security/credentials/jwt/jwt_verifier.c150
-rw-r--r--src/core/lib/security/credentials/jwt/jwt_verifier.h13
-rw-r--r--src/core/lib/security/credentials/oauth2/oauth2_credentials.c50
-rw-r--r--src/core/lib/security/credentials/oauth2/oauth2_credentials.h2
-rw-r--r--src/core/lib/security/credentials/plugin/plugin_credentials.c12
-rw-r--r--src/core/lib/security/credentials/ssl/ssl_credentials.c20
-rw-r--r--src/core/lib/security/transport/client_auth_filter.c28
-rw-r--r--src/core/lib/security/transport/handshake.c374
-rw-r--r--src/core/lib/security/transport/secure_endpoint.c39
-rw-r--r--src/core/lib/security/transport/security_connector.c286
-rw-r--r--src/core/lib/security/transport/security_connector.h78
-rw-r--r--src/core/lib/security/transport/security_handshaker.c501
-rw-r--r--src/core/lib/security/transport/security_handshaker.h (renamed from src/core/lib/security/transport/handshake.h)21
-rw-r--r--src/core/lib/security/transport/server_auth_filter.c36
-rw-r--r--src/core/lib/security/util/b64.c13
-rw-r--r--src/core/lib/security/util/b64.h7
26 files changed, 1037 insertions, 847 deletions
diff --git a/src/core/lib/security/context/security_context.c b/src/core/lib/security/context/security_context.c
index 2204fadf54..fe82fabc31 100644
--- a/src/core/lib/security/context/security_context.c
+++ b/src/core/lib/security/context/security_context.c
@@ -47,6 +47,7 @@
grpc_call_error grpc_call_set_credentials(grpc_call *call,
grpc_call_credentials *creds) {
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_client_security_context *ctx = NULL;
GRPC_API_TRACE("grpc_call_set_credentials(call=%p, creds=%p)", 2,
(call, creds));
@@ -62,9 +63,10 @@ grpc_call_error grpc_call_set_credentials(grpc_call *call,
grpc_call_context_set(call, GRPC_CONTEXT_SECURITY, ctx,
grpc_client_security_context_destroy);
} else {
- grpc_call_credentials_unref(ctx->creds);
+ grpc_call_credentials_unref(&exec_ctx, ctx->creds);
ctx->creds = grpc_call_credentials_ref(creds);
}
+ grpc_exec_ctx_finish(&exec_ctx);
return GRPC_CALL_OK;
}
@@ -96,13 +98,15 @@ grpc_client_security_context *grpc_client_security_context_create(void) {
}
void grpc_client_security_context_destroy(void *ctx) {
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_client_security_context *c = (grpc_client_security_context *)ctx;
- grpc_call_credentials_unref(c->creds);
+ grpc_call_credentials_unref(&exec_ctx, c->creds);
GRPC_AUTH_CONTEXT_UNREF(c->auth_context, "client_security_context");
if (c->extension.instance != NULL && c->extension.destroy != NULL) {
c->extension.destroy(c->extension.instance);
}
gpr_free(ctx);
+ grpc_exec_ctx_finish(&exec_ctx);
}
/* --- grpc_server_security_context --- */
@@ -307,7 +311,7 @@ void grpc_auth_property_reset(grpc_auth_property *property) {
memset(property, 0, sizeof(grpc_auth_property));
}
-static void auth_context_pointer_arg_destroy(void *p) {
+static void auth_context_pointer_arg_destroy(grpc_exec_ctx *exec_ctx, void *p) {
GRPC_AUTH_CONTEXT_UNREF(p, "auth_context_pointer_arg");
}
diff --git a/src/core/lib/security/credentials/composite/composite_credentials.c b/src/core/lib/security/credentials/composite/composite_credentials.c
index d55d00b7b6..be1588dd8b 100644
--- a/src/core/lib/security/credentials/composite/composite_credentials.c
+++ b/src/core/lib/security/credentials/composite/composite_credentials.c
@@ -54,18 +54,20 @@ typedef struct {
grpc_credentials_metadata_cb cb;
} grpc_composite_call_credentials_metadata_context;
-static void composite_call_destruct(grpc_call_credentials *creds) {
+static void composite_call_destruct(grpc_exec_ctx *exec_ctx,
+ grpc_call_credentials *creds) {
grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
size_t i;
for (i = 0; i < c->inner.num_creds; i++) {
- grpc_call_credentials_unref(c->inner.creds_array[i]);
+ grpc_call_credentials_unref(exec_ctx, c->inner.creds_array[i]);
}
gpr_free(c->inner.creds_array);
}
static void composite_call_md_context_destroy(
+ grpc_exec_ctx *exec_ctx,
grpc_composite_call_credentials_metadata_context *ctx) {
- grpc_credentials_md_store_unref(ctx->md_elems);
+ grpc_credentials_md_store_unref(exec_ctx, ctx->md_elems);
gpr_free(ctx);
}
@@ -103,7 +105,7 @@ static void composite_call_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data,
/* We're done!. */
ctx->cb(exec_ctx, ctx->user_data, ctx->md_elems->entries,
ctx->md_elems->num_entries, GRPC_CREDENTIALS_OK, NULL);
- composite_call_md_context_destroy(ctx);
+ composite_call_md_context_destroy(exec_ctx, ctx);
}
static void composite_call_get_request_metadata(
@@ -209,17 +211,19 @@ grpc_call_credentials *grpc_credentials_contains_type(
/* -- Composite channel credentials. -- */
-static void composite_channel_destruct(grpc_channel_credentials *creds) {
+static void composite_channel_destruct(grpc_exec_ctx *exec_ctx,
+ grpc_channel_credentials *creds) {
grpc_composite_channel_credentials *c =
(grpc_composite_channel_credentials *)creds;
- grpc_channel_credentials_unref(c->inner_creds);
- grpc_call_credentials_unref(c->call_creds);
+ grpc_channel_credentials_unref(exec_ctx, c->inner_creds);
+ grpc_call_credentials_unref(exec_ctx, c->call_creds);
}
static grpc_security_status composite_channel_create_security_connector(
- grpc_channel_credentials *creds, grpc_call_credentials *call_creds,
- const char *target, const grpc_channel_args *args,
- grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
+ grpc_exec_ctx *exec_ctx, grpc_channel_credentials *creds,
+ grpc_call_credentials *call_creds, const char *target,
+ const grpc_channel_args *args, grpc_channel_security_connector **sc,
+ grpc_channel_args **new_args) {
grpc_composite_channel_credentials *c =
(grpc_composite_channel_credentials *)creds;
grpc_security_status status = GRPC_SECURITY_ERROR;
@@ -233,11 +237,12 @@ static grpc_security_status composite_channel_create_security_connector(
grpc_call_credentials *composite_call_creds =
grpc_composite_call_credentials_create(c->call_creds, call_creds, NULL);
status = c->inner_creds->vtable->create_security_connector(
- c->inner_creds, composite_call_creds, target, args, sc, new_args);
- grpc_call_credentials_unref(composite_call_creds);
+ exec_ctx, c->inner_creds, composite_call_creds, target, args, sc,
+ new_args);
+ grpc_call_credentials_unref(exec_ctx, composite_call_creds);
} else {
status = c->inner_creds->vtable->create_security_connector(
- c->inner_creds, c->call_creds, target, args, sc, new_args);
+ exec_ctx, c->inner_creds, c->call_creds, target, args, sc, new_args);
}
return status;
}
diff --git a/src/core/lib/security/credentials/credentials.c b/src/core/lib/security/credentials/credentials.c
index 1149e5c2ed..9781a22a86 100644
--- a/src/core/lib/security/credentials/credentials.c
+++ b/src/core/lib/security/credentials/credentials.c
@@ -66,8 +66,8 @@ grpc_credentials_metadata_request *grpc_credentials_metadata_request_create(
}
void grpc_credentials_metadata_request_destroy(
- grpc_credentials_metadata_request *r) {
- grpc_call_credentials_unref(r->creds);
+ grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *r) {
+ grpc_call_credentials_unref(exec_ctx, r->creds);
grpc_http_response_destroy(&r->response);
gpr_free(r);
}
@@ -79,17 +79,22 @@ grpc_channel_credentials *grpc_channel_credentials_ref(
return creds;
}
-void grpc_channel_credentials_unref(grpc_channel_credentials *creds) {
+void grpc_channel_credentials_unref(grpc_exec_ctx *exec_ctx,
+ grpc_channel_credentials *creds) {
if (creds == NULL) return;
if (gpr_unref(&creds->refcount)) {
- if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds);
+ if (creds->vtable->destruct != NULL) {
+ creds->vtable->destruct(exec_ctx, creds);
+ }
gpr_free(creds);
}
}
void grpc_channel_credentials_release(grpc_channel_credentials *creds) {
GRPC_API_TRACE("grpc_channel_credentials_release(creds=%p)", 1, (creds));
- grpc_channel_credentials_unref(creds);
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_channel_credentials_unref(&exec_ctx, creds);
+ grpc_exec_ctx_finish(&exec_ctx);
}
grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds) {
@@ -98,17 +103,22 @@ grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds) {
return creds;
}
-void grpc_call_credentials_unref(grpc_call_credentials *creds) {
+void grpc_call_credentials_unref(grpc_exec_ctx *exec_ctx,
+ grpc_call_credentials *creds) {
if (creds == NULL) return;
if (gpr_unref(&creds->refcount)) {
- if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds);
+ if (creds->vtable->destruct != NULL) {
+ creds->vtable->destruct(exec_ctx, creds);
+ }
gpr_free(creds);
}
}
void grpc_call_credentials_release(grpc_call_credentials *creds) {
GRPC_API_TRACE("grpc_call_credentials_release(creds=%p)", 1, (creds));
- grpc_call_credentials_unref(creds);
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_call_credentials_unref(&exec_ctx, creds);
+ grpc_exec_ctx_finish(&exec_ctx);
}
void grpc_call_credentials_get_request_metadata(
@@ -126,16 +136,16 @@ void grpc_call_credentials_get_request_metadata(
}
grpc_security_status grpc_channel_credentials_create_security_connector(
- grpc_channel_credentials *channel_creds, const char *target,
- const grpc_channel_args *args, grpc_channel_security_connector **sc,
- grpc_channel_args **new_args) {
+ grpc_exec_ctx *exec_ctx, grpc_channel_credentials *channel_creds,
+ const char *target, const grpc_channel_args *args,
+ grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
*new_args = NULL;
if (channel_creds == NULL) {
return GRPC_SECURITY_ERROR;
}
GPR_ASSERT(channel_creds->vtable->create_security_connector != NULL);
return channel_creds->vtable->create_security_connector(
- channel_creds, NULL, target, args, sc, new_args);
+ exec_ctx, channel_creds, NULL, target, args, sc, new_args);
}
grpc_channel_credentials *
@@ -157,10 +167,13 @@ grpc_server_credentials *grpc_server_credentials_ref(
return creds;
}
-void grpc_server_credentials_unref(grpc_server_credentials *creds) {
+void grpc_server_credentials_unref(grpc_exec_ctx *exec_ctx,
+ grpc_server_credentials *creds) {
if (creds == NULL) return;
if (gpr_unref(&creds->refcount)) {
- if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds);
+ if (creds->vtable->destruct != NULL) {
+ creds->vtable->destruct(exec_ctx, creds);
+ }
if (creds->processor.destroy != NULL && creds->processor.state != NULL) {
creds->processor.destroy(creds->processor.state);
}
@@ -170,16 +183,19 @@ 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);
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_server_credentials_unref(&exec_ctx, creds);
+ grpc_exec_ctx_finish(&exec_ctx);
}
grpc_security_status grpc_server_credentials_create_security_connector(
- grpc_server_credentials *creds, grpc_server_security_connector **sc) {
+ grpc_exec_ctx *exec_ctx, grpc_server_credentials *creds,
+ grpc_server_security_connector **sc) {
if (creds == NULL || creds->vtable->create_security_connector == NULL) {
gpr_log(GPR_ERROR, "Server credentials cannot create security context.");
return GRPC_SECURITY_ERROR;
}
- return creds->vtable->create_security_connector(creds, sc);
+ return creds->vtable->create_security_connector(exec_ctx, creds, sc);
}
void grpc_server_credentials_set_auth_metadata_processor(
@@ -196,8 +212,9 @@ 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_destroy(grpc_exec_ctx *exec_ctx,
+ void *p) {
+ grpc_server_credentials_unref(exec_ctx, p);
}
static void *server_credentials_pointer_arg_copy(void *p) {
diff --git a/src/core/lib/security/credentials/credentials.h b/src/core/lib/security/credentials/credentials.h
index 85b3bc5350..3011df6b8a 100644
--- a/src/core/lib/security/credentials/credentials.h
+++ b/src/core/lib/security/credentials/credentials.h
@@ -101,12 +101,13 @@ void grpc_override_well_known_credentials_path_getter(
/* --- grpc_channel_credentials. --- */
typedef struct {
- void (*destruct)(grpc_channel_credentials *c);
+ void (*destruct)(grpc_exec_ctx *exec_ctx, grpc_channel_credentials *c);
grpc_security_status (*create_security_connector)(
- grpc_channel_credentials *c, grpc_call_credentials *call_creds,
- const char *target, const grpc_channel_args *args,
- grpc_channel_security_connector **sc, grpc_channel_args **new_args);
+ grpc_exec_ctx *exec_ctx, grpc_channel_credentials *c,
+ grpc_call_credentials *call_creds, const char *target,
+ const grpc_channel_args *args, grpc_channel_security_connector **sc,
+ grpc_channel_args **new_args);
grpc_channel_credentials *(*duplicate_without_call_credentials)(
grpc_channel_credentials *c);
@@ -120,16 +121,17 @@ struct grpc_channel_credentials {
grpc_channel_credentials *grpc_channel_credentials_ref(
grpc_channel_credentials *creds);
-void grpc_channel_credentials_unref(grpc_channel_credentials *creds);
+void grpc_channel_credentials_unref(grpc_exec_ctx *exec_ctx,
+ grpc_channel_credentials *creds);
/* 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
returned non NULL. In that case the caller is responsible for destroying
new_args after channel creation. */
grpc_security_status grpc_channel_credentials_create_security_connector(
- grpc_channel_credentials *creds, const char *target,
- const grpc_channel_args *args, grpc_channel_security_connector **sc,
- grpc_channel_args **new_args);
+ grpc_exec_ctx *exec_ctx, grpc_channel_credentials *creds,
+ const char *target, const grpc_channel_args *args,
+ grpc_channel_security_connector **sc, grpc_channel_args **new_args);
/* Creates a version of the channel credentials without any attached call
credentials. This can be used in order to open a channel to a non-trusted
@@ -162,7 +164,8 @@ void grpc_credentials_md_store_add_cstrings(grpc_credentials_md_store *store,
const char *key, const char *value);
grpc_credentials_md_store *grpc_credentials_md_store_ref(
grpc_credentials_md_store *store);
-void grpc_credentials_md_store_unref(grpc_credentials_md_store *store);
+void grpc_credentials_md_store_unref(grpc_exec_ctx *exec_ctx,
+ grpc_credentials_md_store *store);
/* --- grpc_call_credentials. --- */
@@ -172,7 +175,7 @@ typedef void (*grpc_credentials_metadata_cb)(
size_t num_md, grpc_credentials_status status, const char *error_details);
typedef struct {
- void (*destruct)(grpc_call_credentials *c);
+ void (*destruct)(grpc_exec_ctx *exec_ctx, grpc_call_credentials *c);
void (*get_request_metadata)(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *c,
grpc_polling_entity *pollent,
@@ -188,7 +191,8 @@ struct grpc_call_credentials {
};
grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds);
-void grpc_call_credentials_unref(grpc_call_credentials *creds);
+void grpc_call_credentials_unref(grpc_exec_ctx *exec_ctx,
+ grpc_call_credentials *creds);
void grpc_call_credentials_get_request_metadata(
grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
grpc_polling_entity *pollent, grpc_auth_metadata_context context,
@@ -202,9 +206,10 @@ grpc_call_credentials *grpc_md_only_test_credentials_create(
/* --- grpc_server_credentials. --- */
typedef struct {
- void (*destruct)(grpc_server_credentials *c);
+ void (*destruct)(grpc_exec_ctx *exec_ctx, grpc_server_credentials *c);
grpc_security_status (*create_security_connector)(
- grpc_server_credentials *c, grpc_server_security_connector **sc);
+ grpc_exec_ctx *exec_ctx, grpc_server_credentials *c,
+ grpc_server_security_connector **sc);
} grpc_server_credentials_vtable;
struct grpc_server_credentials {
@@ -215,12 +220,14 @@ struct grpc_server_credentials {
};
grpc_security_status grpc_server_credentials_create_security_connector(
- grpc_server_credentials *creds, grpc_server_security_connector **sc);
+ grpc_exec_ctx *exec_ctx, grpc_server_credentials *creds,
+ grpc_server_security_connector **sc);
grpc_server_credentials *grpc_server_credentials_ref(
grpc_server_credentials *creds);
-void grpc_server_credentials_unref(grpc_server_credentials *creds);
+void grpc_server_credentials_unref(grpc_exec_ctx *exec_ctx,
+ grpc_server_credentials *creds);
#define GRPC_SERVER_CREDENTIALS_ARG "grpc.server_credentials"
@@ -243,6 +250,6 @@ grpc_credentials_metadata_request *grpc_credentials_metadata_request_create(
void *user_data);
void grpc_credentials_metadata_request_destroy(
- grpc_credentials_metadata_request *r);
+ grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *r);
#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_CREDENTIALS_H */
diff --git a/src/core/lib/security/credentials/credentials_metadata.c b/src/core/lib/security/credentials/credentials_metadata.c
index e6cb567734..68da5fb4a8 100644
--- a/src/core/lib/security/credentials/credentials_metadata.c
+++ b/src/core/lib/security/credentials/credentials_metadata.c
@@ -37,6 +37,8 @@
#include <string.h>
+#include "src/core/lib/slice/slice_internal.h"
+
static void store_ensure_capacity(grpc_credentials_md_store *store) {
if (store->num_entries == store->allocated) {
store->allocated = (store->allocated == 0) ? 1 : store->allocated * 2;
@@ -62,8 +64,8 @@ void grpc_credentials_md_store_add(grpc_credentials_md_store *store,
grpc_slice key, grpc_slice value) {
if (store == NULL) return;
store_ensure_capacity(store);
- store->entries[store->num_entries].key = grpc_slice_ref(key);
- store->entries[store->num_entries].value = grpc_slice_ref(value);
+ store->entries[store->num_entries].key = grpc_slice_ref_internal(key);
+ store->entries[store->num_entries].value = grpc_slice_ref_internal(value);
store->num_entries++;
}
@@ -85,14 +87,15 @@ grpc_credentials_md_store *grpc_credentials_md_store_ref(
return store;
}
-void grpc_credentials_md_store_unref(grpc_credentials_md_store *store) {
+void grpc_credentials_md_store_unref(grpc_exec_ctx *exec_ctx,
+ grpc_credentials_md_store *store) {
if (store == NULL) return;
if (gpr_unref(&store->refcount)) {
if (store->entries != NULL) {
size_t i;
for (i = 0; i < store->num_entries; i++) {
- grpc_slice_unref(store->entries[i].key);
- grpc_slice_unref(store->entries[i].value);
+ grpc_slice_unref_internal(exec_ctx, store->entries[i].key);
+ grpc_slice_unref_internal(exec_ctx, store->entries[i].value);
}
gpr_free(store->entries);
}
diff --git a/src/core/lib/security/credentials/fake/fake_credentials.c b/src/core/lib/security/credentials/fake/fake_credentials.c
index ea4cb76fb9..a8679d097d 100644
--- a/src/core/lib/security/credentials/fake/fake_credentials.c
+++ b/src/core/lib/security/credentials/fake/fake_credentials.c
@@ -45,16 +45,18 @@
/* -- Fake transport security credentials. -- */
static grpc_security_status fake_transport_security_create_security_connector(
- grpc_channel_credentials *c, grpc_call_credentials *call_creds,
- const char *target, const grpc_channel_args *args,
- grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
+ grpc_exec_ctx *exec_ctx, grpc_channel_credentials *c,
+ grpc_call_credentials *call_creds, const char *target,
+ const grpc_channel_args *args, grpc_channel_security_connector **sc,
+ grpc_channel_args **new_args) {
*sc = grpc_fake_channel_security_connector_create(call_creds);
return GRPC_SECURITY_OK;
}
static grpc_security_status
fake_transport_security_server_create_security_connector(
- grpc_server_credentials *c, grpc_server_security_connector **sc) {
+ grpc_exec_ctx *exec_ctx, grpc_server_credentials *c,
+ grpc_server_security_connector **sc) {
*sc = grpc_fake_server_security_connector_create();
return GRPC_SECURITY_OK;
}
@@ -89,9 +91,10 @@ grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
/* -- Metadata-only test credentials. -- */
-static void md_only_test_destruct(grpc_call_credentials *creds) {
+static void md_only_test_destruct(grpc_exec_ctx *exec_ctx,
+ grpc_call_credentials *creds) {
grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
- grpc_credentials_md_store_unref(c->md_store);
+ grpc_credentials_md_store_unref(exec_ctx, c->md_store);
}
static void on_simulated_token_fetch_done(grpc_exec_ctx *exec_ctx,
@@ -101,7 +104,7 @@ static void on_simulated_token_fetch_done(grpc_exec_ctx *exec_ctx,
grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)r->creds;
r->cb(exec_ctx, r->user_data, c->md_store->entries, c->md_store->num_entries,
GRPC_CREDENTIALS_OK, NULL);
- grpc_credentials_metadata_request_destroy(r);
+ grpc_credentials_metadata_request_destroy(exec_ctx, r);
}
static void md_only_test_get_request_metadata(
@@ -113,9 +116,10 @@ static void md_only_test_get_request_metadata(
if (c->is_async) {
grpc_credentials_metadata_request *cb_arg =
grpc_credentials_metadata_request_create(creds, cb, user_data);
- grpc_executor_push(
- grpc_closure_create(on_simulated_token_fetch_done, cb_arg),
- GRPC_ERROR_NONE);
+ grpc_closure_sched(exec_ctx,
+ grpc_closure_create(on_simulated_token_fetch_done,
+ cb_arg, grpc_executor_scheduler),
+ GRPC_ERROR_NONE);
} else {
cb(exec_ctx, user_data, c->md_store->entries, 1, GRPC_CREDENTIALS_OK, NULL);
}
diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.c b/src/core/lib/security/credentials/google_default/google_default_credentials.c
index afe0e3d357..d6e1fe3dcf 100644
--- a/src/core/lib/security/credentials/google_default/google_default_credentials.c
+++ b/src/core/lib/security/credentials/google_default/google_default_credentials.c
@@ -45,6 +45,7 @@
#include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/security/credentials/jwt/jwt_credentials.h"
#include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h"
+#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/support/env.h"
#include "src/core/lib/support/string.h"
@@ -101,11 +102,10 @@ static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, grpc_error *e) {
grpc_pollset_destroy(p);
}
-static int is_stack_running_on_compute_engine(void) {
+static int is_stack_running_on_compute_engine(grpc_exec_ctx *exec_ctx) {
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
@@ -128,13 +128,14 @@ static int is_stack_running_on_compute_engine(void) {
grpc_resource_quota *resource_quota =
grpc_resource_quota_create("google_default_credentials");
grpc_httpcli_get(
- &exec_ctx, &context, &detector.pollent, resource_quota, &request,
+ exec_ctx, &context, &detector.pollent, resource_quota, &request,
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), max_detection_delay),
- grpc_closure_create(on_compute_engine_detection_http_response, &detector),
+ grpc_closure_create(on_compute_engine_detection_http_response, &detector,
+ grpc_schedule_on_exec_ctx),
&detector.response);
- grpc_resource_quota_internal_unref(&exec_ctx, resource_quota);
+ grpc_resource_quota_unref_internal(exec_ctx, resource_quota);
- grpc_exec_ctx_flush(&exec_ctx);
+ grpc_exec_ctx_flush(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. */
@@ -143,7 +144,7 @@ static int is_stack_running_on_compute_engine(void) {
grpc_pollset_worker *worker = NULL;
if (!GRPC_LOG_IF_ERROR(
"pollset_work",
- grpc_pollset_work(&exec_ctx,
+ grpc_pollset_work(exec_ctx,
grpc_polling_entity_pollset(&detector.pollent),
&worker, gpr_now(GPR_CLOCK_MONOTONIC),
gpr_inf_future(GPR_CLOCK_MONOTONIC)))) {
@@ -155,12 +156,13 @@ static int is_stack_running_on_compute_engine(void) {
grpc_httpcli_context_destroy(&context);
grpc_closure_init(&destroy_closure, destroy_pollset,
- grpc_polling_entity_pollset(&detector.pollent));
- grpc_pollset_shutdown(&exec_ctx,
+ grpc_polling_entity_pollset(&detector.pollent),
+ grpc_schedule_on_exec_ctx);
+ grpc_pollset_shutdown(exec_ctx,
grpc_polling_entity_pollset(&detector.pollent),
&destroy_closure);
- grpc_exec_ctx_finish(&exec_ctx);
g_polling_mu = NULL;
+ grpc_exec_ctx_flush(exec_ctx);
gpr_free(grpc_polling_entity_pollset(&detector.pollent));
grpc_http_response_destroy(&detector.response);
@@ -170,7 +172,7 @@ static int is_stack_running_on_compute_engine(void) {
/* Takes ownership of creds_path if not NULL. */
static grpc_error *create_default_creds_from_path(
- char *creds_path, grpc_call_credentials **creds) {
+ grpc_exec_ctx *exec_ctx, char *creds_path, grpc_call_credentials **creds) {
grpc_json *json = NULL;
grpc_auth_json_key key;
grpc_auth_refresh_token token;
@@ -200,7 +202,7 @@ static grpc_error *create_default_creds_from_path(
if (grpc_auth_json_key_is_valid(&key)) {
result =
grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
- key, grpc_max_auth_token_lifetime());
+ exec_ctx, key, grpc_max_auth_token_lifetime());
if (result == NULL) {
error = GRPC_ERROR_CREATE(
"grpc_service_account_jwt_access_credentials_create_from_auth_json_"
@@ -225,7 +227,7 @@ static grpc_error *create_default_creds_from_path(
end:
GPR_ASSERT((result == NULL) + (error == GRPC_ERROR_NONE) == 1);
if (creds_path != NULL) gpr_free(creds_path);
- grpc_slice_unref(creds_data);
+ grpc_slice_unref_internal(exec_ctx, creds_data);
if (json != NULL) grpc_json_destroy(json);
*creds = result;
return error;
@@ -236,6 +238,7 @@ grpc_channel_credentials *grpc_google_default_credentials_create(void) {
grpc_call_credentials *call_creds = NULL;
grpc_error *error = GRPC_ERROR_CREATE("Failed to create Google credentials");
grpc_error *err;
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
GRPC_API_TRACE("grpc_google_default_credentials_create(void)", 0, ());
@@ -250,20 +253,22 @@ grpc_channel_credentials *grpc_google_default_credentials_create(void) {
/* First, try the environment variable. */
err = create_default_creds_from_path(
- gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR), &call_creds);
+ &exec_ctx, gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR), &call_creds);
if (err == GRPC_ERROR_NONE) goto end;
error = grpc_error_add_child(error, err);
/* Then the well-known file. */
err = create_default_creds_from_path(
- grpc_get_well_known_google_credentials_file_path(), &call_creds);
+ &exec_ctx, grpc_get_well_known_google_credentials_file_path(),
+ &call_creds);
if (err == GRPC_ERROR_NONE) goto end;
error = grpc_error_add_child(error, err);
/* At last try to see if we're on compute engine (do the detection only once
since it requires a network test). */
if (!compute_engine_detection_done) {
- int need_compute_engine_creds = is_stack_running_on_compute_engine();
+ int need_compute_engine_creds =
+ is_stack_running_on_compute_engine(&exec_ctx);
compute_engine_detection_done = 1;
if (need_compute_engine_creds) {
call_creds = grpc_google_compute_engine_credentials_create(NULL);
@@ -286,8 +291,8 @@ end:
grpc_composite_channel_credentials_create(ssl_creds, call_creds,
NULL));
GPR_ASSERT(default_credentials != NULL);
- grpc_channel_credentials_unref(ssl_creds);
- grpc_call_credentials_unref(call_creds);
+ grpc_channel_credentials_unref(&exec_ctx, ssl_creds);
+ grpc_call_credentials_unref(&exec_ctx, call_creds);
result = default_credentials;
} else {
gpr_log(GPR_ERROR, "Could not create google default credentials.");
@@ -299,18 +304,21 @@ end:
} else {
GRPC_ERROR_UNREF(error);
}
+ grpc_exec_ctx_finish(&exec_ctx);
return result;
}
void grpc_flush_cached_google_default_credentials(void) {
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
gpr_once_init(&g_once, init_default_credentials);
gpr_mu_lock(&g_state_mu);
if (default_credentials != NULL) {
- grpc_channel_credentials_unref(default_credentials);
+ grpc_channel_credentials_unref(&exec_ctx, default_credentials);
default_credentials = NULL;
}
compute_engine_detection_done = 0;
gpr_mu_unlock(&g_state_mu);
+ grpc_exec_ctx_finish(&exec_ctx);
}
/* -- Well known credentials path. -- */
diff --git a/src/core/lib/security/credentials/iam/iam_credentials.c b/src/core/lib/security/credentials/iam/iam_credentials.c
index 370a384d0e..abd69a9670 100644
--- a/src/core/lib/security/credentials/iam/iam_credentials.c
+++ b/src/core/lib/security/credentials/iam/iam_credentials.c
@@ -42,9 +42,10 @@
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
-static void iam_destruct(grpc_call_credentials *creds) {
+static void iam_destruct(grpc_exec_ctx *exec_ctx,
+ grpc_call_credentials *creds) {
grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
- grpc_credentials_md_store_unref(c->iam_md);
+ grpc_credentials_md_store_unref(exec_ctx, c->iam_md);
}
static void iam_get_request_metadata(grpc_exec_ctx *exec_ctx,
diff --git a/src/core/lib/security/credentials/jwt/jwt_credentials.c b/src/core/lib/security/credentials/jwt/jwt_credentials.c
index 3daf0f4ef7..616be64a54 100644
--- a/src/core/lib/security/credentials/jwt/jwt_credentials.c
+++ b/src/core/lib/security/credentials/jwt/jwt_credentials.c
@@ -42,9 +42,10 @@
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
-static void jwt_reset_cache(grpc_service_account_jwt_access_credentials *c) {
+static void jwt_reset_cache(grpc_exec_ctx *exec_ctx,
+ grpc_service_account_jwt_access_credentials *c) {
if (c->cached.jwt_md != NULL) {
- grpc_credentials_md_store_unref(c->cached.jwt_md);
+ grpc_credentials_md_store_unref(exec_ctx, c->cached.jwt_md);
c->cached.jwt_md = NULL;
}
if (c->cached.service_url != NULL) {
@@ -54,11 +55,12 @@ static void jwt_reset_cache(grpc_service_account_jwt_access_credentials *c) {
c->cached.jwt_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
}
-static void jwt_destruct(grpc_call_credentials *creds) {
+static void jwt_destruct(grpc_exec_ctx *exec_ctx,
+ grpc_call_credentials *creds) {
grpc_service_account_jwt_access_credentials *c =
(grpc_service_account_jwt_access_credentials *)creds;
grpc_auth_json_key_destruct(&c->key);
- jwt_reset_cache(c);
+ jwt_reset_cache(exec_ctx, c);
gpr_mu_destroy(&c->cache_mu);
}
@@ -92,7 +94,7 @@ static void jwt_get_request_metadata(grpc_exec_ctx *exec_ctx,
char *jwt = NULL;
/* Generate a new jwt. */
gpr_mu_lock(&c->cache_mu);
- jwt_reset_cache(c);
+ jwt_reset_cache(exec_ctx, c);
jwt = grpc_jwt_encode_and_sign(&c->key, context.service_url,
c->jwt_lifetime, NULL);
if (jwt != NULL) {
@@ -114,7 +116,7 @@ static void jwt_get_request_metadata(grpc_exec_ctx *exec_ctx,
if (jwt_md != NULL) {
cb(exec_ctx, user_data, jwt_md->entries, jwt_md->num_entries,
GRPC_CREDENTIALS_OK, NULL);
- grpc_credentials_md_store_unref(jwt_md);
+ grpc_credentials_md_store_unref(exec_ctx, jwt_md);
} else {
cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_ERROR,
"Could not generate JWT.");
@@ -126,7 +128,8 @@ static grpc_call_credentials_vtable jwt_vtable = {jwt_destruct,
grpc_call_credentials *
grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
- grpc_auth_json_key key, gpr_timespec token_lifetime) {
+ grpc_exec_ctx *exec_ctx, grpc_auth_json_key key,
+ gpr_timespec token_lifetime) {
grpc_service_account_jwt_access_credentials *c;
if (!grpc_auth_json_key_is_valid(&key)) {
gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation");
@@ -140,7 +143,7 @@ grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
c->key = key;
c->jwt_lifetime = token_lifetime;
gpr_mu_init(&c->cache_mu);
- jwt_reset_cache(c);
+ jwt_reset_cache(exec_ctx, c);
return &c->base;
}
@@ -183,6 +186,11 @@ grpc_call_credentials *grpc_service_account_jwt_access_credentials_create(
gpr_free(clean_json);
}
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);
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_call_credentials *creds =
+ grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
+ &exec_ctx, grpc_auth_json_key_create_from_string(json_key),
+ token_lifetime);
+ grpc_exec_ctx_finish(&exec_ctx);
+ return creds;
}
diff --git a/src/core/lib/security/credentials/jwt/jwt_credentials.h b/src/core/lib/security/credentials/jwt/jwt_credentials.h
index d572606179..39b7aeafe8 100644
--- a/src/core/lib/security/credentials/jwt/jwt_credentials.h
+++ b/src/core/lib/security/credentials/jwt/jwt_credentials.h
@@ -57,6 +57,7 @@ typedef struct {
// Takes ownership of the key.
grpc_call_credentials *
grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
- grpc_auth_json_key key, gpr_timespec token_lifetime);
+ grpc_exec_ctx *exec_ctx, grpc_auth_json_key key,
+ gpr_timespec token_lifetime);
#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JWT_CREDENTIALS_H */
diff --git a/src/core/lib/security/credentials/jwt/jwt_verifier.c b/src/core/lib/security/credentials/jwt/jwt_verifier.c
index 42bd89dd0a..2270be8f44 100644
--- a/src/core/lib/security/credentials/jwt/jwt_verifier.c
+++ b/src/core/lib/security/credentials/jwt/jwt_verifier.c
@@ -36,11 +36,6 @@
#include <limits.h>
#include <string.h>
-#include "src/core/lib/http/httpcli.h"
-#include "src/core/lib/iomgr/polling_entity.h"
-#include "src/core/lib/security/util/b64.h"
-#include "src/core/lib/tsi/ssl_types.h"
-
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
@@ -48,6 +43,13 @@
#include <grpc/support/useful.h>
#include <openssl/pem.h>
+#include "src/core/lib/http/httpcli.h"
+#include "src/core/lib/iomgr/polling_entity.h"
+#include "src/core/lib/security/util/b64.h"
+#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/support/string.h"
+#include "src/core/lib/tsi/ssl_types.h"
+
/* --- Utils. --- */
const char *grpc_jwt_verifier_status_to_string(
@@ -84,11 +86,12 @@ static const EVP_MD *evp_md_from_alg(const char *alg) {
}
}
-static grpc_json *parse_json_part_from_jwt(const char *str, size_t len,
+static grpc_json *parse_json_part_from_jwt(grpc_exec_ctx *exec_ctx,
+ const char *str, size_t len,
grpc_slice *buffer) {
grpc_json *json;
- *buffer = grpc_base64_decode_with_len(str, len, 1);
+ *buffer = grpc_base64_decode_with_len(exec_ctx, str, len, 1);
if (GRPC_SLICE_IS_EMPTY(*buffer)) {
gpr_log(GPR_ERROR, "Invalid base64.");
return NULL;
@@ -96,7 +99,7 @@ static grpc_json *parse_json_part_from_jwt(const char *str, size_t len,
json = grpc_json_parse_string_with_len((char *)GRPC_SLICE_START_PTR(*buffer),
GRPC_SLICE_LENGTH(*buffer));
if (json == NULL) {
- grpc_slice_unref(*buffer);
+ grpc_slice_unref_internal(exec_ctx, *buffer);
gpr_log(GPR_ERROR, "JSON parsing error.");
}
return json;
@@ -132,13 +135,14 @@ typedef struct {
grpc_slice buffer;
} jose_header;
-static void jose_header_destroy(jose_header *h) {
- grpc_slice_unref(h->buffer);
+static void jose_header_destroy(grpc_exec_ctx *exec_ctx, jose_header *h) {
+ grpc_slice_unref_internal(exec_ctx, h->buffer);
gpr_free(h);
}
/* Takes ownership of json and buffer. */
-static jose_header *jose_header_from_json(grpc_json *json, grpc_slice buffer) {
+static jose_header *jose_header_from_json(grpc_exec_ctx *exec_ctx,
+ grpc_json *json, grpc_slice buffer) {
grpc_json *cur;
jose_header *h = gpr_malloc(sizeof(jose_header));
memset(h, 0, sizeof(jose_header));
@@ -173,7 +177,7 @@ static jose_header *jose_header_from_json(grpc_json *json, grpc_slice buffer) {
error:
grpc_json_destroy(json);
- jose_header_destroy(h);
+ jose_header_destroy(exec_ctx, h);
return NULL;
}
@@ -193,9 +197,9 @@ struct grpc_jwt_claims {
grpc_slice buffer;
};
-void grpc_jwt_claims_destroy(grpc_jwt_claims *claims) {
+void grpc_jwt_claims_destroy(grpc_exec_ctx *exec_ctx, grpc_jwt_claims *claims) {
grpc_json_destroy(claims->json);
- grpc_slice_unref(claims->buffer);
+ grpc_slice_unref_internal(exec_ctx, claims->buffer);
gpr_free(claims);
}
@@ -240,7 +244,8 @@ gpr_timespec grpc_jwt_claims_not_before(const grpc_jwt_claims *claims) {
}
/* Takes ownership of json and buffer even in case of failure. */
-grpc_jwt_claims *grpc_jwt_claims_from_json(grpc_json *json, grpc_slice buffer) {
+grpc_jwt_claims *grpc_jwt_claims_from_json(grpc_exec_ctx *exec_ctx,
+ grpc_json *json, grpc_slice buffer) {
grpc_json *cur;
grpc_jwt_claims *claims = gpr_malloc(sizeof(grpc_jwt_claims));
memset(claims, 0, sizeof(grpc_jwt_claims));
@@ -281,7 +286,7 @@ grpc_jwt_claims *grpc_jwt_claims_from_json(grpc_json *json, grpc_slice buffer) {
return claims;
error:
- grpc_jwt_claims_destroy(claims);
+ grpc_jwt_claims_destroy(exec_ctx, claims);
return NULL;
}
@@ -305,6 +310,17 @@ grpc_jwt_verifier_status grpc_jwt_claims_check(const grpc_jwt_claims *claims,
return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE;
}
+ /* This should be probably up to the upper layer to decide but let's harcode
+ the 99% use case here for email issuers, where the JWT must be self
+ issued. */
+ if (grpc_jwt_issuer_email_domain(claims->iss) != NULL &&
+ claims->sub != NULL && strcmp(claims->iss, claims->sub) != 0) {
+ gpr_log(GPR_ERROR,
+ "Email issuer (%s) cannot assert another subject (%s) than itself.",
+ claims->iss, claims->sub);
+ return GRPC_JWT_VERIFIER_BAD_SUBJECT;
+ }
+
if (audience == NULL) {
audience_ok = claims->aud == NULL;
} else {
@@ -362,12 +378,12 @@ static verifier_cb_ctx *verifier_cb_ctx_create(
return ctx;
}
-void verifier_cb_ctx_destroy(verifier_cb_ctx *ctx) {
+void verifier_cb_ctx_destroy(grpc_exec_ctx *exec_ctx, verifier_cb_ctx *ctx) {
if (ctx->audience != NULL) gpr_free(ctx->audience);
- if (ctx->claims != NULL) grpc_jwt_claims_destroy(ctx->claims);
- grpc_slice_unref(ctx->signature);
- grpc_slice_unref(ctx->signed_data);
- jose_header_destroy(ctx->header);
+ if (ctx->claims != NULL) grpc_jwt_claims_destroy(exec_ctx, ctx->claims);
+ grpc_slice_unref_internal(exec_ctx, ctx->signature);
+ grpc_slice_unref_internal(exec_ctx, ctx->signed_data);
+ jose_header_destroy(exec_ctx, ctx->header);
for (size_t i = 0; i < HTTP_RESPONSE_COUNT; i++) {
grpc_http_response_destroy(&ctx->responses[i]);
}
@@ -447,23 +463,24 @@ end:
return result;
}
-static BIGNUM *bignum_from_base64(const char *b64) {
+static BIGNUM *bignum_from_base64(grpc_exec_ctx *exec_ctx, const char *b64) {
BIGNUM *result = NULL;
grpc_slice bin;
if (b64 == NULL) return NULL;
- bin = grpc_base64_decode(b64, 1);
+ bin = grpc_base64_decode(exec_ctx, b64, 1);
if (GRPC_SLICE_IS_EMPTY(bin)) {
gpr_log(GPR_ERROR, "Invalid base64 for big num.");
return NULL;
}
result = BN_bin2bn(GRPC_SLICE_START_PTR(bin),
TSI_SIZE_AS_SIZE(GRPC_SLICE_LENGTH(bin)), NULL);
- grpc_slice_unref(bin);
+ grpc_slice_unref_internal(exec_ctx, bin);
return result;
}
-static EVP_PKEY *pkey_from_jwk(const grpc_json *json, const char *kty) {
+static EVP_PKEY *pkey_from_jwk(grpc_exec_ctx *exec_ctx, const grpc_json *json,
+ const char *kty) {
const grpc_json *key_prop;
RSA *rsa = NULL;
EVP_PKEY *result = NULL;
@@ -480,10 +497,12 @@ static EVP_PKEY *pkey_from_jwk(const grpc_json *json, const char *kty) {
}
for (key_prop = json->child; key_prop != NULL; key_prop = key_prop->next) {
if (strcmp(key_prop->key, "n") == 0) {
- rsa->n = bignum_from_base64(validate_string_field(key_prop, "n"));
+ rsa->n =
+ bignum_from_base64(exec_ctx, validate_string_field(key_prop, "n"));
if (rsa->n == NULL) goto end;
} else if (strcmp(key_prop->key, "e") == 0) {
- rsa->e = bignum_from_base64(validate_string_field(key_prop, "e"));
+ rsa->e =
+ bignum_from_base64(exec_ctx, validate_string_field(key_prop, "e"));
if (rsa->e == NULL) goto end;
}
}
@@ -499,7 +518,8 @@ end:
return result;
}
-static EVP_PKEY *find_verification_key(const grpc_json *json,
+static EVP_PKEY *find_verification_key(grpc_exec_ctx *exec_ctx,
+ const grpc_json *json,
const char *header_alg,
const char *header_kid) {
const grpc_json *jkey;
@@ -543,7 +563,7 @@ static EVP_PKEY *find_verification_key(const grpc_json *json,
}
if (alg != NULL && kid != NULL && kty != NULL &&
strcmp(kid, header_kid) == 0 && strcmp(alg, header_alg) == 0) {
- return pkey_from_jwk(jkey, kty);
+ return pkey_from_jwk(exec_ctx, jkey, kty);
}
}
gpr_log(GPR_ERROR,
@@ -597,7 +617,7 @@ static void on_keys_retrieved(grpc_exec_ctx *exec_ctx, void *user_data,
goto end;
}
verification_key =
- find_verification_key(json, ctx->header->alg, ctx->header->kid);
+ find_verification_key(exec_ctx, json, ctx->header->alg, ctx->header->kid);
if (verification_key == NULL) {
gpr_log(GPR_ERROR, "Could not find verification key with kid %s.",
ctx->header->kid);
@@ -621,8 +641,8 @@ static void on_keys_retrieved(grpc_exec_ctx *exec_ctx, void *user_data,
end:
if (json != NULL) grpc_json_destroy(json);
if (verification_key != NULL) EVP_PKEY_free(verification_key);
- ctx->user_cb(ctx->user_data, status, claims);
- verifier_cb_ctx_destroy(ctx);
+ ctx->user_cb(exec_ctx, ctx->user_data, status, claims);
+ verifier_cb_ctx_destroy(exec_ctx, ctx);
}
static void on_openid_config_retrieved(grpc_exec_ctx *exec_ctx, void *user_data,
@@ -665,17 +685,18 @@ static void on_openid_config_retrieved(grpc_exec_ctx *exec_ctx, void *user_data,
grpc_httpcli_get(
exec_ctx, &ctx->verifier->http_ctx, &ctx->pollent, resource_quota, &req,
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay),
- grpc_closure_create(on_keys_retrieved, ctx),
+ grpc_closure_create(on_keys_retrieved, ctx, grpc_schedule_on_exec_ctx),
&ctx->responses[HTTP_RESPONSE_KEYS]);
- grpc_resource_quota_internal_unref(exec_ctx, resource_quota);
+ grpc_resource_quota_unref_internal(exec_ctx, resource_quota);
grpc_json_destroy(json);
gpr_free(req.host);
return;
error:
if (json != NULL) grpc_json_destroy(json);
- ctx->user_cb(ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, NULL);
- verifier_cb_ctx_destroy(ctx);
+ ctx->user_cb(exec_ctx, ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR,
+ NULL);
+ verifier_cb_ctx_destroy(exec_ctx, ctx);
}
static email_key_mapping *verifier_get_mapping(grpc_jwt_verifier *v,
@@ -705,10 +726,26 @@ static void verifier_put_mapping(grpc_jwt_verifier *v, const char *email_domain,
GPR_ASSERT(v->num_mappings <= v->allocated_mappings);
}
+/* Very non-sophisticated way to detect an email address. Should be good
+ enough for now... */
+const char *grpc_jwt_issuer_email_domain(const char *issuer) {
+ const char *at_sign = strchr(issuer, '@');
+ if (at_sign == NULL) return NULL;
+ const char *email_domain = at_sign + 1;
+ if (*email_domain == '\0') return NULL;
+ const char *dot = strrchr(email_domain, '.');
+ if (dot == NULL || dot == email_domain) return email_domain;
+ GPR_ASSERT(dot > email_domain);
+ /* There may be a subdomain, we just want the domain. */
+ dot = gpr_memrchr(email_domain, '.', (size_t)(dot - email_domain));
+ if (dot == NULL) return email_domain;
+ return dot + 1;
+}
+
/* Takes ownership of ctx. */
static void retrieve_key_and_verify(grpc_exec_ctx *exec_ctx,
verifier_cb_ctx *ctx) {
- const char *at_sign;
+ const char *email_domain;
grpc_closure *http_cb;
char *path_prefix = NULL;
const char *iss;
@@ -733,13 +770,9 @@ static void retrieve_key_and_verify(grpc_exec_ctx *exec_ctx,
Nobody seems to implement the account/email/webfinger part 2. of the spec
so we will rely instead on email/url mappings if we detect such an issuer.
Part 4, on the other hand is implemented by both google and salesforce. */
-
- /* Very non-sophisticated way to detect an email address. Should be good
- enough for now... */
- at_sign = strchr(iss, '@');
- if (at_sign != NULL) {
+ email_domain = grpc_jwt_issuer_email_domain(iss);
+ if (email_domain != NULL) {
email_key_mapping *mapping;
- const char *email_domain = at_sign + 1;
GPR_ASSERT(ctx->verifier != NULL);
mapping = verifier_get_mapping(ctx->verifier, email_domain);
if (mapping == NULL) {
@@ -754,7 +787,8 @@ static void retrieve_key_and_verify(grpc_exec_ctx *exec_ctx,
*(path_prefix++) = '\0';
gpr_asprintf(&req.http.path, "/%s/%s", path_prefix, iss);
}
- http_cb = grpc_closure_create(on_keys_retrieved, ctx);
+ http_cb =
+ grpc_closure_create(on_keys_retrieved, ctx, grpc_schedule_on_exec_ctx);
rsp_idx = HTTP_RESPONSE_KEYS;
} else {
req.host = gpr_strdup(strstr(iss, "https://") == iss ? iss + 8 : iss);
@@ -766,7 +800,8 @@ static void retrieve_key_and_verify(grpc_exec_ctx *exec_ctx,
gpr_asprintf(&req.http.path, "/%s%s", path_prefix,
GRPC_OPENID_CONFIG_URL_SUFFIX);
}
- http_cb = grpc_closure_create(on_openid_config_retrieved, ctx);
+ http_cb = grpc_closure_create(on_openid_config_retrieved, ctx,
+ grpc_schedule_on_exec_ctx);
rsp_idx = HTTP_RESPONSE_OPENID;
}
@@ -779,14 +814,15 @@ static void retrieve_key_and_verify(grpc_exec_ctx *exec_ctx,
exec_ctx, &ctx->verifier->http_ctx, &ctx->pollent, resource_quota, &req,
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay),
http_cb, &ctx->responses[rsp_idx]);
- grpc_resource_quota_internal_unref(exec_ctx, resource_quota);
+ grpc_resource_quota_unref_internal(exec_ctx, resource_quota);
gpr_free(req.host);
gpr_free(req.http.path);
return;
error:
- ctx->user_cb(ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, NULL);
- verifier_cb_ctx_destroy(ctx);
+ ctx->user_cb(exec_ctx, ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR,
+ NULL);
+ verifier_cb_ctx_destroy(exec_ctx, ctx);
}
void grpc_jwt_verifier_verify(grpc_exec_ctx *exec_ctx,
@@ -808,22 +844,24 @@ void grpc_jwt_verifier_verify(grpc_exec_ctx *exec_ctx,
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, (size_t)(dot - cur), &header_buffer);
+ json = parse_json_part_from_jwt(exec_ctx, cur, (size_t)(dot - cur),
+ &header_buffer);
if (json == NULL) goto error;
- header = jose_header_from_json(json, header_buffer);
+ header = jose_header_from_json(exec_ctx, json, header_buffer);
if (header == NULL) goto error;
cur = dot + 1;
dot = strchr(cur, '.');
if (dot == NULL) goto error;
- json = parse_json_part_from_jwt(cur, (size_t)(dot - cur), &claims_buffer);
+ json = parse_json_part_from_jwt(exec_ctx, cur, (size_t)(dot - cur),
+ &claims_buffer);
if (json == NULL) goto error;
- claims = grpc_jwt_claims_from_json(json, claims_buffer);
+ claims = grpc_jwt_claims_from_json(exec_ctx, json, claims_buffer);
if (claims == NULL) goto error;
signed_jwt_len = (size_t)(dot - jwt);
cur = dot + 1;
- signature = grpc_base64_decode(cur, 1);
+ signature = grpc_base64_decode(exec_ctx, cur, 1);
if (GRPC_SLICE_IS_EMPTY(signature)) goto error;
retrieve_key_and_verify(
exec_ctx,
@@ -832,9 +870,9 @@ void grpc_jwt_verifier_verify(grpc_exec_ctx *exec_ctx,
return;
error:
- if (header != NULL) jose_header_destroy(header);
- if (claims != NULL) grpc_jwt_claims_destroy(claims);
- cb(user_data, GRPC_JWT_VERIFIER_BAD_FORMAT, NULL);
+ if (header != NULL) jose_header_destroy(exec_ctx, header);
+ if (claims != NULL) grpc_jwt_claims_destroy(exec_ctx, claims);
+ cb(exec_ctx, user_data, GRPC_JWT_VERIFIER_BAD_FORMAT, NULL);
}
grpc_jwt_verifier *grpc_jwt_verifier_create(
diff --git a/src/core/lib/security/credentials/jwt/jwt_verifier.h b/src/core/lib/security/credentials/jwt/jwt_verifier.h
index f09f9d5d47..4fa320a415 100644
--- a/src/core/lib/security/credentials/jwt/jwt_verifier.h
+++ b/src/core/lib/security/credentials/jwt/jwt_verifier.h
@@ -43,8 +43,7 @@
/* --- Constants. --- */
#define GRPC_OPENID_CONFIG_URL_SUFFIX "/.well-known/openid-configuration"
-#define GRPC_GOOGLE_SERVICE_ACCOUNTS_EMAIL_DOMAIN \
- "developer.gserviceaccount.com"
+#define GRPC_GOOGLE_SERVICE_ACCOUNTS_EMAIL_DOMAIN "gserviceaccount.com"
#define GRPC_GOOGLE_SERVICE_ACCOUNTS_KEY_URL_PREFIX \
"www.googleapis.com/robot/v1/metadata/x509"
@@ -57,6 +56,7 @@ typedef enum {
GRPC_JWT_VERIFIER_BAD_AUDIENCE,
GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR,
GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE,
+ GRPC_JWT_VERIFIER_BAD_SUBJECT,
GRPC_JWT_VERIFIER_GENERIC_ERROR
} grpc_jwt_verifier_status;
@@ -66,7 +66,7 @@ const char *grpc_jwt_verifier_status_to_string(grpc_jwt_verifier_status status);
typedef struct grpc_jwt_claims grpc_jwt_claims;
-void grpc_jwt_claims_destroy(grpc_jwt_claims *claims);
+void grpc_jwt_claims_destroy(grpc_exec_ctx *exec_ctx, grpc_jwt_claims *claims);
/* Returns the whole JSON tree of the claims. */
const grpc_json *grpc_jwt_claims_json(const grpc_jwt_claims *claims);
@@ -115,7 +115,8 @@ void grpc_jwt_verifier_destroy(grpc_jwt_verifier *verifier);
is done (maybe in another thread).
It is the responsibility of the callee to call grpc_jwt_claims_destroy on
the claims. */
-typedef void (*grpc_jwt_verification_done_cb)(void *user_data,
+typedef void (*grpc_jwt_verification_done_cb)(grpc_exec_ctx *exec_ctx,
+ void *user_data,
grpc_jwt_verifier_status status,
grpc_jwt_claims *claims);
@@ -129,8 +130,10 @@ void grpc_jwt_verifier_verify(grpc_exec_ctx *exec_ctx,
/* --- TESTING ONLY exposed functions. --- */
-grpc_jwt_claims *grpc_jwt_claims_from_json(grpc_json *json, grpc_slice buffer);
+grpc_jwt_claims *grpc_jwt_claims_from_json(grpc_exec_ctx *exec_ctx,
+ grpc_json *json, grpc_slice buffer);
grpc_jwt_verifier_status grpc_jwt_claims_check(const grpc_jwt_claims *claims,
const char *audience);
+const char *grpc_jwt_issuer_email_domain(const char *issuer);
#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JWT_VERIFIER_H */
diff --git a/src/core/lib/security/credentials/oauth2/oauth2_credentials.c b/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
index b3625b22c0..1b0e43a1e4 100644
--- a/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
+++ b/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
@@ -118,18 +118,19 @@ void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token *refresh_token) {
// Oauth2 Token Fetcher credentials.
//
-static void oauth2_token_fetcher_destruct(grpc_call_credentials *creds) {
+static void oauth2_token_fetcher_destruct(grpc_exec_ctx *exec_ctx,
+ grpc_call_credentials *creds) {
grpc_oauth2_token_fetcher_credentials *c =
(grpc_oauth2_token_fetcher_credentials *)creds;
- grpc_credentials_md_store_unref(c->access_token_md);
+ grpc_credentials_md_store_unref(exec_ctx, c->access_token_md);
gpr_mu_destroy(&c->mu);
grpc_httpcli_context_destroy(&c->httpcli_context);
}
grpc_credentials_status
grpc_oauth2_token_fetcher_credentials_parse_server_response(
- const grpc_http_response *response, grpc_credentials_md_store **token_md,
- gpr_timespec *token_lifetime) {
+ grpc_exec_ctx *exec_ctx, const grpc_http_response *response,
+ grpc_credentials_md_store **token_md, gpr_timespec *token_lifetime) {
char *null_terminated_body = NULL;
char *new_access_token = NULL;
grpc_credentials_status status = GRPC_CREDENTIALS_OK;
@@ -198,7 +199,7 @@ grpc_oauth2_token_fetcher_credentials_parse_server_response(
token_lifetime->tv_sec = strtol(expires_in->value, NULL, 10);
token_lifetime->tv_nsec = 0;
token_lifetime->clock_type = GPR_TIMESPAN;
- if (*token_md != NULL) grpc_credentials_md_store_unref(*token_md);
+ if (*token_md != NULL) grpc_credentials_md_store_unref(exec_ctx, *token_md);
*token_md = grpc_credentials_md_store_create(1);
grpc_credentials_md_store_add_cstrings(
*token_md, GRPC_AUTHORIZATION_METADATA_KEY, new_access_token);
@@ -207,7 +208,7 @@ grpc_oauth2_token_fetcher_credentials_parse_server_response(
end:
if (status != GRPC_CREDENTIALS_OK && (*token_md != NULL)) {
- grpc_credentials_md_store_unref(*token_md);
+ grpc_credentials_md_store_unref(exec_ctx, *token_md);
*token_md = NULL;
}
if (null_terminated_body != NULL) gpr_free(null_terminated_body);
@@ -230,7 +231,7 @@ static void on_oauth2_token_fetcher_http_response(grpc_exec_ctx *exec_ctx,
gpr_mu_lock(&c->mu);
status = grpc_oauth2_token_fetcher_credentials_parse_server_response(
- &r->response, &c->access_token_md, &token_lifetime);
+ exec_ctx, &r->response, &c->access_token_md, &token_lifetime);
if (status == GRPC_CREDENTIALS_OK) {
c->token_expiration =
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), token_lifetime);
@@ -242,7 +243,7 @@ static void on_oauth2_token_fetcher_http_response(grpc_exec_ctx *exec_ctx,
"Error occured when fetching oauth2 token.");
}
gpr_mu_unlock(&c->mu);
- grpc_credentials_metadata_request_destroy(r);
+ grpc_credentials_metadata_request_destroy(exec_ctx, r);
}
static void oauth2_token_fetcher_get_request_metadata(
@@ -268,7 +269,7 @@ static void oauth2_token_fetcher_get_request_metadata(
if (cached_access_token_md != NULL) {
cb(exec_ctx, user_data, cached_access_token_md->entries,
cached_access_token_md->num_entries, GRPC_CREDENTIALS_OK, NULL);
- grpc_credentials_md_store_unref(cached_access_token_md);
+ grpc_credentials_md_store_unref(exec_ctx, cached_access_token_md);
} else {
c->fetch_func(
exec_ctx,
@@ -312,10 +313,12 @@ static void compute_engine_fetch_oauth2(
extreme memory pressure. */
grpc_resource_quota *resource_quota =
grpc_resource_quota_create("oauth2_credentials");
- grpc_httpcli_get(exec_ctx, httpcli_context, pollent, resource_quota, &request,
- deadline, grpc_closure_create(response_cb, metadata_req),
- &metadata_req->response);
- grpc_resource_quota_internal_unref(exec_ctx, resource_quota);
+ grpc_httpcli_get(
+ exec_ctx, httpcli_context, pollent, resource_quota, &request, deadline,
+ grpc_closure_create(response_cb, metadata_req, grpc_schedule_on_exec_ctx),
+
+ &metadata_req->response);
+ grpc_resource_quota_unref_internal(exec_ctx, resource_quota);
}
grpc_call_credentials *grpc_google_compute_engine_credentials_create(
@@ -334,11 +337,12 @@ grpc_call_credentials *grpc_google_compute_engine_credentials_create(
// Google Refresh Token credentials.
//
-static void refresh_token_destruct(grpc_call_credentials *creds) {
+static void refresh_token_destruct(grpc_exec_ctx *exec_ctx,
+ grpc_call_credentials *creds) {
grpc_google_refresh_token_credentials *c =
(grpc_google_refresh_token_credentials *)creds;
grpc_auth_refresh_token_destruct(&c->refresh_token);
- oauth2_token_fetcher_destruct(&c->base.base);
+ oauth2_token_fetcher_destruct(exec_ctx, &c->base.base);
}
static grpc_call_credentials_vtable refresh_token_vtable = {
@@ -368,11 +372,12 @@ static void refresh_token_fetch_oauth2(
extreme memory pressure. */
grpc_resource_quota *resource_quota =
grpc_resource_quota_create("oauth2_credentials_refresh");
- grpc_httpcli_post(exec_ctx, httpcli_context, pollent, resource_quota,
- &request, body, strlen(body), deadline,
- grpc_closure_create(response_cb, metadata_req),
- &metadata_req->response);
- grpc_resource_quota_internal_unref(exec_ctx, resource_quota);
+ grpc_httpcli_post(
+ exec_ctx, httpcli_context, pollent, resource_quota, &request, body,
+ strlen(body), deadline,
+ grpc_closure_create(response_cb, metadata_req, grpc_schedule_on_exec_ctx),
+ &metadata_req->response);
+ grpc_resource_quota_unref_internal(exec_ctx, resource_quota);
gpr_free(body);
}
@@ -424,9 +429,10 @@ grpc_call_credentials *grpc_google_refresh_token_credentials_create(
// Oauth2 Access Token credentials.
//
-static void access_token_destruct(grpc_call_credentials *creds) {
+static void access_token_destruct(grpc_exec_ctx *exec_ctx,
+ grpc_call_credentials *creds) {
grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
- grpc_credentials_md_store_unref(c->access_token_md);
+ grpc_credentials_md_store_unref(exec_ctx, c->access_token_md);
}
static void access_token_get_request_metadata(
diff --git a/src/core/lib/security/credentials/oauth2/oauth2_credentials.h b/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
index 7f6f205c22..2d7c02ccf5 100644
--- a/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
+++ b/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
@@ -103,7 +103,7 @@ grpc_refresh_token_credentials_create_from_auth_refresh_token(
// Exposed for testing only.
grpc_credentials_status
grpc_oauth2_token_fetcher_credentials_parse_server_response(
- const struct grpc_http_response *response,
+ grpc_exec_ctx *exec_ctx, const struct grpc_http_response *response,
grpc_credentials_md_store **token_md, gpr_timespec *token_lifetime);
#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_OAUTH2_OAUTH2_CREDENTIALS_H */
diff --git a/src/core/lib/security/credentials/plugin/plugin_credentials.c b/src/core/lib/security/credentials/plugin/plugin_credentials.c
index 5d950098a0..f90d7dce83 100644
--- a/src/core/lib/security/credentials/plugin/plugin_credentials.c
+++ b/src/core/lib/security/credentials/plugin/plugin_credentials.c
@@ -35,20 +35,22 @@
#include <string.h>
-#include "src/core/lib/surface/api_trace.h"
-
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
+#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/surface/api_trace.h"
+
typedef struct {
void *user_data;
grpc_credentials_metadata_cb cb;
} grpc_metadata_plugin_request;
-static void plugin_destruct(grpc_call_credentials *creds) {
+static void plugin_destruct(grpc_exec_ctx *exec_ctx,
+ grpc_call_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);
@@ -100,8 +102,8 @@ static void plugin_md_request_metadata_ready(void *request,
r->cb(&exec_ctx, r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK,
NULL);
for (i = 0; i < num_md; i++) {
- grpc_slice_unref(md_array[i].key);
- grpc_slice_unref(md_array[i].value);
+ grpc_slice_unref_internal(&exec_ctx, md_array[i].key);
+ grpc_slice_unref_internal(&exec_ctx, md_array[i].value);
}
gpr_free(md_array);
} else if (num_md == 0) {
diff --git a/src/core/lib/security/credentials/ssl/ssl_credentials.c b/src/core/lib/security/credentials/ssl/ssl_credentials.c
index 0dc1fccec4..4eebb7d613 100644
--- a/src/core/lib/security/credentials/ssl/ssl_credentials.c
+++ b/src/core/lib/security/credentials/ssl/ssl_credentials.c
@@ -57,7 +57,8 @@ static void ssl_copy_key_material(const char *input, unsigned char **output,
// SSL Channel Credentials.
//
-static void ssl_destruct(grpc_channel_credentials *creds) {
+static void ssl_destruct(grpc_exec_ctx *exec_ctx,
+ grpc_channel_credentials *creds) {
grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds;
if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
if (c->config.pem_private_key != NULL) gpr_free(c->config.pem_private_key);
@@ -65,9 +66,10 @@ static void ssl_destruct(grpc_channel_credentials *creds) {
}
static grpc_security_status ssl_create_security_connector(
- grpc_channel_credentials *creds, grpc_call_credentials *call_creds,
- const char *target, const grpc_channel_args *args,
- grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
+ grpc_exec_ctx *exec_ctx, grpc_channel_credentials *creds,
+ grpc_call_credentials *call_creds, const char *target,
+ const grpc_channel_args *args, grpc_channel_security_connector **sc,
+ grpc_channel_args **new_args) {
grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds;
grpc_security_status status = GRPC_SECURITY_OK;
size_t i = 0;
@@ -83,7 +85,7 @@ static grpc_security_status ssl_create_security_connector(
}
}
status = grpc_ssl_channel_security_connector_create(
- call_creds, &c->config, target, overridden_target_name, sc);
+ exec_ctx, call_creds, &c->config, target, overridden_target_name, sc);
if (status != GRPC_SECURITY_OK) {
return status;
}
@@ -138,7 +140,8 @@ grpc_channel_credentials *grpc_ssl_credentials_create(
// SSL Server Credentials.
//
-static void ssl_server_destruct(grpc_server_credentials *creds) {
+static void ssl_server_destruct(grpc_exec_ctx *exec_ctx,
+ grpc_server_credentials *creds) {
grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds;
size_t i;
for (i = 0; i < c->config.num_key_cert_pairs; i++) {
@@ -161,9 +164,10 @@ static void ssl_server_destruct(grpc_server_credentials *creds) {
}
static grpc_security_status ssl_server_create_security_connector(
- grpc_server_credentials *creds, grpc_server_security_connector **sc) {
+ grpc_exec_ctx *exec_ctx, grpc_server_credentials *creds,
+ grpc_server_security_connector **sc) {
grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds;
- return grpc_ssl_server_security_connector_create(&c->config, sc);
+ return grpc_ssl_server_security_connector_create(exec_ctx, &c->config, sc);
}
static grpc_server_credentials_vtable ssl_server_vtable = {
diff --git a/src/core/lib/security/transport/client_auth_filter.c b/src/core/lib/security/transport/client_auth_filter.c
index 053bf5972c..b7f6fd23e3 100644
--- a/src/core/lib/security/transport/client_auth_filter.c
+++ b/src/core/lib/security/transport/client_auth_filter.c
@@ -44,6 +44,7 @@
#include "src/core/lib/security/context/security_context.h"
#include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/security/transport/security_connector.h"
+#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/surface/call.h"
#include "src/core/lib/transport/static_metadata.h"
@@ -93,7 +94,8 @@ static void bubble_up_error(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
call_data *calld = elem->call_data;
gpr_log(GPR_ERROR, "Client side authentication failure: %s", error_msg);
grpc_slice error_slice = grpc_slice_from_copied_string(error_msg);
- grpc_transport_stream_op_add_close(&calld->op, status, &error_slice);
+ grpc_transport_stream_op_add_close(exec_ctx, &calld->op, status,
+ &error_slice);
grpc_call_next_op(exec_ctx, elem, &calld->op);
}
@@ -121,8 +123,9 @@ static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data,
for (i = 0; i < num_md; i++) {
grpc_metadata_batch_add_tail(
mdb, &calld->md_links[i],
- grpc_mdelem_from_slices(grpc_slice_ref(md_elems[i].key),
- grpc_slice_ref(md_elems[i].value)));
+ grpc_mdelem_from_slices(exec_ctx,
+ grpc_slice_ref_internal(md_elems[i].key),
+ grpc_slice_ref_internal(md_elems[i].value)));
}
grpc_call_next_op(exec_ctx, elem, op);
}
@@ -248,10 +251,10 @@ static void auth_start_transport_op(grpc_exec_ctx *exec_ctx,
/* Pointer comparison is OK for md_elems created from the same context.
*/
if (md->key == GRPC_MDSTR_AUTHORITY) {
- if (calld->host != NULL) GRPC_MDSTR_UNREF(calld->host);
+ if (calld->host != NULL) GRPC_MDSTR_UNREF(exec_ctx, calld->host);
calld->host = GRPC_MDSTR_REF(md->value);
} else if (md->key == GRPC_MDSTR_PATH) {
- if (calld->method != NULL) GRPC_MDSTR_UNREF(calld->method);
+ if (calld->method != NULL) GRPC_MDSTR_UNREF(exec_ctx, calld->method);
calld->method = GRPC_MDSTR_REF(md->value);
}
}
@@ -292,20 +295,20 @@ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info,
void *ignored) {
call_data *calld = elem->call_data;
- grpc_call_credentials_unref(calld->creds);
+ grpc_call_credentials_unref(exec_ctx, calld->creds);
if (calld->host != NULL) {
- GRPC_MDSTR_UNREF(calld->host);
+ GRPC_MDSTR_UNREF(exec_ctx, calld->host);
}
if (calld->method != NULL) {
- GRPC_MDSTR_UNREF(calld->method);
+ GRPC_MDSTR_UNREF(exec_ctx, calld->method);
}
reset_auth_metadata_context(&calld->auth_md_context);
}
/* Constructor for channel_data */
-static void init_channel_elem(grpc_exec_ctx *exec_ctx,
- grpc_channel_element *elem,
- grpc_channel_element_args *args) {
+static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx,
+ grpc_channel_element *elem,
+ grpc_channel_element_args *args) {
grpc_security_connector *sc =
grpc_find_security_connector_in_args(args->channel_args);
grpc_auth_context *auth_context =
@@ -327,6 +330,7 @@ static void init_channel_elem(grpc_exec_ctx *exec_ctx,
sc, "client_auth_filter");
chand->auth_context =
GRPC_AUTH_CONTEXT_REF(auth_context, "client_auth_filter");
+ return GRPC_ERROR_NONE;
}
/* Destructor for channel data */
@@ -336,7 +340,7 @@ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
channel_data *chand = elem->channel_data;
grpc_channel_security_connector *sc = chand->security_connector;
if (sc != NULL) {
- GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "client_auth_filter");
+ GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, &sc->base, "client_auth_filter");
}
GRPC_AUTH_CONTEXT_UNREF(chand->auth_context, "client_auth_filter");
}
diff --git a/src/core/lib/security/transport/handshake.c b/src/core/lib/security/transport/handshake.c
deleted file mode 100644
index 9623797610..0000000000
--- a/src/core/lib/security/transport/handshake.c
+++ /dev/null
@@ -1,374 +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/lib/security/transport/handshake.h"
-
-#include <stdbool.h>
-#include <string.h>
-
-#include <grpc/slice_buffer.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include "src/core/lib/iomgr/timer.h"
-#include "src/core/lib/security/context/security_context.h"
-#include "src/core/lib/security/transport/secure_endpoint.h"
-#include "src/core/lib/security/transport/tsi_error.h"
-
-#define GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE 256
-
-typedef struct {
- grpc_security_connector *connector;
- tsi_handshaker *handshaker;
- bool is_client_side;
- unsigned char *handshake_buffer;
- size_t handshake_buffer_size;
- grpc_endpoint *wrapped_endpoint;
- grpc_endpoint *secure_endpoint;
- grpc_slice_buffer left_overs;
- grpc_slice_buffer incoming;
- grpc_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_auth_context *auth_context;
- grpc_timer timer;
- gpr_refcount refs;
-} grpc_security_handshake;
-
-static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
- void *setup,
- grpc_error *error);
-
-static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *setup,
- grpc_error *error);
-
-static void security_connector_remove_handshake(grpc_security_handshake *h) {
- GPR_ASSERT(!h->is_client_side);
- grpc_security_connector_handshake_list *node;
- grpc_security_connector_handshake_list *tmp;
- grpc_server_security_connector *sc =
- (grpc_server_security_connector *)h->connector;
- gpr_mu_lock(&sc->mu);
- node = sc->handshaking_handshakes;
- if (node && node->handshake == h) {
- sc->handshaking_handshakes = node->next;
- gpr_free(node);
- gpr_mu_unlock(&sc->mu);
- return;
- }
- while (node) {
- if (node->next->handshake == h) {
- tmp = node->next;
- node->next = node->next->next;
- gpr_free(tmp);
- gpr_mu_unlock(&sc->mu);
- return;
- }
- node = node->next;
- }
- gpr_mu_unlock(&sc->mu);
-}
-
-static void unref_handshake(grpc_security_handshake *h) {
- if (gpr_unref(&h->refs)) {
- if (h->handshaker != NULL) tsi_handshaker_destroy(h->handshaker);
- if (h->handshake_buffer != NULL) gpr_free(h->handshake_buffer);
- grpc_slice_buffer_destroy(&h->left_overs);
- grpc_slice_buffer_destroy(&h->outgoing);
- grpc_slice_buffer_destroy(&h->incoming);
- GRPC_AUTH_CONTEXT_UNREF(h->auth_context, "handshake");
- GRPC_SECURITY_CONNECTOR_UNREF(h->connector, "handshake");
- gpr_free(h);
- }
-}
-
-static void security_handshake_done(grpc_exec_ctx *exec_ctx,
- grpc_security_handshake *h,
- grpc_error *error) {
- grpc_timer_cancel(exec_ctx, &h->timer);
- if (!h->is_client_side) {
- security_connector_remove_handshake(h);
- }
- if (error == GRPC_ERROR_NONE) {
- h->cb(exec_ctx, h->user_data, GRPC_SECURITY_OK, h->secure_endpoint,
- h->auth_context);
- } else {
- const char *msg = grpc_error_string(error);
- gpr_log(GPR_DEBUG, "Security handshake failed: %s", msg);
- grpc_error_free_string(msg);
-
- 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, NULL, NULL);
- }
- unref_handshake(h);
- GRPC_ERROR_UNREF(error);
-}
-
-static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *user_data,
- grpc_security_status status,
- grpc_auth_context *auth_context) {
- grpc_security_handshake *h = user_data;
- tsi_frame_protector *protector;
- tsi_result result;
- if (status != GRPC_SECURITY_OK) {
- security_handshake_done(
- exec_ctx, h,
- grpc_error_set_int(GRPC_ERROR_CREATE("Error checking peer."),
- GRPC_ERROR_INT_SECURITY_STATUS, status));
- return;
- }
- h->auth_context = GRPC_AUTH_CONTEXT_REF(auth_context, "handshake");
- result =
- tsi_handshaker_create_frame_protector(h->handshaker, NULL, &protector);
- if (result != TSI_OK) {
- security_handshake_done(
- exec_ctx, h,
- grpc_set_tsi_error_result(
- GRPC_ERROR_CREATE("Frame protector creation failed"), result));
- 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, GRPC_ERROR_NONE);
- return;
-}
-
-static void check_peer(grpc_exec_ctx *exec_ctx, grpc_security_handshake *h) {
- tsi_peer peer;
- tsi_result result = tsi_handshaker_extract_peer(h->handshaker, &peer);
-
- if (result != TSI_OK) {
- security_handshake_done(
- exec_ctx, h, grpc_set_tsi_error_result(
- GRPC_ERROR_CREATE("Peer extraction failed"), result));
- return;
- }
- grpc_security_connector_check_peer(exec_ctx, h->connector, peer,
- on_peer_checked, h);
-}
-
-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;
- grpc_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) {
- security_handshake_done(exec_ctx, h,
- grpc_set_tsi_error_result(
- GRPC_ERROR_CREATE("Handshake failed"), result));
- return;
- }
-
- to_send =
- grpc_slice_from_copied_buffer((const char *)h->handshake_buffer, offset);
- grpc_slice_buffer_reset_and_unref(&h->outgoing);
- grpc_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,
- grpc_error *error) {
- grpc_security_handshake *h = handshake;
- size_t consumed_slice_size = 0;
- tsi_result result = TSI_OK;
- size_t i;
- size_t num_left_overs;
- int has_left_overs_in_current_slice = 0;
-
- if (error != GRPC_ERROR_NONE) {
- security_handshake_done(
- exec_ctx, h,
- GRPC_ERROR_CREATE_REFERENCING("Handshake read failed", &error, 1));
- return;
- }
-
- for (i = 0; i < h->incoming.count; i++) {
- consumed_slice_size = GRPC_SLICE_LENGTH(h->incoming.slices[i]);
- result = tsi_handshaker_process_bytes_from_peer(
- h->handshaker, GRPC_SLICE_START_PTR(h->incoming.slices[i]),
- &consumed_slice_size);
- if (!tsi_handshaker_is_in_progress(h->handshaker)) break;
- }
-
- if (tsi_handshaker_is_in_progress(h->handshaker)) {
- /* We may need more data. */
- if (result == TSI_INCOMPLETE_DATA) {
- grpc_endpoint_read(exec_ctx, h->wrapped_endpoint, &h->incoming,
- &h->on_handshake_data_received_from_peer);
- return;
- } else {
- send_handshake_bytes_to_peer(exec_ctx, h);
- return;
- }
- }
-
- if (result != TSI_OK) {
- security_handshake_done(exec_ctx, h,
- grpc_set_tsi_error_result(
- GRPC_ERROR_CREATE("Handshake failed"), result));
- return;
- }
-
- /* Handshake is done and successful this point. */
- has_left_overs_in_current_slice =
- (consumed_slice_size < GRPC_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) {
- grpc_slice_buffer_add(
- &h->left_overs,
- grpc_slice_split_tail(&h->incoming.slices[i], consumed_slice_size));
- grpc_slice_unref(
- h->incoming.slices[i]); /* split_tail above increments refcount. */
- }
- grpc_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, grpc_error *error) {
- grpc_security_handshake *h = handshake;
-
- /* Make sure that write is OK. */
- if (error != GRPC_ERROR_NONE) {
- if (handshake != NULL)
- security_handshake_done(
- exec_ctx, h,
- GRPC_ERROR_CREATE_REFERENCING("Handshake write failed", &error, 1));
- 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);
- }
-}
-
-static void on_timeout(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
- grpc_security_handshake *h = arg;
- if (error == GRPC_ERROR_NONE) {
- grpc_endpoint_shutdown(exec_ctx, h->wrapped_endpoint);
- }
- unref_handshake(h);
-}
-
-void grpc_do_security_handshake(
- grpc_exec_ctx *exec_ctx, tsi_handshaker *handshaker,
- grpc_security_connector *connector, bool is_client_side,
- grpc_endpoint *nonsecure_endpoint, grpc_slice_buffer *read_buffer,
- gpr_timespec deadline, grpc_security_handshake_done_cb cb,
- void *user_data) {
- grpc_security_connector_handshake_list *handshake_node;
- grpc_security_handshake *h = gpr_malloc(sizeof(grpc_security_handshake));
- memset(h, 0, sizeof(grpc_security_handshake));
- h->handshaker = handshaker;
- h->connector = GRPC_SECURITY_CONNECTOR_REF(connector, "handshake");
- h->is_client_side = is_client_side;
- h->handshake_buffer_size = GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE;
- h->handshake_buffer = gpr_malloc(h->handshake_buffer_size);
- h->wrapped_endpoint = nonsecure_endpoint;
- h->user_data = user_data;
- h->cb = cb;
- gpr_ref_init(&h->refs, 2); /* timer and handshake proper each get a ref */
- grpc_closure_init(&h->on_handshake_data_sent_to_peer,
- on_handshake_data_sent_to_peer, h);
- grpc_closure_init(&h->on_handshake_data_received_from_peer,
- on_handshake_data_received_from_peer, h);
- grpc_slice_buffer_init(&h->left_overs);
- grpc_slice_buffer_init(&h->outgoing);
- grpc_slice_buffer_init(&h->incoming);
- if (read_buffer != NULL) {
- grpc_slice_buffer_move_into(read_buffer, &h->incoming);
- gpr_free(read_buffer);
- }
- if (!is_client_side) {
- grpc_server_security_connector *server_connector =
- (grpc_server_security_connector *)connector;
- handshake_node = gpr_malloc(sizeof(grpc_security_connector_handshake_list));
- handshake_node->handshake = h;
- gpr_mu_lock(&server_connector->mu);
- handshake_node->next = server_connector->handshaking_handshakes;
- server_connector->handshaking_handshakes = handshake_node;
- gpr_mu_unlock(&server_connector->mu);
- }
- send_handshake_bytes_to_peer(exec_ctx, h);
- grpc_timer_init(exec_ctx, &h->timer,
- gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
- on_timeout, h, gpr_now(GPR_CLOCK_MONOTONIC));
-}
-
-void grpc_security_handshake_shutdown(grpc_exec_ctx *exec_ctx,
- void *handshake) {
- grpc_security_handshake *h = handshake;
- grpc_endpoint_shutdown(exec_ctx, h->wrapped_endpoint);
-}
diff --git a/src/core/lib/security/transport/secure_endpoint.c b/src/core/lib/security/transport/secure_endpoint.c
index 1b278410e8..18a7a6f7e7 100644
--- a/src/core/lib/security/transport/secure_endpoint.c
+++ b/src/core/lib/security/transport/secure_endpoint.c
@@ -46,6 +46,7 @@
#include "src/core/lib/profiling/timers.h"
#include "src/core/lib/security/transport/secure_endpoint.h"
#include "src/core/lib/security/transport/tsi_error.h"
+#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/tsi/transport_security_interface.h"
@@ -80,11 +81,11 @@ static void destroy(grpc_exec_ctx *exec_ctx, secure_endpoint *secure_ep) {
secure_endpoint *ep = secure_ep;
grpc_endpoint_destroy(exec_ctx, ep->wrapped_ep);
tsi_frame_protector_destroy(ep->protector);
- grpc_slice_buffer_destroy(&ep->leftover_bytes);
- grpc_slice_unref(ep->read_staging_buffer);
- grpc_slice_unref(ep->write_staging_buffer);
- grpc_slice_buffer_destroy(&ep->output_buffer);
- grpc_slice_buffer_destroy(&ep->source_buffer);
+ grpc_slice_buffer_destroy_internal(exec_ctx, &ep->leftover_bytes);
+ grpc_slice_unref_internal(exec_ctx, ep->read_staging_buffer);
+ grpc_slice_unref_internal(exec_ctx, ep->write_staging_buffer);
+ grpc_slice_buffer_destroy_internal(exec_ctx, &ep->output_buffer);
+ grpc_slice_buffer_destroy_internal(exec_ctx, &ep->source_buffer);
gpr_mu_destroy(&ep->protector_mu);
gpr_free(ep);
}
@@ -146,7 +147,7 @@ static void call_read_cb(grpc_exec_ctx *exec_ctx, secure_endpoint *ep,
}
}
ep->read_buffer = NULL;
- grpc_exec_ctx_sched(exec_ctx, ep->read_cb, error, NULL);
+ grpc_closure_sched(exec_ctx, ep->read_cb, error);
SECURE_ENDPOINT_UNREF(exec_ctx, ep, "read");
}
@@ -160,7 +161,7 @@ static void on_read(grpc_exec_ctx *exec_ctx, void *user_data,
uint8_t *end = GRPC_SLICE_END_PTR(ep->read_staging_buffer);
if (error != GRPC_ERROR_NONE) {
- grpc_slice_buffer_reset_and_unref(ep->read_buffer);
+ grpc_slice_buffer_reset_and_unref_internal(exec_ctx, ep->read_buffer);
call_read_cb(exec_ctx, ep, GRPC_ERROR_CREATE_REFERENCING(
"Secure read failed", &error, 1));
return;
@@ -215,10 +216,10 @@ static void on_read(grpc_exec_ctx *exec_ctx, void *user_data,
/* TODO(yangg) experiment with moving this block after read_cb to see if it
helps latency */
- grpc_slice_buffer_reset_and_unref(&ep->source_buffer);
+ grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &ep->source_buffer);
if (result != TSI_OK) {
- grpc_slice_buffer_reset_and_unref(ep->read_buffer);
+ grpc_slice_buffer_reset_and_unref_internal(exec_ctx, ep->read_buffer);
call_read_cb(exec_ctx, ep, grpc_set_tsi_error_result(
GRPC_ERROR_CREATE("Unwrap failed"), result));
return;
@@ -232,7 +233,7 @@ static void endpoint_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep,
secure_endpoint *ep = (secure_endpoint *)secure_ep;
ep->read_cb = cb;
ep->read_buffer = slices;
- grpc_slice_buffer_reset_and_unref(ep->read_buffer);
+ grpc_slice_buffer_reset_and_unref_internal(exec_ctx, ep->read_buffer);
SECURE_ENDPOINT_REF(ep, "read");
if (ep->leftover_bytes.count) {
@@ -264,7 +265,7 @@ static void endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep,
uint8_t *cur = GRPC_SLICE_START_PTR(ep->write_staging_buffer);
uint8_t *end = GRPC_SLICE_END_PTR(ep->write_staging_buffer);
- grpc_slice_buffer_reset_and_unref(&ep->output_buffer);
+ grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &ep->output_buffer);
if (grpc_trace_secure_endpoint) {
for (i = 0; i < slices->count; i++) {
@@ -328,11 +329,10 @@ static void endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep,
if (result != TSI_OK) {
/* TODO(yangg) do different things according to the error type? */
- grpc_slice_buffer_reset_and_unref(&ep->output_buffer);
- grpc_exec_ctx_sched(
+ grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &ep->output_buffer);
+ grpc_closure_sched(
exec_ctx, cb,
- grpc_set_tsi_error_result(GRPC_ERROR_CREATE("Wrap failed"), result),
- NULL);
+ grpc_set_tsi_error_result(GRPC_ERROR_CREATE("Wrap failed"), result));
GPR_TIMER_END("secure_endpoint.endpoint_write", 0);
return;
}
@@ -372,7 +372,10 @@ static char *endpoint_get_peer(grpc_endpoint *secure_ep) {
return grpc_endpoint_get_peer(ep->wrapped_ep);
}
-static int endpoint_get_fd(grpc_endpoint *secure_ep) { return -1; }
+static int endpoint_get_fd(grpc_endpoint *secure_ep) {
+ secure_endpoint *ep = (secure_endpoint *)secure_ep;
+ return grpc_endpoint_get_fd(ep->wrapped_ep);
+}
static grpc_workqueue *endpoint_get_workqueue(grpc_endpoint *secure_ep) {
secure_endpoint *ep = (secure_endpoint *)secure_ep;
@@ -407,14 +410,14 @@ grpc_endpoint *grpc_secure_endpoint_create(
grpc_slice_buffer_init(&ep->leftover_bytes);
for (i = 0; i < leftover_nslices; i++) {
grpc_slice_buffer_add(&ep->leftover_bytes,
- grpc_slice_ref(leftover_slices[i]));
+ grpc_slice_ref_internal(leftover_slices[i]));
}
ep->write_staging_buffer = grpc_slice_malloc(STAGING_BUFFER_SIZE);
ep->read_staging_buffer = grpc_slice_malloc(STAGING_BUFFER_SIZE);
grpc_slice_buffer_init(&ep->output_buffer);
grpc_slice_buffer_init(&ep->source_buffer);
ep->read_buffer = NULL;
- grpc_closure_init(&ep->on_read, on_read, ep);
+ grpc_closure_init(&ep->on_read, on_read, ep, grpc_schedule_on_exec_ctx);
gpr_mu_init(&ep->protector_mu);
gpr_ref_init(&ep->ref, 1);
return &ep->base;
diff --git a/src/core/lib/security/transport/security_connector.c b/src/core/lib/security/transport/security_connector.c
index 0fbd63a7e1..5aa26e0577 100644
--- a/src/core/lib/security/transport/security_connector.c
+++ b/src/core/lib/security/transport/security_connector.c
@@ -43,11 +43,12 @@
#include <grpc/support/string_util.h>
#include "src/core/ext/transport/chttp2/alpn/alpn.h"
+#include "src/core/lib/channel/handshaker.h"
#include "src/core/lib/iomgr/load_file.h"
#include "src/core/lib/security/context/security_context.h"
#include "src/core/lib/security/credentials/credentials.h"
-#include "src/core/lib/security/transport/handshake.h"
#include "src/core/lib/security/transport/secure_endpoint.h"
+#include "src/core/lib/security/transport/security_handshaker.h"
#include "src/core/lib/support/env.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/tsi/fake_transport_security.h"
@@ -111,58 +112,34 @@ const tsi_peer_property *tsi_peer_get_property_by_name(const tsi_peer *peer,
return NULL;
}
-void grpc_server_security_connector_shutdown(
- grpc_exec_ctx *exec_ctx, grpc_server_security_connector *connector) {
- grpc_security_connector_handshake_list *tmp;
- gpr_mu_lock(&connector->mu);
- while (connector->handshaking_handshakes) {
- tmp = connector->handshaking_handshakes;
- grpc_security_handshake_shutdown(
- exec_ctx, connector->handshaking_handshakes->handshake);
- connector->handshaking_handshakes = tmp->next;
- gpr_free(tmp);
+void grpc_channel_security_connector_add_handshakers(
+ grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *connector,
+ grpc_handshake_manager *handshake_mgr) {
+ if (connector != NULL) {
+ connector->add_handshakers(exec_ctx, connector, handshake_mgr);
}
- gpr_mu_unlock(&connector->mu);
}
-void grpc_channel_security_connector_do_handshake(
- grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
- grpc_endpoint *nonsecure_endpoint, grpc_slice_buffer *read_buffer,
- gpr_timespec deadline, grpc_security_handshake_done_cb cb,
- void *user_data) {
- if (sc == NULL || nonsecure_endpoint == NULL) {
- gpr_free(read_buffer);
- cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
- } else {
- sc->do_handshake(exec_ctx, sc, nonsecure_endpoint, read_buffer, deadline,
- cb, user_data);
- }
-}
-
-void grpc_server_security_connector_do_handshake(
- grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc,
- grpc_tcp_server_acceptor *acceptor, grpc_endpoint *nonsecure_endpoint,
- grpc_slice_buffer *read_buffer, gpr_timespec deadline,
- grpc_security_handshake_done_cb cb, void *user_data) {
- if (sc == NULL || nonsecure_endpoint == NULL) {
- gpr_free(read_buffer);
- cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
- } else {
- sc->do_handshake(exec_ctx, sc, acceptor, nonsecure_endpoint, read_buffer,
- deadline, cb, user_data);
+void grpc_server_security_connector_add_handshakers(
+ grpc_exec_ctx *exec_ctx, grpc_server_security_connector *connector,
+ grpc_handshake_manager *handshake_mgr) {
+ if (connector != NULL) {
+ connector->add_handshakers(exec_ctx, connector, handshake_mgr);
}
}
void grpc_security_connector_check_peer(grpc_exec_ctx *exec_ctx,
grpc_security_connector *sc,
tsi_peer peer,
- grpc_security_peer_check_cb cb,
- void *user_data) {
+ grpc_auth_context **auth_context,
+ grpc_closure *on_peer_checked) {
if (sc == NULL) {
- cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL);
+ grpc_closure_sched(
+ exec_ctx, on_peer_checked,
+ GRPC_ERROR_CREATE("cannot check peer -- no security connector"));
tsi_peer_destruct(&peer);
} else {
- sc->vtable->check_peer(exec_ctx, sc, peer, cb, user_data);
+ sc->vtable->check_peer(exec_ctx, sc, peer, auth_context, on_peer_checked);
}
}
@@ -195,7 +172,8 @@ grpc_security_connector *grpc_security_connector_ref(
}
#ifdef GRPC_SECURITY_CONNECTOR_REFCOUNT_DEBUG
-void grpc_security_connector_unref(grpc_security_connector *sc,
+void grpc_security_connector_unref(grpc_exec_ctx *exec_ctx,
+ grpc_security_connector *sc,
const char *file, int line,
const char *reason) {
if (sc == NULL) return;
@@ -203,14 +181,15 @@ void grpc_security_connector_unref(grpc_security_connector *sc,
"SECURITY_CONNECTOR:%p unref %d -> %d %s", sc,
(int)sc->refcount.count, (int)sc->refcount.count - 1, reason);
#else
-void grpc_security_connector_unref(grpc_security_connector *sc) {
+void grpc_security_connector_unref(grpc_exec_ctx *exec_ctx,
+ grpc_security_connector *sc) {
if (sc == NULL) return;
#endif
- if (gpr_unref(&sc->refcount)) sc->vtable->destroy(sc);
+ if (gpr_unref(&sc->refcount)) sc->vtable->destroy(exec_ctx, sc);
}
-static void connector_pointer_arg_destroy(void *p) {
- GRPC_SECURITY_CONNECTOR_UNREF(p, "connector_pointer_arg_destroy");
+static void connector_pointer_arg_destroy(grpc_exec_ctx *exec_ctx, void *p) {
+ GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, p, "connector_pointer_arg_destroy");
}
static void *connector_pointer_arg_copy(void *p) {
@@ -256,51 +235,51 @@ grpc_security_connector *grpc_find_security_connector_in_args(
/* -- Fake implementation. -- */
-static void fake_channel_destroy(grpc_security_connector *sc) {
+static void fake_channel_destroy(grpc_exec_ctx *exec_ctx,
+ grpc_security_connector *sc) {
grpc_channel_security_connector *c = (grpc_channel_security_connector *)sc;
- grpc_call_credentials_unref(c->request_metadata_creds);
+ grpc_call_credentials_unref(exec_ctx, c->request_metadata_creds);
gpr_free(sc);
}
-static void fake_server_destroy(grpc_security_connector *sc) {
- grpc_server_security_connector *c = (grpc_server_security_connector *)sc;
- gpr_mu_destroy(&c->mu);
+static void fake_server_destroy(grpc_exec_ctx *exec_ctx,
+ grpc_security_connector *sc) {
gpr_free(sc);
}
static void fake_check_peer(grpc_exec_ctx *exec_ctx,
grpc_security_connector *sc, tsi_peer peer,
- grpc_security_peer_check_cb cb, void *user_data) {
+ grpc_auth_context **auth_context,
+ grpc_closure *on_peer_checked) {
const char *prop_name;
- grpc_security_status status = GRPC_SECURITY_OK;
- grpc_auth_context *auth_context = NULL;
+ grpc_error *error = GRPC_ERROR_NONE;
+ *auth_context = NULL;
if (peer.property_count != 1) {
- gpr_log(GPR_ERROR, "Fake peers should only have 1 property.");
- status = GRPC_SECURITY_ERROR;
+ error = GRPC_ERROR_CREATE("Fake peers should only have 1 property.");
goto end;
}
prop_name = peer.properties[0].name;
if (prop_name == NULL ||
strcmp(prop_name, TSI_CERTIFICATE_TYPE_PEER_PROPERTY)) {
- gpr_log(GPR_ERROR, "Unexpected property in fake peer: %s.",
- prop_name == NULL ? "<EMPTY>" : prop_name);
- status = GRPC_SECURITY_ERROR;
+ char *msg;
+ gpr_asprintf(&msg, "Unexpected property in fake peer: %s.",
+ prop_name == NULL ? "<EMPTY>" : prop_name);
+ error = GRPC_ERROR_CREATE(msg);
+ gpr_free(msg);
goto end;
}
if (strncmp(peer.properties[0].value.data, TSI_FAKE_CERTIFICATE_TYPE,
peer.properties[0].value.length)) {
- gpr_log(GPR_ERROR, "Invalid value for cert type property.");
- status = GRPC_SECURITY_ERROR;
+ error = GRPC_ERROR_CREATE("Invalid value for cert type property.");
goto end;
}
- auth_context = grpc_auth_context_create(NULL);
+ *auth_context = grpc_auth_context_create(NULL);
grpc_auth_context_add_cstring_property(
- auth_context, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
+ *auth_context, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
GRPC_FAKE_TRANSPORT_SECURITY_TYPE);
end:
- cb(exec_ctx, user_data, status, auth_context);
- grpc_auth_context_unref(auth_context);
+ grpc_closure_sched(exec_ctx, on_peer_checked, error);
tsi_peer_destruct(&peer);
}
@@ -313,26 +292,24 @@ static void fake_channel_check_call_host(grpc_exec_ctx *exec_ctx,
cb(exec_ctx, user_data, GRPC_SECURITY_OK);
}
-static void fake_channel_do_handshake(grpc_exec_ctx *exec_ctx,
- grpc_channel_security_connector *sc,
- grpc_endpoint *nonsecure_endpoint,
- grpc_slice_buffer *read_buffer,
- gpr_timespec deadline,
- grpc_security_handshake_done_cb cb,
- void *user_data) {
- grpc_do_security_handshake(exec_ctx, tsi_create_fake_handshaker(1), &sc->base,
- true, nonsecure_endpoint, read_buffer, deadline,
- cb, user_data);
+static void fake_channel_add_handshakers(
+ grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
+ grpc_handshake_manager *handshake_mgr) {
+ grpc_handshake_manager_add(
+ handshake_mgr,
+ grpc_security_handshaker_create(
+ exec_ctx, tsi_create_fake_handshaker(true /* is_client */),
+ &sc->base));
}
-static void fake_server_do_handshake(
- grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc,
- grpc_tcp_server_acceptor *acceptor, grpc_endpoint *nonsecure_endpoint,
- grpc_slice_buffer *read_buffer, gpr_timespec deadline,
- grpc_security_handshake_done_cb cb, void *user_data) {
- grpc_do_security_handshake(exec_ctx, tsi_create_fake_handshaker(0), &sc->base,
- false, nonsecure_endpoint, read_buffer, deadline,
- cb, user_data);
+static void fake_server_add_handshakers(grpc_exec_ctx *exec_ctx,
+ grpc_server_security_connector *sc,
+ grpc_handshake_manager *handshake_mgr) {
+ grpc_handshake_manager_add(
+ handshake_mgr,
+ grpc_security_handshaker_create(
+ exec_ctx, tsi_create_fake_handshaker(false /* is_client */),
+ &sc->base));
}
static grpc_security_connector_vtable fake_channel_vtable = {
@@ -350,7 +327,7 @@ grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
c->base.vtable = &fake_channel_vtable;
c->request_metadata_creds = grpc_call_credentials_ref(request_metadata_creds);
c->check_call_host = fake_channel_check_call_host;
- c->do_handshake = fake_channel_do_handshake;
+ c->add_handshakers = fake_channel_add_handshakers;
return c;
}
@@ -362,8 +339,7 @@ grpc_server_security_connector *grpc_fake_server_security_connector_create(
gpr_ref_init(&c->base.refcount, 1);
c->base.vtable = &fake_server_vtable;
c->base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME;
- c->do_handshake = fake_server_do_handshake;
- gpr_mu_init(&c->mu);
+ c->add_handshakers = fake_server_add_handshakers;
return c;
}
@@ -381,10 +357,11 @@ typedef struct {
tsi_ssl_handshaker_factory *handshaker_factory;
} grpc_ssl_server_security_connector;
-static void ssl_channel_destroy(grpc_security_connector *sc) {
+static void ssl_channel_destroy(grpc_exec_ctx *exec_ctx,
+ grpc_security_connector *sc) {
grpc_ssl_channel_security_connector *c =
(grpc_ssl_channel_security_connector *)sc;
- grpc_call_credentials_unref(c->base.request_metadata_creds);
+ grpc_call_credentials_unref(exec_ctx, c->base.request_metadata_creds);
if (c->handshaker_factory != NULL) {
tsi_ssl_handshaker_factory_destroy(c->handshaker_factory);
}
@@ -393,14 +370,13 @@ static void ssl_channel_destroy(grpc_security_connector *sc) {
gpr_free(sc);
}
-static void ssl_server_destroy(grpc_security_connector *sc) {
+static void ssl_server_destroy(grpc_exec_ctx *exec_ctx,
+ grpc_security_connector *sc) {
grpc_ssl_server_security_connector *c =
(grpc_ssl_server_security_connector *)sc;
-
if (c->handshaker_factory != NULL) {
tsi_ssl_handshaker_factory_destroy(c->handshaker_factory);
}
- gpr_mu_destroy(&c->base.mu);
gpr_free(sc);
}
@@ -419,49 +395,35 @@ static grpc_security_status ssl_create_handshaker(
return GRPC_SECURITY_OK;
}
-static void ssl_channel_do_handshake(grpc_exec_ctx *exec_ctx,
- grpc_channel_security_connector *sc,
- grpc_endpoint *nonsecure_endpoint,
- grpc_slice_buffer *read_buffer,
- gpr_timespec deadline,
- grpc_security_handshake_done_cb cb,
- void *user_data) {
+static void ssl_channel_add_handshakers(grpc_exec_ctx *exec_ctx,
+ grpc_channel_security_connector *sc,
+ grpc_handshake_manager *handshake_mgr) {
grpc_ssl_channel_security_connector *c =
(grpc_ssl_channel_security_connector *)sc;
- tsi_handshaker *handshaker;
- grpc_security_status status = ssl_create_handshaker(
- c->handshaker_factory, true,
- c->overridden_target_name != NULL ? c->overridden_target_name
- : c->target_name,
- &handshaker);
- if (status != GRPC_SECURITY_OK) {
- gpr_free(read_buffer);
- cb(exec_ctx, user_data, status, NULL, NULL);
- } else {
- grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, true,
- nonsecure_endpoint, read_buffer, deadline, cb,
- user_data);
- }
-}
-
-static void ssl_server_do_handshake(
- grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc,
- grpc_tcp_server_acceptor *acceptor, grpc_endpoint *nonsecure_endpoint,
- grpc_slice_buffer *read_buffer, gpr_timespec deadline,
- grpc_security_handshake_done_cb cb, void *user_data) {
+ // Instantiate TSI handshaker.
+ tsi_handshaker *tsi_hs = NULL;
+ ssl_create_handshaker(c->handshaker_factory, true /* is_client */,
+ c->overridden_target_name != NULL
+ ? c->overridden_target_name
+ : c->target_name,
+ &tsi_hs);
+ // Create handshakers.
+ grpc_handshake_manager_add(handshake_mgr, grpc_security_handshaker_create(
+ exec_ctx, tsi_hs, &sc->base));
+}
+
+static void ssl_server_add_handshakers(grpc_exec_ctx *exec_ctx,
+ grpc_server_security_connector *sc,
+ grpc_handshake_manager *handshake_mgr) {
grpc_ssl_server_security_connector *c =
(grpc_ssl_server_security_connector *)sc;
- tsi_handshaker *handshaker;
- grpc_security_status status =
- ssl_create_handshaker(c->handshaker_factory, false, NULL, &handshaker);
- if (status != GRPC_SECURITY_OK) {
- gpr_free(read_buffer);
- cb(exec_ctx, user_data, status, NULL, NULL);
- } else {
- grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, false,
- nonsecure_endpoint, read_buffer, deadline, cb,
- user_data);
- }
+ // Instantiate TSI handshaker.
+ tsi_handshaker *tsi_hs = NULL;
+ ssl_create_handshaker(c->handshaker_factory, false /* is_client */,
+ NULL /* peer_name */, &tsi_hs);
+ // Create handshakers.
+ grpc_handshake_manager_add(handshake_mgr, grpc_security_handshaker_create(
+ exec_ctx, tsi_hs, &sc->base));
}
static int ssl_host_matches_name(const tsi_peer *peer, const char *peer_name) {
@@ -518,57 +480,53 @@ grpc_auth_context *tsi_ssl_peer_to_auth_context(const tsi_peer *peer) {
return ctx;
}
-static grpc_security_status ssl_check_peer(grpc_security_connector *sc,
- const char *peer_name,
- const tsi_peer *peer,
- grpc_auth_context **auth_context) {
+static grpc_error *ssl_check_peer(grpc_security_connector *sc,
+ const char *peer_name, const tsi_peer *peer,
+ grpc_auth_context **auth_context) {
/* Check the ALPN. */
const tsi_peer_property *p =
tsi_peer_get_property_by_name(peer, TSI_SSL_ALPN_SELECTED_PROTOCOL);
if (p == NULL) {
- gpr_log(GPR_ERROR, "Missing selected ALPN property.");
- return GRPC_SECURITY_ERROR;
+ return GRPC_ERROR_CREATE(
+ "Cannot check peer: missing selected ALPN property.");
}
if (!grpc_chttp2_is_alpn_version_supported(p->value.data, p->value.length)) {
- gpr_log(GPR_ERROR, "Invalid ALPN value.");
- return GRPC_SECURITY_ERROR;
+ return GRPC_ERROR_CREATE("Cannot check peer: invalid ALPN value.");
}
/* Check the peer name if specified. */
if (peer_name != NULL && !ssl_host_matches_name(peer, peer_name)) {
- gpr_log(GPR_ERROR, "Peer name %s is not in peer certificate", peer_name);
- return GRPC_SECURITY_ERROR;
+ char *msg;
+ gpr_asprintf(&msg, "Peer name %s is not in peer certificate", peer_name);
+ grpc_error *error = GRPC_ERROR_CREATE(msg);
+ gpr_free(msg);
+ return error;
}
*auth_context = tsi_ssl_peer_to_auth_context(peer);
- return GRPC_SECURITY_OK;
+ return GRPC_ERROR_NONE;
}
static void ssl_channel_check_peer(grpc_exec_ctx *exec_ctx,
grpc_security_connector *sc, tsi_peer peer,
- grpc_security_peer_check_cb cb,
- void *user_data) {
+ grpc_auth_context **auth_context,
+ grpc_closure *on_peer_checked) {
grpc_ssl_channel_security_connector *c =
(grpc_ssl_channel_security_connector *)sc;
- grpc_security_status status;
- grpc_auth_context *auth_context = NULL;
- status = ssl_check_peer(sc, c->overridden_target_name != NULL
- ? c->overridden_target_name
- : c->target_name,
- &peer, &auth_context);
- cb(exec_ctx, user_data, status, auth_context);
- grpc_auth_context_unref(auth_context);
+ grpc_error *error = ssl_check_peer(sc, c->overridden_target_name != NULL
+ ? c->overridden_target_name
+ : c->target_name,
+ &peer, auth_context);
+ grpc_closure_sched(exec_ctx, on_peer_checked, error);
tsi_peer_destruct(&peer);
}
static void ssl_server_check_peer(grpc_exec_ctx *exec_ctx,
grpc_security_connector *sc, tsi_peer peer,
- grpc_security_peer_check_cb cb,
- void *user_data) {
- grpc_auth_context *auth_context = NULL;
- grpc_security_status status = ssl_check_peer(sc, NULL, &peer, &auth_context);
+ grpc_auth_context **auth_context,
+ grpc_closure *on_peer_checked) {
+ grpc_error *error = ssl_check_peer(sc, NULL, &peer, auth_context);
tsi_peer_destruct(&peer);
- cb(exec_ctx, user_data, status, auth_context);
- grpc_auth_context_unref(auth_context);
+ grpc_closure_sched(exec_ctx, on_peer_checked, error);
}
static void add_shallow_auth_property_to_peer(tsi_peer *peer,
@@ -719,7 +677,7 @@ size_t grpc_get_default_ssl_roots(const unsigned char **pem_root_certs) {
}
grpc_security_status grpc_ssl_channel_security_connector_create(
- grpc_call_credentials *request_metadata_creds,
+ grpc_exec_ctx *exec_ctx, grpc_call_credentials *request_metadata_creds,
const grpc_ssl_config *config, const char *target_name,
const char *overridden_target_name, grpc_channel_security_connector **sc) {
size_t num_alpn_protocols = grpc_chttp2_num_alpn_versions();
@@ -765,7 +723,7 @@ grpc_security_status grpc_ssl_channel_security_connector_create(
c->base.request_metadata_creds =
grpc_call_credentials_ref(request_metadata_creds);
c->base.check_call_host = ssl_channel_check_call_host;
- c->base.do_handshake = ssl_channel_do_handshake;
+ c->base.add_handshakers = ssl_channel_add_handshakers;
gpr_split_host_port(target_name, &c->target_name, &port);
gpr_free(port);
if (overridden_target_name != NULL) {
@@ -780,7 +738,7 @@ grpc_security_status grpc_ssl_channel_security_connector_create(
if (result != TSI_OK) {
gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
tsi_result_to_string(result));
- ssl_channel_destroy(&c->base.base);
+ ssl_channel_destroy(exec_ctx, &c->base.base);
*sc = NULL;
goto error;
}
@@ -796,7 +754,8 @@ error:
}
grpc_security_status grpc_ssl_server_security_connector_create(
- const grpc_ssl_server_config *config, grpc_server_security_connector **sc) {
+ grpc_exec_ctx *exec_ctx, const grpc_ssl_server_config *config,
+ grpc_server_security_connector **sc) {
size_t num_alpn_protocols = grpc_chttp2_num_alpn_versions();
const unsigned char **alpn_protocol_strings =
gpr_malloc(sizeof(const char *) * num_alpn_protocols);
@@ -836,12 +795,11 @@ grpc_security_status grpc_ssl_server_security_connector_create(
if (result != TSI_OK) {
gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
tsi_result_to_string(result));
- ssl_server_destroy(&c->base.base);
+ ssl_server_destroy(exec_ctx, &c->base.base);
*sc = NULL;
goto error;
}
- gpr_mu_init(&c->base.mu);
- c->base.do_handshake = ssl_server_do_handshake;
+ c->base.add_handshakers = ssl_server_add_handshakers;
*sc = &c->base;
gpr_free((void *)alpn_protocol_strings);
gpr_free(alpn_protocol_string_lengths);
diff --git a/src/core/lib/security/transport/security_connector.h b/src/core/lib/security/transport/security_connector.h
index dc02692b01..eba4e6d1d7 100644
--- a/src/core/lib/security/transport/security_connector.h
+++ b/src/core/lib/security/transport/security_connector.h
@@ -35,6 +35,8 @@
#define GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_CONNECTOR_H
#include <grpc/grpc_security.h>
+
+#include "src/core/lib/channel/handshaker.h"
#include "src/core/lib/iomgr/endpoint.h"
#include "src/core/lib/iomgr/tcp_server.h"
#include "src/core/lib/tsi/transport_security_interface.h"
@@ -57,21 +59,11 @@ typedef struct grpc_security_connector grpc_security_connector;
#define GRPC_SECURITY_CONNECTOR_ARG "grpc.security_connector"
-typedef void (*grpc_security_peer_check_cb)(grpc_exec_ctx *exec_ctx,
- void *user_data,
- grpc_security_status status,
- grpc_auth_context *auth_context);
-
-/* 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 *secure_endpoint, grpc_auth_context *auth_context);
-
typedef struct {
- void (*destroy)(grpc_security_connector *sc);
+ void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc);
void (*check_peer)(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc,
- tsi_peer peer, grpc_security_peer_check_cb cb,
- void *user_data);
+ tsi_peer peer, grpc_auth_context **auth_context,
+ grpc_closure *on_peer_checked);
} grpc_security_connector_vtable;
typedef struct grpc_security_connector_handshake_list {
@@ -89,29 +81,32 @@ struct grpc_security_connector {
#ifdef GRPC_SECURITY_CONNECTOR_REFCOUNT_DEBUG
#define GRPC_SECURITY_CONNECTOR_REF(p, r) \
grpc_security_connector_ref((p), __FILE__, __LINE__, (r))
-#define GRPC_SECURITY_CONNECTOR_UNREF(p, r) \
- grpc_security_connector_unref((p), __FILE__, __LINE__, (r))
+#define GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, p, r) \
+ grpc_security_connector_unref((exec_ctx), (p), __FILE__, __LINE__, (r))
grpc_security_connector *grpc_security_connector_ref(
grpc_security_connector *policy, const char *file, int line,
const char *reason);
-void grpc_security_connector_unref(grpc_security_connector *policy,
+void grpc_security_connector_unref(grpc_exec_ctx *exec_ctx,
+ grpc_security_connector *policy,
const char *file, int line,
const char *reason);
#else
#define GRPC_SECURITY_CONNECTOR_REF(p, r) grpc_security_connector_ref((p))
-#define GRPC_SECURITY_CONNECTOR_UNREF(p, r) grpc_security_connector_unref((p))
+#define GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, p, r) \
+ grpc_security_connector_unref((exec_ctx), (p))
grpc_security_connector *grpc_security_connector_ref(
grpc_security_connector *policy);
-void grpc_security_connector_unref(grpc_security_connector *policy);
+void grpc_security_connector_unref(grpc_exec_ctx *exec_ctx,
+ grpc_security_connector *policy);
#endif
/* Check the peer. Callee takes ownership of the peer object.
- The callback will include the resulting auth_context. */
+ When done, sets *auth_context and invokes on_peer_checked. */
void grpc_security_connector_check_peer(grpc_exec_ctx *exec_ctx,
grpc_security_connector *sc,
tsi_peer peer,
- grpc_security_peer_check_cb cb,
- void *user_data);
+ grpc_auth_context **auth_context,
+ grpc_closure *on_peer_checked);
/* Util to encapsulate the connector in a channel arg. */
grpc_arg grpc_security_connector_to_arg(grpc_security_connector *sc);
@@ -141,11 +136,9 @@ struct grpc_channel_security_connector {
grpc_channel_security_connector *sc, const char *host,
grpc_auth_context *auth_context,
grpc_security_call_host_check_cb cb, void *user_data);
- void (*do_handshake)(grpc_exec_ctx *exec_ctx,
- grpc_channel_security_connector *sc,
- grpc_endpoint *nonsecure_endpoint,
- grpc_slice_buffer *read_buffer, gpr_timespec deadline,
- grpc_security_handshake_done_cb cb, void *user_data);
+ void (*add_handshakers)(grpc_exec_ctx *exec_ctx,
+ grpc_channel_security_connector *sc,
+ grpc_handshake_manager *handshake_mgr);
};
/* Checks that the host that will be set for a call is acceptable. */
@@ -154,11 +147,10 @@ void grpc_channel_security_connector_check_call_host(
const char *host, grpc_auth_context *auth_context,
grpc_security_call_host_check_cb cb, void *user_data);
-/* Handshake. */
-void grpc_channel_security_connector_do_handshake(
+/* Registers handshakers with \a handshake_mgr. */
+void grpc_channel_security_connector_add_handshakers(
grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *connector,
- grpc_endpoint *nonsecure_endpoint, grpc_slice_buffer *read_buffer,
- gpr_timespec deadline, grpc_security_handshake_done_cb cb, void *user_data);
+ grpc_handshake_manager *handshake_mgr);
/* --- server_security_connector object. ---
@@ -169,25 +161,14 @@ typedef struct grpc_server_security_connector grpc_server_security_connector;
struct grpc_server_security_connector {
grpc_security_connector base;
- gpr_mu mu;
- grpc_security_connector_handshake_list *handshaking_handshakes;
- const grpc_channel_args *channel_args;
- void (*do_handshake)(grpc_exec_ctx *exec_ctx,
- grpc_server_security_connector *sc,
- grpc_tcp_server_acceptor *acceptor,
- grpc_endpoint *nonsecure_endpoint,
- grpc_slice_buffer *read_buffer, gpr_timespec deadline,
- grpc_security_handshake_done_cb cb, void *user_data);
+ void (*add_handshakers)(grpc_exec_ctx *exec_ctx,
+ grpc_server_security_connector *sc,
+ grpc_handshake_manager *handshake_mgr);
};
-void grpc_server_security_connector_do_handshake(
+void grpc_server_security_connector_add_handshakers(
grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc,
- grpc_tcp_server_acceptor *acceptor, grpc_endpoint *nonsecure_endpoint,
- grpc_slice_buffer *read_buffer, gpr_timespec deadline,
- grpc_security_handshake_done_cb cb, void *user_data);
-
-void grpc_server_security_connector_shutdown(
- grpc_exec_ctx *exec_ctx, grpc_server_security_connector *connector);
+ grpc_handshake_manager *handshake_mgr);
/* --- Creation security connectors. --- */
@@ -225,7 +206,7 @@ typedef struct {
specific error code otherwise.
*/
grpc_security_status grpc_ssl_channel_security_connector_create(
- grpc_call_credentials *request_metadata_creds,
+ grpc_exec_ctx *exec_ctx, grpc_call_credentials *request_metadata_creds,
const grpc_ssl_config *config, const char *target_name,
const char *overridden_target_name, grpc_channel_security_connector **sc);
@@ -254,7 +235,8 @@ typedef struct {
specific error code otherwise.
*/
grpc_security_status grpc_ssl_server_security_connector_create(
- const grpc_ssl_server_config *config, grpc_server_security_connector **sc);
+ grpc_exec_ctx *exec_ctx, const grpc_ssl_server_config *config,
+ grpc_server_security_connector **sc);
/* Util. */
const tsi_peer_property *tsi_peer_get_property_by_name(const tsi_peer *peer,
diff --git a/src/core/lib/security/transport/security_handshaker.c b/src/core/lib/security/transport/security_handshaker.c
new file mode 100644
index 0000000000..5e75856c7a
--- /dev/null
+++ b/src/core/lib/security/transport/security_handshaker.c
@@ -0,0 +1,501 @@
+/*
+ *
+ * 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/lib/security/transport/security_handshaker.h"
+
+#include <stdbool.h>
+#include <string.h>
+
+#include <grpc/slice_buffer.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/channel/handshaker.h"
+#include "src/core/lib/channel/handshaker_registry.h"
+#include "src/core/lib/security/context/security_context.h"
+#include "src/core/lib/security/transport/secure_endpoint.h"
+#include "src/core/lib/security/transport/tsi_error.h"
+#include "src/core/lib/slice/slice_internal.h"
+
+#define GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE 256
+
+typedef struct {
+ grpc_handshaker base;
+
+ // State set at creation time.
+ tsi_handshaker *handshaker;
+ grpc_security_connector *connector;
+
+ gpr_mu mu;
+ gpr_refcount refs;
+
+ bool shutdown;
+ // Endpoint and read buffer to destroy after a shutdown.
+ grpc_endpoint *endpoint_to_destroy;
+ grpc_slice_buffer *read_buffer_to_destroy;
+
+ // State saved while performing the handshake.
+ grpc_handshaker_args *args;
+ grpc_closure *on_handshake_done;
+
+ unsigned char *handshake_buffer;
+ size_t handshake_buffer_size;
+ grpc_slice_buffer left_overs;
+ grpc_slice_buffer outgoing;
+ grpc_closure on_handshake_data_sent_to_peer;
+ grpc_closure on_handshake_data_received_from_peer;
+ grpc_closure on_peer_checked;
+ grpc_auth_context *auth_context;
+} security_handshaker;
+
+static void security_handshaker_unref(grpc_exec_ctx *exec_ctx,
+ security_handshaker *h) {
+ if (gpr_unref(&h->refs)) {
+ gpr_mu_destroy(&h->mu);
+ tsi_handshaker_destroy(h->handshaker);
+ if (h->endpoint_to_destroy != NULL) {
+ grpc_endpoint_destroy(exec_ctx, h->endpoint_to_destroy);
+ }
+ if (h->read_buffer_to_destroy != NULL) {
+ grpc_slice_buffer_destroy_internal(exec_ctx, h->read_buffer_to_destroy);
+ gpr_free(h->read_buffer_to_destroy);
+ }
+ gpr_free(h->handshake_buffer);
+ grpc_slice_buffer_destroy_internal(exec_ctx, &h->left_overs);
+ grpc_slice_buffer_destroy_internal(exec_ctx, &h->outgoing);
+ GRPC_AUTH_CONTEXT_UNREF(h->auth_context, "handshake");
+ GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, h->connector, "handshake");
+ gpr_free(h);
+ }
+}
+
+// Set args fields to NULL, saving the endpoint and read buffer for
+// later destruction.
+static void cleanup_args_for_failure_locked(grpc_exec_ctx *exec_ctx,
+ security_handshaker *h) {
+ h->endpoint_to_destroy = h->args->endpoint;
+ h->args->endpoint = NULL;
+ h->read_buffer_to_destroy = h->args->read_buffer;
+ h->args->read_buffer = NULL;
+ grpc_channel_args_destroy(exec_ctx, h->args->args);
+ h->args->args = NULL;
+}
+
+// If the handshake failed or we're shutting down, clean up and invoke the
+// callback with the error.
+static void security_handshake_failed_locked(grpc_exec_ctx *exec_ctx,
+ security_handshaker *h,
+ grpc_error *error) {
+ if (error == GRPC_ERROR_NONE) {
+ // If we were shut down after the handshake succeeded but before an
+ // endpoint callback was invoked, we need to generate our own error.
+ error = GRPC_ERROR_CREATE("Handshaker shutdown");
+ }
+ const char *msg = grpc_error_string(error);
+ gpr_log(GPR_DEBUG, "Security handshake failed: %s", msg);
+ grpc_error_free_string(msg);
+ if (!h->shutdown) {
+ // TODO(ctiller): It is currently necessary to shutdown endpoints
+ // before destroying them, even if we know that there are no
+ // pending read/write callbacks. This should be fixed, at which
+ // point this can be removed.
+ grpc_endpoint_shutdown(exec_ctx, h->args->endpoint);
+ // Not shutting down, so the write failed. Clean up before
+ // invoking the callback.
+ cleanup_args_for_failure_locked(exec_ctx, h);
+ // Set shutdown to true so that subsequent calls to
+ // security_handshaker_shutdown() do nothing.
+ h->shutdown = true;
+ }
+ // Invoke callback.
+ grpc_closure_sched(exec_ctx, h->on_handshake_done, error);
+}
+
+static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
+ security_handshaker *h = arg;
+ gpr_mu_lock(&h->mu);
+ if (error != GRPC_ERROR_NONE || h->shutdown) {
+ security_handshake_failed_locked(exec_ctx, h, GRPC_ERROR_REF(error));
+ goto done;
+ }
+ // Get frame protector.
+ tsi_frame_protector *protector;
+ tsi_result result =
+ tsi_handshaker_create_frame_protector(h->handshaker, NULL, &protector);
+ if (result != TSI_OK) {
+ error = grpc_set_tsi_error_result(
+ GRPC_ERROR_CREATE("Frame protector creation failed"), result);
+ security_handshake_failed_locked(exec_ctx, h, error);
+ goto done;
+ }
+ // Success.
+ // Create secure endpoint.
+ h->args->endpoint = grpc_secure_endpoint_create(
+ protector, h->args->endpoint, h->left_overs.slices, h->left_overs.count);
+ h->left_overs.count = 0;
+ h->left_overs.length = 0;
+ // Clear out the read buffer before it gets passed to the transport,
+ // since any excess bytes were already copied to h->left_overs.
+ grpc_slice_buffer_reset_and_unref_internal(exec_ctx, h->args->read_buffer);
+ // Add auth context to channel args.
+ grpc_arg auth_context_arg = grpc_auth_context_to_arg(h->auth_context);
+ grpc_channel_args *tmp_args = h->args->args;
+ h->args->args =
+ grpc_channel_args_copy_and_add(tmp_args, &auth_context_arg, 1);
+ grpc_channel_args_destroy(exec_ctx, tmp_args);
+ // Invoke callback.
+ grpc_closure_sched(exec_ctx, h->on_handshake_done, GRPC_ERROR_NONE);
+ // Set shutdown to true so that subsequent calls to
+ // security_handshaker_shutdown() do nothing.
+ h->shutdown = true;
+done:
+ gpr_mu_unlock(&h->mu);
+ security_handshaker_unref(exec_ctx, h);
+}
+
+static grpc_error *check_peer_locked(grpc_exec_ctx *exec_ctx,
+ security_handshaker *h) {
+ tsi_peer peer;
+ tsi_result result = tsi_handshaker_extract_peer(h->handshaker, &peer);
+ if (result != TSI_OK) {
+ return grpc_set_tsi_error_result(
+ GRPC_ERROR_CREATE("Peer extraction failed"), result);
+ }
+ grpc_security_connector_check_peer(exec_ctx, h->connector, peer,
+ &h->auth_context, &h->on_peer_checked);
+ return GRPC_ERROR_NONE;
+}
+
+static grpc_error *send_handshake_bytes_to_peer_locked(grpc_exec_ctx *exec_ctx,
+ security_handshaker *h) {
+ // Get data to send.
+ tsi_result result = TSI_OK;
+ size_t offset = 0;
+ 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) {
+ return grpc_set_tsi_error_result(GRPC_ERROR_CREATE("Handshake failed"),
+ result);
+ }
+ // Send data.
+ grpc_slice to_send =
+ grpc_slice_from_copied_buffer((const char *)h->handshake_buffer, offset);
+ grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &h->outgoing);
+ grpc_slice_buffer_add(&h->outgoing, to_send);
+ grpc_endpoint_write(exec_ctx, h->args->endpoint, &h->outgoing,
+ &h->on_handshake_data_sent_to_peer);
+ return GRPC_ERROR_NONE;
+}
+
+static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
+ void *arg, grpc_error *error) {
+ security_handshaker *h = arg;
+ gpr_mu_lock(&h->mu);
+ if (error != GRPC_ERROR_NONE || h->shutdown) {
+ security_handshake_failed_locked(
+ exec_ctx, h,
+ GRPC_ERROR_CREATE_REFERENCING("Handshake read failed", &error, 1));
+ gpr_mu_unlock(&h->mu);
+ security_handshaker_unref(exec_ctx, h);
+ return;
+ }
+ // Process received data.
+ tsi_result result = TSI_OK;
+ size_t consumed_slice_size = 0;
+ size_t i;
+ for (i = 0; i < h->args->read_buffer->count; i++) {
+ consumed_slice_size = GRPC_SLICE_LENGTH(h->args->read_buffer->slices[i]);
+ result = tsi_handshaker_process_bytes_from_peer(
+ h->handshaker, GRPC_SLICE_START_PTR(h->args->read_buffer->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->args->endpoint, h->args->read_buffer,
+ &h->on_handshake_data_received_from_peer);
+ goto done;
+ } else {
+ error = send_handshake_bytes_to_peer_locked(exec_ctx, h);
+ if (error != GRPC_ERROR_NONE) {
+ security_handshake_failed_locked(exec_ctx, h, error);
+ gpr_mu_unlock(&h->mu);
+ security_handshaker_unref(exec_ctx, h);
+ return;
+ }
+ goto done;
+ }
+ }
+ if (result != TSI_OK) {
+ security_handshake_failed_locked(
+ exec_ctx, h, grpc_set_tsi_error_result(
+ GRPC_ERROR_CREATE("Handshake failed"), result));
+ gpr_mu_unlock(&h->mu);
+ security_handshaker_unref(exec_ctx, h);
+ return;
+ }
+ /* Handshake is done and successful this point. */
+ bool has_left_overs_in_current_slice =
+ (consumed_slice_size <
+ GRPC_SLICE_LENGTH(h->args->read_buffer->slices[i]));
+ size_t num_left_overs = (has_left_overs_in_current_slice ? 1 : 0) +
+ h->args->read_buffer->count - i - 1;
+ if (num_left_overs > 0) {
+ /* Put the leftovers in our buffer (ownership transfered). */
+ if (has_left_overs_in_current_slice) {
+ grpc_slice_buffer_add(
+ &h->left_overs,
+ grpc_slice_split_tail(&h->args->read_buffer->slices[i],
+ consumed_slice_size));
+ /* split_tail above increments refcount. */
+ grpc_slice_unref_internal(exec_ctx, h->args->read_buffer->slices[i]);
+ }
+ grpc_slice_buffer_addn(
+ &h->left_overs, &h->args->read_buffer->slices[i + 1],
+ num_left_overs - (size_t)has_left_overs_in_current_slice);
+ }
+ // Check peer.
+ error = check_peer_locked(exec_ctx, h);
+ if (error != GRPC_ERROR_NONE) {
+ security_handshake_failed_locked(exec_ctx, h, error);
+ gpr_mu_unlock(&h->mu);
+ security_handshaker_unref(exec_ctx, h);
+ return;
+ }
+done:
+ gpr_mu_unlock(&h->mu);
+}
+
+static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
+ security_handshaker *h = arg;
+ gpr_mu_lock(&h->mu);
+ if (error != GRPC_ERROR_NONE || h->shutdown) {
+ security_handshake_failed_locked(
+ exec_ctx, h,
+ GRPC_ERROR_CREATE_REFERENCING("Handshake write failed", &error, 1));
+ gpr_mu_unlock(&h->mu);
+ security_handshaker_unref(exec_ctx, h);
+ return;
+ }
+ /* We may be done. */
+ if (tsi_handshaker_is_in_progress(h->handshaker)) {
+ grpc_endpoint_read(exec_ctx, h->args->endpoint, h->args->read_buffer,
+ &h->on_handshake_data_received_from_peer);
+ } else {
+ error = check_peer_locked(exec_ctx, h);
+ if (error != GRPC_ERROR_NONE) {
+ security_handshake_failed_locked(exec_ctx, h, error);
+ gpr_mu_unlock(&h->mu);
+ security_handshaker_unref(exec_ctx, h);
+ return;
+ }
+ }
+ gpr_mu_unlock(&h->mu);
+}
+
+//
+// public handshaker API
+//
+
+static void security_handshaker_destroy(grpc_exec_ctx *exec_ctx,
+ grpc_handshaker *handshaker) {
+ security_handshaker *h = (security_handshaker *)handshaker;
+ security_handshaker_unref(exec_ctx, h);
+}
+
+static void security_handshaker_shutdown(grpc_exec_ctx *exec_ctx,
+ grpc_handshaker *handshaker) {
+ security_handshaker *h = (security_handshaker *)handshaker;
+ gpr_mu_lock(&h->mu);
+ if (!h->shutdown) {
+ h->shutdown = true;
+ grpc_endpoint_shutdown(exec_ctx, h->args->endpoint);
+ cleanup_args_for_failure_locked(exec_ctx, h);
+ }
+ gpr_mu_unlock(&h->mu);
+}
+
+static void security_handshaker_do_handshake(grpc_exec_ctx *exec_ctx,
+ grpc_handshaker *handshaker,
+ grpc_tcp_server_acceptor *acceptor,
+ grpc_closure *on_handshake_done,
+ grpc_handshaker_args *args) {
+ security_handshaker *h = (security_handshaker *)handshaker;
+ gpr_mu_lock(&h->mu);
+ h->args = args;
+ h->on_handshake_done = on_handshake_done;
+ gpr_ref(&h->refs);
+ grpc_error *error = send_handshake_bytes_to_peer_locked(exec_ctx, h);
+ if (error != GRPC_ERROR_NONE) {
+ security_handshake_failed_locked(exec_ctx, h, error);
+ gpr_mu_unlock(&h->mu);
+ security_handshaker_unref(exec_ctx, h);
+ return;
+ }
+ gpr_mu_unlock(&h->mu);
+}
+
+static const grpc_handshaker_vtable security_handshaker_vtable = {
+ security_handshaker_destroy, security_handshaker_shutdown,
+ security_handshaker_do_handshake};
+
+static grpc_handshaker *security_handshaker_create(
+ grpc_exec_ctx *exec_ctx, tsi_handshaker *handshaker,
+ grpc_security_connector *connector) {
+ security_handshaker *h = gpr_malloc(sizeof(security_handshaker));
+ memset(h, 0, sizeof(security_handshaker));
+ grpc_handshaker_init(&security_handshaker_vtable, &h->base);
+ h->handshaker = handshaker;
+ h->connector = GRPC_SECURITY_CONNECTOR_REF(connector, "handshake");
+ gpr_mu_init(&h->mu);
+ gpr_ref_init(&h->refs, 1);
+ h->handshake_buffer_size = GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE;
+ h->handshake_buffer = gpr_malloc(h->handshake_buffer_size);
+ grpc_closure_init(&h->on_handshake_data_sent_to_peer,
+ on_handshake_data_sent_to_peer, h,
+ grpc_schedule_on_exec_ctx);
+ grpc_closure_init(&h->on_handshake_data_received_from_peer,
+ on_handshake_data_received_from_peer, h,
+ grpc_schedule_on_exec_ctx);
+ grpc_closure_init(&h->on_peer_checked, on_peer_checked, h,
+ grpc_schedule_on_exec_ctx);
+ grpc_slice_buffer_init(&h->left_overs);
+ grpc_slice_buffer_init(&h->outgoing);
+ return &h->base;
+}
+
+//
+// fail_handshaker
+//
+
+static void fail_handshaker_destroy(grpc_exec_ctx *exec_ctx,
+ grpc_handshaker *handshaker) {
+ gpr_free(handshaker);
+}
+
+static void fail_handshaker_shutdown(grpc_exec_ctx *exec_ctx,
+ grpc_handshaker *handshaker) {}
+
+static void fail_handshaker_do_handshake(grpc_exec_ctx *exec_ctx,
+ grpc_handshaker *handshaker,
+ grpc_tcp_server_acceptor *acceptor,
+ grpc_closure *on_handshake_done,
+ grpc_handshaker_args *args) {
+ grpc_closure_sched(exec_ctx, on_handshake_done,
+ GRPC_ERROR_CREATE("Failed to create security handshaker"));
+}
+
+static const grpc_handshaker_vtable fail_handshaker_vtable = {
+ fail_handshaker_destroy, fail_handshaker_shutdown,
+ fail_handshaker_do_handshake};
+
+static grpc_handshaker *fail_handshaker_create() {
+ grpc_handshaker *h = gpr_malloc(sizeof(*h));
+ grpc_handshaker_init(&fail_handshaker_vtable, h);
+ return h;
+}
+
+//
+// handshaker factories
+//
+
+static void client_handshaker_factory_add_handshakers(
+ grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *handshaker_factory,
+ const grpc_channel_args *args, grpc_handshake_manager *handshake_mgr) {
+ grpc_channel_security_connector *security_connector =
+ (grpc_channel_security_connector *)grpc_find_security_connector_in_args(
+ args);
+ grpc_channel_security_connector_add_handshakers(exec_ctx, security_connector,
+ handshake_mgr);
+}
+
+static void server_handshaker_factory_add_handshakers(
+ grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *hf,
+ const grpc_channel_args *args, grpc_handshake_manager *handshake_mgr) {
+ grpc_server_security_connector *security_connector =
+ (grpc_server_security_connector *)grpc_find_security_connector_in_args(
+ args);
+ grpc_server_security_connector_add_handshakers(exec_ctx, security_connector,
+ handshake_mgr);
+}
+
+static void handshaker_factory_destroy(
+ grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *handshaker_factory) {}
+
+static const grpc_handshaker_factory_vtable client_handshaker_factory_vtable = {
+ client_handshaker_factory_add_handshakers, handshaker_factory_destroy};
+
+static grpc_handshaker_factory client_handshaker_factory = {
+ &client_handshaker_factory_vtable};
+
+static const grpc_handshaker_factory_vtable server_handshaker_factory_vtable = {
+ server_handshaker_factory_add_handshakers, handshaker_factory_destroy};
+
+static grpc_handshaker_factory server_handshaker_factory = {
+ &server_handshaker_factory_vtable};
+
+//
+// exported functions
+//
+
+grpc_handshaker *grpc_security_handshaker_create(
+ grpc_exec_ctx *exec_ctx, tsi_handshaker *handshaker,
+ grpc_security_connector *connector) {
+ // If no TSI handshaker was created, return a handshaker that always fails.
+ // Otherwise, return a real security handshaker.
+ if (handshaker == NULL) {
+ return fail_handshaker_create();
+ } else {
+ return security_handshaker_create(exec_ctx, handshaker, connector);
+ }
+}
+
+void grpc_security_register_handshaker_factories() {
+ grpc_handshaker_factory_register(false /* at_start */, HANDSHAKER_CLIENT,
+ &client_handshaker_factory);
+ grpc_handshaker_factory_register(false /* at_start */, HANDSHAKER_SERVER,
+ &server_handshaker_factory);
+}
diff --git a/src/core/lib/security/transport/handshake.h b/src/core/lib/security/transport/security_handshaker.h
index f894540515..0b9eda178f 100644
--- a/src/core/lib/security/transport/handshake.h
+++ b/src/core/lib/security/transport/security_handshaker.h
@@ -31,20 +31,19 @@
*
*/
-#ifndef GRPC_CORE_LIB_SECURITY_TRANSPORT_HANDSHAKE_H
-#define GRPC_CORE_LIB_SECURITY_TRANSPORT_HANDSHAKE_H
+#ifndef GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_HANDSHAKER_H
+#define GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_HANDSHAKER_H
-#include "src/core/lib/iomgr/endpoint.h"
+#include "src/core/lib/channel/handshaker.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/security/transport/security_connector.h"
-/* Calls the callback upon completion. Takes owership of handshaker and
- * read_buffer. */
-void grpc_do_security_handshake(
+/// Creates a security handshaker using \a handshaker.
+grpc_handshaker *grpc_security_handshaker_create(
grpc_exec_ctx *exec_ctx, tsi_handshaker *handshaker,
- grpc_security_connector *connector, bool is_client_side,
- grpc_endpoint *nonsecure_endpoint, grpc_slice_buffer *read_buffer,
- gpr_timespec deadline, grpc_security_handshake_done_cb cb, void *user_data);
+ grpc_security_connector *connector);
-void grpc_security_handshake_shutdown(grpc_exec_ctx *exec_ctx, void *handshake);
+/// Registers security handshaker factories.
+void grpc_security_register_handshaker_factories();
-#endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_HANDSHAKE_H */
+#endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_HANDSHAKER_H */
diff --git a/src/core/lib/security/transport/server_auth_filter.c b/src/core/lib/security/transport/server_auth_filter.c
index eaa1d0720b..5e98ba895d 100644
--- a/src/core/lib/security/transport/server_auth_filter.c
+++ b/src/core/lib/security/transport/server_auth_filter.c
@@ -83,7 +83,8 @@ static grpc_metadata_array metadata_batch_to_md_array(
return result;
}
-static grpc_mdelem *remove_consumed_md(void *user_data, grpc_mdelem *md) {
+static grpc_mdelem *remove_consumed_md(grpc_exec_ctx *exec_ctx, void *user_data,
+ grpc_mdelem *md) {
grpc_call_element *elem = user_data;
call_data *calld = elem->call_data;
size_t i;
@@ -129,10 +130,10 @@ static void on_md_processing_done(
if (status == GRPC_STATUS_OK) {
calld->consumed_md = consumed_md;
calld->num_consumed_md = num_consumed_md;
- grpc_metadata_batch_filter(calld->recv_initial_metadata, remove_consumed_md,
- elem);
+ grpc_metadata_batch_filter(&exec_ctx, calld->recv_initial_metadata,
+ remove_consumed_md, elem);
grpc_metadata_array_destroy(&calld->md);
- grpc_exec_ctx_sched(&exec_ctx, calld->on_done_recv, GRPC_ERROR_NONE, NULL);
+ grpc_closure_sched(&exec_ctx, calld->on_done_recv, GRPC_ERROR_NONE);
} else {
grpc_slice message;
grpc_transport_stream_op *close_op = gpr_malloc(sizeof(*close_op));
@@ -148,13 +149,13 @@ static void on_md_processing_done(
calld->transport_op->send_message = NULL;
}
calld->transport_op->send_trailing_metadata = NULL;
- close_op->on_complete = grpc_closure_create(destroy_op, close_op);
- grpc_transport_stream_op_add_close(close_op, status, &message);
+ close_op->on_complete =
+ grpc_closure_create(destroy_op, close_op, grpc_schedule_on_exec_ctx);
+ grpc_transport_stream_op_add_close(&exec_ctx, close_op, status, &message);
grpc_call_next_op(&exec_ctx, elem, close_op);
- grpc_exec_ctx_sched(&exec_ctx, calld->on_done_recv,
- grpc_error_set_int(GRPC_ERROR_CREATE(error_details),
- GRPC_ERROR_INT_GRPC_STATUS, status),
- NULL);
+ grpc_closure_sched(&exec_ctx, calld->on_done_recv,
+ grpc_error_set_int(GRPC_ERROR_CREATE(error_details),
+ GRPC_ERROR_INT_GRPC_STATUS, status));
}
grpc_exec_ctx_finish(&exec_ctx);
@@ -174,8 +175,7 @@ static void auth_on_recv(grpc_exec_ctx *exec_ctx, void *user_data,
return;
}
}
- grpc_exec_ctx_sched(exec_ctx, calld->on_done_recv, GRPC_ERROR_REF(error),
- NULL);
+ grpc_closure_sched(exec_ctx, calld->on_done_recv, GRPC_ERROR_REF(error));
}
static void set_recv_ops_md_callbacks(grpc_call_element *elem,
@@ -214,7 +214,8 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
/* initialize members */
memset(calld, 0, sizeof(*calld));
- grpc_closure_init(&calld->auth_on_recv, auth_on_recv, elem);
+ grpc_closure_init(&calld->auth_on_recv, auth_on_recv, elem,
+ grpc_schedule_on_exec_ctx);
if (args->context[GRPC_CONTEXT_SECURITY].value != NULL) {
args->context[GRPC_CONTEXT_SECURITY].destroy(
@@ -238,9 +239,9 @@ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
void *ignored) {}
/* Constructor for channel_data */
-static void init_channel_elem(grpc_exec_ctx *exec_ctx,
- grpc_channel_element *elem,
- grpc_channel_element_args *args) {
+static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx,
+ grpc_channel_element *elem,
+ grpc_channel_element_args *args) {
grpc_auth_context *auth_context =
grpc_find_auth_context_in_args(args->channel_args);
grpc_server_credentials *creds =
@@ -256,6 +257,7 @@ static void init_channel_elem(grpc_exec_ctx *exec_ctx,
chand->auth_context =
GRPC_AUTH_CONTEXT_REF(auth_context, "server_auth_filter");
chand->creds = grpc_server_credentials_ref(creds);
+ return GRPC_ERROR_NONE;
}
/* Destructor for channel data */
@@ -264,7 +266,7 @@ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
/* grab pointers to our data from the channel element */
channel_data *chand = elem->channel_data;
GRPC_AUTH_CONTEXT_UNREF(chand->auth_context, "server_auth_filter");
- grpc_server_credentials_unref(chand->creds);
+ grpc_server_credentials_unref(exec_ctx, chand->creds);
}
const grpc_channel_filter grpc_server_auth_filter = {
diff --git a/src/core/lib/security/util/b64.c b/src/core/lib/security/util/b64.c
index 4892e8e621..bbd7e335a6 100644
--- a/src/core/lib/security/util/b64.c
+++ b/src/core/lib/security/util/b64.c
@@ -40,6 +40,8 @@
#include <grpc/support/log.h>
#include <grpc/support/useful.h>
+#include "src/core/lib/slice/slice_internal.h"
+
/* --- Constants. --- */
static const int8_t base64_bytes[] = {
@@ -120,8 +122,9 @@ char *grpc_base64_encode(const void *vdata, size_t data_size, int url_safe,
return result;
}
-grpc_slice grpc_base64_decode(const char *b64, int url_safe) {
- return grpc_base64_decode_with_len(b64, strlen(b64), url_safe);
+grpc_slice grpc_base64_decode(grpc_exec_ctx *exec_ctx, const char *b64,
+ int url_safe) {
+ return grpc_base64_decode_with_len(exec_ctx, b64, strlen(b64), url_safe);
}
static void decode_one_char(const unsigned char *codes, unsigned char *result,
@@ -182,8 +185,8 @@ static int decode_group(const unsigned char *codes, size_t num_codes,
return 1;
}
-grpc_slice grpc_base64_decode_with_len(const char *b64, size_t b64_len,
- int url_safe) {
+grpc_slice grpc_base64_decode_with_len(grpc_exec_ctx *exec_ctx, const char *b64,
+ size_t b64_len, int url_safe) {
grpc_slice result = grpc_slice_malloc(b64_len);
unsigned char *current = GRPC_SLICE_START_PTR(result);
size_t result_size = 0;
@@ -228,6 +231,6 @@ grpc_slice grpc_base64_decode_with_len(const char *b64, size_t b64_len,
return result;
fail:
- grpc_slice_unref(result);
+ grpc_slice_unref_internal(exec_ctx, result);
return gpr_empty_slice();
}
diff --git a/src/core/lib/security/util/b64.h b/src/core/lib/security/util/b64.h
index 6ea0b5365b..d42a136f61 100644
--- a/src/core/lib/security/util/b64.h
+++ b/src/core/lib/security/util/b64.h
@@ -43,10 +43,11 @@ char *grpc_base64_encode(const void *data, size_t data_size, int url_safe,
/* Decodes data according to the base64 specification. Returns an empty
slice in case of failure. */
-grpc_slice grpc_base64_decode(const char *b64, int url_safe);
+grpc_slice grpc_base64_decode(grpc_exec_ctx *exec_ctx, const char *b64,
+ int url_safe);
/* Same as above except that the length is provided by the caller. */
-grpc_slice grpc_base64_decode_with_len(const char *b64, size_t b64_len,
- int url_safe);
+grpc_slice grpc_base64_decode_with_len(grpc_exec_ctx *exec_ctx, const char *b64,
+ size_t b64_len, int url_safe);
#endif /* GRPC_CORE_LIB_SECURITY_UTIL_B64_H */