load_system_roots_supported.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2018 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
20 
21 #include <algorithm>
22 #include <memory>
23 #include <vector>
24 
25 #if defined(GPR_LINUX) || defined(GPR_ANDROID) || defined(GPR_FREEBSD) || \
26  defined(GPR_APPLE)
27 
28 #include <dirent.h>
29 #include <fcntl.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <sys/param.h>
33 #include <sys/stat.h>
34 #include <unistd.h>
35 
36 #include <grpc/support/alloc.h>
37 #include <grpc/support/log.h>
38 
46 
47 GPR_GLOBAL_CONFIG_DEFINE_STRING(grpc_system_ssl_roots_dir, "",
48  "Custom directory to SSL Roots");
49 
50 namespace grpc_core {
51 namespace {
52 
53 #if defined(GPR_LINUX) || defined(GPR_ANDROID)
54 const char* kCertFiles[] = {
55  "/etc/ssl/certs/ca-certificates.crt", "/etc/pki/tls/certs/ca-bundle.crt",
56  "/etc/ssl/ca-bundle.pem", "/etc/pki/tls/cacert.pem",
57  "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem"};
58 const char* kCertDirectories[] = {
59  "/etc/ssl/certs", "/system/etc/security/cacerts", "/usr/local/share/certs",
60  "/etc/pki/tls/certs", "/etc/openssl/certs"};
61 #elif defined(GPR_FREEBSD) // endif GPR_LINUX || GPR_ANDROID
62 const char* kCertFiles[] = {"/etc/ssl/cert.pem",
63  "/usr/local/share/certs/ca-root-nss.crt"};
64 const char* kCertDirectories[] = {""};
65 #elif defined(GPR_APPLE) // endif GPR_FREEBSD
66 const char* kCertFiles[] = {"/etc/ssl/cert.pem"};
67 const char* kCertDirectories[] = {""};
68 #endif // GPR_APPLE
69 
70 grpc_slice GetSystemRootCerts() {
71  grpc_slice valid_bundle_slice = grpc_empty_slice();
72  size_t num_cert_files_ = GPR_ARRAY_SIZE(kCertFiles);
73  for (size_t i = 0; i < num_cert_files_; i++) {
75  grpc_load_file(kCertFiles[i], 1, &valid_bundle_slice);
77  return valid_bundle_slice;
78  } else {
80  }
81  }
82  return grpc_empty_slice();
83 }
84 
85 } // namespace
86 
87 void GetAbsoluteFilePath(const char* valid_file_dir,
88  const char* file_entry_name, char* path_buffer) {
89  if (valid_file_dir != nullptr && file_entry_name != nullptr) {
90  int path_len = snprintf(path_buffer, MAXPATHLEN, "%s/%s", valid_file_dir,
91  file_entry_name);
92  if (path_len == 0) {
93  gpr_log(GPR_ERROR, "failed to get absolute path for file: %s",
94  file_entry_name);
95  }
96  }
97 }
98 
99 grpc_slice CreateRootCertsBundle(const char* certs_directory) {
100  grpc_slice bundle_slice = grpc_empty_slice();
101  if (certs_directory == nullptr) {
102  return bundle_slice;
103  }
104  DIR* ca_directory = opendir(certs_directory);
105  if (ca_directory == nullptr) {
106  return bundle_slice;
107  }
108  struct FileData {
109  char path[MAXPATHLEN];
110  off_t size;
111  };
112  std::vector<FileData> roots_filenames;
113  size_t total_bundle_size = 0;
114  struct dirent* directory_entry;
115  while ((directory_entry = readdir(ca_directory)) != nullptr) {
116  struct stat dir_entry_stat;
117  const char* file_entry_name = directory_entry->d_name;
118  FileData file_data;
119  GetAbsoluteFilePath(certs_directory, file_entry_name, file_data.path);
120  int stat_return = stat(file_data.path, &dir_entry_stat);
121  if (stat_return == -1 || !S_ISREG(dir_entry_stat.st_mode)) {
122  // no subdirectories.
123  if (stat_return == -1) {
124  gpr_log(GPR_ERROR, "failed to get status for file: %s", file_data.path);
125  }
126  continue;
127  }
128  file_data.size = dir_entry_stat.st_size;
129  total_bundle_size += file_data.size;
130  roots_filenames.push_back(file_data);
131  }
132  closedir(ca_directory);
133  char* bundle_string = static_cast<char*>(gpr_zalloc(total_bundle_size + 1));
134  size_t bytes_read = 0;
135  for (size_t i = 0; i < roots_filenames.size(); i++) {
136  int file_descriptor = open(roots_filenames[i].path, O_RDONLY);
137  if (file_descriptor != -1) {
138  // Read file into bundle.
139  size_t cert_file_size = roots_filenames[i].size;
140  int read_ret =
141  read(file_descriptor, bundle_string + bytes_read, cert_file_size);
142  if (read_ret != -1) {
143  bytes_read += read_ret;
144  } else {
145  gpr_log(GPR_ERROR, "failed to read file: %s", roots_filenames[i].path);
146  }
147  }
148  }
149  bundle_slice = grpc_slice_new(bundle_string, bytes_read, gpr_free);
150  return bundle_slice;
151 }
152 
155  // Prioritize user-specified custom directory if flag is set.
156  UniquePtr<char> custom_dir = GPR_GLOBAL_CONFIG_GET(grpc_system_ssl_roots_dir);
157  if (strlen(custom_dir.get()) > 0) {
158  result = CreateRootCertsBundle(custom_dir.get());
159  }
160  // If the custom directory is empty/invalid/not specified, fallback to
161  // distribution-specific directory.
163  result = GetSystemRootCerts();
164  }
166  for (size_t i = 0; i < GPR_ARRAY_SIZE(kCertDirectories); i++) {
167  result = CreateRootCertsBundle(kCertDirectories[i]);
168  if (!GRPC_SLICE_IS_EMPTY(result)) {
169  break;
170  }
171  }
172  }
173  return result;
174 }
175 
176 } // namespace grpc_core
177 
178 #endif /* GPR_LINUX || GPR_ANDROID || GPR_FREEBSD || GPR_APPLE */
_gevent_test_main.result
result
Definition: _gevent_test_main.py:96
load_system_roots.h
log.h
grpc_load_file
grpc_error_handle grpc_load_file(const char *filename, int add_null_terminator, grpc_slice *output)
Definition: load_file.cc:33
load_file.h
GPR_GLOBAL_CONFIG_GET
#define GPR_GLOBAL_CONFIG_GET(name)
Definition: global_config_generic.h:24
grpc_core
Definition: call_metric_recorder.h:31
grpc_slice_new
GPRAPI grpc_slice grpc_slice_new(void *p, size_t len, void(*destroy)(void *))
Definition: slice/slice.cc:103
string.h
gpr_free
GPRAPI void gpr_free(void *ptr)
Definition: alloc.cc:51
useful.h
error
grpc_error_handle error
Definition: retry_filter.cc:499
check_documentation.path
path
Definition: check_documentation.py:57
versiongenerate.file_data
string file_data
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/xcode/Scripts/versiongenerate.py:84
gpr_zalloc
GPRAPI void * gpr_zalloc(size_t size)
Definition: alloc.cc:40
memory.h
GRPC_SLICE_IS_EMPTY
#define GRPC_SLICE_IS_EMPTY(slice)
Definition: include/grpc/impl/codegen/slice.h:112
gpr_log
GPRAPI void gpr_log(const char *file, int line, gpr_log_severity severity, const char *format,...) GPR_PRINT_FORMAT_CHECK(4
bytes_read
static size_t bytes_read
Definition: test-ipc-heavy-traffic-deadlock-bug.c:47
grpc_empty_slice
GPRAPI grpc_slice grpc_empty_slice(void)
Definition: slice/slice.cc:42
grpc_slice
Definition: include/grpc/impl/codegen/slice.h:65
error.h
GPR_ERROR
#define GPR_ERROR
Definition: include/grpc/impl/codegen/log.h:57
load_system_roots_supported.h
GPR_ARRAY_SIZE
#define GPR_ARRAY_SIZE(array)
Definition: useful.h:129
read
int read(izstream &zs, T *x, Items items)
Definition: bloaty/third_party/zlib/contrib/iostream2/zstream.h:115
global_config.h
grpc_core::LoadSystemRootCerts
grpc_slice LoadSystemRootCerts()
Definition: load_system_roots_fallback.cc:31
GPR_GLOBAL_CONFIG_DEFINE_STRING
#define GPR_GLOBAL_CONFIG_DEFINE_STRING(name, default_value, help)
Definition: global_config_env.h:122
alloc.h
GRPC_ERROR_UNREF
#define GRPC_ERROR_UNREF(err)
Definition: error.h:262
open
#define open
Definition: test-fs.c:46
stat
#define stat
Definition: test-fs.c:50
grpc_error
Definition: error_internal.h:42
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
GRPC_ERROR_IS_NONE
#define GRPC_ERROR_IS_NONE(err)
Definition: error.h:241
port_platform.h


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:00:29