aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/security
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/security')
-rw-r--r--src/core/security/base64.c10
-rw-r--r--src/core/security/client_auth_filter.c3
-rw-r--r--src/core/security/credentials.c222
-rw-r--r--src/core/security/credentials.h29
-rw-r--r--src/core/security/google_default_credentials.c8
-rw-r--r--src/core/security/handshake.c122
-rw-r--r--src/core/security/jwt_verifier.c12
-rw-r--r--src/core/security/secure_endpoint.c188
-rw-r--r--src/core/security/security_connector.c20
-rw-r--r--src/core/security/security_context.c13
-rw-r--r--src/core/security/server_auth_filter.c47
-rw-r--r--src/core/security/server_secure_chttp2.c9
12 files changed, 348 insertions, 335 deletions
diff --git a/src/core/security/base64.c b/src/core/security/base64.c
index 8dfaef846f..5226d2c578 100644
--- a/src/core/security/base64.c
+++ b/src/core/security/base64.c
@@ -125,13 +125,14 @@ gpr_slice grpc_base64_decode(const char *b64, int url_safe) {
static void decode_one_char(const unsigned char *codes, unsigned char *result,
size_t *result_offset) {
- gpr_uint32 packed = (codes[0] << 2) | (codes[1] >> 4);
+ gpr_uint32 packed = ((gpr_uint32)codes[0] << 2) | ((gpr_uint32)codes[1] >> 4);
result[(*result_offset)++] = (unsigned char)packed;
}
static void decode_two_chars(const unsigned char *codes, unsigned char *result,
size_t *result_offset) {
- gpr_uint32 packed = (codes[0] << 10) | (codes[1] << 4) | (codes[2] >> 2);
+ gpr_uint32 packed = ((gpr_uint32)codes[0] << 10) |
+ ((gpr_uint32)codes[1] << 4) | ((gpr_uint32)codes[2] >> 2);
result[(*result_offset)++] = (unsigned char)(packed >> 8);
result[(*result_offset)++] = (unsigned char)(packed);
}
@@ -171,8 +172,9 @@ static int decode_group(const unsigned char *codes, size_t num_codes,
decode_two_chars(codes, result, result_offset);
} else {
/* No padding. */
- gpr_uint32 packed =
- (codes[0] << 18) | (codes[1] << 12) | (codes[2] << 6) | codes[3];
+ gpr_uint32 packed = ((gpr_uint32)codes[0] << 18) |
+ ((gpr_uint32)codes[1] << 12) |
+ ((gpr_uint32)codes[2] << 6) | codes[3];
result[(*result_offset)++] = (unsigned char)(packed >> 16);
result[(*result_offset)++] = (unsigned char)(packed >> 8);
result[(*result_offset)++] = (unsigned char)(packed);
diff --git a/src/core/security/client_auth_filter.c b/src/core/security/client_auth_filter.c
index 8e63978b82..f3ecfd0e60 100644
--- a/src/core/security/client_auth_filter.c
+++ b/src/core/security/client_auth_filter.c
@@ -153,7 +153,8 @@ static void send_security_metadata(grpc_call_element *elem,
}
if (channel_creds_has_md && call_creds_has_md) {
- calld->creds = grpc_composite_credentials_create(channel_creds, ctx->creds);
+ calld->creds =
+ grpc_composite_credentials_create(channel_creds, ctx->creds, NULL);
if (calld->creds == NULL) {
bubble_up_error(elem, GRPC_STATUS_INVALID_ARGUMENT,
"Incompatible credentials set on channel and call.");
diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c
index 8852cab3e7..a764413300 100644
--- a/src/core/security/credentials.c
+++ b/src/core/security/credentials.c
@@ -87,7 +87,10 @@ grpc_credentials *grpc_credentials_ref(grpc_credentials *creds) {
void grpc_credentials_unref(grpc_credentials *creds) {
if (creds == NULL) return;
- if (gpr_unref(&creds->refcount)) creds->vtable->destroy(creds);
+ if (gpr_unref(&creds->refcount)) {
+ creds->vtable->destruct(creds);
+ gpr_free(creds);
+ }
}
void grpc_credentials_release(grpc_credentials *creds) {
@@ -135,9 +138,26 @@ grpc_security_status grpc_credentials_create_security_connector(
creds, target, args, request_metadata_creds, sc, new_args);
}
-void grpc_server_credentials_release(grpc_server_credentials *creds) {
+grpc_server_credentials *grpc_server_credentials_ref(
+ grpc_server_credentials *creds) {
+ if (creds == NULL) return NULL;
+ gpr_ref(&creds->refcount);
+ return creds;
+}
+
+void grpc_server_credentials_unref(grpc_server_credentials *creds) {
if (creds == NULL) return;
- creds->vtable->destroy(creds);
+ if (gpr_unref(&creds->refcount)) {
+ creds->vtable->destruct(creds);
+ if (creds->processor.destroy != NULL && creds->processor.state != NULL) {
+ creds->processor.destroy(creds->processor.state);
+ }
+ gpr_free(creds);
+ }
+}
+
+void grpc_server_credentials_release(grpc_server_credentials *creds) {
+ grpc_server_credentials_unref(creds);
}
grpc_security_status grpc_server_credentials_create_security_connector(
@@ -152,20 +172,22 @@ grpc_security_status grpc_server_credentials_create_security_connector(
void grpc_server_credentials_set_auth_metadata_processor(
grpc_server_credentials *creds, grpc_auth_metadata_processor processor) {
if (creds == NULL) return;
+ if (creds->processor.destroy != NULL && creds->processor.state != NULL) {
+ creds->processor.destroy(creds->processor.state);
+ }
creds->processor = processor;
}
/* -- Ssl credentials. -- */
-static void ssl_destroy(grpc_credentials *creds) {
+static void ssl_destruct(grpc_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);
if (c->config.pem_cert_chain != NULL) gpr_free(c->config.pem_cert_chain);
- gpr_free(creds);
}
-static void ssl_server_destroy(grpc_server_credentials *creds) {
+static void ssl_server_destruct(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++) {
@@ -185,7 +207,6 @@ static void ssl_server_destroy(grpc_server_credentials *creds) {
gpr_free(c->config.pem_cert_chains_sizes);
}
if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
- gpr_free(creds);
}
static int ssl_has_request_metadata(const grpc_credentials *creds) { return 0; }
@@ -231,11 +252,11 @@ static grpc_security_status ssl_server_create_security_connector(
}
static grpc_credentials_vtable ssl_vtable = {
- ssl_destroy, ssl_has_request_metadata, ssl_has_request_metadata_only, NULL,
+ ssl_destruct, ssl_has_request_metadata, ssl_has_request_metadata_only, NULL,
ssl_create_security_connector};
static grpc_server_credentials_vtable ssl_server_vtable = {
- ssl_server_destroy, ssl_server_create_security_connector};
+ ssl_server_destruct, ssl_server_create_security_connector};
static void ssl_copy_key_material(const char *input, unsigned char **output,
size_t *output_size) {
@@ -298,8 +319,10 @@ static void ssl_build_server_config(
}
grpc_credentials *grpc_ssl_credentials_create(
- const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair) {
+ const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
+ void *reserved) {
grpc_ssl_credentials *c = gpr_malloc(sizeof(grpc_ssl_credentials));
+ GPR_ASSERT(reserved == NULL);
memset(c, 0, sizeof(grpc_ssl_credentials));
c->base.type = GRPC_CREDENTIALS_TYPE_SSL;
c->base.vtable = &ssl_vtable;
@@ -310,11 +333,13 @@ grpc_credentials *grpc_ssl_credentials_create(
grpc_server_credentials *grpc_ssl_server_credentials_create(
const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
- size_t num_key_cert_pairs, int force_client_auth) {
+ size_t num_key_cert_pairs, int force_client_auth, void *reserved) {
grpc_ssl_server_credentials *c =
gpr_malloc(sizeof(grpc_ssl_server_credentials));
+ GPR_ASSERT(reserved == NULL);
memset(c, 0, sizeof(grpc_ssl_server_credentials));
c->base.type = GRPC_CREDENTIALS_TYPE_SSL;
+ gpr_ref_init(&c->base.refcount, 1);
c->base.vtable = &ssl_server_vtable;
ssl_build_server_config(pem_root_certs, pem_key_cert_pairs,
num_key_cert_pairs, force_client_auth, &c->config);
@@ -335,13 +360,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_destroy(grpc_credentials *creds) {
+static void jwt_destruct(grpc_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);
gpr_mu_destroy(&c->cache_mu);
- gpr_free(c);
}
static int jwt_has_request_metadata(const grpc_credentials *creds) { return 1; }
@@ -406,7 +430,7 @@ static void jwt_get_request_metadata(grpc_credentials *creds,
}
static grpc_credentials_vtable jwt_vtable = {
- jwt_destroy, jwt_has_request_metadata, jwt_has_request_metadata_only,
+ jwt_destruct, jwt_has_request_metadata, jwt_has_request_metadata_only,
jwt_get_request_metadata, NULL};
grpc_credentials *
@@ -430,20 +454,20 @@ grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
}
grpc_credentials *grpc_service_account_jwt_access_credentials_create(
- const char *json_key, gpr_timespec token_lifetime) {
+ const char *json_key, gpr_timespec token_lifetime, void *reserved) {
+ GPR_ASSERT(reserved == NULL);
return grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
grpc_auth_json_key_create_from_string(json_key), token_lifetime);
}
/* -- Oauth2TokenFetcher credentials -- */
-static void oauth2_token_fetcher_destroy(grpc_credentials *creds) {
+static void oauth2_token_fetcher_destruct(grpc_credentials *creds) {
grpc_oauth2_token_fetcher_credentials *c =
(grpc_oauth2_token_fetcher_credentials *)creds;
grpc_credentials_md_store_unref(c->access_token_md);
gpr_mu_destroy(&c->mu);
grpc_httpcli_context_destroy(&c->httpcli_context);
- gpr_free(c);
}
static int oauth2_token_fetcher_has_request_metadata(
@@ -613,10 +637,10 @@ static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c,
grpc_httpcli_context_init(&c->httpcli_context);
}
-/* -- ComputeEngine credentials. -- */
+/* -- GoogleComputeEngine credentials. -- */
static grpc_credentials_vtable compute_engine_vtable = {
- oauth2_token_fetcher_destroy, oauth2_token_fetcher_has_request_metadata,
+ oauth2_token_fetcher_destruct, oauth2_token_fetcher_has_request_metadata,
oauth2_token_fetcher_has_request_metadata_only,
oauth2_token_fetcher_get_request_metadata, NULL};
@@ -635,94 +659,27 @@ static void compute_engine_fetch_oauth2(
metadata_req);
}
-grpc_credentials *grpc_compute_engine_credentials_create(void) {
+grpc_credentials *grpc_google_compute_engine_credentials_create(
+ void *reserved) {
grpc_oauth2_token_fetcher_credentials *c =
gpr_malloc(sizeof(grpc_oauth2_token_fetcher_credentials));
+ GPR_ASSERT(reserved == NULL);
init_oauth2_token_fetcher(c, compute_engine_fetch_oauth2);
c->base.vtable = &compute_engine_vtable;
return &c->base;
}
-/* -- ServiceAccount credentials. -- */
-
-static void service_account_destroy(grpc_credentials *creds) {
- grpc_service_account_credentials *c =
- (grpc_service_account_credentials *)creds;
- if (c->scope != NULL) gpr_free(c->scope);
- grpc_auth_json_key_destruct(&c->key);
- oauth2_token_fetcher_destroy(&c->base.base);
-}
-
-static grpc_credentials_vtable service_account_vtable = {
- service_account_destroy, oauth2_token_fetcher_has_request_metadata,
- oauth2_token_fetcher_has_request_metadata_only,
- oauth2_token_fetcher_get_request_metadata, NULL};
-
-static void service_account_fetch_oauth2(
- grpc_credentials_metadata_request *metadata_req,
- grpc_httpcli_context *httpcli_context, grpc_pollset *pollset,
- grpc_httpcli_response_cb response_cb, gpr_timespec deadline) {
- grpc_service_account_credentials *c =
- (grpc_service_account_credentials *)metadata_req->creds;
- grpc_httpcli_header header = {"Content-Type",
- "application/x-www-form-urlencoded"};
- grpc_httpcli_request request;
- char *body = NULL;
- char *jwt = grpc_jwt_encode_and_sign(&c->key, GRPC_JWT_OAUTH2_AUDIENCE,
- c->token_lifetime, c->scope);
- if (jwt == NULL) {
- grpc_httpcli_response response;
- memset(&response, 0, sizeof(grpc_httpcli_response));
- response.status = 400; /* Invalid request. */
- gpr_log(GPR_ERROR, "Could not create signed jwt.");
- /* Do not even send the request, just call the response callback. */
- response_cb(metadata_req, &response);
- return;
- }
- gpr_asprintf(&body, "%s%s", GRPC_SERVICE_ACCOUNT_POST_BODY_PREFIX, jwt);
- memset(&request, 0, sizeof(grpc_httpcli_request));
- request.host = GRPC_GOOGLE_OAUTH2_SERVICE_HOST;
- request.path = GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH;
- request.hdr_count = 1;
- request.hdrs = &header;
- request.handshaker = &grpc_httpcli_ssl;
- grpc_httpcli_post(httpcli_context, pollset, &request, body, strlen(body),
- deadline, response_cb, metadata_req);
- gpr_free(body);
- gpr_free(jwt);
-}
-
-grpc_credentials *grpc_service_account_credentials_create(
- const char *json_key, const char *scope, gpr_timespec token_lifetime) {
- grpc_service_account_credentials *c;
- grpc_auth_json_key key = grpc_auth_json_key_create_from_string(json_key);
+/* -- GoogleRefreshToken credentials. -- */
- if (scope == NULL || (strlen(scope) == 0) ||
- !grpc_auth_json_key_is_valid(&key)) {
- gpr_log(GPR_ERROR,
- "Invalid input for service account credentials creation");
- return NULL;
- }
- c = gpr_malloc(sizeof(grpc_service_account_credentials));
- memset(c, 0, sizeof(grpc_service_account_credentials));
- init_oauth2_token_fetcher(&c->base, service_account_fetch_oauth2);
- c->base.base.vtable = &service_account_vtable;
- c->scope = gpr_strdup(scope);
- c->key = key;
- c->token_lifetime = token_lifetime;
- return &c->base.base;
-}
-
-/* -- RefreshToken credentials. -- */
-
-static void refresh_token_destroy(grpc_credentials *creds) {
- grpc_refresh_token_credentials *c = (grpc_refresh_token_credentials *)creds;
+static void refresh_token_destruct(grpc_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_destroy(&c->base.base);
+ oauth2_token_fetcher_destruct(&c->base.base);
}
static grpc_credentials_vtable refresh_token_vtable = {
- refresh_token_destroy, oauth2_token_fetcher_has_request_metadata,
+ refresh_token_destruct, oauth2_token_fetcher_has_request_metadata,
oauth2_token_fetcher_has_request_metadata_only,
oauth2_token_fetcher_get_request_metadata, NULL};
@@ -730,8 +687,8 @@ static void refresh_token_fetch_oauth2(
grpc_credentials_metadata_request *metadata_req,
grpc_httpcli_context *httpcli_context, grpc_pollset *pollset,
grpc_httpcli_response_cb response_cb, gpr_timespec deadline) {
- grpc_refresh_token_credentials *c =
- (grpc_refresh_token_credentials *)metadata_req->creds;
+ grpc_google_refresh_token_credentials *c =
+ (grpc_google_refresh_token_credentials *)metadata_req->creds;
grpc_httpcli_header header = {"Content-Type",
"application/x-www-form-urlencoded"};
grpc_httpcli_request request;
@@ -750,33 +707,34 @@ static void refresh_token_fetch_oauth2(
gpr_free(body);
}
-grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token(
+grpc_credentials *
+grpc_refresh_token_credentials_create_from_auth_refresh_token(
grpc_auth_refresh_token refresh_token) {
- grpc_refresh_token_credentials *c;
+ grpc_google_refresh_token_credentials *c;
if (!grpc_auth_refresh_token_is_valid(&refresh_token)) {
gpr_log(GPR_ERROR, "Invalid input for refresh token credentials creation");
return NULL;
}
- c = gpr_malloc(sizeof(grpc_refresh_token_credentials));
- memset(c, 0, sizeof(grpc_refresh_token_credentials));
+ c = gpr_malloc(sizeof(grpc_google_refresh_token_credentials));
+ memset(c, 0, sizeof(grpc_google_refresh_token_credentials));
init_oauth2_token_fetcher(&c->base, refresh_token_fetch_oauth2);
c->base.base.vtable = &refresh_token_vtable;
c->refresh_token = refresh_token;
return &c->base.base;
}
-grpc_credentials *grpc_refresh_token_credentials_create(
- const char *json_refresh_token) {
+grpc_credentials *grpc_google_refresh_token_credentials_create(
+ const char *json_refresh_token, void *reserved) {
+ GPR_ASSERT(reserved == NULL);
return grpc_refresh_token_credentials_create_from_auth_refresh_token(
grpc_auth_refresh_token_create_from_string(json_refresh_token));
}
/* -- Metadata-only credentials. -- */
-static void md_only_test_destroy(grpc_credentials *creds) {
+static void md_only_test_destruct(grpc_credentials *creds) {
grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
grpc_credentials_md_store_unref(c->md_store);
- gpr_free(c);
}
static int md_only_test_has_request_metadata(const grpc_credentials *creds) {
@@ -817,7 +775,7 @@ static void md_only_test_get_request_metadata(grpc_credentials *creds,
}
static grpc_credentials_vtable md_only_test_vtable = {
- md_only_test_destroy, md_only_test_has_request_metadata,
+ md_only_test_destruct, md_only_test_has_request_metadata,
md_only_test_has_request_metadata_only, md_only_test_get_request_metadata,
NULL};
@@ -838,10 +796,9 @@ grpc_credentials *grpc_md_only_test_credentials_create(const char *md_key,
/* -- Oauth2 Access Token credentials. -- */
-static void access_token_destroy(grpc_credentials *creds) {
+static void access_token_destruct(grpc_credentials *creds) {
grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
grpc_credentials_md_store_unref(c->access_token_md);
- gpr_free(c);
}
static int access_token_has_request_metadata(const grpc_credentials *creds) {
@@ -863,15 +820,16 @@ static void access_token_get_request_metadata(grpc_credentials *creds,
}
static grpc_credentials_vtable access_token_vtable = {
- access_token_destroy, access_token_has_request_metadata,
+ access_token_destruct, access_token_has_request_metadata,
access_token_has_request_metadata_only, access_token_get_request_metadata,
NULL};
-grpc_credentials *grpc_access_token_credentials_create(
- const char *access_token) {
+grpc_credentials *grpc_access_token_credentials_create(const char *access_token,
+ void *reserved) {
grpc_access_token_credentials *c =
gpr_malloc(sizeof(grpc_access_token_credentials));
char *token_md_value;
+ GPR_ASSERT(reserved == NULL);
memset(c, 0, sizeof(grpc_access_token_credentials));
c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2;
c->base.vtable = &access_token_vtable;
@@ -886,14 +844,14 @@ grpc_credentials *grpc_access_token_credentials_create(
/* -- Fake transport security credentials. -- */
-static void fake_transport_security_credentials_destroy(
+static void fake_transport_security_credentials_destruct(
grpc_credentials *creds) {
- gpr_free(creds);
+ /* Nothing to do here. */
}
-static void fake_transport_security_server_credentials_destroy(
+static void fake_transport_security_server_credentials_destruct(
grpc_server_credentials *creds) {
- gpr_free(creds);
+ /* Nothing to do here. */
}
static int fake_transport_security_has_request_metadata(
@@ -922,14 +880,14 @@ fake_transport_security_server_create_security_connector(
}
static grpc_credentials_vtable fake_transport_security_credentials_vtable = {
- fake_transport_security_credentials_destroy,
+ fake_transport_security_credentials_destruct,
fake_transport_security_has_request_metadata,
fake_transport_security_has_request_metadata_only, NULL,
fake_transport_security_create_security_connector};
static grpc_server_credentials_vtable
fake_transport_security_server_credentials_vtable = {
- fake_transport_security_server_credentials_destroy,
+ fake_transport_security_server_credentials_destruct,
fake_transport_security_server_create_security_connector};
grpc_credentials *grpc_fake_transport_security_credentials_create(void) {
@@ -946,6 +904,7 @@ grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
grpc_server_credentials *c = gpr_malloc(sizeof(grpc_server_credentials));
memset(c, 0, sizeof(grpc_server_credentials));
c->type = GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
+ gpr_ref_init(&c->refcount, 1);
c->vtable = &fake_transport_security_server_credentials_vtable;
return c;
}
@@ -962,14 +921,13 @@ typedef struct {
grpc_credentials_metadata_cb cb;
} grpc_composite_credentials_metadata_context;
-static void composite_destroy(grpc_credentials *creds) {
+static void composite_destruct(grpc_credentials *creds) {
grpc_composite_credentials *c = (grpc_composite_credentials *)creds;
size_t i;
for (i = 0; i < c->inner.num_creds; i++) {
grpc_credentials_unref(c->inner.creds_array[i]);
}
gpr_free(c->inner.creds_array);
- gpr_free(creds);
}
static int composite_has_request_metadata(const grpc_credentials *creds) {
@@ -1085,7 +1043,7 @@ static grpc_security_status composite_create_security_connector(
}
static grpc_credentials_vtable composite_credentials_vtable = {
- composite_destroy, composite_has_request_metadata,
+ composite_destruct, composite_has_request_metadata,
composite_has_request_metadata_only, composite_get_request_metadata,
composite_create_security_connector};
@@ -1101,12 +1059,14 @@ static grpc_credentials_array get_creds_array(grpc_credentials **creds_addr) {
}
grpc_credentials *grpc_composite_credentials_create(grpc_credentials *creds1,
- grpc_credentials *creds2) {
+ grpc_credentials *creds2,
+ void *reserved) {
size_t i;
size_t creds_array_byte_size;
grpc_credentials_array creds1_array;
grpc_credentials_array creds2_array;
grpc_composite_credentials *c;
+ GPR_ASSERT(reserved == NULL);
GPR_ASSERT(creds1 != NULL);
GPR_ASSERT(creds2 != NULL);
c = gpr_malloc(sizeof(grpc_composite_credentials));
@@ -1182,10 +1142,9 @@ grpc_credentials *grpc_credentials_contains_type(
/* -- IAM credentials. -- */
-static void iam_destroy(grpc_credentials *creds) {
- grpc_iam_credentials *c = (grpc_iam_credentials *)creds;
+static void iam_destruct(grpc_credentials *creds) {
+ grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
grpc_credentials_md_store_unref(c->iam_md);
- gpr_free(c);
}
static int iam_has_request_metadata(const grpc_credentials *creds) { return 1; }
@@ -1199,22 +1158,23 @@ static void iam_get_request_metadata(grpc_credentials *creds,
const char *service_url,
grpc_credentials_metadata_cb cb,
void *user_data) {
- grpc_iam_credentials *c = (grpc_iam_credentials *)creds;
+ grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
cb(user_data, c->iam_md->entries, c->iam_md->num_entries,
GRPC_CREDENTIALS_OK);
}
static grpc_credentials_vtable iam_vtable = {
- iam_destroy, iam_has_request_metadata, iam_has_request_metadata_only,
+ iam_destruct, iam_has_request_metadata, iam_has_request_metadata_only,
iam_get_request_metadata, NULL};
-grpc_credentials *grpc_iam_credentials_create(const char *token,
- const char *authority_selector) {
- grpc_iam_credentials *c;
+grpc_credentials *grpc_google_iam_credentials_create(
+ const char *token, const char *authority_selector, void *reserved) {
+ grpc_google_iam_credentials *c;
+ GPR_ASSERT(reserved == NULL);
GPR_ASSERT(token != NULL);
GPR_ASSERT(authority_selector != NULL);
- c = gpr_malloc(sizeof(grpc_iam_credentials));
- memset(c, 0, sizeof(grpc_iam_credentials));
+ c = gpr_malloc(sizeof(grpc_google_iam_credentials));
+ memset(c, 0, sizeof(grpc_google_iam_credentials));
c->base.type = GRPC_CREDENTIALS_TYPE_IAM;
c->base.vtable = &iam_vtable;
gpr_ref_init(&c->base.refcount, 1);
diff --git a/src/core/security/credentials.h b/src/core/security/credentials.h
index 29cd1ac87f..8e4fed7615 100644
--- a/src/core/security/credentials.h
+++ b/src/core/security/credentials.h
@@ -129,7 +129,7 @@ typedef void (*grpc_credentials_metadata_cb)(void *user_data,
grpc_credentials_status status);
typedef struct {
- void (*destroy)(grpc_credentials *c);
+ void (*destruct)(grpc_credentials *c);
int (*has_request_metadata)(const grpc_credentials *c);
int (*has_request_metadata_only)(const grpc_credentials *c);
void (*get_request_metadata)(grpc_credentials *c, grpc_pollset *pollset,
@@ -210,20 +210,28 @@ grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token(
/* --- grpc_server_credentials. --- */
typedef struct {
- void (*destroy)(grpc_server_credentials *c);
+ void (*destruct)(grpc_server_credentials *c);
grpc_security_status (*create_security_connector)(
grpc_server_credentials *c, grpc_security_connector **sc);
} grpc_server_credentials_vtable;
+
+/* TODO(jboeuf): Add a refcount. */
struct grpc_server_credentials {
const grpc_server_credentials_vtable *vtable;
const char *type;
+ gpr_refcount refcount;
grpc_auth_metadata_processor processor;
};
grpc_security_status grpc_server_credentials_create_security_connector(
grpc_server_credentials *creds, grpc_security_connector **sc);
+grpc_server_credentials *grpc_server_credentials_ref(
+ grpc_server_credentials *creds);
+
+void grpc_server_credentials_unref(grpc_server_credentials *creds);
+
/* -- Ssl credentials. -- */
typedef struct {
@@ -277,21 +285,12 @@ typedef struct {
grpc_fetch_oauth2_func fetch_func;
} grpc_oauth2_token_fetcher_credentials;
-/* -- ServiceAccount credentials. -- */
-
-typedef struct {
- grpc_oauth2_token_fetcher_credentials base;
- grpc_auth_json_key key;
- char *scope;
- gpr_timespec token_lifetime;
-} grpc_service_account_credentials;
-
-/* -- RefreshToken credentials. -- */
+/* -- GoogleRefreshToken credentials. -- */
typedef struct {
grpc_oauth2_token_fetcher_credentials base;
grpc_auth_refresh_token refresh_token;
-} grpc_refresh_token_credentials;
+} grpc_google_refresh_token_credentials;
/* -- Oauth2 Access Token credentials. -- */
@@ -308,12 +307,12 @@ typedef struct {
int is_async;
} grpc_md_only_test_credentials;
-/* -- IAM credentials. -- */
+/* -- GoogleIAM credentials. -- */
typedef struct {
grpc_credentials base;
grpc_credentials_md_store *iam_md;
-} grpc_iam_credentials;
+} grpc_google_iam_credentials;
/* -- Composite credentials. -- */
diff --git a/src/core/security/google_default_credentials.c b/src/core/security/google_default_credentials.c
index d6092ece32..874dd59e84 100644
--- a/src/core/security/google_default_credentials.c
+++ b/src/core/security/google_default_credentials.c
@@ -115,7 +115,7 @@ static int is_stack_running_on_compute_engine(void) {
gpr_mu_lock(GRPC_POLLSET_MU(&detector.pollset));
while (!detector.is_done) {
grpc_pollset_worker worker;
- grpc_pollset_work(&detector.pollset, &worker,
+ grpc_pollset_work(&detector.pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC),
gpr_inf_future(GPR_CLOCK_MONOTONIC));
}
gpr_mu_unlock(GRPC_POLLSET_MU(&detector.pollset));
@@ -194,7 +194,7 @@ grpc_credentials *grpc_google_default_credentials_create(void) {
int need_compute_engine_creds = is_stack_running_on_compute_engine();
compute_engine_detection_done = 1;
if (need_compute_engine_creds) {
- result = grpc_compute_engine_credentials_create();
+ result = grpc_google_compute_engine_credentials_create(NULL);
}
}
@@ -202,9 +202,9 @@ end:
if (!serving_cached_credentials && result != NULL) {
/* Blend with default ssl credentials and add a global reference so that it
can be cached and re-served. */
- grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL);
+ grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL, NULL);
default_credentials = grpc_credentials_ref(
- grpc_composite_credentials_create(ssl_creds, result));
+ grpc_composite_credentials_create(ssl_creds, result, NULL));
GPR_ASSERT(default_credentials != NULL);
grpc_credentials_unref(ssl_creds);
grpc_credentials_unref(result);
diff --git a/src/core/security/handshake.c b/src/core/security/handshake.c
index 62208ca8f2..3b49271373 100644
--- a/src/core/security/handshake.c
+++ b/src/core/security/handshake.c
@@ -50,17 +50,18 @@ typedef struct {
grpc_endpoint *wrapped_endpoint;
grpc_endpoint *secure_endpoint;
gpr_slice_buffer left_overs;
+ gpr_slice_buffer incoming;
+ gpr_slice_buffer outgoing;
grpc_security_handshake_done_cb cb;
void *user_data;
+ grpc_iomgr_closure on_handshake_data_sent_to_peer;
+ grpc_iomgr_closure on_handshake_data_received_from_peer;
} grpc_security_handshake;
-static void on_handshake_data_received_from_peer(void *handshake,
- gpr_slice *slices,
- size_t nslices,
- grpc_endpoint_cb_status error);
-static void on_handshake_data_sent_to_peer(void *handshake,
- grpc_endpoint_cb_status error);
+static void on_handshake_data_received_from_peer(void *setup, int success);
+
+static void on_handshake_data_sent_to_peer(void *setup, int success);
static void security_handshake_done(grpc_security_handshake *h,
int is_success) {
@@ -76,9 +77,11 @@ static void security_handshake_done(grpc_security_handshake *h,
}
h->cb(h->user_data, GRPC_SECURITY_ERROR, h->wrapped_endpoint, NULL);
}
+ if (h->handshaker != NULL) tsi_handshaker_destroy(h->handshaker);
if (h->handshake_buffer != NULL) gpr_free(h->handshake_buffer);
gpr_slice_buffer_destroy(&h->left_overs);
- tsi_handshaker_destroy(h->handshaker);
+ gpr_slice_buffer_destroy(&h->outgoing);
+ gpr_slice_buffer_destroy(&h->incoming);
GRPC_SECURITY_CONNECTOR_UNREF(h->connector, "handshake");
gpr_free(h);
}
@@ -103,6 +106,8 @@ static void on_peer_checked(void *user_data, grpc_security_status status) {
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(h, 1);
return;
}
@@ -133,7 +138,6 @@ static void send_handshake_bytes_to_peer(grpc_security_handshake *h) {
size_t offset = 0;
tsi_result result = TSI_OK;
gpr_slice to_send;
- grpc_endpoint_write_status write_status;
do {
size_t to_send_size = h->handshake_buffer_size - offset;
@@ -156,28 +160,25 @@ static void send_handshake_bytes_to_peer(grpc_security_handshake *h) {
to_send =
gpr_slice_from_copied_buffer((const char *)h->handshake_buffer, offset);
+ gpr_slice_buffer_reset_and_unref(&h->outgoing);
+ gpr_slice_buffer_add(&h->outgoing, to_send);
/* TODO(klempner,jboeuf): This should probably use the client setup
deadline */
- write_status = grpc_endpoint_write(h->wrapped_endpoint, &to_send, 1,
- on_handshake_data_sent_to_peer, h);
- if (write_status == GRPC_ENDPOINT_WRITE_ERROR) {
- gpr_log(GPR_ERROR, "Could not send handshake data to peer.");
- security_handshake_done(h, 0);
- } else if (write_status == GRPC_ENDPOINT_WRITE_DONE) {
- on_handshake_data_sent_to_peer(h, GRPC_ENDPOINT_CB_OK);
- }
-}
-
-static void cleanup_slices(gpr_slice *slices, size_t num_slices) {
- size_t i;
- for (i = 0; i < num_slices; i++) {
- gpr_slice_unref(slices[i]);
+ switch (grpc_endpoint_write(h->wrapped_endpoint, &h->outgoing,
+ &h->on_handshake_data_sent_to_peer)) {
+ case GRPC_ENDPOINT_ERROR:
+ gpr_log(GPR_ERROR, "Could not send handshake data to peer.");
+ security_handshake_done(h, 0);
+ break;
+ case GRPC_ENDPOINT_DONE:
+ on_handshake_data_sent_to_peer(h, 1);
+ break;
+ case GRPC_ENDPOINT_PENDING:
+ break;
}
}
-static void on_handshake_data_received_from_peer(
- void *handshake, gpr_slice *slices, size_t nslices,
- grpc_endpoint_cb_status error) {
+static void on_handshake_data_received_from_peer(void *handshake, int success) {
grpc_security_handshake *h = handshake;
size_t consumed_slice_size = 0;
tsi_result result = TSI_OK;
@@ -185,32 +186,37 @@ static void on_handshake_data_received_from_peer(
size_t num_left_overs;
int has_left_overs_in_current_slice = 0;
- if (error != GRPC_ENDPOINT_CB_OK) {
+ if (!success) {
gpr_log(GPR_ERROR, "Read failed.");
- cleanup_slices(slices, nslices);
security_handshake_done(h, 0);
return;
}
- for (i = 0; i < nslices; i++) {
- consumed_slice_size = GPR_SLICE_LENGTH(slices[i]);
+ for (i = 0; i < h->incoming.count; i++) {
+ consumed_slice_size = GPR_SLICE_LENGTH(h->incoming.slices[i]);
result = tsi_handshaker_process_bytes_from_peer(
- h->handshaker, GPR_SLICE_START_PTR(slices[i]), &consumed_slice_size);
+ h->handshaker, GPR_SLICE_START_PTR(h->incoming.slices[i]),
+ &consumed_slice_size);
if (!tsi_handshaker_is_in_progress(h->handshaker)) break;
}
if (tsi_handshaker_is_in_progress(h->handshaker)) {
/* We may need more data. */
if (result == TSI_INCOMPLETE_DATA) {
- /* TODO(klempner,jboeuf): This should probably use the client setup
- deadline */
- grpc_endpoint_notify_on_read(
- h->wrapped_endpoint, on_handshake_data_received_from_peer, handshake);
- cleanup_slices(slices, nslices);
+ switch (grpc_endpoint_read(h->wrapped_endpoint, &h->incoming,
+ &h->on_handshake_data_received_from_peer)) {
+ case GRPC_ENDPOINT_DONE:
+ on_handshake_data_received_from_peer(h, 1);
+ break;
+ case GRPC_ENDPOINT_ERROR:
+ on_handshake_data_received_from_peer(h, 0);
+ break;
+ case GRPC_ENDPOINT_PENDING:
+ break;
+ }
return;
} else {
send_handshake_bytes_to_peer(h);
- cleanup_slices(slices, nslices);
return;
}
}
@@ -218,42 +224,41 @@ static void on_handshake_data_received_from_peer(
if (result != TSI_OK) {
gpr_log(GPR_ERROR, "Handshake failed with error %s",
tsi_result_to_string(result));
- cleanup_slices(slices, nslices);
security_handshake_done(h, 0);
return;
}
/* Handshake is done and successful this point. */
has_left_overs_in_current_slice =
- (consumed_slice_size < GPR_SLICE_LENGTH(slices[i]));
- num_left_overs = (has_left_overs_in_current_slice ? 1 : 0) + nslices - i - 1;
+ (consumed_slice_size < GPR_SLICE_LENGTH(h->incoming.slices[i]));
+ num_left_overs =
+ (has_left_overs_in_current_slice ? 1 : 0) + h->incoming.count - i - 1;
if (num_left_overs == 0) {
- cleanup_slices(slices, nslices);
check_peer(h);
return;
}
- cleanup_slices(slices, nslices - num_left_overs);
/* Put the leftovers in our buffer (ownership transfered). */
if (has_left_overs_in_current_slice) {
- gpr_slice_buffer_add(&h->left_overs,
- gpr_slice_split_tail(&slices[i], consumed_slice_size));
- gpr_slice_unref(slices[i]); /* split_tail above increments refcount. */
+ gpr_slice_buffer_add(
+ &h->left_overs,
+ gpr_slice_split_tail(&h->incoming.slices[i], consumed_slice_size));
+ gpr_slice_unref(
+ h->incoming.slices[i]); /* split_tail above increments refcount. */
}
gpr_slice_buffer_addn(
- &h->left_overs, &slices[i + 1],
+ &h->left_overs, &h->incoming.slices[i + 1],
num_left_overs - (size_t)has_left_overs_in_current_slice);
check_peer(h);
}
/* If handshake is NULL, the handshake is done. */
-static void on_handshake_data_sent_to_peer(void *handshake,
- grpc_endpoint_cb_status error) {
+static void on_handshake_data_sent_to_peer(void *handshake, int success) {
grpc_security_handshake *h = handshake;
/* Make sure that write is OK. */
- if (error != GRPC_ENDPOINT_CB_OK) {
- gpr_log(GPR_ERROR, "Write failed with error %d.", error);
+ if (!success) {
+ gpr_log(GPR_ERROR, "Write failed.");
if (handshake != NULL) security_handshake_done(h, 0);
return;
}
@@ -262,8 +267,17 @@ static void on_handshake_data_sent_to_peer(void *handshake,
if (tsi_handshaker_is_in_progress(h->handshaker)) {
/* TODO(klempner,jboeuf): This should probably use the client setup
deadline */
- grpc_endpoint_notify_on_read(
- h->wrapped_endpoint, on_handshake_data_received_from_peer, handshake);
+ switch (grpc_endpoint_read(h->wrapped_endpoint, &h->incoming,
+ &h->on_handshake_data_received_from_peer)) {
+ case GRPC_ENDPOINT_ERROR:
+ on_handshake_data_received_from_peer(h, 0);
+ break;
+ case GRPC_ENDPOINT_PENDING:
+ break;
+ case GRPC_ENDPOINT_DONE:
+ on_handshake_data_received_from_peer(h, 1);
+ break;
+ }
} else {
check_peer(h);
}
@@ -283,6 +297,12 @@ void grpc_do_security_handshake(tsi_handshaker *handshaker,
h->wrapped_endpoint = nonsecure_endpoint;
h->user_data = user_data;
h->cb = cb;
+ grpc_iomgr_closure_init(&h->on_handshake_data_sent_to_peer,
+ on_handshake_data_sent_to_peer, h);
+ grpc_iomgr_closure_init(&h->on_handshake_data_received_from_peer,
+ on_handshake_data_received_from_peer, h);
gpr_slice_buffer_init(&h->left_overs);
+ gpr_slice_buffer_init(&h->outgoing);
+ gpr_slice_buffer_init(&h->incoming);
send_handshake_bytes_to_peer(h);
}
diff --git a/src/core/security/jwt_verifier.c b/src/core/security/jwt_verifier.c
index 38ad134a6a..790f2178db 100644
--- a/src/core/security/jwt_verifier.c
+++ b/src/core/security/jwt_verifier.c
@@ -33,6 +33,7 @@
#include "src/core/security/jwt_verifier.h"
+#include <limits.h>
#include <string.h>
#include "src/core/httpcli/httpcli.h"
@@ -412,7 +413,9 @@ static EVP_PKEY *extract_pkey_from_x509(const char *x509_str) {
X509 *x509 = NULL;
EVP_PKEY *result = NULL;
BIO *bio = BIO_new(BIO_s_mem());
- BIO_write(bio, x509_str, strlen(x509_str));
+ size_t len = strlen(x509_str);
+ GPR_ASSERT(len < INT_MAX);
+ BIO_write(bio, x509_str, (int)len);
x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
if (x509 == NULL) {
gpr_log(GPR_ERROR, "Unable to parse x509 cert.");
@@ -439,7 +442,8 @@ static BIGNUM *bignum_from_base64(const char *b64) {
gpr_log(GPR_ERROR, "Invalid base64 for big num.");
return NULL;
}
- result = BN_bin2bn(GPR_SLICE_START_PTR(bin), GPR_SLICE_LENGTH(bin), NULL);
+ result =
+ BN_bin2bn(GPR_SLICE_START_PTR(bin), (int)GPR_SLICE_LENGTH(bin), NULL);
gpr_slice_unref(bin);
return result;
}
@@ -769,7 +773,7 @@ void grpc_jwt_verifier_verify(grpc_jwt_verifier *verifier,
GPR_ASSERT(verifier != NULL && jwt != NULL && audience != NULL && cb != NULL);
dot = strchr(cur, '.');
if (dot == NULL) goto error;
- json = parse_json_part_from_jwt(cur, dot - cur, &header_buffer);
+ json = parse_json_part_from_jwt(cur, (size_t)(dot - cur), &header_buffer);
if (json == NULL) goto error;
header = jose_header_from_json(json, header_buffer);
if (header == NULL) goto error;
@@ -777,7 +781,7 @@ void grpc_jwt_verifier_verify(grpc_jwt_verifier *verifier,
cur = dot + 1;
dot = strchr(cur, '.');
if (dot == NULL) goto error;
- json = parse_json_part_from_jwt(cur, dot - cur, &claims_buffer);
+ json = parse_json_part_from_jwt(cur, (size_t)(dot - cur), &claims_buffer);
if (json == NULL) goto error;
claims = grpc_jwt_claims_from_json(json, claims_buffer);
if (claims == NULL) goto error;
diff --git a/src/core/security/secure_endpoint.c b/src/core/security/secure_endpoint.c
index 81b3e33cb2..b696e384fc 100644
--- a/src/core/security/secure_endpoint.c
+++ b/src/core/security/secure_endpoint.c
@@ -49,15 +49,15 @@ typedef struct {
struct tsi_frame_protector *protector;
gpr_mu protector_mu;
/* saved upper level callbacks and user_data. */
- grpc_endpoint_read_cb read_cb;
- void *read_user_data;
- grpc_endpoint_write_cb write_cb;
- void *write_user_data;
+ grpc_iomgr_closure *read_cb;
+ grpc_iomgr_closure *write_cb;
+ grpc_iomgr_closure on_read;
+ gpr_slice_buffer *read_buffer;
+ gpr_slice_buffer source_buffer;
/* saved handshaker leftover data to unprotect. */
gpr_slice_buffer leftover_bytes;
/* buffers for read and write */
gpr_slice read_staging_buffer;
- gpr_slice_buffer input_buffer;
gpr_slice write_staging_buffer;
gpr_slice_buffer output_buffer;
@@ -67,62 +67,91 @@ typedef struct {
int grpc_trace_secure_endpoint = 0;
-static void secure_endpoint_ref(secure_endpoint *ep) { gpr_ref(&ep->ref); }
-
static void destroy(secure_endpoint *secure_ep) {
secure_endpoint *ep = secure_ep;
grpc_endpoint_destroy(ep->wrapped_ep);
tsi_frame_protector_destroy(ep->protector);
gpr_slice_buffer_destroy(&ep->leftover_bytes);
gpr_slice_unref(ep->read_staging_buffer);
- gpr_slice_buffer_destroy(&ep->input_buffer);
gpr_slice_unref(ep->write_staging_buffer);
gpr_slice_buffer_destroy(&ep->output_buffer);
+ gpr_slice_buffer_destroy(&ep->source_buffer);
gpr_mu_destroy(&ep->protector_mu);
gpr_free(ep);
}
+/*#define GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG*/
+#ifdef GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG
+#define SECURE_ENDPOINT_UNREF(ep, reason) \
+ secure_endpoint_unref((ep), (reason), __FILE__, __LINE__)
+#define SECURE_ENDPOINT_REF(ep, reason) \
+ secure_endpoint_ref((ep), (reason), __FILE__, __LINE__)
+static void secure_endpoint_unref(secure_endpoint *ep, const char *reason,
+ const char *file, int line) {
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP unref %p : %s %d -> %d",
+ ep, reason, ep->ref.count, ep->ref.count - 1);
+ if (gpr_unref(&ep->ref)) {
+ destroy(ep);
+ }
+}
+
+static void secure_endpoint_ref(secure_endpoint *ep, const char *reason,
+ const char *file, int line) {
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP ref %p : %s %d -> %d",
+ ep, reason, ep->ref.count, ep->ref.count + 1);
+ gpr_ref(&ep->ref);
+}
+#else
+#define SECURE_ENDPOINT_UNREF(ep, reason) secure_endpoint_unref((ep))
+#define SECURE_ENDPOINT_REF(ep, reason) secure_endpoint_ref((ep))
static void secure_endpoint_unref(secure_endpoint *ep) {
if (gpr_unref(&ep->ref)) {
destroy(ep);
}
}
+static void secure_endpoint_ref(secure_endpoint *ep) { gpr_ref(&ep->ref); }
+#endif
+
static void flush_read_staging_buffer(secure_endpoint *ep, gpr_uint8 **cur,
gpr_uint8 **end) {
- gpr_slice_buffer_add(&ep->input_buffer, ep->read_staging_buffer);
+ gpr_slice_buffer_add(ep->read_buffer, ep->read_staging_buffer);
ep->read_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE);
*cur = GPR_SLICE_START_PTR(ep->read_staging_buffer);
*end = GPR_SLICE_END_PTR(ep->read_staging_buffer);
}
-static void call_read_cb(secure_endpoint *ep, gpr_slice *slices, size_t nslices,
- grpc_endpoint_cb_status error) {
+static void call_read_cb(secure_endpoint *ep, int success) {
if (grpc_trace_secure_endpoint) {
size_t i;
- for (i = 0; i < nslices; i++) {
- char *data = gpr_dump_slice(slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
+ for (i = 0; i < ep->read_buffer->count; i++) {
+ char *data = gpr_dump_slice(ep->read_buffer->slices[i],
+ GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_DEBUG, "READ %p: %s", ep, data);
gpr_free(data);
}
}
- ep->read_cb(ep->read_user_data, slices, nslices, error);
- secure_endpoint_unref(ep);
+ ep->read_buffer = NULL;
+ ep->read_cb->cb(ep->read_cb->cb_arg, success);
+ SECURE_ENDPOINT_UNREF(ep, "read");
}
-static void on_read(void *user_data, gpr_slice *slices, size_t nslices,
- grpc_endpoint_cb_status error) {
+static int on_read(void *user_data, int success) {
unsigned i;
gpr_uint8 keep_looping = 0;
- size_t input_buffer_count = 0;
tsi_result result = TSI_OK;
secure_endpoint *ep = (secure_endpoint *)user_data;
gpr_uint8 *cur = GPR_SLICE_START_PTR(ep->read_staging_buffer);
gpr_uint8 *end = GPR_SLICE_END_PTR(ep->read_staging_buffer);
+ if (!success) {
+ gpr_slice_buffer_reset_and_unref(ep->read_buffer);
+ return 0;
+ }
+
/* TODO(yangg) check error, maybe bail out early */
- for (i = 0; i < nslices; i++) {
- gpr_slice encrypted = slices[i];
+ for (i = 0; i < ep->source_buffer.count; i++) {
+ gpr_slice encrypted = ep->source_buffer.slices[i];
gpr_uint8 *message_bytes = GPR_SLICE_START_PTR(encrypted);
size_t message_size = GPR_SLICE_LENGTH(encrypted);
@@ -161,7 +190,7 @@ static void on_read(void *user_data, gpr_slice *slices, size_t nslices,
if (cur != GPR_SLICE_START_PTR(ep->read_staging_buffer)) {
gpr_slice_buffer_add(
- &ep->input_buffer,
+ ep->read_buffer,
gpr_slice_split_head(
&ep->read_staging_buffer,
(size_t)(cur - GPR_SLICE_START_PTR(ep->read_staging_buffer))));
@@ -169,38 +198,53 @@ static void on_read(void *user_data, gpr_slice *slices, size_t nslices,
/* TODO(yangg) experiment with moving this block after read_cb to see if it
helps latency */
- for (i = 0; i < nslices; i++) {
- gpr_slice_unref(slices[i]);
- }
+ gpr_slice_buffer_reset_and_unref(&ep->source_buffer);
if (result != TSI_OK) {
- gpr_slice_buffer_reset_and_unref(&ep->input_buffer);
- call_read_cb(ep, NULL, 0, GRPC_ENDPOINT_CB_ERROR);
- return;
+ gpr_slice_buffer_reset_and_unref(ep->read_buffer);
+ return 0;
}
- /* The upper level will unref the slices. */
- input_buffer_count = ep->input_buffer.count;
- ep->input_buffer.count = 0;
- call_read_cb(ep, ep->input_buffer.slices, input_buffer_count, error);
+
+ return 1;
+}
+
+static void on_read_cb(void *user_data, int success) {
+ call_read_cb(user_data, on_read(user_data, success));
}
-static void endpoint_notify_on_read(grpc_endpoint *secure_ep,
- grpc_endpoint_read_cb cb, void *user_data) {
+static grpc_endpoint_op_status endpoint_read(grpc_endpoint *secure_ep,
+ gpr_slice_buffer *slices,
+ grpc_iomgr_closure *cb) {
secure_endpoint *ep = (secure_endpoint *)secure_ep;
+ int immediate_read_success = -1;
ep->read_cb = cb;
- ep->read_user_data = user_data;
-
- secure_endpoint_ref(ep);
+ ep->read_buffer = slices;
+ gpr_slice_buffer_reset_and_unref(ep->read_buffer);
if (ep->leftover_bytes.count) {
- size_t leftover_nslices = ep->leftover_bytes.count;
- ep->leftover_bytes.count = 0;
- on_read(ep, ep->leftover_bytes.slices, leftover_nslices,
- GRPC_ENDPOINT_CB_OK);
- return;
+ gpr_slice_buffer_swap(&ep->leftover_bytes, &ep->source_buffer);
+ GPR_ASSERT(ep->leftover_bytes.count == 0);
+ return on_read(ep, 1) ? GRPC_ENDPOINT_DONE : GRPC_ENDPOINT_ERROR;
}
- grpc_endpoint_notify_on_read(ep->wrapped_ep, on_read, ep);
+ SECURE_ENDPOINT_REF(ep, "read");
+
+ switch (
+ grpc_endpoint_read(ep->wrapped_ep, &ep->source_buffer, &ep->on_read)) {
+ case GRPC_ENDPOINT_DONE:
+ immediate_read_success = on_read(ep, 1);
+ break;
+ case GRPC_ENDPOINT_PENDING:
+ return GRPC_ENDPOINT_PENDING;
+ case GRPC_ENDPOINT_ERROR:
+ immediate_read_success = on_read(ep, 0);
+ break;
+ }
+
+ GPR_ASSERT(immediate_read_success != -1);
+ SECURE_ENDPOINT_UNREF(ep, "read");
+
+ return immediate_read_success ? GRPC_ENDPOINT_DONE : GRPC_ENDPOINT_ERROR;
}
static void flush_write_staging_buffer(secure_endpoint *ep, gpr_uint8 **cur,
@@ -211,36 +255,28 @@ static void flush_write_staging_buffer(secure_endpoint *ep, gpr_uint8 **cur,
*end = GPR_SLICE_END_PTR(ep->write_staging_buffer);
}
-static void on_write(void *data, grpc_endpoint_cb_status error) {
- secure_endpoint *ep = data;
- ep->write_cb(ep->write_user_data, error);
- secure_endpoint_unref(ep);
-}
-
-static grpc_endpoint_write_status endpoint_write(grpc_endpoint *secure_ep,
- gpr_slice *slices,
- size_t nslices,
- grpc_endpoint_write_cb cb,
- void *user_data) {
+static grpc_endpoint_op_status endpoint_write(grpc_endpoint *secure_ep,
+ gpr_slice_buffer *slices,
+ grpc_iomgr_closure *cb) {
unsigned i;
- size_t output_buffer_count = 0;
tsi_result result = TSI_OK;
secure_endpoint *ep = (secure_endpoint *)secure_ep;
gpr_uint8 *cur = GPR_SLICE_START_PTR(ep->write_staging_buffer);
gpr_uint8 *end = GPR_SLICE_END_PTR(ep->write_staging_buffer);
- grpc_endpoint_write_status status;
- GPR_ASSERT(ep->output_buffer.count == 0);
+
+ gpr_slice_buffer_reset_and_unref(&ep->output_buffer);
if (grpc_trace_secure_endpoint) {
- for (i = 0; i < nslices; i++) {
- char *data = gpr_dump_slice(slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
+ for (i = 0; i < slices->count; i++) {
+ char *data =
+ gpr_dump_slice(slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_DEBUG, "WRITE %p: %s", ep, data);
gpr_free(data);
}
}
- for (i = 0; i < nslices; i++) {
- gpr_slice plain = slices[i];
+ for (i = 0; i < slices->count; i++) {
+ gpr_slice plain = slices->slices[i];
gpr_uint8 *message_bytes = GPR_SLICE_START_PTR(plain);
size_t message_size = GPR_SLICE_LENGTH(plain);
while (message_size > 0) {
@@ -290,29 +326,13 @@ static grpc_endpoint_write_status endpoint_write(grpc_endpoint *secure_ep,
}
}
- for (i = 0; i < nslices; i++) {
- gpr_slice_unref(slices[i]);
- }
-
if (result != TSI_OK) {
/* TODO(yangg) do different things according to the error type? */
gpr_slice_buffer_reset_and_unref(&ep->output_buffer);
- return GRPC_ENDPOINT_WRITE_ERROR;
+ return GRPC_ENDPOINT_ERROR;
}
- /* clear output_buffer and let the lower level handle its slices. */
- output_buffer_count = ep->output_buffer.count;
- ep->output_buffer.count = 0;
- ep->write_cb = cb;
- ep->write_user_data = user_data;
- /* Need to keep the endpoint alive across a transport */
- secure_endpoint_ref(ep);
- status = grpc_endpoint_write(ep->wrapped_ep, ep->output_buffer.slices,
- output_buffer_count, on_write, ep);
- if (status != GRPC_ENDPOINT_WRITE_PENDING) {
- secure_endpoint_unref(ep);
- }
- return status;
+ return grpc_endpoint_write(ep->wrapped_ep, &ep->output_buffer, cb);
}
static void endpoint_shutdown(grpc_endpoint *secure_ep) {
@@ -320,9 +340,9 @@ static void endpoint_shutdown(grpc_endpoint *secure_ep) {
grpc_endpoint_shutdown(ep->wrapped_ep);
}
-static void endpoint_unref(grpc_endpoint *secure_ep) {
+static void endpoint_destroy(grpc_endpoint *secure_ep) {
secure_endpoint *ep = (secure_endpoint *)secure_ep;
- secure_endpoint_unref(ep);
+ SECURE_ENDPOINT_UNREF(ep, "destroy");
}
static void endpoint_add_to_pollset(grpc_endpoint *secure_ep,
@@ -343,9 +363,9 @@ static char *endpoint_get_peer(grpc_endpoint *secure_ep) {
}
static const grpc_endpoint_vtable vtable = {
- endpoint_notify_on_read, endpoint_write,
+ endpoint_read, endpoint_write,
endpoint_add_to_pollset, endpoint_add_to_pollset_set,
- endpoint_shutdown, endpoint_unref,
+ endpoint_shutdown, endpoint_destroy,
endpoint_get_peer};
grpc_endpoint *grpc_secure_endpoint_create(
@@ -363,8 +383,10 @@ grpc_endpoint *grpc_secure_endpoint_create(
}
ep->write_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE);
ep->read_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE);
- gpr_slice_buffer_init(&ep->input_buffer);
gpr_slice_buffer_init(&ep->output_buffer);
+ gpr_slice_buffer_init(&ep->source_buffer);
+ ep->read_buffer = NULL;
+ grpc_iomgr_closure_init(&ep->on_read, on_read_cb, ep);
gpr_mu_init(&ep->protector_mu);
gpr_ref_init(&ep->ref, 1);
return &ep->base;
diff --git a/src/core/security/security_connector.c b/src/core/security/security_connector.c
index 983ac7635d..f6460a323e 100644
--- a/src/core/security/security_connector.c
+++ b/src/core/security/security_connector.c
@@ -604,6 +604,16 @@ grpc_security_status grpc_ssl_channel_security_connector_create(
if (!check_request_metadata_creds(request_metadata_creds)) {
goto error;
}
+ if (config->pem_root_certs == NULL) {
+ pem_root_certs_size = grpc_get_default_ssl_roots(&pem_root_certs);
+ if (pem_root_certs == NULL || pem_root_certs_size == 0) {
+ gpr_log(GPR_ERROR, "Could not get default pem root certs.");
+ goto error;
+ }
+ } else {
+ pem_root_certs = config->pem_root_certs;
+ pem_root_certs_size = config->pem_root_certs_size;
+ }
c = gpr_malloc(sizeof(grpc_ssl_channel_security_connector));
memset(c, 0, sizeof(grpc_ssl_channel_security_connector));
@@ -619,16 +629,6 @@ grpc_security_status grpc_ssl_channel_security_connector_create(
if (overridden_target_name != NULL) {
c->overridden_target_name = gpr_strdup(overridden_target_name);
}
- if (config->pem_root_certs == NULL) {
- pem_root_certs_size = grpc_get_default_ssl_roots(&pem_root_certs);
- if (pem_root_certs == NULL || pem_root_certs_size == 0) {
- gpr_log(GPR_ERROR, "Could not get default pem root certs.");
- goto error;
- }
- } else {
- pem_root_certs = config->pem_root_certs;
- pem_root_certs_size = config->pem_root_certs_size;
- }
result = tsi_create_ssl_client_handshaker_factory(
config->pem_private_key, config->pem_private_key_size,
config->pem_cert_chain, config->pem_cert_chain_size, pem_root_certs,
diff --git a/src/core/security/security_context.c b/src/core/security/security_context.c
index c1b434f302..95d80ba122 100644
--- a/src/core/security/security_context.c
+++ b/src/core/security/security_context.c
@@ -42,19 +42,6 @@
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
-/* --- grpc_process_auth_metadata_func --- */
-
-static grpc_auth_metadata_processor server_processor = {NULL, NULL};
-
-grpc_auth_metadata_processor grpc_server_get_auth_metadata_processor(void) {
- return server_processor;
-}
-
-void grpc_server_register_auth_metadata_processor(
- grpc_auth_metadata_processor processor) {
- server_processor = processor;
-}
-
/* --- grpc_call --- */
grpc_call_error grpc_call_set_credentials(grpc_call *call,
diff --git a/src/core/security/server_auth_filter.c b/src/core/security/server_auth_filter.c
index 2f42f01f53..d134201e87 100644
--- a/src/core/security/server_auth_filter.c
+++ b/src/core/security/server_auth_filter.c
@@ -50,6 +50,7 @@ typedef struct call_data {
handling it. */
grpc_iomgr_closure auth_on_recv;
grpc_transport_stream_op transport_op;
+ grpc_metadata_array md;
const grpc_metadata *consumed_md;
size_t num_consumed_md;
grpc_stream_op *md_op;
@@ -90,13 +91,17 @@ static grpc_mdelem *remove_consumed_md(void *user_data, grpc_mdelem *md) {
call_data *calld = elem->call_data;
size_t i;
for (i = 0; i < calld->num_consumed_md; i++) {
+ const grpc_metadata *consumed_md = &calld->consumed_md[i];
/* Maybe we could do a pointer comparison but we do not have any guarantee
that the metadata processor used the same pointers for consumed_md in the
callback. */
- if (memcmp(GPR_SLICE_START_PTR(md->key->slice), calld->consumed_md[i].key,
+ if (GPR_SLICE_LENGTH(md->key->slice) != strlen(consumed_md->key) ||
+ GPR_SLICE_LENGTH(md->value->slice) != consumed_md->value_length) {
+ continue;
+ }
+ if (memcmp(GPR_SLICE_START_PTR(md->key->slice), consumed_md->key,
GPR_SLICE_LENGTH(md->key->slice)) == 0 &&
- memcmp(GPR_SLICE_START_PTR(md->value->slice),
- calld->consumed_md[i].value,
+ memcmp(GPR_SLICE_START_PTR(md->value->slice), consumed_md->value,
GPR_SLICE_LENGTH(md->value->slice)) == 0) {
return NULL; /* Delete. */
}
@@ -104,24 +109,36 @@ static grpc_mdelem *remove_consumed_md(void *user_data, grpc_mdelem *md) {
return md;
}
-static void on_md_processing_done(void *user_data,
- const grpc_metadata *consumed_md,
- size_t num_consumed_md, int success) {
+static void on_md_processing_done(
+ void *user_data, const grpc_metadata *consumed_md, size_t num_consumed_md,
+ const grpc_metadata *response_md, size_t num_response_md,
+ grpc_status_code status, const char *error_details) {
grpc_call_element *elem = user_data;
call_data *calld = elem->call_data;
- if (success) {
+ /* TODO(jboeuf): Implement support for response_md. */
+ if (response_md != NULL && num_response_md > 0) {
+ gpr_log(GPR_INFO,
+ "response_md in auth metadata processing not supported for now. "
+ "Ignoring...");
+ }
+
+ if (status == GRPC_STATUS_OK) {
calld->consumed_md = consumed_md;
calld->num_consumed_md = num_consumed_md;
grpc_metadata_batch_filter(&calld->md_op->data.metadata, remove_consumed_md,
elem);
- calld->on_done_recv->cb(calld->on_done_recv->cb_arg, success);
+ grpc_metadata_array_destroy(&calld->md);
+ calld->on_done_recv->cb(calld->on_done_recv->cb_arg, 1);
} else {
- gpr_slice message = gpr_slice_from_copied_string(
- "Authentication metadata processing failed.");
+ gpr_slice message;
+ grpc_metadata_array_destroy(&calld->md);
+ error_details = error_details != NULL
+ ? error_details
+ : "Authentication metadata processing failed.";
+ message = gpr_slice_from_copied_string(error_details);
grpc_sopb_reset(calld->recv_ops);
- grpc_transport_stream_op_add_close(&calld->transport_op,
- GRPC_STATUS_UNAUTHENTICATED, &message);
+ grpc_transport_stream_op_add_close(&calld->transport_op, status, &message);
grpc_call_next_op(elem, &calld->transport_op);
}
}
@@ -135,17 +152,15 @@ static void auth_on_recv(void *user_data, int success) {
size_t nops = calld->recv_ops->nops;
grpc_stream_op *ops = calld->recv_ops->ops;
for (i = 0; i < nops; i++) {
- grpc_metadata_array md_array;
grpc_stream_op *op = &ops[i];
if (op->type != GRPC_OP_METADATA || calld->got_client_metadata) continue;
calld->got_client_metadata = 1;
if (chand->processor.process == NULL) continue;
calld->md_op = op;
- md_array = metadata_batch_to_md_array(&op->data.metadata);
+ calld->md = metadata_batch_to_md_array(&op->data.metadata);
chand->processor.process(chand->processor.state, calld->auth_context,
- md_array.metadata, md_array.count,
+ calld->md.metadata, calld->md.count,
on_md_processing_done, elem);
- grpc_metadata_array_destroy(&md_array);
return;
}
}
diff --git a/src/core/security/server_secure_chttp2.c b/src/core/security/server_secure_chttp2.c
index a3976ac239..f7318b2079 100644
--- a/src/core/security/server_secure_chttp2.c
+++ b/src/core/security/server_secure_chttp2.c
@@ -60,7 +60,7 @@ typedef struct grpc_server_secure_state {
grpc_server *server;
grpc_tcp_server *tcp;
grpc_security_connector *sc;
- grpc_auth_metadata_processor processor;
+ grpc_server_credentials *creds;
tcp_endpoint_list *handshaking_tcp_endpoints;
int is_shutdown;
gpr_mu mu;
@@ -78,6 +78,7 @@ static void state_unref(grpc_server_secure_state *state) {
gpr_mu_unlock(&state->mu);
/* clean up */
GRPC_SECURITY_CONNECTOR_UNREF(state->sc, "server");
+ grpc_server_credentials_unref(state->creds);
gpr_free(state);
}
}
@@ -90,7 +91,8 @@ static void setup_transport(void *statep, grpc_transport *transport,
grpc_channel_args *args_copy;
grpc_arg args_to_add[2];
args_to_add[0] = grpc_security_connector_to_arg(state->sc);
- args_to_add[1] = grpc_auth_metadata_processor_to_arg(&state->processor);
+ args_to_add[1] =
+ grpc_auth_metadata_processor_to_arg(&state->creds->processor);
args_copy = grpc_channel_args_copy_and_add(
grpc_server_get_channel_args(state->server), args_to_add,
GPR_ARRAY_SIZE(args_to_add));
@@ -260,7 +262,8 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
state->server = server;
state->tcp = tcp;
state->sc = sc;
- state->processor = creds->processor;
+ state->creds = grpc_server_credentials_ref(creds);
+
state->handshaking_tcp_endpoints = NULL;
state->is_shutdown = 0;
gpr_mu_init(&state->mu);