aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/lib/security
diff options
context:
space:
mode:
authorGravatar Yash Tibrewal <yashkt@google.com>2018-08-13 10:53:06 -0700
committerGravatar Yash Tibrewal <yashkt@google.com>2018-08-13 10:53:06 -0700
commit556775d7c78125e051c6571d4c528de214024c23 (patch)
tree77d3e0effdb58b01e9e257a8dcd03a024acedf31 /src/core/lib/security
parent0ec6973b743e8e1f463bdcc8691e1869097c92f0 (diff)
parentba7ca9742eb7484009b75c268dba7e56b8feaebb (diff)
Merge master
Diffstat (limited to 'src/core/lib/security')
-rw-r--r--src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc5
-rw-r--r--src/core/lib/security/security_connector/load_system_roots.h29
-rw-r--r--src/core/lib/security/security_connector/load_system_roots_fallback.cc32
-rw-r--r--src/core/lib/security/security_connector/load_system_roots_linux.cc165
-rw-r--r--src/core/lib/security/security_connector/load_system_roots_linux.h44
-rw-r--r--src/core/lib/security/security_connector/security_connector.cc27
-rw-r--r--src/core/lib/security/transport/client_auth_filter.cc4
-rw-r--r--src/core/lib/security/transport/server_auth_filter.cc2
8 files changed, 296 insertions, 12 deletions
diff --git a/src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc b/src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc
index 7c4d7a71cd..8454fd7558 100644
--- a/src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc
+++ b/src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc
@@ -41,8 +41,9 @@ namespace internal {
bool check_bios_data(const char* bios_data_file) {
char* bios_data = read_bios_file(bios_data_file);
- bool result = (!strcmp(bios_data, GRPC_ALTS_EXPECT_NAME_GOOGLE)) ||
- (!strcmp(bios_data, GRPC_ALTS_EXPECT_NAME_GCE));
+ bool result =
+ bios_data && ((!strcmp(bios_data, GRPC_ALTS_EXPECT_NAME_GOOGLE)) ||
+ (!strcmp(bios_data, GRPC_ALTS_EXPECT_NAME_GCE)));
gpr_free(bios_data);
return result;
}
diff --git a/src/core/lib/security/security_connector/load_system_roots.h b/src/core/lib/security/security_connector/load_system_roots.h
new file mode 100644
index 0000000000..5fdec15498
--- /dev/null
+++ b/src/core/lib/security/security_connector/load_system_roots.h
@@ -0,0 +1,29 @@
+/*
+ *
+ * Copyright 2018 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.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_LOAD_SYSTEM_ROOTS_H
+#define GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_LOAD_SYSTEM_ROOTS_H
+
+namespace grpc_core {
+
+// Returns a slice containing roots from the OS trust store
+grpc_slice LoadSystemRootCerts();
+
+} // namespace grpc_core
+
+#endif /* GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_LOAD_SYSTEM_ROOTS_H */
diff --git a/src/core/lib/security/security_connector/load_system_roots_fallback.cc b/src/core/lib/security/security_connector/load_system_roots_fallback.cc
new file mode 100644
index 0000000000..73d1245f33
--- /dev/null
+++ b/src/core/lib/security/security_connector/load_system_roots_fallback.cc
@@ -0,0 +1,32 @@
+/*
+ *
+ * Copyright 2018 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 <grpc/support/port_platform.h>
+
+#include <grpc/slice_buffer.h>
+#include "src/core/lib/security/security_connector/load_system_roots.h"
+
+#ifndef GPR_LINUX
+
+namespace grpc_core {
+
+grpc_slice LoadSystemRootCerts() { return grpc_empty_slice(); }
+
+} // namespace grpc_core
+
+#endif /* GPR_LINUX */
diff --git a/src/core/lib/security/security_connector/load_system_roots_linux.cc b/src/core/lib/security/security_connector/load_system_roots_linux.cc
new file mode 100644
index 0000000000..924fa8a3e2
--- /dev/null
+++ b/src/core/lib/security/security_connector/load_system_roots_linux.cc
@@ -0,0 +1,165 @@
+/*
+ *
+ * Copyright 2018 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 <grpc/support/port_platform.h>
+
+#include <grpc/slice_buffer.h>
+#include "src/core/lib/security/security_connector/load_system_roots_linux.h"
+
+#ifdef GPR_LINUX
+
+#include "src/core/lib/security/security_connector/load_system_roots.h"
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/lib/gpr/env.h"
+#include "src/core/lib/gpr/string.h"
+#include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/gprpp/inlined_vector.h"
+#include "src/core/lib/iomgr/load_file.h"
+
+namespace grpc_core {
+namespace {
+
+const char* kLinuxCertFiles[] = {
+ "/etc/ssl/certs/ca-certificates.crt", "/etc/pki/tls/certs/ca-bundle.crt",
+ "/etc/ssl/ca-bundle.pem", "/etc/pki/tls/cacert.pem",
+ "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem"};
+const char* kLinuxCertDirectories[] = {
+ "/etc/ssl/certs", "/system/etc/security/cacerts", "/usr/local/share/certs",
+ "/etc/pki/tls/certs", "/etc/openssl/certs"};
+
+grpc_slice GetSystemRootCerts() {
+ grpc_slice valid_bundle_slice = grpc_empty_slice();
+ size_t num_cert_files_ = GPR_ARRAY_SIZE(kLinuxCertFiles);
+ for (size_t i = 0; i < num_cert_files_; i++) {
+ grpc_error* error =
+ grpc_load_file(kLinuxCertFiles[i], 1, &valid_bundle_slice);
+ if (error == GRPC_ERROR_NONE) {
+ return valid_bundle_slice;
+ }
+ }
+ return grpc_empty_slice();
+}
+
+} // namespace
+
+void GetAbsoluteFilePath(const char* valid_file_dir,
+ const char* file_entry_name, char* path_buffer) {
+ if (valid_file_dir != nullptr && file_entry_name != nullptr) {
+ int path_len = snprintf(path_buffer, MAXPATHLEN, "%s/%s", valid_file_dir,
+ file_entry_name);
+ if (path_len == 0) {
+ gpr_log(GPR_ERROR, "failed to get absolute path for file: %s",
+ file_entry_name);
+ }
+ }
+}
+
+grpc_slice CreateRootCertsBundle(const char* certs_directory) {
+ grpc_slice bundle_slice = grpc_empty_slice();
+ if (certs_directory == nullptr) {
+ return bundle_slice;
+ }
+ DIR* ca_directory = opendir(certs_directory);
+ if (ca_directory == nullptr) {
+ return bundle_slice;
+ }
+ struct FileData {
+ char path[MAXPATHLEN];
+ off_t size;
+ };
+ InlinedVector<FileData, 2> roots_filenames;
+ size_t total_bundle_size = 0;
+ struct dirent* directory_entry;
+ while ((directory_entry = readdir(ca_directory)) != nullptr) {
+ struct stat dir_entry_stat;
+ const char* file_entry_name = directory_entry->d_name;
+ FileData file_data;
+ GetAbsoluteFilePath(certs_directory, file_entry_name, file_data.path);
+ int stat_return = stat(file_data.path, &dir_entry_stat);
+ if (stat_return == -1 || !S_ISREG(dir_entry_stat.st_mode)) {
+ // no subdirectories.
+ if (stat_return == -1) {
+ gpr_log(GPR_ERROR, "failed to get status for file: %s", file_data.path);
+ }
+ continue;
+ }
+ file_data.size = dir_entry_stat.st_size;
+ total_bundle_size += file_data.size;
+ roots_filenames.push_back(file_data);
+ }
+ closedir(ca_directory);
+ char* bundle_string = static_cast<char*>(gpr_zalloc(total_bundle_size + 1));
+ size_t bytes_read = 0;
+ for (size_t i = 0; i < roots_filenames.size(); i++) {
+ int file_descriptor = open(roots_filenames[i].path, O_RDONLY);
+ if (file_descriptor != -1) {
+ // Read file into bundle.
+ size_t cert_file_size = roots_filenames[i].size;
+ int read_ret =
+ read(file_descriptor, bundle_string + bytes_read, cert_file_size);
+ if (read_ret != -1) {
+ bytes_read += read_ret;
+ } else {
+ gpr_log(GPR_ERROR, "failed to read file: %s", roots_filenames[i].path);
+ }
+ }
+ }
+ bundle_slice = grpc_slice_new(bundle_string, bytes_read, gpr_free);
+ return bundle_slice;
+}
+
+grpc_slice LoadSystemRootCerts() {
+ grpc_slice result = grpc_empty_slice();
+ // Prioritize user-specified custom directory if flag is set.
+ char* custom_dir = gpr_getenv("GRPC_SYSTEM_SSL_ROOTS_DIR");
+ if (custom_dir != nullptr) {
+ result = CreateRootCertsBundle(custom_dir);
+ gpr_free(custom_dir);
+ }
+ // If the custom directory is empty/invalid/not specified, fallback to
+ // distribution-specific directory.
+ if (GRPC_SLICE_IS_EMPTY(result)) {
+ result = GetSystemRootCerts();
+ }
+ if (GRPC_SLICE_IS_EMPTY(result)) {
+ for (size_t i = 0; i < GPR_ARRAY_SIZE(kLinuxCertDirectories); i++) {
+ result = CreateRootCertsBundle(kLinuxCertDirectories[i]);
+ if (!GRPC_SLICE_IS_EMPTY(result)) {
+ break;
+ }
+ }
+ }
+ return result;
+}
+
+} // namespace grpc_core
+
+#endif /* GPR_LINUX */
diff --git a/src/core/lib/security/security_connector/load_system_roots_linux.h b/src/core/lib/security/security_connector/load_system_roots_linux.h
new file mode 100644
index 0000000000..12617df492
--- /dev/null
+++ b/src/core/lib/security/security_connector/load_system_roots_linux.h
@@ -0,0 +1,44 @@
+/*
+ *
+ * Copyright 2018 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.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_LOAD_SYSTEM_ROOTS_LINUX_H
+#define GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_LOAD_SYSTEM_ROOTS_LINUX_H
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_LINUX
+
+namespace grpc_core {
+
+// Creates a bundle slice containing the contents of all certificate files in
+// a directory.
+// Returns such slice.
+// Exposed for testing purposes only.
+grpc_slice CreateRootCertsBundle(const char* certs_directory);
+
+// Gets the absolute file path needed to load a certificate file.
+// Populates path_buffer, which must be of size MAXPATHLEN.
+// Exposed for testing purposes only.
+void GetAbsoluteFilePath(const char* valid_file_dir,
+ const char* file_entry_name, char* path_buffer);
+
+} // namespace grpc_core
+
+#endif /* GPR_LINUX */
+#endif /* GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_LOAD_SYSTEM_ROOTS_LINUX_H \
+ */
diff --git a/src/core/lib/security/security_connector/security_connector.cc b/src/core/lib/security/security_connector/security_connector.cc
index cc72bb6164..04b4c87c71 100644
--- a/src/core/lib/security/security_connector/security_connector.cc
+++ b/src/core/lib/security/security_connector/security_connector.cc
@@ -21,7 +21,6 @@
#include "src/core/lib/security/security_connector/security_connector.h"
#include <stdbool.h>
-#include <string.h>
#include <grpc/slice_buffer.h>
#include <grpc/support/alloc.h>
@@ -39,6 +38,7 @@
#include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/security/credentials/fake/fake_credentials.h"
#include "src/core/lib/security/credentials/ssl/ssl_credentials.h"
+#include "src/core/lib/security/security_connector/load_system_roots.h"
#include "src/core/lib/security/transport/secure_endpoint.h"
#include "src/core/lib/security/transport/security_handshaker.h"
#include "src/core/lib/security/transport/target_authority_table.h"
@@ -57,6 +57,16 @@ static const char* installed_roots_path =
INSTALL_PREFIX "/share/grpc/roots.pem";
#endif
+/** Environment variable used as a flag to enable/disable loading system root
+ certificates from the OS trust store. */
+#ifndef GRPC_USE_SYSTEM_SSL_ROOTS_ENV_VAR
+#define GRPC_USE_SYSTEM_SSL_ROOTS_ENV_VAR "GRPC_USE_SYSTEM_SSL_ROOTS"
+#endif
+
+#ifndef TSI_OPENSSL_ALPN_SUPPORT
+#define TSI_OPENSSL_ALPN_SUPPORT 1
+#endif
+
/* -- Overridden default roots. -- */
static grpc_ssl_roots_override_callback ssl_roots_override_cb = nullptr;
@@ -850,7 +860,8 @@ grpc_auth_context* grpc_ssl_peer_to_auth_context(const tsi_peer* peer) {
static grpc_error* ssl_check_peer(grpc_security_connector* sc,
const char* peer_name, const tsi_peer* peer,
grpc_auth_context** auth_context) {
- /* Check the ALPN. */
+#if TSI_OPENSSL_ALPN_SUPPORT
+ /* Check the ALPN if ALPN is supported. */
const tsi_peer_property* p =
tsi_peer_get_property_by_name(peer, TSI_SSL_ALPN_SELECTED_PROTOCOL);
if (p == nullptr) {
@@ -861,7 +872,7 @@ static grpc_error* ssl_check_peer(grpc_security_connector* sc,
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Cannot check peer: invalid ALPN value.");
}
-
+#endif /* TSI_OPENSSL_ALPN_SUPPORT */
/* Check the peer name if specified. */
if (peer_name != nullptr && !grpc_ssl_host_matches_name(peer, peer_name)) {
char* msg;
@@ -1181,6 +1192,10 @@ const char* DefaultSslRootStore::GetPemRootCerts() {
grpc_slice DefaultSslRootStore::ComputePemRootCerts() {
grpc_slice result = grpc_empty_slice();
+ char* use_system_roots_env_value =
+ gpr_getenv(GRPC_USE_SYSTEM_SSL_ROOTS_ENV_VAR);
+ const bool use_system_roots = gpr_is_true(use_system_roots_env_value);
+ gpr_free(use_system_roots_env_value);
// First try to load the roots from the environment.
char* default_root_certs_path =
gpr_getenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR);
@@ -1202,7 +1217,11 @@ grpc_slice DefaultSslRootStore::ComputePemRootCerts() {
}
gpr_free(pem_root_certs);
}
- // Fall back to installed certs if needed.
+ // Try loading roots from OS trust store if flag is enabled.
+ if (GRPC_SLICE_IS_EMPTY(result) && use_system_roots) {
+ result = LoadSystemRootCerts();
+ }
+ // Fallback to roots manually shipped with gRPC.
if (GRPC_SLICE_IS_EMPTY(result) &&
ovrd_res != GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY) {
GRPC_LOG_IF_ERROR("load_file",
diff --git a/src/core/lib/security/transport/client_auth_filter.cc b/src/core/lib/security/transport/client_auth_filter.cc
index 9b5c6f3490..0f125e7c26 100644
--- a/src/core/lib/security/transport/client_auth_filter.cc
+++ b/src/core/lib/security/transport/client_auth_filter.cc
@@ -167,7 +167,6 @@ static void cancel_get_request_metadata(void* arg, grpc_error* error) {
grpc_call_credentials_cancel_get_request_metadata(
calld->creds, &calld->md_array, GRPC_ERROR_REF(error));
}
- GRPC_CALL_STACK_UNREF(calld->owning_call, "cancel_get_request_metadata");
}
static void send_security_metadata(grpc_call_element* elem,
@@ -222,7 +221,6 @@ static void send_security_metadata(grpc_call_element* elem,
GRPC_ERROR_UNREF(error);
} else {
// Async return; register cancellation closure with call combiner.
- GRPC_CALL_STACK_REF(calld->owning_call, "cancel_get_request_metadata");
grpc_call_combiner_set_notify_on_cancel(
calld->call_combiner,
GRPC_CLOSURE_INIT(&calld->get_request_metadata_cancel_closure,
@@ -265,7 +263,6 @@ static void cancel_check_call_host(void* arg, grpc_error* error) {
chand->security_connector, &calld->async_result_closure,
GRPC_ERROR_REF(error));
}
- GRPC_CALL_STACK_UNREF(calld->owning_call, "cancel_check_call_host");
}
static void auth_start_transport_stream_op_batch(
@@ -318,7 +315,6 @@ static void auth_start_transport_stream_op_batch(
GRPC_ERROR_UNREF(error);
} else {
// Async return; register cancellation closure with call combiner.
- GRPC_CALL_STACK_REF(calld->owning_call, "cancel_check_call_host");
grpc_call_combiner_set_notify_on_cancel(
calld->call_combiner,
GRPC_CLOSURE_INIT(&calld->check_call_host_cancel_closure,
diff --git a/src/core/lib/security/transport/server_auth_filter.cc b/src/core/lib/security/transport/server_auth_filter.cc
index 2dbefdf131..19cbb03b63 100644
--- a/src/core/lib/security/transport/server_auth_filter.cc
+++ b/src/core/lib/security/transport/server_auth_filter.cc
@@ -156,7 +156,6 @@ static void cancel_call(void* arg, grpc_error* error) {
on_md_processing_done_inner(elem, nullptr, 0, nullptr, 0,
GRPC_ERROR_REF(error));
}
- GRPC_CALL_STACK_UNREF(calld->owning_call, "cancel_call");
}
static void recv_initial_metadata_ready(void* arg, grpc_error* error) {
@@ -168,7 +167,6 @@ static void recv_initial_metadata_ready(void* arg, grpc_error* error) {
if (chand->creds != nullptr && chand->creds->processor.process != nullptr) {
// We're calling out to the application, so we need to make sure
// to drop the call combiner early if we get cancelled.
- GRPC_CALL_STACK_REF(calld->owning_call, "cancel_call");
GRPC_CLOSURE_INIT(&calld->cancel_closure, cancel_call, elem,
grpc_schedule_on_exec_ctx);
grpc_call_combiner_set_notify_on_cancel(calld->call_combiner,