| 
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 | +    DWORD 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(): %#lx", 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, find_data.cFileName, 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(): %#lx", 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