diff options
author | 2017-10-23 15:33:21 -0700 | |
---|---|---|
committer | 2017-10-25 16:23:01 -0700 | |
commit | 34a57d0346afe95e11104462c30dc468b0cb0b89 (patch) | |
tree | 67db15f7b8b361e0618199dc55215f3b4d626201 /test/core/security/security_connector_test.cc | |
parent | c563b583cb9b7fecc33971581368796d2df4759d (diff) |
rename all test core files to cc and a lot of C++ style conversions
Diffstat (limited to 'test/core/security/security_connector_test.cc')
-rw-r--r-- | test/core/security/security_connector_test.cc | 405 |
1 files changed, 405 insertions, 0 deletions
diff --git a/test/core/security/security_connector_test.cc b/test/core/security/security_connector_test.cc new file mode 100644 index 0000000000..eecf0f462b --- /dev/null +++ b/test/core/security/security_connector_test.cc @@ -0,0 +1,405 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include <stdio.h> +#include <string.h> + +#include <grpc/grpc_security.h> +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/string_util.h> +#include <grpc/support/useful.h> + +#include "src/core/lib/security/context/security_context.h" +#include "src/core/lib/security/transport/security_connector.h" +#include "src/core/lib/slice/slice_string_helpers.h" +#include "src/core/lib/support/env.h" +#include "src/core/lib/support/string.h" +#include "src/core/lib/support/tmpfile.h" +#include "src/core/tsi/ssl_transport_security.h" +#include "src/core/tsi/transport_security.h" +#include "test/core/util/test_config.h" + +static int check_transport_security_type(const grpc_auth_context *ctx) { + grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name( + ctx, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME); + const grpc_auth_property *prop = grpc_auth_property_iterator_next(&it); + if (prop == NULL) return 0; + if (strncmp(prop->value, GRPC_SSL_TRANSPORT_SECURITY_TYPE, + prop->value_length) != 0) { + return 0; + } + /* Check that we have only one property with this name. */ + if (grpc_auth_property_iterator_next(&it) != NULL) return 0; + return 1; +} + +static int check_peer_property(const tsi_peer *peer, + const tsi_peer_property *expected) { + size_t i; + for (i = 0; i < peer->property_count; i++) { + const tsi_peer_property *prop = &peer->properties[i]; + if ((strcmp(prop->name, expected->name) == 0) && + (prop->value.length == expected->value.length) && + (memcmp(prop->value.data, expected->value.data, + expected->value.length) == 0)) { + return 1; + } + } + return 0; /* Not found... */ +} + +static int check_ssl_peer_equivalence(const tsi_peer *original, + const tsi_peer *reconstructed) { + /* The reconstructed peer only has CN, SAN and pem cert properties. */ + size_t i; + for (i = 0; i < original->property_count; i++) { + const tsi_peer_property *prop = &original->properties[i]; + if ((strcmp(prop->name, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) || + (strcmp(prop->name, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == + 0) || + (strcmp(prop->name, TSI_X509_PEM_CERT_PROPERTY) == 0)) { + if (!check_peer_property(reconstructed, prop)) return 0; + } + } + return 1; +} + +static void test_unauthenticated_ssl_peer(void) { + tsi_peer peer; + tsi_peer rpeer; + 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)); + + 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"); +} + +static int check_identity(const grpc_auth_context *ctx, + const char *expected_property_name, + const char **expected_identities, + size_t num_identities) { + grpc_auth_property_iterator it; + const grpc_auth_property *prop; + size_t i; + GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx)); + it = grpc_auth_context_peer_identity(ctx); + for (i = 0; i < num_identities; i++) { + prop = grpc_auth_property_iterator_next(&it); + if (prop == NULL) { + gpr_log(GPR_ERROR, "Expected identity value %s not found.", + expected_identities[i]); + return 0; + } + if (strcmp(prop->name, expected_property_name) != 0) { + gpr_log(GPR_ERROR, "Expected peer identity property name %s and got %s.", + expected_property_name, prop->name); + return 0; + } + if (strncmp(prop->value, expected_identities[i], prop->value_length) != 0) { + gpr_log(GPR_ERROR, "Expected peer identity %s and got %s.", + expected_identities[i], prop->value); + return 0; + } + } + return 1; +} + +static int check_x509_cn(const grpc_auth_context *ctx, + const char *expected_cn) { + grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name( + ctx, GRPC_X509_CN_PROPERTY_NAME); + const grpc_auth_property *prop = grpc_auth_property_iterator_next(&it); + if (prop == NULL) { + gpr_log(GPR_ERROR, "CN property not found."); + return 0; + } + if (strncmp(prop->value, expected_cn, prop->value_length) != 0) { + gpr_log(GPR_ERROR, "Expected CN %s and got %s", expected_cn, prop->value); + return 0; + } + if (grpc_auth_property_iterator_next(&it) != NULL) { + gpr_log(GPR_ERROR, "Expected only one property for CN."); + return 0; + } + return 1; +} + +static int check_x509_pem_cert(const grpc_auth_context *ctx, + const char *expected_pem_cert) { + grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name( + ctx, GRPC_X509_PEM_CERT_PROPERTY_NAME); + const grpc_auth_property *prop = grpc_auth_property_iterator_next(&it); + if (prop == NULL) { + gpr_log(GPR_ERROR, "Pem certificate property not found."); + return 0; + } + if (strncmp(prop->value, expected_pem_cert, prop->value_length) != 0) { + gpr_log(GPR_ERROR, "Expected pem cert %s and got %s", expected_pem_cert, + prop->value); + return 0; + } + if (grpc_auth_property_iterator_next(&it) != NULL) { + gpr_log(GPR_ERROR, "Expected only one property for pem cert."); + return 0; + } + return 1; +} + +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"); +} + +static void test_cn_and_one_san_ssl_peer_to_auth_context(void) { + tsi_peer peer; + tsi_peer rpeer; + grpc_auth_context *ctx; + const char *expected_cn = "cn1"; + const char *expected_san = "san1"; + const char *expected_pem_cert = "pem_cert1"; + GPR_ASSERT(tsi_construct_peer(4, &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); + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + TSI_X509_PEM_CERT_PROPERTY, expected_pem_cert, + &peer.properties[3]) == 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)); + 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"); +} + +static void test_cn_and_multiple_sans_ssl_peer_to_auth_context(void) { + tsi_peer peer; + tsi_peer rpeer; + grpc_auth_context *ctx; + const char *expected_cn = "cn1"; + const char *expected_sans[] = {"san1", "san2", "san3"}; + const char *expected_pem_cert = "pem_cert1"; + size_t i; + GPR_ASSERT(tsi_construct_peer(3 + 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( + 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); + 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[3 + 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)); + 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"); +} + +static void test_cn_and_multiple_sans_and_others_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"; + const char *expected_sans[] = {"san1", "san2", "san3"}; + size_t i; + GPR_ASSERT(tsi_construct_peer(5 + 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); + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + TSI_X509_PEM_CERT_PROPERTY, expected_pem_cert, + &peer.properties[4]) == 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[5 + 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)); + 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"); +} + +static const char *roots_for_override_api = "roots for override api"; + +static grpc_ssl_roots_override_result override_roots_success( + char **pem_root_certs) { + *pem_root_certs = gpr_strdup(roots_for_override_api); + return GRPC_SSL_ROOTS_OVERRIDE_OK; +} + +static grpc_ssl_roots_override_result override_roots_permanent_failure( + char **pem_root_certs) { + return GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY; +} + +static void test_default_ssl_roots(void) { + const char *roots_for_env_var = "roots for env var"; + + char *roots_env_var_file_path; + FILE *roots_env_var_file = + gpr_tmpfile("test_roots_for_env_var", &roots_env_var_file_path); + fwrite(roots_for_env_var, 1, strlen(roots_for_env_var), roots_env_var_file); + fclose(roots_env_var_file); + + /* First let's get the root through the override: set the env to an invalid + value. */ + gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, ""); + grpc_set_ssl_roots_override_callback(override_roots_success); + grpc_slice roots = grpc_get_default_ssl_roots_for_testing(); + char *roots_contents = grpc_slice_to_c_string(roots); + grpc_slice_unref(roots); + GPR_ASSERT(strcmp(roots_contents, roots_for_override_api) == 0); + gpr_free(roots_contents); + + /* Now let's set the env var: We should get the contents pointed value + instead. */ + gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, roots_env_var_file_path); + roots = grpc_get_default_ssl_roots_for_testing(); + roots_contents = grpc_slice_to_c_string(roots); + grpc_slice_unref(roots); + GPR_ASSERT(strcmp(roots_contents, roots_for_env_var) == 0); + gpr_free(roots_contents); + + /* Now reset the env var. We should fall back to the value overridden using + the api. */ + gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, ""); + roots = grpc_get_default_ssl_roots_for_testing(); + roots_contents = grpc_slice_to_c_string(roots); + grpc_slice_unref(roots); + GPR_ASSERT(strcmp(roots_contents, roots_for_override_api) == 0); + gpr_free(roots_contents); + + /* Now setup a permanent failure for the overridden roots and we should get + an empty slice. */ + grpc_set_ssl_roots_override_callback(override_roots_permanent_failure); + roots = grpc_get_default_ssl_roots_for_testing(); + GPR_ASSERT(GRPC_SLICE_IS_EMPTY(roots)); + + /* Cleanup. */ + remove(roots_env_var_file_path); + gpr_free(roots_env_var_file_path); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + + test_unauthenticated_ssl_peer(); + test_cn_only_ssl_peer_to_auth_context(); + test_cn_and_one_san_ssl_peer_to_auth_context(); + test_cn_and_multiple_sans_ssl_peer_to_auth_context(); + test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context(); + test_default_ssl_roots(); + + grpc_shutdown(); + return 0; +} |