static void test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context( void) { tsi_peer peer; grpc_auth_context *ctx; const char *expected_cn = "cn1"; const char *expected_sans[] = {"san1", "san2", "san3"}; size_t i; GPR_ASSERT(tsi_construct_peer(4 + GPR_ARRAY_SIZE(expected_sans), &peer) == TSI_OK); GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE, &peer.properties[0]) == TSI_OK); GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( "foo", "bar", &peer.properties[1]) == TSI_OK); GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, expected_cn, &peer.properties[2]) == TSI_OK); GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( "chapi", "chapo", &peer.properties[3]) == TSI_OK); for (i = 0; i < GPR_ARRAY_SIZE(expected_sans); i++) { GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, expected_sans[i], &peer.properties[4 + i]) == TSI_OK); } ctx = tsi_ssl_peer_to_auth_context(&peer); GPR_ASSERT(ctx != NULL); GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx)); GPR_ASSERT(check_identity(ctx, GRPC_X509_SAN_PROPERTY_NAME, expected_sans, GPR_ARRAY_SIZE(expected_sans))); GPR_ASSERT(check_transport_security_type(ctx)); GPR_ASSERT(check_x509_cn(ctx, expected_cn)); tsi_peer_destruct(&peer); GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); }
static void fake_check_peer(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, tsi_peer peer, grpc_security_peer_check_cb cb, void *user_data) { const char *prop_name; grpc_security_status status = GRPC_SECURITY_OK; grpc_auth_context *auth_context = NULL; if (peer.property_count != 1) { gpr_log(GPR_ERROR, "Fake peers should only have 1 property."); status = GRPC_SECURITY_ERROR; goto end; } prop_name = peer.properties[0].name; if (prop_name == NULL || strcmp(prop_name, TSI_CERTIFICATE_TYPE_PEER_PROPERTY)) { gpr_log(GPR_ERROR, "Unexpected property in fake peer: %s.", prop_name == NULL ? "<EMPTY>" : prop_name); status = GRPC_SECURITY_ERROR; goto end; } if (strncmp(peer.properties[0].value.data, TSI_FAKE_CERTIFICATE_TYPE, peer.properties[0].value.length)) { gpr_log(GPR_ERROR, "Invalid value for cert type property."); status = GRPC_SECURITY_ERROR; goto end; } auth_context = grpc_auth_context_create(NULL); grpc_auth_context_add_cstring_property( auth_context, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, GRPC_FAKE_TRANSPORT_SECURITY_TYPE); end: cb(exec_ctx, user_data, status, auth_context); grpc_auth_context_unref(auth_context); tsi_peer_destruct(&peer); }
static void test_cn_only_ssl_peer_to_auth_context(void) { tsi_peer peer; tsi_peer rpeer; grpc_auth_context *ctx; const char *expected_cn = "cn1"; const char *expected_pem_cert = "pem_cert1"; GPR_ASSERT(tsi_construct_peer(3, &peer) == TSI_OK); GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE, &peer.properties[0]) == TSI_OK); GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, expected_cn, &peer.properties[1]) == TSI_OK); GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( TSI_X509_PEM_CERT_PROPERTY, expected_pem_cert, &peer.properties[2]) == TSI_OK); ctx = tsi_ssl_peer_to_auth_context(&peer); GPR_ASSERT(ctx != NULL); GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx)); GPR_ASSERT(check_identity(ctx, GRPC_X509_CN_PROPERTY_NAME, &expected_cn, 1)); GPR_ASSERT(check_transport_security_type(ctx)); GPR_ASSERT(check_x509_cn(ctx, expected_cn)); GPR_ASSERT(check_x509_pem_cert(ctx, expected_pem_cert)); rpeer = tsi_shallow_peer_from_ssl_auth_context(ctx); GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer)); tsi_shallow_peer_destruct(&rpeer); tsi_peer_destruct(&peer); GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); }
/* Gets information about the peer's X509 cert as a tsi_peer object. */ static tsi_result peer_from_x509(X509* cert, int include_certificate_type, tsi_peer* peer) { /* TODO(jboeuf): Maybe add more properties. */ GENERAL_NAMES* subject_alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0); int subject_alt_name_count = (subject_alt_names != NULL) ? sk_GENERAL_NAME_num(subject_alt_names) : 0; size_t property_count = (include_certificate_type ? 1 : 0) + 1 /* common name */ + subject_alt_name_count; tsi_result result = tsi_construct_peer(property_count, peer); if (result != TSI_OK) return result; do { if (include_certificate_type) { result = tsi_construct_string_peer_property_from_cstring( TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE, &peer->properties[0]); if (result != TSI_OK) break; } result = peer_property_from_x509_common_name( cert, &peer->properties[include_certificate_type ? 1 : 0]); if (result != TSI_OK) break; if (subject_alt_name_count != 0) { result = add_subject_alt_names_properties_to_peer(peer, subject_alt_names, subject_alt_name_count); if (result != TSI_OK) break; } } while (0); if (subject_alt_names != NULL) { sk_GENERAL_NAME_pop_free(subject_alt_names, GENERAL_NAME_free); } if (result != TSI_OK) tsi_peer_destruct(peer); return result; }
static void test_cn_and_one_san_ssl_peer_to_auth_context(void) { tsi_peer peer; grpc_auth_context *ctx; const char *expected_cn = "cn1"; const char *expected_san = "san1"; GPR_ASSERT(tsi_construct_peer(3, &peer) == TSI_OK); GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE, &peer.properties[0]) == TSI_OK); GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, expected_cn, &peer.properties[1]) == TSI_OK); GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, expected_san, &peer.properties[2]) == TSI_OK); ctx = tsi_ssl_peer_to_auth_context(&peer); GPR_ASSERT(ctx != NULL); GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx)); GPR_ASSERT( check_identity(ctx, GRPC_X509_SAN_PROPERTY_NAME, &expected_san, 1)); GPR_ASSERT(check_transport_security_type(ctx)); GPR_ASSERT(check_x509_cn(ctx, expected_cn)); tsi_peer_destruct(&peer); GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); }
static grpc_security_status fake_check_peer(grpc_security_context *ctx, tsi_peer peer, grpc_security_check_cb cb, void *user_data) { const char *prop_name; grpc_security_status status = GRPC_SECURITY_OK; if (peer.property_count != 1) { gpr_log(GPR_ERROR, "Fake peers should only have 1 property."); status = GRPC_SECURITY_ERROR; goto end; } prop_name = peer.properties[0].name; if (prop_name == NULL || strcmp(prop_name, TSI_CERTIFICATE_TYPE_PEER_PROPERTY)) { gpr_log(GPR_ERROR, "Unexpected property in fake peer: %s.", prop_name == NULL ? "<EMPTY>" : prop_name); status = GRPC_SECURITY_ERROR; goto end; } if (peer.properties[0].type != TSI_PEER_PROPERTY_TYPE_STRING) { gpr_log(GPR_ERROR, "Invalid type of cert type property."); status = GRPC_SECURITY_ERROR; goto end; } if (strncmp(peer.properties[0].value.string.data, TSI_FAKE_CERTIFICATE_TYPE, peer.properties[0].value.string.length)) { gpr_log(GPR_ERROR, "Invalid value for cert type property."); status = GRPC_SECURITY_ERROR; goto end; } end: tsi_peer_destruct(&peer); return status; }
static grpc_security_status fake_check_peer(grpc_security_connector *sc, tsi_peer peer, grpc_security_check_cb cb, void *user_data) { const char *prop_name; grpc_security_status status = GRPC_SECURITY_OK; if (peer.property_count != 1) { gpr_log(GPR_ERROR, "Fake peers should only have 1 property."); status = GRPC_SECURITY_ERROR; goto end; } prop_name = peer.properties[0].name; if (prop_name == NULL || strcmp(prop_name, TSI_CERTIFICATE_TYPE_PEER_PROPERTY)) { gpr_log(GPR_ERROR, "Unexpected property in fake peer: %s.", prop_name == NULL ? "<EMPTY>" : prop_name); status = GRPC_SECURITY_ERROR; goto end; } if (strncmp(peer.properties[0].value.data, TSI_FAKE_CERTIFICATE_TYPE, peer.properties[0].value.length)) { gpr_log(GPR_ERROR, "Invalid value for cert type property."); status = GRPC_SECURITY_ERROR; goto end; } GRPC_AUTH_CONTEXT_UNREF(sc->auth_context, "connector"); sc->auth_context = grpc_auth_context_create(NULL, 1); sc->auth_context->properties[0] = grpc_auth_property_init_from_cstring( GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, GRPC_FAKE_TRANSPORT_SECURITY_TYPE); end: tsi_peer_destruct(&peer); return status; }
static grpc_security_status ssl_server_check_peer(grpc_security_connector *sc, tsi_peer peer, grpc_security_check_cb cb, void *user_data) { grpc_security_status status = ssl_check_peer(sc, NULL, &peer); tsi_peer_destruct(&peer); return status; }
grpc_security_status grpc_security_connector_check_peer( grpc_security_connector *sc, tsi_peer peer, grpc_security_check_cb cb, void *user_data) { if (sc == NULL) { tsi_peer_destruct(&peer); return GRPC_SECURITY_ERROR; } return sc->vtable->check_peer(sc, peer, cb, user_data); }
grpc_security_status grpc_security_context_check_peer( grpc_security_context *ctx, tsi_peer peer, grpc_security_check_cb cb, void *user_data) { if (ctx == NULL) { tsi_peer_destruct(&peer); return GRPC_SECURITY_ERROR; } return ctx->vtable->check_peer(ctx, peer, cb, user_data); }
static grpc_security_status ssl_server_check_peer(grpc_security_context *ctx, tsi_peer peer, grpc_security_check_cb cb, void *user_data) { /* TODO(jboeuf): Find a way to expose the peer to the authorization layer. */ grpc_security_status status = ssl_check_peer(NULL, &peer); tsi_peer_destruct(&peer); return status; }
static void ssl_server_check_peer(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, tsi_peer peer, grpc_security_peer_check_cb cb, void *user_data) { grpc_auth_context *auth_context = NULL; grpc_security_status status = ssl_check_peer(sc, NULL, &peer, &auth_context); tsi_peer_destruct(&peer); cb(exec_ctx, user_data, status, auth_context); grpc_auth_context_unref(auth_context); }
void grpc_security_connector_check_peer(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, tsi_peer peer, grpc_security_peer_check_cb cb, void *user_data) { if (sc == NULL) { cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL); tsi_peer_destruct(&peer); } else { sc->vtable->check_peer(exec_ctx, sc, peer, cb, user_data); } }
static void ssl_channel_destroy(grpc_security_context *ctx) { grpc_ssl_channel_security_context *c = (grpc_ssl_channel_security_context *)ctx; grpc_credentials_unref(c->base.request_metadata_creds); if (c->handshaker_factory != NULL) { tsi_ssl_handshaker_factory_destroy(c->handshaker_factory); } if (c->target_name != NULL) gpr_free(c->target_name); if (c->overridden_target_name != NULL) gpr_free(c->overridden_target_name); tsi_peer_destruct(&c->peer); gpr_free(ctx); }
static void ssl_channel_destroy(grpc_security_connector *sc) { grpc_ssl_channel_security_connector *c = (grpc_ssl_channel_security_connector *)sc; grpc_credentials_unref(c->base.request_metadata_creds); if (c->handshaker_factory != NULL) { tsi_ssl_handshaker_factory_destroy(c->handshaker_factory); } if (c->target_name != NULL) gpr_free(c->target_name); if (c->overridden_target_name != NULL) gpr_free(c->overridden_target_name); tsi_peer_destruct(&c->peer); GRPC_AUTH_CONTEXT_UNREF(sc->auth_context, "connector"); gpr_free(sc); }
static void test_unauthenticated_ssl_peer(void) { tsi_peer peer; grpc_auth_context *ctx; GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK); GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE, &peer.properties[0]) == TSI_OK); ctx = tsi_ssl_peer_to_auth_context(&peer); GPR_ASSERT(ctx != NULL); GPR_ASSERT(!grpc_auth_context_peer_is_authenticated(ctx)); GPR_ASSERT(check_transport_security_type(ctx)); tsi_peer_destruct(&peer); GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); }
static void test_peer_matches_name(void) { size_t i = 0; for (i = 0; i < GPR_ARRAY_SIZE(cert_name_test_entries); i++) { const cert_name_test_entry *entry = &cert_name_test_entries[i]; tsi_peer peer = peer_from_cert_name_test_entry(entry); int result = tsi_ssl_peer_matches_name(&peer, entry->host_name); if (result != entry->expected) { char *entry_str = cert_name_test_entry_to_string(entry); gpr_log(GPR_ERROR, "%s", entry_str); gpr_free(entry_str); GPR_ASSERT(0); /* Unexpected result. */ } tsi_peer_destruct(&peer); } }
static grpc_security_status ssl_channel_check_peer(grpc_security_connector *sc, tsi_peer peer, grpc_security_check_cb cb, void *user_data) { grpc_ssl_channel_security_connector *c = (grpc_ssl_channel_security_connector *)sc; grpc_security_status status; tsi_peer_destruct(&c->peer); c->peer = peer; status = ssl_check_peer(sc, c->overridden_target_name != NULL ? c->overridden_target_name : c->target_name, &peer); return status; }
static void ssl_channel_check_peer(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, tsi_peer peer, grpc_security_peer_check_cb cb, void *user_data) { grpc_ssl_channel_security_connector *c = (grpc_ssl_channel_security_connector *)sc; grpc_security_status status; grpc_auth_context *auth_context = NULL; status = ssl_check_peer(sc, c->overridden_target_name != NULL ? c->overridden_target_name : c->target_name, &peer, &auth_context); cb(exec_ctx, user_data, status, auth_context); grpc_auth_context_unref(auth_context); tsi_peer_destruct(&peer); }
static void httpcli_ssl_check_peer(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, tsi_peer peer, grpc_security_peer_check_cb cb, void *user_data) { grpc_httpcli_ssl_channel_security_connector *c = (grpc_httpcli_ssl_channel_security_connector *)sc; grpc_security_status status = GRPC_SECURITY_OK; /* Check the peer name. */ if (c->secure_peer_name != NULL && !tsi_ssl_peer_matches_name(&peer, c->secure_peer_name)) { gpr_log(GPR_ERROR, "Peer name %s is not in peer certificate", c->secure_peer_name); status = GRPC_SECURITY_ERROR; } cb(exec_ctx, user_data, status, NULL); tsi_peer_destruct(&peer); }
static void httpcli_ssl_check_peer(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, tsi_peer peer, grpc_auth_context **auth_context, grpc_closure *on_peer_checked) { grpc_httpcli_ssl_channel_security_connector *c = (grpc_httpcli_ssl_channel_security_connector *)sc; grpc_error *error = GRPC_ERROR_NONE; /* Check the peer name. */ if (c->secure_peer_name != NULL && !tsi_ssl_peer_matches_name(&peer, c->secure_peer_name)) { char *msg; gpr_asprintf(&msg, "Peer name %s is not in peer certificate", c->secure_peer_name); error = GRPC_ERROR_CREATE(msg); gpr_free(msg); } grpc_exec_ctx_sched(exec_ctx, on_peer_checked, error, NULL); tsi_peer_destruct(&peer); }