Removing the auth context from the security connector.

The security connector is a channel/server port wide construct. On the
other hand, the auth_context is a per-connection construct.
pull/4523/head
Julien Boeuf 9 years ago
parent 788767a18f
commit 366f42c12d
  1. 15
      src/core/httpcli/httpcli_security_connector.c
  2. 22
      src/core/security/client_auth_filter.c
  3. 22
      src/core/security/handshake.c
  4. 79
      src/core/security/security_connector.c
  5. 43
      src/core/security/security_connector.h
  6. 10
      src/core/security/server_secure_chttp2.c
  7. 12
      src/core/surface/secure_channel_create.c

@ -68,7 +68,7 @@ static void httpcli_ssl_do_handshake(grpc_exec_ctx *exec_ctx,
tsi_result result = TSI_OK; tsi_result result = TSI_OK;
tsi_handshaker *handshaker; tsi_handshaker *handshaker;
if (c->handshaker_factory == NULL) { if (c->handshaker_factory == NULL) {
cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL); cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
return; return;
} }
result = tsi_ssl_handshaker_factory_create_handshaker( result = tsi_ssl_handshaker_factory_create_handshaker(
@ -76,16 +76,16 @@ static void httpcli_ssl_do_handshake(grpc_exec_ctx *exec_ctx,
if (result != TSI_OK) { if (result != TSI_OK) {
gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.", gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
tsi_result_to_string(result)); tsi_result_to_string(result));
cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL); cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
} else { } else {
grpc_do_security_handshake(exec_ctx, handshaker, sc, nonsecure_endpoint, cb, grpc_do_security_handshake(exec_ctx, handshaker, sc, nonsecure_endpoint, cb,
user_data); user_data);
} }
} }
static grpc_security_status httpcli_ssl_check_peer(grpc_security_connector *sc, static void httpcli_ssl_check_peer(grpc_exec_ctx *exec_ctx,
tsi_peer peer, grpc_security_connector *sc, tsi_peer peer,
grpc_security_check_cb cb, grpc_security_peer_check_cb cb,
void *user_data) { void *user_data) {
grpc_httpcli_ssl_channel_security_connector *c = grpc_httpcli_ssl_channel_security_connector *c =
(grpc_httpcli_ssl_channel_security_connector *)sc; (grpc_httpcli_ssl_channel_security_connector *)sc;
@ -99,7 +99,7 @@ static grpc_security_status httpcli_ssl_check_peer(grpc_security_connector *sc,
status = GRPC_SECURITY_ERROR; status = GRPC_SECURITY_ERROR;
} }
tsi_peer_destruct(&peer); tsi_peer_destruct(&peer);
return status; cb(exec_ctx, user_data, status, NULL);
} }
static grpc_security_connector_vtable httpcli_ssl_vtable = { static grpc_security_connector_vtable httpcli_ssl_vtable = {
@ -149,7 +149,8 @@ typedef struct {
static void on_secure_transport_setup_done(grpc_exec_ctx *exec_ctx, void *rp, static void on_secure_transport_setup_done(grpc_exec_ctx *exec_ctx, void *rp,
grpc_security_status status, grpc_security_status status,
grpc_endpoint *secure_endpoint) { grpc_endpoint *secure_endpoint,
grpc_auth_context *auth_context) {
on_done_closure *c = rp; on_done_closure *c = rp;
if (status != GRPC_SECURITY_OK) { if (status != GRPC_SECURITY_OK) {
gpr_log(GPR_ERROR, "Secure transport setup failed with error %d.", status); gpr_log(GPR_ERROR, "Secure transport setup failed with error %d.", status);

@ -68,6 +68,7 @@ typedef struct {
/* We can have a per-channel credentials. */ /* We can have a per-channel credentials. */
typedef struct { typedef struct {
grpc_channel_security_connector *security_connector; grpc_channel_security_connector *security_connector;
grpc_auth_context *auth_context;
} channel_data; } channel_data;
static void reset_auth_metadata_context( static void reset_auth_metadata_context(
@ -122,6 +123,7 @@ static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data,
} }
void build_auth_metadata_context(grpc_security_connector *sc, void build_auth_metadata_context(grpc_security_connector *sc,
grpc_auth_context *auth_context,
call_data *calld) { call_data *calld) {
char *service = gpr_strdup(grpc_mdstr_as_c_string(calld->method)); char *service = gpr_strdup(grpc_mdstr_as_c_string(calld->method));
char *last_slash = strrchr(service, '/'); char *last_slash = strrchr(service, '/');
@ -145,7 +147,7 @@ void build_auth_metadata_context(grpc_security_connector *sc,
calld->auth_md_context.service_url = service_url; calld->auth_md_context.service_url = service_url;
calld->auth_md_context.method_name = method_name; calld->auth_md_context.method_name = method_name;
calld->auth_md_context.channel_auth_context = calld->auth_md_context.channel_auth_context =
GRPC_AUTH_CONTEXT_REF(sc->auth_context, "grpc_auth_metadata_context"); GRPC_AUTH_CONTEXT_REF(auth_context, "grpc_auth_metadata_context");
gpr_free(service); gpr_free(service);
} }
@ -179,7 +181,8 @@ static void send_security_metadata(grpc_exec_ctx *exec_ctx,
call_creds_has_md ? ctx->creds : channel_call_creds); call_creds_has_md ? ctx->creds : channel_call_creds);
} }
build_auth_metadata_context(&chand->security_connector->base, calld); build_auth_metadata_context(&chand->security_connector->base,
chand->auth_context, calld);
calld->op = *op; /* Copy op (originates from the caller's stack). */ calld->op = *op; /* Copy op (originates from the caller's stack). */
GPR_ASSERT(calld->pollset); GPR_ASSERT(calld->pollset);
grpc_call_credentials_get_request_metadata( grpc_call_credentials_get_request_metadata(
@ -230,7 +233,7 @@ static void auth_start_transport_op(grpc_exec_ctx *exec_ctx,
sec_ctx = op->context[GRPC_CONTEXT_SECURITY].value; sec_ctx = op->context[GRPC_CONTEXT_SECURITY].value;
GRPC_AUTH_CONTEXT_UNREF(sec_ctx->auth_context, "client auth filter"); GRPC_AUTH_CONTEXT_UNREF(sec_ctx->auth_context, "client auth filter");
sec_ctx->auth_context = GRPC_AUTH_CONTEXT_REF( sec_ctx->auth_context = GRPC_AUTH_CONTEXT_REF(
chand->security_connector->base.auth_context, "client_auth_filter"); chand->auth_context, "client_auth_filter");
} }
if (op->send_initial_metadata != NULL) { if (op->send_initial_metadata != NULL) {
@ -307,6 +310,9 @@ static void init_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element_args *args) { grpc_channel_element_args *args) {
grpc_security_connector *sc = grpc_security_connector *sc =
grpc_find_security_connector_in_args(args->channel_args); grpc_find_security_connector_in_args(args->channel_args);
grpc_auth_context *auth_context =
grpc_find_auth_context_in_args(args->channel_args);
/* grab pointers to our data from the channel element */ /* grab pointers to our data from the channel element */
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
@ -315,12 +321,15 @@ static void init_channel_elem(grpc_exec_ctx *exec_ctx,
path */ path */
GPR_ASSERT(!args->is_last); GPR_ASSERT(!args->is_last);
GPR_ASSERT(sc != NULL); GPR_ASSERT(sc != NULL);
GPR_ASSERT(auth_context != NULL);
/* initialize members */ /* initialize members */
GPR_ASSERT(sc->is_client_side); GPR_ASSERT(sc->is_client_side);
chand->security_connector = chand->security_connector =
(grpc_channel_security_connector *)GRPC_SECURITY_CONNECTOR_REF( (grpc_channel_security_connector *)GRPC_SECURITY_CONNECTOR_REF(
sc, "client_auth_filter"); sc, "client_auth_filter");
chand->auth_context =
GRPC_AUTH_CONTEXT_REF(auth_context, "client_auth_filter");
} }
/* Destructor for channel data */ /* Destructor for channel data */
@ -328,10 +337,11 @@ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem) { grpc_channel_element *elem) {
/* grab pointers to our data from the channel element */ /* grab pointers to our data from the channel element */
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
grpc_channel_security_connector *ctx = chand->security_connector; grpc_channel_security_connector *sc = chand->security_connector;
if (ctx != NULL) { if (sc != NULL) {
GRPC_SECURITY_CONNECTOR_UNREF(&ctx->base, "client_auth_filter"); GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "client_auth_filter");
} }
GRPC_AUTH_CONTEXT_UNREF(chand->auth_context, "client_auth_filter");
} }
const grpc_channel_filter grpc_client_auth_filter = { const grpc_channel_filter grpc_client_auth_filter = {

@ -35,6 +35,7 @@
#include <string.h> #include <string.h>
#include "src/core/security/security_context.h"
#include "src/core/security/secure_endpoint.h" #include "src/core/security/secure_endpoint.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
@ -56,6 +57,7 @@ typedef struct {
void *user_data; void *user_data;
grpc_closure on_handshake_data_sent_to_peer; grpc_closure on_handshake_data_sent_to_peer;
grpc_closure on_handshake_data_received_from_peer; grpc_closure on_handshake_data_received_from_peer;
grpc_auth_context *auth_context;
} grpc_security_handshake; } grpc_security_handshake;
static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx, static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
@ -96,7 +98,8 @@ static void security_handshake_done(grpc_exec_ctx *exec_ctx,
security_connector_remove_handshake(h); security_connector_remove_handshake(h);
} }
if (is_success) { if (is_success) {
h->cb(exec_ctx, h->user_data, GRPC_SECURITY_OK, h->secure_endpoint); h->cb(exec_ctx, h->user_data, GRPC_SECURITY_OK, h->secure_endpoint,
h->auth_context);
} else { } else {
if (h->secure_endpoint != NULL) { if (h->secure_endpoint != NULL) {
grpc_endpoint_shutdown(exec_ctx, h->secure_endpoint); grpc_endpoint_shutdown(exec_ctx, h->secure_endpoint);
@ -104,19 +107,21 @@ static void security_handshake_done(grpc_exec_ctx *exec_ctx,
} else { } else {
grpc_endpoint_destroy(exec_ctx, h->wrapped_endpoint); grpc_endpoint_destroy(exec_ctx, h->wrapped_endpoint);
} }
h->cb(exec_ctx, h->user_data, GRPC_SECURITY_ERROR, NULL); h->cb(exec_ctx, h->user_data, GRPC_SECURITY_ERROR, NULL, NULL);
} }
if (h->handshaker != NULL) tsi_handshaker_destroy(h->handshaker); if (h->handshaker != NULL) tsi_handshaker_destroy(h->handshaker);
if (h->handshake_buffer != NULL) gpr_free(h->handshake_buffer); if (h->handshake_buffer != NULL) gpr_free(h->handshake_buffer);
gpr_slice_buffer_destroy(&h->left_overs); gpr_slice_buffer_destroy(&h->left_overs);
gpr_slice_buffer_destroy(&h->outgoing); gpr_slice_buffer_destroy(&h->outgoing);
gpr_slice_buffer_destroy(&h->incoming); gpr_slice_buffer_destroy(&h->incoming);
GRPC_AUTH_CONTEXT_UNREF(h->auth_context, "handshake");
GRPC_SECURITY_CONNECTOR_UNREF(h->connector, "handshake"); GRPC_SECURITY_CONNECTOR_UNREF(h->connector, "handshake");
gpr_free(h); gpr_free(h);
} }
static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *user_data, static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *user_data,
grpc_security_status status) { grpc_security_status status,
grpc_auth_context *auth_context) {
grpc_security_handshake *h = user_data; grpc_security_handshake *h = user_data;
tsi_frame_protector *protector; tsi_frame_protector *protector;
tsi_result result; tsi_result result;
@ -125,6 +130,7 @@ static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *user_data,
security_handshake_done(exec_ctx, h, 0); security_handshake_done(exec_ctx, h, 0);
return; return;
} }
h->auth_context = GRPC_AUTH_CONTEXT_REF(auth_context, "handshake");
result = result =
tsi_handshaker_create_frame_protector(h->handshaker, NULL, &protector); tsi_handshaker_create_frame_protector(h->handshaker, NULL, &protector);
if (result != TSI_OK) { if (result != TSI_OK) {
@ -143,7 +149,6 @@ static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *user_data,
} }
static void check_peer(grpc_exec_ctx *exec_ctx, grpc_security_handshake *h) { static void check_peer(grpc_exec_ctx *exec_ctx, grpc_security_handshake *h) {
grpc_security_status peer_status;
tsi_peer peer; tsi_peer peer;
tsi_result result = tsi_handshaker_extract_peer(h->handshaker, &peer); tsi_result result = tsi_handshaker_extract_peer(h->handshaker, &peer);
@ -153,15 +158,8 @@ static void check_peer(grpc_exec_ctx *exec_ctx, grpc_security_handshake *h) {
security_handshake_done(exec_ctx, h, 0); security_handshake_done(exec_ctx, h, 0);
return; return;
} }
peer_status = grpc_security_connector_check_peer(h->connector, peer, grpc_security_connector_check_peer(exec_ctx, h->connector, peer,
on_peer_checked, h); on_peer_checked, h);
if (peer_status == GRPC_SECURITY_ERROR) {
gpr_log(GPR_ERROR, "Peer check failed.");
security_handshake_done(exec_ctx, h, 0);
return;
} else if (peer_status == GRPC_SECURITY_OK) {
on_peer_checked(exec_ctx, h, peer_status);
}
} }
static void send_handshake_bytes_to_peer(grpc_exec_ctx *exec_ctx, static void send_handshake_bytes_to_peer(grpc_exec_ctx *exec_ctx,

@ -124,25 +124,26 @@ void grpc_security_connector_do_handshake(grpc_exec_ctx *exec_ctx,
grpc_security_handshake_done_cb cb, grpc_security_handshake_done_cb cb,
void *user_data) { void *user_data) {
if (sc == NULL || nonsecure_endpoint == NULL) { if (sc == NULL || nonsecure_endpoint == NULL) {
cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL); cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
} else { } else {
sc->vtable->do_handshake(exec_ctx, sc, nonsecure_endpoint, cb, user_data); sc->vtable->do_handshake(exec_ctx, sc, nonsecure_endpoint, cb, user_data);
} }
} }
grpc_security_status grpc_security_connector_check_peer( void grpc_security_connector_check_peer(
grpc_security_connector *sc, tsi_peer peer, grpc_security_check_cb cb, grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, tsi_peer peer,
void *user_data) { grpc_security_peer_check_cb cb, void *user_data) {
if (sc == NULL) { if (sc == NULL) {
tsi_peer_destruct(&peer); tsi_peer_destruct(&peer);
return GRPC_SECURITY_ERROR; cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL);
} else {
sc->vtable->check_peer(exec_ctx, sc, peer, cb, user_data);
} }
return sc->vtable->check_peer(sc, peer, cb, user_data);
} }
grpc_security_status grpc_channel_security_connector_check_call_host( grpc_security_status grpc_channel_security_connector_check_call_host(
grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc, grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
const char *host, grpc_security_check_cb cb, void *user_data) { const char *host, grpc_security_call_host_check_cb cb, void *user_data) {
if (sc == NULL || sc->check_call_host == NULL) return GRPC_SECURITY_ERROR; if (sc == NULL || sc->check_call_host == NULL) return GRPC_SECURITY_ERROR;
return sc->check_call_host(exec_ctx, sc, host, cb, user_data); return sc->check_call_host(exec_ctx, sc, host, cb, user_data);
} }
@ -229,22 +230,20 @@ typedef struct {
static void fake_channel_destroy(grpc_security_connector *sc) { static void fake_channel_destroy(grpc_security_connector *sc) {
grpc_channel_security_connector *c = (grpc_channel_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(c->request_metadata_creds);
GRPC_AUTH_CONTEXT_UNREF(sc->auth_context, "connector");
gpr_free(sc); gpr_free(sc);
} }
static void fake_server_destroy(grpc_security_connector *sc) { static void fake_server_destroy(grpc_security_connector *sc) {
GRPC_AUTH_CONTEXT_UNREF(sc->auth_context, "connector");
gpr_mu_destroy(&sc->mu); gpr_mu_destroy(&sc->mu);
gpr_free(sc); gpr_free(sc);
} }
static grpc_security_status fake_check_peer(grpc_security_connector *sc, static void fake_check_peer(grpc_exec_ctx *exec_ctx,
tsi_peer peer, grpc_security_connector *sc, tsi_peer peer,
grpc_security_check_cb cb, grpc_security_peer_check_cb cb, void *user_data) {
void *user_data) {
const char *prop_name; const char *prop_name;
grpc_security_status status = GRPC_SECURITY_OK; grpc_security_status status = GRPC_SECURITY_OK;
grpc_auth_context *auth_context = NULL;
if (peer.property_count != 1) { if (peer.property_count != 1) {
gpr_log(GPR_ERROR, "Fake peers should only have 1 property."); gpr_log(GPR_ERROR, "Fake peers should only have 1 property.");
status = GRPC_SECURITY_ERROR; status = GRPC_SECURITY_ERROR;
@ -264,20 +263,20 @@ static grpc_security_status fake_check_peer(grpc_security_connector *sc,
status = GRPC_SECURITY_ERROR; status = GRPC_SECURITY_ERROR;
goto end; goto end;
} }
GRPC_AUTH_CONTEXT_UNREF(sc->auth_context, "connector"); auth_context = grpc_auth_context_create(NULL);
sc->auth_context = grpc_auth_context_create(NULL);
grpc_auth_context_add_cstring_property( grpc_auth_context_add_cstring_property(
sc->auth_context, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, auth_context, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
GRPC_FAKE_TRANSPORT_SECURITY_TYPE); GRPC_FAKE_TRANSPORT_SECURITY_TYPE);
end: end:
cb(exec_ctx, user_data, status, auth_context);
tsi_peer_destruct(&peer); tsi_peer_destruct(&peer);
return status; grpc_auth_context_unref(auth_context);
} }
static grpc_security_status fake_channel_check_call_host( static grpc_security_status fake_channel_check_call_host(
grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc, grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
const char *host, grpc_security_check_cb cb, void *user_data) { const char *host, grpc_security_call_host_check_cb cb, void *user_data) {
grpc_fake_channel_security_connector *c = grpc_fake_channel_security_connector *c =
(grpc_fake_channel_security_connector *)sc; (grpc_fake_channel_security_connector *)sc;
if (c->call_host_check_is_async) { if (c->call_host_check_is_async) {
@ -347,6 +346,8 @@ typedef struct {
tsi_ssl_handshaker_factory *handshaker_factory; tsi_ssl_handshaker_factory *handshaker_factory;
char *target_name; char *target_name;
char *overridden_target_name; char *overridden_target_name;
/* TODO(jboeuf): Remove this: the security connector is channel-wide construct
as opposed to the peer which is for one transport (or sub-channel). */
tsi_peer peer; tsi_peer peer;
} grpc_ssl_channel_security_connector; } grpc_ssl_channel_security_connector;
@ -365,7 +366,6 @@ static void ssl_channel_destroy(grpc_security_connector *sc) {
if (c->target_name != NULL) gpr_free(c->target_name); if (c->target_name != NULL) gpr_free(c->target_name);
if (c->overridden_target_name != NULL) gpr_free(c->overridden_target_name); if (c->overridden_target_name != NULL) gpr_free(c->overridden_target_name);
tsi_peer_destruct(&c->peer); tsi_peer_destruct(&c->peer);
GRPC_AUTH_CONTEXT_UNREF(sc->auth_context, "connector");
gpr_free(sc); gpr_free(sc);
} }
@ -376,7 +376,6 @@ static void ssl_server_destroy(grpc_security_connector *sc) {
if (c->handshaker_factory != NULL) { if (c->handshaker_factory != NULL) {
tsi_ssl_handshaker_factory_destroy(c->handshaker_factory); tsi_ssl_handshaker_factory_destroy(c->handshaker_factory);
} }
GRPC_AUTH_CONTEXT_UNREF(sc->auth_context, "connector");
gpr_mu_destroy(&sc->mu); gpr_mu_destroy(&sc->mu);
gpr_free(sc); gpr_free(sc);
} }
@ -410,7 +409,7 @@ static void ssl_channel_do_handshake(grpc_exec_ctx *exec_ctx,
: c->target_name, : c->target_name,
&handshaker); &handshaker);
if (status != GRPC_SECURITY_OK) { if (status != GRPC_SECURITY_OK) {
cb(exec_ctx, user_data, status, NULL); cb(exec_ctx, user_data, status, NULL, NULL);
} else { } else {
grpc_do_security_handshake(exec_ctx, handshaker, sc, nonsecure_endpoint, cb, grpc_do_security_handshake(exec_ctx, handshaker, sc, nonsecure_endpoint, cb,
user_data); user_data);
@ -428,7 +427,7 @@ static void ssl_server_do_handshake(grpc_exec_ctx *exec_ctx,
grpc_security_status status = grpc_security_status status =
ssl_create_handshaker(c->handshaker_factory, 0, NULL, &handshaker); ssl_create_handshaker(c->handshaker_factory, 0, NULL, &handshaker);
if (status != GRPC_SECURITY_OK) { if (status != GRPC_SECURITY_OK) {
cb(exec_ctx, user_data, status, NULL); cb(exec_ctx, user_data, status, NULL, NULL);
} else { } else {
grpc_do_security_handshake(exec_ctx, handshaker, sc, nonsecure_endpoint, cb, grpc_do_security_handshake(exec_ctx, handshaker, sc, nonsecure_endpoint, cb,
user_data); user_data);
@ -488,7 +487,8 @@ grpc_auth_context *tsi_ssl_peer_to_auth_context(const tsi_peer *peer) {
static grpc_security_status ssl_check_peer(grpc_security_connector *sc, static grpc_security_status ssl_check_peer(grpc_security_connector *sc,
const char *peer_name, const char *peer_name,
const tsi_peer *peer) { const tsi_peer *peer,
grpc_auth_context **auth_context) {
/* Check the ALPN. */ /* Check the ALPN. */
const tsi_peer_property *p = const tsi_peer_property *p =
tsi_peer_get_property_by_name(peer, TSI_SSL_ALPN_SELECTED_PROTOCOL); tsi_peer_get_property_by_name(peer, TSI_SSL_ALPN_SELECTED_PROTOCOL);
@ -506,41 +506,40 @@ static grpc_security_status ssl_check_peer(grpc_security_connector *sc,
gpr_log(GPR_ERROR, "Peer name %s is not in peer certificate", peer_name); gpr_log(GPR_ERROR, "Peer name %s is not in peer certificate", peer_name);
return GRPC_SECURITY_ERROR; return GRPC_SECURITY_ERROR;
} }
if (sc->auth_context != NULL) { *auth_context = tsi_ssl_peer_to_auth_context(peer);
GRPC_AUTH_CONTEXT_UNREF(sc->auth_context, "connector");
}
sc->auth_context = tsi_ssl_peer_to_auth_context(peer);
return GRPC_SECURITY_OK; return GRPC_SECURITY_OK;
} }
static grpc_security_status ssl_channel_check_peer(grpc_security_connector *sc, static void ssl_channel_check_peer(
tsi_peer peer, grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, tsi_peer peer,
grpc_security_check_cb cb, grpc_security_peer_check_cb cb, void *user_data) {
void *user_data) {
grpc_ssl_channel_security_connector *c = grpc_ssl_channel_security_connector *c =
(grpc_ssl_channel_security_connector *)sc; (grpc_ssl_channel_security_connector *)sc;
grpc_security_status status; grpc_security_status status;
grpc_auth_context *auth_context = NULL;
tsi_peer_destruct(&c->peer); tsi_peer_destruct(&c->peer);
c->peer = peer; c->peer = peer;
status = ssl_check_peer(sc, c->overridden_target_name != NULL status = ssl_check_peer(sc, c->overridden_target_name != NULL
? c->overridden_target_name ? c->overridden_target_name
: c->target_name, : c->target_name,
&peer); &peer, &auth_context);
return status; cb(exec_ctx, user_data, status, auth_context);
grpc_auth_context_unref(auth_context);
} }
static grpc_security_status ssl_server_check_peer(grpc_security_connector *sc, static void ssl_server_check_peer(
tsi_peer peer, grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, tsi_peer peer,
grpc_security_check_cb cb, grpc_security_peer_check_cb cb, void *user_data) {
void *user_data) { grpc_auth_context *auth_context = NULL;
grpc_security_status status = ssl_check_peer(sc, NULL, &peer); grpc_security_status status = ssl_check_peer(sc, NULL, &peer, &auth_context);
tsi_peer_destruct(&peer); tsi_peer_destruct(&peer);
return status; cb(exec_ctx, user_data, status, auth_context);
grpc_auth_context_unref(auth_context);
} }
static grpc_security_status ssl_channel_check_call_host( static grpc_security_status ssl_channel_check_call_host(
grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc, grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
const char *host, grpc_security_check_cb cb, void *user_data) { const char *host, grpc_security_call_host_check_cb cb, void *user_data) {
grpc_ssl_channel_security_connector *c = grpc_ssl_channel_security_connector *c =
(grpc_ssl_channel_security_connector *)sc; (grpc_ssl_channel_security_connector *)sc;

@ -60,22 +60,23 @@ typedef struct grpc_security_connector grpc_security_connector;
#define GRPC_SECURITY_CONNECTOR_ARG "grpc.security_connector" #define GRPC_SECURITY_CONNECTOR_ARG "grpc.security_connector"
typedef void (*grpc_security_check_cb)(grpc_exec_ctx *exec_ctx, void *user_data, typedef void (*grpc_security_peer_check_cb)(grpc_exec_ctx *exec_ctx,
grpc_security_status status);
/* Ownership of the secure_endpoint is transfered. */
typedef void (*grpc_security_handshake_done_cb)(grpc_exec_ctx *exec_ctx,
void *user_data, void *user_data,
grpc_security_status status, grpc_security_status status,
grpc_endpoint *secure_endpoint); 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 { typedef struct {
void (*destroy)(grpc_security_connector *sc); void (*destroy)(grpc_security_connector *sc);
void (*do_handshake)(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, void (*do_handshake)(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc,
grpc_endpoint *nonsecure_endpoint, grpc_endpoint *nonsecure_endpoint,
grpc_security_handshake_done_cb cb, void *user_data); grpc_security_handshake_done_cb cb, void *user_data);
grpc_security_status (*check_peer)(grpc_security_connector *sc, tsi_peer peer, void (*check_peer)(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc,
grpc_security_check_cb cb, tsi_peer peer, grpc_security_peer_check_cb cb,
void *user_data); void *user_data);
} grpc_security_connector_vtable; } grpc_security_connector_vtable;
@ -89,9 +90,8 @@ struct grpc_security_connector {
gpr_refcount refcount; gpr_refcount refcount;
int is_client_side; int is_client_side;
const char *url_scheme; const char *url_scheme;
grpc_auth_context *auth_context; /* Populated after the peer is checked. */
/* Used on server side only. */ /* Used on server side only. */
/* TODO(yangg) maybe create a grpc_server_security_connector with these */ /* TODO(yangg): Create a grpc_server_security_connector with these. */
gpr_mu mu; gpr_mu mu;
grpc_security_connector_handshake_list *handshaking_handshakes; grpc_security_connector_handshake_list *handshaking_handshakes;
const grpc_channel_args *channel_args; const grpc_channel_args *channel_args;
@ -125,14 +125,12 @@ void grpc_security_connector_do_handshake(grpc_exec_ctx *exec_ctx,
void *user_data); void *user_data);
/* Check the peer. /* Check the peer.
Implementations can choose to check the peer either synchronously or
asynchronously. In the first case, a successful call will return
GRPC_SECURITY_OK. In the asynchronous case, the call will return
GRPC_SECURITY_PENDING unless an error is detected early on.
Ownership of the peer is transfered. Ownership of the peer is transfered.
*/ TODO(jboeuf): Pass the peer by const pointer and do not pass ownership. */
grpc_security_status grpc_security_connector_check_peer( void grpc_security_connector_check_peer(grpc_exec_ctx *exec_ctx,
grpc_security_connector *sc, tsi_peer peer, grpc_security_check_cb cb, grpc_security_connector *sc,
tsi_peer peer,
grpc_security_peer_check_cb cb,
void *user_data); void *user_data);
void grpc_security_connector_shutdown(grpc_exec_ctx *exec_ctx, void grpc_security_connector_shutdown(grpc_exec_ctx *exec_ctx,
@ -155,13 +153,17 @@ grpc_security_connector *grpc_find_security_connector_in_args(
typedef struct grpc_channel_security_connector grpc_channel_security_connector; typedef struct grpc_channel_security_connector grpc_channel_security_connector;
typedef void (*grpc_security_call_host_check_cb)(grpc_exec_ctx *exec_ctx,
void *user_data,
grpc_security_status status);
struct grpc_channel_security_connector { struct grpc_channel_security_connector {
grpc_security_connector base; /* requires is_client_side to be non 0. */ grpc_security_connector base; /* requires is_client_side to be non 0. */
grpc_call_credentials *request_metadata_creds; grpc_call_credentials *request_metadata_creds;
grpc_security_status (*check_call_host)(grpc_exec_ctx *exec_ctx, grpc_security_status (*check_call_host)(grpc_exec_ctx *exec_ctx,
grpc_channel_security_connector *sc, grpc_channel_security_connector *sc,
const char *host, const char *host,
grpc_security_check_cb cb, grpc_security_call_host_check_cb cb,
void *user_data); void *user_data);
}; };
@ -169,10 +171,11 @@ struct grpc_channel_security_connector {
Implementations can choose do the check either synchronously or Implementations can choose do the check either synchronously or
asynchronously. In the first case, a successful call will return asynchronously. In the first case, a successful call will return
GRPC_SECURITY_OK. In the asynchronous case, the call will return GRPC_SECURITY_OK. In the asynchronous case, the call will return
GRPC_SECURITY_PENDING unless an error is detected early on. */ GRPC_SECURITY_PENDING unless an error is detected early on.
TODO(jboeuf): add a grpc_auth_context param to test against. */
grpc_security_status grpc_channel_security_connector_check_call_host( grpc_security_status grpc_channel_security_connector_check_call_host(
grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc, grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
const char *host, grpc_security_check_cb cb, void *user_data); const char *host, grpc_security_call_host_check_cb cb, void *user_data);
/* --- Creation security connectors. --- */ /* --- Creation security connectors. --- */

@ -81,14 +81,15 @@ static void state_unref(grpc_server_secure_state *state) {
} }
static void setup_transport(grpc_exec_ctx *exec_ctx, void *statep, static void setup_transport(grpc_exec_ctx *exec_ctx, void *statep,
grpc_transport *transport) { grpc_transport *transport,
grpc_auth_context *auth_context) {
static grpc_channel_filter const *extra_filters[] = { static grpc_channel_filter const *extra_filters[] = {
&grpc_server_auth_filter, &grpc_http_server_filter}; &grpc_server_auth_filter, &grpc_http_server_filter};
grpc_server_secure_state *state = statep; grpc_server_secure_state *state = statep;
grpc_channel_args *args_copy; grpc_channel_args *args_copy;
grpc_arg args_to_add[2]; grpc_arg args_to_add[2];
args_to_add[0] = grpc_server_credentials_to_arg(state->creds); args_to_add[0] = grpc_server_credentials_to_arg(state->creds);
args_to_add[1] = grpc_auth_context_to_arg(state->sc->auth_context); args_to_add[1] = grpc_auth_context_to_arg(auth_context);
args_copy = grpc_channel_args_copy_and_add( args_copy = grpc_channel_args_copy_and_add(
grpc_server_get_channel_args(state->server), args_to_add, grpc_server_get_channel_args(state->server), args_to_add,
GPR_ARRAY_SIZE(args_to_add)); GPR_ARRAY_SIZE(args_to_add));
@ -99,7 +100,8 @@ static void setup_transport(grpc_exec_ctx *exec_ctx, void *statep,
static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *statep, static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *statep,
grpc_security_status status, grpc_security_status status,
grpc_endpoint *secure_endpoint) { grpc_endpoint *secure_endpoint,
grpc_auth_context *auth_context) {
grpc_server_secure_state *state = statep; grpc_server_secure_state *state = statep;
grpc_transport *transport; grpc_transport *transport;
if (status == GRPC_SECURITY_OK) { if (status == GRPC_SECURITY_OK) {
@ -109,7 +111,7 @@ static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *statep,
transport = grpc_create_chttp2_transport( transport = grpc_create_chttp2_transport(
exec_ctx, grpc_server_get_channel_args(state->server), exec_ctx, grpc_server_get_channel_args(state->server),
secure_endpoint, 0); secure_endpoint, 0);
setup_transport(exec_ctx, state, transport); setup_transport(exec_ctx, state, transport, auth_context);
grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL, 0); grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL, 0);
} else { } else {
/* We need to consume this here, because the server may already have /* We need to consume this here, because the server may already have

@ -49,6 +49,7 @@
#include "src/core/iomgr/tcp_client.h" #include "src/core/iomgr/tcp_client.h"
#include "src/core/security/auth_filters.h" #include "src/core/security/auth_filters.h"
#include "src/core/security/credentials.h" #include "src/core/security/credentials.h"
#include "src/core/security/security_context.h"
#include "src/core/surface/api_trace.h" #include "src/core/surface/api_trace.h"
#include "src/core/surface/channel.h" #include "src/core/surface/channel.h"
#include "src/core/transport/chttp2_transport.h" #include "src/core/transport/chttp2_transport.h"
@ -88,7 +89,8 @@ static void connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) {
static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *arg, static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
grpc_security_status status, grpc_security_status status,
grpc_endpoint *secure_endpoint) { grpc_endpoint *secure_endpoint,
grpc_auth_context *auth_context) {
connector *c = arg; connector *c = arg;
grpc_closure *notify; grpc_closure *notify;
gpr_mu_lock(&c->mu); gpr_mu_lock(&c->mu);
@ -103,8 +105,14 @@ static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
} else { } else {
c->connecting_endpoint = NULL; c->connecting_endpoint = NULL;
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
{
grpc_arg auth_context_arg = grpc_auth_context_to_arg(auth_context);
grpc_channel_args *args_copy = grpc_channel_args_copy_and_add(
c->args.channel_args, &auth_context_arg, 1);
c->result->transport = grpc_create_chttp2_transport( c->result->transport = grpc_create_chttp2_transport(
exec_ctx, c->args.channel_args, secure_endpoint, 1); exec_ctx, args_copy, secure_endpoint, 1);
grpc_channel_args_destroy(args_copy);
}
grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL, grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL,
0); 0);
c->result->filters = gpr_malloc(sizeof(grpc_channel_filter *) * 2); c->result->filters = gpr_malloc(sizeof(grpc_channel_filter *) * 2);

Loading…
Cancel
Save