aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/security
diff options
context:
space:
mode:
authorGravatar Donna Dionne <donnadionne@google.com>2015-02-21 10:29:06 -0800
committerGravatar Donna Dionne <donnadionne@google.com>2015-02-21 10:29:06 -0800
commit2c77f75b74f266da0970f30333a290f2eb38cdfd (patch)
treecd818aba0dde90b3060c221916caf8a98f5cb3f4 /src/core/security
parentb5795aa24d1605b04c9f61b87adf6f7b26af23e1 (diff)
parentf3599aed6cb48bc4f132546e7f4e5747914ca291 (diff)
Merge branch 'master' of github.com:google/grpc into docker_python
Diffstat (limited to 'src/core/security')
-rw-r--r--src/core/security/auth.c32
-rw-r--r--src/core/security/credentials.c158
-rw-r--r--src/core/security/credentials.h3
-rw-r--r--src/core/security/json_token.c34
-rw-r--r--src/core/security/json_token.h13
-rw-r--r--src/core/security/security_context.c4
-rw-r--r--src/core/security/security_context.h6
7 files changed, 219 insertions, 31 deletions
diff --git a/src/core/security/auth.c b/src/core/security/auth.c
index 58679a87aa..92878e3b7e 100644
--- a/src/core/security/auth.c
+++ b/src/core/security/auth.c
@@ -48,6 +48,7 @@
typedef struct {
grpc_credentials *creds;
grpc_mdstr *host;
+ grpc_mdstr *method;
grpc_call_op op;
} call_data;
@@ -56,6 +57,7 @@ typedef struct {
grpc_channel_security_context *security_context;
grpc_mdctx *md_ctx;
grpc_mdstr *authority_string;
+ grpc_mdstr *path_string;
grpc_mdstr *error_msg_key;
} channel_data;
@@ -89,6 +91,26 @@ static void on_credentials_metadata(void *user_data, grpc_mdelem **md_elems,
grpc_call_next_op(elem, &((call_data *)elem->call_data)->op);
}
+static char *build_service_url(const char *url_scheme, call_data *calld) {
+ char *service_url;
+ char *service = gpr_strdup(grpc_mdstr_as_c_string(calld->method));
+ char *last_slash = strrchr(service, '/');
+ if (last_slash == NULL) {
+ gpr_log(GPR_ERROR, "No '/' found in fully qualified method name");
+ service[0] = '\0';
+ } else if (last_slash == service) {
+ /* No service part in fully qualified method name: will just be "/". */
+ service[1] = '\0';
+ } else {
+ *last_slash = '\0';
+ }
+ if (url_scheme == NULL) url_scheme = "";
+ gpr_asprintf(&service_url, "%s://%s%s", url_scheme,
+ grpc_mdstr_as_c_string(calld->host), service);
+ gpr_free(service);
+ return service_url;
+}
+
static void send_security_metadata(grpc_call_element *elem, grpc_call_op *op) {
/* grab pointers to our data from the call element */
call_data *calld = elem->call_data;
@@ -106,9 +128,12 @@ static void send_security_metadata(grpc_call_element *elem, grpc_call_op *op) {
}
if (channel_creds != NULL &&
grpc_credentials_has_request_metadata(channel_creds)) {
+ char *service_url =
+ build_service_url(channeld->security_context->base.url_scheme, calld);
calld->op = *op; /* Copy op (originates from the caller's stack). */
- grpc_credentials_get_request_metadata(channel_creds,
+ grpc_credentials_get_request_metadata(channel_creds, service_url,
on_credentials_metadata, elem);
+ gpr_free(service_url);
} else {
grpc_call_next_op(elem, op);
}
@@ -146,6 +171,9 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem,
if (op->data.metadata->key == channeld->authority_string) {
if (calld->host != NULL) grpc_mdstr_unref(calld->host);
calld->host = grpc_mdstr_ref(op->data.metadata->value);
+ } else if (op->data.metadata->key == channeld->path_string) {
+ if (calld->method != NULL) grpc_mdstr_unref(calld->method);
+ calld->method = grpc_mdstr_ref(op->data.metadata->value);
}
grpc_call_next_op(elem, op);
break;
@@ -194,6 +222,7 @@ static void init_call_elem(grpc_call_element *elem,
call_data *calld = elem->call_data;
calld->creds = NULL;
calld->host = NULL;
+ calld->method = NULL;
}
/* Destructor for call_data */
@@ -230,6 +259,7 @@ static void init_channel_elem(grpc_channel_element *elem,
channeld->md_ctx = metadata_context;
channeld->authority_string =
grpc_mdstr_from_string(channeld->md_ctx, ":authority");
+ channeld->path_string = grpc_mdstr_from_string(channeld->md_ctx, ":path");
channeld->error_msg_key =
grpc_mdstr_from_string(channeld->md_ctx, "grpc-message");
}
diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c
index a21c27bff9..42d1a900fc 100644
--- a/src/core/security/credentials.c
+++ b/src/core/security/credentials.c
@@ -33,6 +33,10 @@
#include "src/core/security/credentials.h"
+#include <string.h>
+#include <stdio.h>
+
+#include "src/core/json/json.h"
#include "src/core/httpcli/httpcli.h"
#include "src/core/iomgr/iomgr.h"
#include "src/core/security/json_token.h"
@@ -42,14 +46,9 @@
#include <grpc/support/sync.h>
#include <grpc/support/time.h>
-#include "src/core/json/json.h"
-
-#include <string.h>
-#include <stdio.h>
-
/* -- Constants. -- */
-#define GRPC_OAUTH2_TOKEN_REFRESH_THRESHOLD_SECS 60
+#define GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS 60
#define GRPC_COMPUTE_ENGINE_METADATA_HOST "metadata"
#define GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH \
@@ -113,6 +112,7 @@ int grpc_credentials_has_request_metadata_only(grpc_credentials *creds) {
}
void grpc_credentials_get_request_metadata(grpc_credentials *creds,
+ const char *service_url,
grpc_credentials_metadata_cb cb,
void *user_data) {
if (creds == NULL || !grpc_credentials_has_request_metadata(creds) ||
@@ -122,7 +122,7 @@ void grpc_credentials_get_request_metadata(grpc_credentials *creds,
}
return;
}
- creds->vtable->get_request_metadata(creds, cb, user_data);
+ creds->vtable->get_request_metadata(creds, service_url, cb, user_data);
}
void grpc_server_credentials_release(grpc_server_credentials *creds) {
@@ -288,6 +288,128 @@ grpc_server_credentials *grpc_ssl_server_credentials_create(
return &c->base;
}
+/* -- Jwt credentials -- */
+
+typedef struct {
+ grpc_credentials base;
+ grpc_mdctx *md_ctx;
+
+ /* Have a simple cache for now with just 1 entry. We could have a map based on
+ the service_url for a more sophisticated one. */
+ gpr_mu cache_mu;
+ struct {
+ grpc_mdelem *jwt_md;
+ char *service_url;
+ gpr_timespec jwt_expiration;
+ } cached;
+
+ grpc_auth_json_key key;
+ gpr_timespec jwt_lifetime;
+} grpc_jwt_credentials;
+
+static void jwt_reset_cache(grpc_jwt_credentials *c) {
+ if (c->cached.jwt_md != NULL) {
+ grpc_mdelem_unref(c->cached.jwt_md);
+ c->cached.jwt_md = NULL;
+ }
+ if (c->cached.service_url != NULL) {
+ gpr_free(c->cached.service_url);
+ c->cached.service_url = NULL;
+ }
+ c->cached.jwt_expiration = gpr_inf_past;
+}
+
+static void jwt_destroy(grpc_credentials *creds) {
+ grpc_jwt_credentials *c = (grpc_jwt_credentials *)creds;
+ grpc_auth_json_key_destruct(&c->key);
+ jwt_reset_cache(c);
+ gpr_mu_destroy(&c->cache_mu);
+ grpc_mdctx_unref(c->md_ctx);
+ gpr_free(c);
+}
+
+static int jwt_has_request_metadata(const grpc_credentials *creds) { return 1; }
+
+static int jwt_has_request_metadata_only(const grpc_credentials *creds) {
+ return 1;
+}
+
+
+static void jwt_get_request_metadata(grpc_credentials *creds,
+ const char *service_url,
+ grpc_credentials_metadata_cb cb,
+ void *user_data) {
+ grpc_jwt_credentials *c = (grpc_jwt_credentials *)creds;
+ gpr_timespec refresh_threshold = {GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS,
+ 0};
+
+ /* See if we can return a cached jwt. */
+ grpc_mdelem *jwt_md = NULL;
+ {
+ gpr_mu_lock(&c->cache_mu);
+ if (c->cached.service_url != NULL &&
+ !strcmp(c->cached.service_url, service_url) &&
+ c->cached.jwt_md != NULL &&
+ (gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration, gpr_now()),
+ refresh_threshold) > 0)) {
+ jwt_md = grpc_mdelem_ref(c->cached.jwt_md);
+ }
+ gpr_mu_unlock(&c->cache_mu);
+ }
+
+ if (jwt_md == NULL) {
+ char *jwt = NULL;
+ /* Generate a new jwt. */
+ gpr_mu_lock(&c->cache_mu);
+ jwt_reset_cache(c);
+ jwt = grpc_jwt_encode_and_sign(&c->key, service_url, c->jwt_lifetime, NULL);
+ if (jwt != NULL) {
+ char *md_value;
+ gpr_asprintf(&md_value, "Bearer %s", jwt);
+ gpr_free(jwt);
+ c->cached.jwt_expiration = gpr_time_add(gpr_now(), c->jwt_lifetime);
+ c->cached.service_url = gpr_strdup(service_url);
+ c->cached.jwt_md = grpc_mdelem_from_strings(
+ c->md_ctx, GRPC_AUTHORIZATION_METADATA_KEY, md_value);
+ gpr_free(md_value);
+ jwt_md = grpc_mdelem_ref(c->cached.jwt_md);
+ }
+ gpr_mu_unlock(&c->cache_mu);
+ }
+
+ if (jwt_md != NULL) {
+ cb(user_data, &jwt_md, 1, GRPC_CREDENTIALS_OK);
+ grpc_mdelem_unref(jwt_md);
+ } else {
+ cb(user_data, NULL, 0, GRPC_CREDENTIALS_ERROR);
+ }
+}
+
+static grpc_credentials_vtable jwt_vtable = {
+ jwt_destroy, jwt_has_request_metadata, jwt_has_request_metadata_only,
+ jwt_get_request_metadata};
+
+grpc_credentials *grpc_jwt_credentials_create(const char *json_key,
+ gpr_timespec token_lifetime) {
+ grpc_jwt_credentials *c;
+ grpc_auth_json_key key = grpc_auth_json_key_create_from_string(json_key);
+ if (!grpc_auth_json_key_is_valid(&key)) {
+ gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation");
+ return NULL;
+ }
+ c = gpr_malloc(sizeof(grpc_jwt_credentials));
+ memset(c, 0, sizeof(grpc_jwt_credentials));
+ c->base.type = GRPC_CREDENTIALS_TYPE_JWT;
+ gpr_ref_init(&c->base.refcount, 1);
+ c->base.vtable = &jwt_vtable;
+ c->md_ctx = grpc_mdctx_create();
+ c->key = key;
+ c->jwt_lifetime = token_lifetime;
+ gpr_mu_init(&c->cache_mu);
+ jwt_reset_cache(c);
+ return &c->base;
+}
+
/* -- Oauth2TokenFetcher credentials -- */
/* This object is a base for credentials that need to acquire an oauth2 token
@@ -439,10 +561,11 @@ static void on_oauth2_token_fetcher_http_response(
}
static void oauth2_token_fetcher_get_request_metadata(
- grpc_credentials *creds, grpc_credentials_metadata_cb cb, void *user_data) {
+ grpc_credentials *creds, const char *service_url,
+ grpc_credentials_metadata_cb cb, void *user_data) {
grpc_oauth2_token_fetcher_credentials *c =
(grpc_oauth2_token_fetcher_credentials *)creds;
- gpr_timespec refresh_threshold = {GRPC_OAUTH2_TOKEN_REFRESH_THRESHOLD_SECS,
+ gpr_timespec refresh_threshold = {GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS,
0};
grpc_mdelem *cached_access_token_md = NULL;
{
@@ -535,7 +658,8 @@ static void service_account_fetch_oauth2(
"application/x-www-form-urlencoded"};
grpc_httpcli_request request;
char *body = NULL;
- char *jwt = grpc_jwt_encode_and_sign(&c->key, c->scope, c->token_lifetime);
+ 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));
@@ -616,6 +740,7 @@ void on_simulated_token_fetch_done(void *user_data, int success) {
}
static void fake_oauth2_get_request_metadata(grpc_credentials *creds,
+ const char *service_url,
grpc_credentials_metadata_cb cb,
void *user_data) {
grpc_fake_oauth2_credentials *c = (grpc_fake_oauth2_credentials *)creds;
@@ -709,6 +834,7 @@ typedef struct {
size_t creds_index;
grpc_mdelem **md_elems;
size_t num_md;
+ char *service_url;
void *user_data;
grpc_credentials_metadata_cb cb;
} grpc_composite_credentials_metadata_context;
@@ -754,6 +880,7 @@ static void composite_md_context_destroy(
grpc_mdelem_unref(ctx->md_elems[i]);
}
gpr_free(ctx->md_elems);
+ if (ctx->service_url != NULL) gpr_free(ctx->service_url);
gpr_free(ctx);
}
@@ -783,8 +910,8 @@ static void composite_metadata_cb(void *user_data, grpc_mdelem **md_elems,
grpc_credentials *inner_creds =
ctx->composite_creds->inner.creds_array[ctx->creds_index++];
if (grpc_credentials_has_request_metadata(inner_creds)) {
- grpc_credentials_get_request_metadata(inner_creds, composite_metadata_cb,
- ctx);
+ grpc_credentials_get_request_metadata(inner_creds, ctx->service_url,
+ composite_metadata_cb, ctx);
return;
}
}
@@ -795,6 +922,7 @@ static void composite_metadata_cb(void *user_data, grpc_mdelem **md_elems,
}
static void composite_get_request_metadata(grpc_credentials *creds,
+ const char *service_url,
grpc_credentials_metadata_cb cb,
void *user_data) {
grpc_composite_credentials *c = (grpc_composite_credentials *)creds;
@@ -805,14 +933,15 @@ static void composite_get_request_metadata(grpc_credentials *creds,
}
ctx = gpr_malloc(sizeof(grpc_composite_credentials_metadata_context));
memset(ctx, 0, sizeof(grpc_composite_credentials_metadata_context));
+ ctx->service_url = gpr_strdup(service_url);
ctx->user_data = user_data;
ctx->cb = cb;
ctx->composite_creds = c;
while (ctx->creds_index < c->inner.num_creds) {
grpc_credentials *inner_creds = c->inner.creds_array[ctx->creds_index++];
if (grpc_credentials_has_request_metadata(inner_creds)) {
- grpc_credentials_get_request_metadata(inner_creds, composite_metadata_cb,
- ctx);
+ grpc_credentials_get_request_metadata(inner_creds, service_url,
+ composite_metadata_cb, ctx);
return;
}
}
@@ -916,6 +1045,7 @@ static int iam_has_request_metadata_only(const grpc_credentials *creds) {
}
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;
diff --git a/src/core/security/credentials.h b/src/core/security/credentials.h
index 614db96ad7..7b8929492b 100644
--- a/src/core/security/credentials.h
+++ b/src/core/security/credentials.h
@@ -50,6 +50,7 @@ typedef enum {
#define GRPC_CREDENTIALS_TYPE_SSL "Ssl"
#define GRPC_CREDENTIALS_TYPE_OAUTH2 "Oauth2"
+#define GRPC_CREDENTIALS_TYPE_JWT "Jwt"
#define GRPC_CREDENTIALS_TYPE_IAM "Iam"
#define GRPC_CREDENTIALS_TYPE_COMPOSITE "Composite"
#define GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY "FakeTransportSecurity"
@@ -71,6 +72,7 @@ typedef struct {
int (*has_request_metadata)(const grpc_credentials *c);
int (*has_request_metadata_only)(const grpc_credentials *c);
void (*get_request_metadata)(grpc_credentials *c,
+ const char *service_url,
grpc_credentials_metadata_cb cb,
void *user_data);
} grpc_credentials_vtable;
@@ -86,6 +88,7 @@ void grpc_credentials_unref(grpc_credentials *creds);
int grpc_credentials_has_request_metadata(grpc_credentials *creds);
int grpc_credentials_has_request_metadata_only(grpc_credentials *creds);
void grpc_credentials_get_request_metadata(grpc_credentials *creds,
+ const char *service_url,
grpc_credentials_metadata_cb cb,
void *user_data);
typedef struct {
diff --git a/src/core/security/json_token.c b/src/core/security/json_token.c
index 20d62e2b43..26d57036a6 100644
--- a/src/core/security/json_token.c
+++ b/src/core/security/json_token.c
@@ -55,7 +55,6 @@ const gpr_timespec grpc_max_auth_token_lifetime = {3600, 0};
#define GRPC_AUTH_JSON_KEY_TYPE_INVALID "invalid"
#define GRPC_AUTH_JSON_KEY_TYPE_SERVICE_ACCOUNT "service_account"
-#define GRPC_JWT_AUDIENCE "https://www.googleapis.com/oauth2/v3/token"
#define GRPC_JWT_RSA_SHA256_ALGORITHM "RS256"
#define GRPC_JWT_TYPE "JWT"
@@ -171,8 +170,8 @@ void grpc_auth_json_key_destruct(grpc_auth_json_key *json_key) {
/* --- jwt encoding and signature. --- */
static grpc_json *create_child(grpc_json *brother, grpc_json *parent,
- const char *key, const char *value,
- grpc_json_type type) {
+ const char *key, const char *value,
+ grpc_json_type type) {
grpc_json *child = grpc_json_create(type);
if (brother) brother->next = child;
if (!parent->child) parent->child = child;
@@ -182,14 +181,15 @@ static grpc_json *create_child(grpc_json *brother, grpc_json *parent,
return child;
}
-static char *encoded_jwt_header(const char *algorithm) {
+static char *encoded_jwt_header(const char *key_id, const char *algorithm) {
grpc_json *json = grpc_json_create(GRPC_JSON_OBJECT);
grpc_json *child = NULL;
char *json_str = NULL;
char *result = NULL;
child = create_child(NULL, json, "alg", algorithm, GRPC_JSON_STRING);
- create_child(child, json, "typ", GRPC_JWT_TYPE, GRPC_JSON_STRING);
+ child = create_child(child, json, "typ", GRPC_JWT_TYPE, GRPC_JSON_STRING);
+ create_child(child, json, "kid", key_id, GRPC_JSON_STRING);
json_str = grpc_json_dump_to_string(json, 0);
result = grpc_base64_encode(json_str, strlen(json_str), 1, 0);
@@ -199,7 +199,8 @@ static char *encoded_jwt_header(const char *algorithm) {
}
static char *encoded_jwt_claim(const grpc_auth_json_key *json_key,
- const char *scope, gpr_timespec token_lifetime) {
+ const char *audience,
+ gpr_timespec token_lifetime, const char *scope) {
grpc_json *json = grpc_json_create(GRPC_JSON_OBJECT);
grpc_json *child = NULL;
char *json_str = NULL;
@@ -217,8 +218,15 @@ static char *encoded_jwt_claim(const grpc_auth_json_key *json_key,
child = create_child(NULL, json, "iss", json_key->client_email,
GRPC_JSON_STRING);
- child = create_child(child, json, "scope", scope, GRPC_JSON_STRING);
- child = create_child(child, json, "aud", GRPC_JWT_AUDIENCE, GRPC_JSON_STRING);
+ if (scope != NULL) {
+ child = create_child(child, json, "scope", scope, GRPC_JSON_STRING);
+ } else {
+ /* Unscoped JWTs need a sub field. */
+ child = create_child(child, json, "sub", json_key->client_email,
+ GRPC_JSON_STRING);
+ }
+
+ child = create_child(child, json, "aud", audience, GRPC_JSON_STRING);
child = create_child(child, json, "iat", now_str, GRPC_JSON_NUMBER);
create_child(child, json, "exp", expiration_str, GRPC_JSON_NUMBER);
@@ -300,14 +308,16 @@ end:
}
char *grpc_jwt_encode_and_sign(const grpc_auth_json_key *json_key,
- const char *scope, gpr_timespec token_lifetime) {
+ const char *audience,
+ gpr_timespec token_lifetime, const char *scope) {
if (g_jwt_encode_and_sign_override != NULL) {
- return g_jwt_encode_and_sign_override(json_key, scope, token_lifetime);
+ return g_jwt_encode_and_sign_override(json_key, audience, token_lifetime,
+ scope);
} else {
const char *sig_algo = GRPC_JWT_RSA_SHA256_ALGORITHM;
char *to_sign = dot_concat_and_free_strings(
- encoded_jwt_header(sig_algo),
- encoded_jwt_claim(json_key, scope, token_lifetime));
+ encoded_jwt_header(json_key->private_key_id, sig_algo),
+ encoded_jwt_claim(json_key, audience, token_lifetime, scope));
char *sig = compute_and_encode_signature(json_key, sig_algo, to_sign);
if (sig == NULL) {
gpr_free(to_sign);
diff --git a/src/core/security/json_token.h b/src/core/security/json_token.h
index 5a9b2dab4b..1ef9682f52 100644
--- a/src/core/security/json_token.h
+++ b/src/core/security/json_token.h
@@ -37,6 +37,10 @@
#include <grpc/support/slice.h>
#include <openssl/rsa.h>
+/* --- Constants. --- */
+
+#define GRPC_JWT_OAUTH2_AUDIENCE "https://www.googleapis.com/oauth2/v3/token"
+
/* --- auth_json_key parsing. --- */
typedef struct {
@@ -61,14 +65,15 @@ void grpc_auth_json_key_destruct(grpc_auth_json_key *json_key);
/* --- json token encoding and signing. --- */
/* Caller is responsible for calling gpr_free on the returned value. May return
- NULL on invalid input. */
+ NULL on invalid input. The scope parameter may be NULL. */
char *grpc_jwt_encode_and_sign(const grpc_auth_json_key *json_key,
- const char *scope, gpr_timespec token_lifetime);
+ const char *audience,
+ gpr_timespec token_lifetime, const char *scope);
/* Override encode_and_sign function for testing. */
typedef char *(*grpc_jwt_encode_and_sign_override)(
- const grpc_auth_json_key *json_key, const char *scope,
- gpr_timespec token_lifetime);
+ const grpc_auth_json_key *json_key, const char *audience,
+ gpr_timespec token_lifetime, const char *scope);
/* Set a custom encode_and_sign override for testing. */
void grpc_jwt_encode_and_sign_set_override(
diff --git a/src/core/security/security_context.c b/src/core/security/security_context.c
index 37a312bc81..71bd06b271 100644
--- a/src/core/security/security_context.c
+++ b/src/core/security/security_context.c
@@ -238,6 +238,7 @@ grpc_channel_security_context *grpc_fake_channel_security_context_create(
gpr_malloc(sizeof(grpc_fake_channel_security_context));
gpr_ref_init(&c->base.base.refcount, 1);
c->base.base.is_client_side = 1;
+ c->base.base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME;
c->base.base.vtable = &fake_channel_vtable;
GPR_ASSERT(check_request_metadata_creds(request_metadata_creds));
c->base.request_metadata_creds = grpc_credentials_ref(request_metadata_creds);
@@ -250,6 +251,7 @@ grpc_security_context *grpc_fake_server_security_context_create(void) {
grpc_security_context *c = gpr_malloc(sizeof(grpc_security_context));
gpr_ref_init(&c->refcount, 1);
c->vtable = &fake_server_vtable;
+ c->url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME;
return c;
}
@@ -458,6 +460,7 @@ grpc_security_status grpc_ssl_channel_security_context_create(
gpr_ref_init(&c->base.base.refcount, 1);
c->base.base.vtable = &ssl_channel_vtable;
c->base.base.is_client_side = 1;
+ c->base.base.url_scheme = GRPC_SSL_URL_SCHEME;
c->base.request_metadata_creds = grpc_credentials_ref(request_metadata_creds);
c->base.check_call_host = ssl_channel_check_call_host;
if (target_name != NULL) {
@@ -525,6 +528,7 @@ grpc_security_status grpc_ssl_server_security_context_create(
memset(c, 0, sizeof(grpc_ssl_server_security_context));
gpr_ref_init(&c->base.refcount, 1);
+ c->base.url_scheme = GRPC_SSL_URL_SCHEME;
c->base.vtable = &ssl_server_vtable;
result = tsi_create_ssl_server_handshaker_factory(
(const unsigned char **)config->pem_private_keys,
diff --git a/src/core/security/security_context.h b/src/core/security/security_context.h
index 2b9610fac3..40e2daceb8 100644
--- a/src/core/security/security_context.h
+++ b/src/core/security/security_context.h
@@ -47,6 +47,11 @@ typedef enum {
GRPC_SECURITY_ERROR
} grpc_security_status;
+/* --- URL schemes. --- */
+
+#define GRPC_SSL_URL_SCHEME "https"
+#define GRPC_FAKE_SECURITY_URL_SCHEME "http+fake_security"
+
/* --- security_context object. ---
A security context object represents away to configure the underlying
@@ -72,6 +77,7 @@ struct grpc_security_context {
const grpc_security_context_vtable *vtable;
gpr_refcount refcount;
int is_client_side;
+ const char *url_scheme;
};
/* Increments the refcount. */