|
7 | 7 | * https://www.openssl.org/source/license.html |
8 | 8 | */ |
9 | 9 |
|
| 10 | +#include <errno.h> |
10 | 11 | #include <stdbool.h> |
11 | 12 | #include <stdio.h> |
12 | 13 | #include <stdlib.h> |
13 | 14 | #include <string.h> |
| 15 | +#include <sys/stat.h> |
14 | 16 | #ifndef _WIN32 |
| 17 | +# include <dirent.h> |
15 | 18 | # include <libgen.h> |
16 | 19 | # include <unistd.h> |
17 | 20 | #else |
@@ -144,6 +147,146 @@ make_nonce(struct nonce_cfg *cfg) |
144 | 147 | } |
145 | 148 | } |
146 | 149 |
|
| 150 | +static size_t |
| 151 | +read_cert(const char * const dir, const char * const name, X509_STORE * const store) |
| 152 | +{ |
| 153 | + X509 *x509 = NULL; |
| 154 | + char *path = NULL; |
| 155 | + size_t ret = 1; |
| 156 | + |
| 157 | + path = perflib_mk_file_path(dir, name); |
| 158 | + if (path == NULL) { |
| 159 | + warn("Failed to allocate cert name in directory \"%s\" for file \"%s\"", |
| 160 | + dir, name); |
| 161 | + goto out; |
| 162 | + } |
| 163 | + |
| 164 | + x509 = load_cert_from_file(path); |
| 165 | + if (x509 == NULL) { |
| 166 | + goto out; |
| 167 | + } |
| 168 | + |
| 169 | + if (!X509_STORE_add_cert(store, x509)) { |
| 170 | + warnx("Failed to add a certificate from \"%s\" to the store\n", path); |
| 171 | + goto out; |
| 172 | + } |
| 173 | + |
| 174 | + if (verbosity >= VERBOSITY_DEBUG) |
| 175 | + fprintf(stderr, "Successfully added a certificate from \"%s\"" |
| 176 | + " to the store\n", path); |
| 177 | + |
| 178 | + ret = 1; |
| 179 | + |
| 180 | + out: |
| 181 | + X509_free(x509); |
| 182 | + OPENSSL_free(path); |
| 183 | + |
| 184 | + return ret; |
| 185 | +} |
| 186 | + |
| 187 | +#if defined(_WIN32) |
| 188 | +static size_t |
| 189 | +read_certsdir(char * const dir, X509_STORE * const store) |
| 190 | +{ |
| 191 | + const size_t dir_len = strlen(dir); |
| 192 | + const size_t glob_len = dir_len + sizeof("\\*"); |
| 193 | + size_t cnt = 0; |
| 194 | + char *search_glob = NULL; |
| 195 | + HANDLE find_handle = INVALID_HANDLE_VALUE; |
| 196 | + WIN32_FIND_DATA find_data; |
| 197 | + DOWRD last_err; |
| 198 | + |
| 199 | + search_glob = OPENSSL_malloc(glob_len); |
| 200 | + if (search_glob == NULL) { |
| 201 | + warnx("Error allocating a search glob for \"%s\"", dir); |
| 202 | + return 0; |
| 203 | + } |
| 204 | + |
| 205 | + if (snprintf(search_glob, glob_len, "%s\\*", dir) != glob_len - 1) { |
| 206 | + warnx("Error generating a search glob for \"%s\"", dir); |
| 207 | + goto out; |
| 208 | + } |
| 209 | + |
| 210 | + find_handle = FindFirstFileA(search_glob, &find_data); |
| 211 | + if (find_handle == INVALID_HANDLE_VALUE) { |
| 212 | + warnx("Error in FindFirstFile(): %lu", GetLastError()); |
| 213 | + goto out; |
| 214 | + } |
| 215 | + |
| 216 | + do { |
| 217 | + if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { |
| 218 | + if (verbosity >= VERBOSITY_DEBUG) |
| 219 | + warnx("\"%s\\%s\" is a directory file, skipping", |
| 220 | + dir, find_data.cFileName); |
| 221 | + continue; |
| 222 | + } |
| 223 | + |
| 224 | + cnt += read_cert(dir, e->d_name, store); |
| 225 | + } while (FindNextFileA(find_handle, &find_data) != 0) |
| 226 | + |
| 227 | + last_err = GetLastError(); |
| 228 | + if (last_err != ERROR_NO_MORE_FILES) |
| 229 | + warnx("Error in FindNextFile(): %lu", last_err); |
| 230 | + |
| 231 | + out: |
| 232 | + if (find_handle != INVALID_HANDLE_VALUE) |
| 233 | + FindClose(find_handle); |
| 234 | + OPENSSL_free(search_glob); |
| 235 | + |
| 236 | + return cnt; |
| 237 | +} |
| 238 | +#else /* !defined(_WIN32) */ |
| 239 | +static size_t |
| 240 | +read_certsdir(char * const dir, X509_STORE * const store) |
| 241 | +{ |
| 242 | + struct stat st; |
| 243 | + struct dirent *e; |
| 244 | + DIR *d = opendir(dir); |
| 245 | + size_t cnt = 0; |
| 246 | + |
| 247 | + if (d == NULL) { |
| 248 | + warn("Could not open \"%s\"", dir); |
| 249 | + |
| 250 | + return 0; |
| 251 | + } |
| 252 | + |
| 253 | + while (1) { |
| 254 | + errno = 0; |
| 255 | + e = readdir(d); |
| 256 | + |
| 257 | + if (e == NULL) { |
| 258 | + if (errno != 0) |
| 259 | + warn("An error occurred while reading directory \"%s\"", dir); |
| 260 | + |
| 261 | + break; |
| 262 | + } |
| 263 | + |
| 264 | + if (e->d_type != DT_REG && e->d_type != DT_UNKNOWN) { |
| 265 | + if (verbosity >= VERBOSITY_DEBUG) |
| 266 | + warnx("\"%s/%s\" is not a regular file, skipping", |
| 267 | + dir, e->d_name); |
| 268 | + continue; |
| 269 | + } |
| 270 | + |
| 271 | + cnt += read_cert(dir, e->d_name, store); |
| 272 | + } |
| 273 | + |
| 274 | + return cnt; |
| 275 | +} |
| 276 | +#endif /* defined(_WIN32) */ |
| 277 | + |
| 278 | +static size_t |
| 279 | +read_certsdirs(char * const * const dirs, const int dir_cnt, |
| 280 | + X509_STORE * const store) |
| 281 | +{ |
| 282 | + size_t cnt = 0; |
| 283 | + |
| 284 | + for (int i = 0; i < dir_cnt; i++) |
| 285 | + cnt += read_certsdir(dirs[i], store); |
| 286 | + |
| 287 | + return cnt; |
| 288 | +} |
| 289 | + |
147 | 290 | static void |
148 | 291 | do_x509storeissuer(size_t num) |
149 | 292 | { |
@@ -256,11 +399,10 @@ main(int argc, char *argv[]) |
256 | 399 | size_t total_count = 0; |
257 | 400 | size_t total_found = 0; |
258 | 401 | double avcalltime; |
259 | | - char *cert = NULL; |
260 | 402 | int ret = EXIT_FAILURE; |
261 | | - BIO *bio = NULL; |
262 | 403 | int opt; |
263 | 404 | int dirs_start; |
| 405 | + size_t num_certs = 0; |
264 | 406 | struct nonce_cfg nonce_cfg; |
265 | 407 |
|
266 | 408 | parse_nonce_cfg(NONCE_CFG, &nonce_cfg); |
@@ -311,6 +453,12 @@ main(int argc, char *argv[]) |
311 | 453 | if (store == NULL || !X509_STORE_set_default_paths(store)) |
312 | 454 | errx(EXIT_FAILURE, "Failed to create X509_STORE"); |
313 | 455 |
|
| 456 | + num_certs += read_certsdirs(argv + dirs_start, argc - dirs_start - 1, |
| 457 | + store); |
| 458 | + |
| 459 | + if (verbosity >= VERBOSITY_DEBUG_STATS) |
| 460 | + fprintf(stderr, "Added %zu certificates to the store\n", num_certs); |
| 461 | + |
314 | 462 | counts = OPENSSL_malloc(sizeof(size_t) * threadcount); |
315 | 463 | if (counts == NULL) |
316 | 464 | errx(EXIT_FAILURE, "Failed to create counts array"); |
@@ -358,8 +506,6 @@ main(int argc, char *argv[]) |
358 | 506 | err: |
359 | 507 | X509_free(x509_nonce); |
360 | 508 | X509_STORE_free(store); |
361 | | - BIO_free(bio); |
362 | | - OPENSSL_free(cert); |
363 | 509 | OPENSSL_free(founds); |
364 | 510 | OPENSSL_free(counts); |
365 | 511 | return ret; |
|
0 commit comments