clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name certhash.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/openssl/obj -resource-dir /usr/local/llvm16/lib/clang/16 -D LIBRESSL_INTERNAL -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/openssl/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.bin/openssl/certhash.c
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | #include <sys/types.h> |
19 | #include <sys/stat.h> |
20 | |
21 | #include <errno.h> |
22 | #include <dirent.h> |
23 | #include <fcntl.h> |
24 | #include <limits.h> |
25 | #include <stdio.h> |
26 | #include <string.h> |
27 | #include <unistd.h> |
28 | |
29 | #include <openssl/bio.h> |
30 | #include <openssl/evp.h> |
31 | #include <openssl/pem.h> |
32 | #include <openssl/x509.h> |
33 | |
34 | #include "apps.h" |
35 | |
36 | static struct { |
37 | int dryrun; |
38 | int verbose; |
39 | } cfg; |
40 | |
41 | static const struct option certhash_options[] = { |
42 | { |
43 | .name = "n", |
44 | .desc = "Perform a dry-run - do not make any changes", |
45 | .type = OPTION_FLAG, |
46 | .opt.flag = &cfg.dryrun, |
47 | }, |
48 | { |
49 | .name = "v", |
50 | .desc = "Verbose", |
51 | .type = OPTION_FLAG, |
52 | .opt.flag = &cfg.verbose, |
53 | }, |
54 | { NULL }, |
55 | }; |
56 | |
57 | struct hashinfo { |
58 | char *filename; |
59 | char *target; |
60 | unsigned long hash; |
61 | unsigned int index; |
62 | unsigned char fingerprint[EVP_MAX_MD_SIZE]; |
63 | int is_crl; |
64 | int is_dup; |
65 | int exists; |
66 | int changed; |
67 | struct hashinfo *reference; |
68 | struct hashinfo *next; |
69 | }; |
70 | |
71 | static struct hashinfo * |
72 | hashinfo(const char *filename, unsigned long hash, unsigned char *fingerprint) |
73 | { |
74 | struct hashinfo *hi; |
75 | |
76 | if ((hi = calloc(1, sizeof(*hi))) == NULL) |
77 | return (NULL); |
78 | if (filename != NULL) { |
79 | if ((hi->filename = strdup(filename)) == NULL) { |
80 | free(hi); |
81 | return (NULL); |
82 | } |
83 | } |
84 | hi->hash = hash; |
85 | if (fingerprint != NULL) |
86 | memcpy(hi->fingerprint, fingerprint, sizeof(hi->fingerprint)); |
87 | |
88 | return (hi); |
89 | } |
90 | |
91 | static void |
92 | hashinfo_free(struct hashinfo *hi) |
93 | { |
94 | if (hi == NULL) |
95 | return; |
96 | |
97 | free(hi->filename); |
98 | free(hi->target); |
99 | free(hi); |
100 | } |
101 | |
102 | #ifdef DEBUG |
103 | static void |
104 | hashinfo_print(struct hashinfo *hi) |
105 | { |
106 | int i; |
107 | |
108 | printf("hashinfo %s %08lx %u %i\n", hi->filename, hi->hash, |
109 | hi->index, hi->is_crl); |
110 | for (i = 0; i < (int)EVP_MAX_MD_SIZE; i++) { |
111 | printf("%02X%c", hi->fingerprint[i], |
112 | (i + 1 == (int)EVP_MAX_MD_SIZE) ? '\n' : ':'); |
113 | } |
114 | } |
115 | #endif |
116 | |
117 | static int |
118 | hashinfo_compare(const void *a, const void *b) |
119 | { |
120 | struct hashinfo *hia = *(struct hashinfo **)a; |
121 | struct hashinfo *hib = *(struct hashinfo **)b; |
122 | int rv; |
123 | |
124 | rv = hia->hash < hib->hash ? -1 : hia->hash > hib->hash; |
125 | if (rv != 0) |
126 | return (rv); |
127 | rv = memcmp(hia->fingerprint, hib->fingerprint, |
128 | sizeof(hia->fingerprint)); |
129 | if (rv != 0) |
130 | return (rv); |
131 | return strcmp(hia->filename, hib->filename); |
132 | } |
133 | |
134 | static struct hashinfo * |
135 | hashinfo_chain(struct hashinfo *head, struct hashinfo *entry) |
136 | { |
137 | struct hashinfo *hi = head; |
138 | |
139 | if (hi == NULL) |
140 | return (entry); |
141 | while (hi->next != NULL) |
142 | hi = hi->next; |
143 | hi->next = entry; |
144 | |
145 | return (head); |
146 | } |
147 | |
148 | static void |
149 | hashinfo_chain_free(struct hashinfo *hi) |
150 | { |
151 | struct hashinfo *next; |
152 | |
153 | while (hi != NULL) { |
154 | next = hi->next; |
155 | hashinfo_free(hi); |
156 | hi = next; |
157 | } |
158 | } |
159 | |
160 | static size_t |
161 | hashinfo_chain_length(struct hashinfo *hi) |
162 | { |
163 | int len = 0; |
164 | |
165 | while (hi != NULL) { |
166 | len++; |
167 | hi = hi->next; |
168 | } |
169 | return (len); |
170 | } |
171 | |
172 | static int |
173 | hashinfo_chain_sort(struct hashinfo **head) |
174 | { |
175 | struct hashinfo **list, *entry; |
176 | size_t len; |
177 | int i; |
178 | |
179 | if (*head == NULL) |
180 | return (0); |
181 | |
182 | len = hashinfo_chain_length(*head); |
183 | if ((list = reallocarray(NULL, len, sizeof(struct hashinfo *))) == NULL) |
184 | return (-1); |
185 | |
186 | for (entry = *head, i = 0; entry != NULL; entry = entry->next, i++) |
187 | list[i] = entry; |
188 | qsort(list, len, sizeof(struct hashinfo *), hashinfo_compare); |
189 | |
190 | *head = entry = list[0]; |
191 | for (i = 1; i < len; i++) { |
192 | entry->next = list[i]; |
193 | entry = list[i]; |
194 | } |
195 | entry->next = NULL; |
196 | |
197 | free(list); |
198 | return (0); |
199 | } |
200 | |
201 | static char * |
202 | hashinfo_linkname(struct hashinfo *hi) |
203 | { |
204 | char *filename; |
205 | |
206 | if (asprintf(&filename, "%08lx.%s%u", hi->hash, |
207 | (hi->is_crl ? "r" : ""), hi->index) == -1) |
208 | return (NULL); |
209 | |
210 | return (filename); |
211 | } |
212 | |
213 | static int |
214 | filename_is_hash(const char *filename) |
215 | { |
216 | const char *p = filename; |
217 | |
218 | while ((*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'f')) |
219 | p++; |
220 | if (*p++ != '.') |
221 | return (0); |
222 | if (*p == 'r') |
223 | p++; |
224 | while (*p >= '0' && *p <= '9') |
225 | p++; |
226 | if (*p != '\0') |
227 | return (0); |
228 | |
229 | return (1); |
230 | } |
231 | |
232 | static int |
233 | filename_is_pem(const char *filename) |
234 | { |
235 | const char *q, *p = filename; |
236 | |
237 | if ((q = strchr(p, '\0')) == NULL) |
238 | return (0); |
239 | if ((q - p) < 4) |
240 | return (0); |
241 | if (strncmp((q - 4), ".pem", 4) != 0) |
242 | return (0); |
243 | |
244 | return (1); |
245 | } |
246 | |
247 | static struct hashinfo * |
248 | hashinfo_from_linkname(const char *linkname, const char *target) |
249 | { |
250 | struct hashinfo *hi = NULL; |
251 | const char *errstr; |
252 | char *l, *p, *ep; |
253 | long long val; |
254 | |
255 | if ((l = strdup(linkname)) == NULL) |
256 | goto err; |
257 | if ((p = strchr(l, '.')) == NULL) |
258 | goto err; |
259 | *p++ = '\0'; |
260 | |
261 | if ((hi = hashinfo(linkname, 0, NULL)) == NULL) |
262 | goto err; |
263 | if ((hi->target = strdup(target)) == NULL) |
264 | goto err; |
265 | |
266 | errno = 0; |
267 | val = strtoll(l, &ep, 16); |
268 | if (l[0] == '\0' || *ep != '\0') |
269 | goto err; |
270 | if (errno == ERANGE && (val == LLONG_MAX || val == LLONG_MIN)) |
271 | goto err; |
272 | if (val < 0 || val > ULONG_MAX) |
273 | goto err; |
274 | hi->hash = (unsigned long)val; |
275 | |
276 | if (*p == 'r') { |
277 | hi->is_crl = 1; |
278 | p++; |
279 | } |
280 | |
281 | val = strtonum(p, 0, 0xffffffff, &errstr); |
282 | if (errstr != NULL) |
283 | goto err; |
284 | |
285 | hi->index = (unsigned int)val; |
286 | |
287 | goto done; |
288 | |
289 | err: |
290 | hashinfo_free(hi); |
291 | hi = NULL; |
292 | |
293 | done: |
294 | free(l); |
295 | |
296 | return (hi); |
297 | } |
298 | |
299 | static struct hashinfo * |
300 | certhash_cert(BIO *bio, const char *filename) |
301 | { |
302 | unsigned char fingerprint[EVP_MAX_MD_SIZE]; |
303 | struct hashinfo *hi = NULL; |
304 | const EVP_MD *digest; |
305 | X509 *cert = NULL; |
306 | unsigned long hash; |
307 | unsigned int len; |
308 | |
309 | if ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) == NULL) |
310 | goto err; |
311 | |
312 | hash = X509_subject_name_hash(cert); |
313 | |
314 | digest = EVP_sha256(); |
315 | if (X509_digest(cert, digest, fingerprint, &len) != 1) { |
316 | fprintf(stderr, "out of memory\n"); |
317 | goto err; |
318 | } |
319 | |
320 | hi = hashinfo(filename, hash, fingerprint); |
321 | |
322 | err: |
323 | X509_free(cert); |
324 | |
325 | return (hi); |
326 | } |
327 | |
328 | static struct hashinfo * |
329 | certhash_crl(BIO *bio, const char *filename) |
330 | { |
331 | unsigned char fingerprint[EVP_MAX_MD_SIZE]; |
332 | struct hashinfo *hi = NULL; |
333 | const EVP_MD *digest; |
334 | X509_CRL *crl = NULL; |
335 | unsigned long hash; |
336 | unsigned int len; |
337 | |
338 | if ((crl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) == NULL) |
339 | return (NULL); |
340 | |
341 | hash = X509_NAME_hash(X509_CRL_get_issuer(crl)); |
342 | |
343 | digest = EVP_sha256(); |
344 | if (X509_CRL_digest(crl, digest, fingerprint, &len) != 1) { |
345 | fprintf(stderr, "out of memory\n"); |
346 | goto err; |
347 | } |
348 | |
349 | hi = hashinfo(filename, hash, fingerprint); |
350 | |
351 | err: |
352 | X509_CRL_free(crl); |
353 | |
354 | return (hi); |
355 | } |
356 | |
357 | static int |
358 | certhash_addlink(struct hashinfo **links, struct hashinfo *hi) |
359 | { |
360 | struct hashinfo *link = NULL; |
361 | |
362 | if ((link = hashinfo(NULL, hi->hash, hi->fingerprint)) == NULL) |
| |
363 | goto err; |
364 | |
365 | if ((link->filename = hashinfo_linkname(hi)) == NULL) |
| 49 | | Assuming the condition is false | |
|
| |
366 | goto err; |
367 | |
368 | link->reference = hi; |
369 | link->changed = 1; |
370 | *links = hashinfo_chain(*links, link); |
| 51 | | Value assigned to 'cfg.dryrun', which participates in a condition later | |
|
371 | hi->reference = link; |
372 | |
373 | return (0); |
374 | |
375 | err: |
376 | hashinfo_free(link); |
377 | return (-1); |
378 | } |
379 | |
380 | static void |
381 | certhash_findlink(struct hashinfo *links, struct hashinfo *hi) |
382 | { |
383 | struct hashinfo *link; |
384 | |
385 | for (link = links; link != NULL; link = link->next) { |
386 | if (link->is_crl == hi->is_crl && |
387 | link->hash == hi->hash && |
388 | link->index == hi->index && |
389 | link->reference == NULL) { |
390 | link->reference = hi; |
391 | if (link->target == NULL || |
392 | strcmp(link->target, hi->filename) != 0) |
393 | link->changed = 1; |
394 | hi->reference = link; |
395 | break; |
396 | } |
397 | } |
398 | } |
399 | |
400 | static void |
401 | certhash_index(struct hashinfo *head, const char *name) |
402 | { |
403 | struct hashinfo *last, *entry; |
404 | int index = 0; |
405 | |
406 | last = NULL; |
407 | for (entry = head; entry != NULL; entry = entry->next) { |
408 | if (last != NULL) { |
409 | if (entry->hash == last->hash) { |
410 | if (memcmp(entry->fingerprint, |
411 | last->fingerprint, |
412 | sizeof(entry->fingerprint)) == 0) { |
413 | fprintf(stderr, "WARNING: duplicate %s " |
414 | "in %s (using %s), ignoring...\n", |
415 | name, entry->filename, |
416 | last->filename); |
417 | entry->is_dup = 1; |
418 | continue; |
419 | } |
420 | index++; |
421 | } else { |
422 | index = 0; |
423 | } |
424 | } |
425 | entry->index = index; |
426 | last = entry; |
427 | } |
428 | } |
429 | |
430 | static int |
431 | certhash_merge(struct hashinfo **links, struct hashinfo **certs, |
432 | struct hashinfo **crls) |
433 | { |
434 | struct hashinfo *cert, *crl; |
435 | |
436 | |
437 | if (hashinfo_chain_sort(certs) == -1) |
| 36 | | Assuming the condition is false | |
|
| |
438 | return (-1); |
439 | if (hashinfo_chain_sort(crls) == -1) |
| 38 | | Assuming the condition is false | |
|
| |
440 | return (-1); |
441 | certhash_index(*certs, "certificate"); |
442 | certhash_index(*crls, "CRL"); |
443 | |
444 | |
445 | for (cert = *certs; cert != NULL; cert = cert->next) { |
| 40 | | Loop condition is true. Entering loop body | |
|
| 43 | | Loop condition is false. Execution continues on line 450 | |
|
446 | if (cert->is_dup == 1) |
| 41 | | Assuming field 'is_dup' is not equal to 1 | |
|
| |
447 | continue; |
448 | certhash_findlink(*links, cert); |
449 | } |
450 | for (crl = *crls; crl != NULL; crl = crl->next) { |
| 44 | | Loop condition is false. Execution continues on line 457 | |
|
451 | if (crl->is_dup == 1) |
452 | continue; |
453 | certhash_findlink(*links, crl); |
454 | } |
455 | |
456 | |
457 | for (cert = *certs; cert != NULL; cert = cert->next) { |
| 54 | | Assuming 'cert' is equal to NULL | |
|
| 55 | | Loop condition is false. Execution continues on line 463 | |
|
458 | if (cert->is_dup == 1 || cert->reference != NULL) |
| 45 | | Assuming field 'reference' is equal to NULL | |
|
| |
459 | continue; |
460 | if (certhash_addlink(links, cert) == -1) |
| 47 | | Calling 'certhash_addlink' | |
|
| 52 | | Returning from 'certhash_addlink' | |
|
| |
461 | return (-1); |
462 | } |
463 | for (crl = *crls; crl != NULL; crl = crl->next) { |
| 56 | | Loop condition is false. Execution continues on line 470 | |
|
464 | if (crl->is_dup == 1 || crl->reference != NULL) |
465 | continue; |
466 | if (certhash_addlink(links, crl) == -1) |
467 | return (-1); |
468 | } |
469 | |
470 | return (0); |
471 | } |
472 | |
473 | static int |
474 | certhash_link(struct dirent *dep, struct hashinfo **links) |
475 | { |
476 | struct hashinfo *hi = NULL; |
477 | char target[PATH_MAX]; |
478 | struct stat sb; |
479 | int n; |
480 | |
481 | if (lstat(dep->d_name, &sb) == -1) { |
482 | fprintf(stderr, "failed to stat %s\n", dep->d_name); |
483 | return (-1); |
484 | } |
485 | if (!S_ISLNK(sb.st_mode)) |
486 | return (0); |
487 | |
488 | n = readlink(dep->d_name, target, sizeof(target) - 1); |
489 | if (n == -1) { |
490 | fprintf(stderr, "failed to readlink %s\n", dep->d_name); |
491 | return (-1); |
492 | } |
493 | if (n >= sizeof(target) - 1) { |
494 | fprintf(stderr, "symbolic link is too long %s\n", dep->d_name); |
495 | return (-1); |
496 | } |
497 | target[n] = '\0'; |
498 | |
499 | hi = hashinfo_from_linkname(dep->d_name, target); |
500 | if (hi == NULL) { |
501 | fprintf(stderr, "failed to get hash info %s\n", dep->d_name); |
502 | return (-1); |
503 | } |
504 | hi->exists = 1; |
505 | *links = hashinfo_chain(*links, hi); |
506 | |
507 | return (0); |
508 | } |
509 | |
510 | static int |
511 | certhash_file(struct dirent *dep, struct hashinfo **certs, |
512 | struct hashinfo **crls) |
513 | { |
514 | struct hashinfo *hi = NULL; |
515 | int has_cert, has_crl; |
516 | int ret = -1; |
517 | BIO *bio = NULL; |
518 | FILE *f; |
519 | |
520 | has_cert = has_crl = 0; |
521 | |
522 | if ((f = fopen(dep->d_name, "r")) == NULL) { |
523 | fprintf(stderr, "failed to fopen %s\n", dep->d_name); |
524 | goto err; |
525 | } |
526 | if ((bio = BIO_new_fp(f, BIO_CLOSE)) == NULL) { |
527 | fprintf(stderr, "failed to create bio\n"); |
528 | fclose(f); |
529 | goto err; |
530 | } |
531 | |
532 | if ((hi = certhash_cert(bio, dep->d_name)) != NULL) { |
533 | has_cert = 1; |
534 | *certs = hashinfo_chain(*certs, hi); |
535 | } |
536 | |
537 | if (BIO_reset(bio) != 0) { |
538 | fprintf(stderr, "BIO_reset failed\n"); |
539 | goto err; |
540 | } |
541 | |
542 | if ((hi = certhash_crl(bio, dep->d_name)) != NULL) { |
543 | has_crl = hi->is_crl = 1; |
544 | *crls = hashinfo_chain(*crls, hi); |
545 | } |
546 | |
547 | if (!has_cert && !has_crl) |
548 | fprintf(stderr, "PEM file %s does not contain a certificate " |
549 | "or CRL, ignoring...\n", dep->d_name); |
550 | |
551 | ret = 0; |
552 | |
553 | err: |
554 | BIO_free(bio); |
555 | |
556 | return (ret); |
557 | } |
558 | |
559 | static int |
560 | certhash_directory(const char *path) |
561 | { |
562 | struct hashinfo *links = NULL, *certs = NULL, *crls = NULL, *link; |
563 | int ret = 0; |
564 | struct dirent *dep; |
565 | DIR *dip = NULL; |
566 | |
567 | if ((dip = opendir(".")) == NULL) { |
| 30 | | Assuming the condition is false | |
|
| |
568 | fprintf(stderr, "failed to open directory %s\n", path); |
569 | goto err; |
570 | } |
571 | |
572 | if (cfg.verbose) |
| |
573 | fprintf(stdout, "scanning directory %s\n", path); |
574 | |
575 | |
576 | while ((dep = readdir(dip)) != NULL) { |
| 33 | | Assuming the condition is false | |
|
| 34 | | Loop condition is false. Execution continues on line 587 | |
|
577 | if (filename_is_hash(dep->d_name)) { |
578 | if (certhash_link(dep, &links) == -1) |
579 | goto err; |
580 | } |
581 | if (filename_is_pem(dep->d_name)) { |
582 | if (certhash_file(dep, &certs, &crls) == -1) |
583 | goto err; |
584 | } |
585 | } |
586 | |
587 | if (certhash_merge(&links, &certs, &crls) == -1) { |
| 35 | | Calling 'certhash_merge' | |
|
| 57 | | Returning from 'certhash_merge' | |
|
| |
588 | fprintf(stderr, "certhash merge failed\n"); |
589 | goto err; |
590 | } |
591 | |
592 | |
593 | for (link = links; link != NULL; link = link->next) { |
| 59 | | Assuming 'link' is not equal to NULL | |
|
| 68 | | Assuming 'link' is equal to NULL | |
|
| 69 | | Loop condition is false. Execution continues on line 611 | |
|
594 | if (link->exists == 0 || |
| 60 | | Assuming field 'exists' is not equal to 0 | |
|
595 | (link->reference != NULL && link->changed == 0)) |
| 61 | | Assuming field 'reference' is equal to NULL | |
|
596 | continue; |
597 | if (cfg.verbose) |
| 62 | | Assuming field 'verbose' is 0 | |
|
| |
598 | fprintf(stdout, "%s link %s -> %s\n", |
599 | (cfg.dryrun ? "would remove" : |
600 | "removing"), link->filename, link->target); |
601 | if (cfg.dryrun) |
| 64 | | Assuming field 'dryrun' is 0 | |
|
| |
602 | continue; |
603 | if (unlink(link->filename) == -1) { |
| 66 | | Assuming the condition is false | |
|
| |
604 | fprintf(stderr, "failed to remove link %s\n", |
605 | link->filename); |
606 | goto err; |
607 | } |
608 | } |
609 | |
610 | |
611 | for (link = links; link != NULL; link = link->next) { |
612 | if (link->exists == 1 && link->changed == 0) |
| 70 | | Assuming field 'exists' is not equal to 1 | |
|
613 | continue; |
614 | if (cfg.verbose) |
| |
615 | fprintf(stdout, "%s link %s -> %s\n", |
616 | (cfg.dryrun ? "would create" : |
617 | "creating"), link->filename, |
618 | link->reference->filename); |
619 | if (cfg.dryrun) |
| |
620 | continue; |
621 | if (symlink(link->reference->filename, link->filename) == -1) { |
| 73 | | Access to field 'filename' results in a dereference of a null pointer (loaded from field 'reference') |
|
622 | fprintf(stderr, "failed to create link %s -> %s\n", |
623 | link->filename, link->reference->filename); |
624 | goto err; |
625 | } |
626 | } |
627 | |
628 | goto done; |
629 | |
630 | err: |
631 | ret = 1; |
632 | |
633 | done: |
634 | hashinfo_chain_free(certs); |
635 | hashinfo_chain_free(crls); |
636 | hashinfo_chain_free(links); |
637 | |
638 | if (dip != NULL) |
639 | closedir(dip); |
640 | return (ret); |
641 | } |
642 | |
643 | static void |
644 | certhash_usage(void) |
645 | { |
646 | fprintf(stderr, "usage: certhash [-nv] dir ...\n"); |
647 | options_usage(certhash_options); |
648 | } |
649 | |
650 | int |
651 | certhash_main(int argc, char **argv) |
652 | { |
653 | int argsused; |
654 | int i, cwdfd, ret = 0; |
655 | |
656 | if (pledge("stdio cpath wpath rpath", NULL) == -1) { |
| 1 | Assuming the condition is false | |
|
| |
657 | perror("pledge"); |
658 | exit(1); |
659 | } |
660 | |
661 | memset(&cfg, 0, sizeof(cfg)); |
662 | |
663 | if (options_parse(argc, argv, certhash_options, NULL, &argsused) != 0) { |
| 3 | | Assuming the condition is false | |
|
| |
664 | certhash_usage(); |
665 | return (1); |
666 | } |
667 | |
668 | if ((cwdfd = open(".", O_RDONLY)) == -1) { |
| 5 | | Assuming the condition is false | |
|
| |
669 | perror("failed to open current directory"); |
670 | return (1); |
671 | } |
672 | |
673 | for (i = argsused; i < argc; i++) { |
| 7 | | Assuming 'i' is < 'argc' | |
|
| 8 | | Loop condition is true. Entering loop body | |
|
| 13 | | Assuming 'i' is < 'argc' | |
|
| 14 | | Loop condition is true. Entering loop body | |
|
| 19 | | Assuming 'i' is < 'argc' | |
|
| 20 | | Loop condition is true. Entering loop body | |
|
| 25 | | Assuming 'i' is < 'argc' | |
|
| 26 | | Loop condition is true. Entering loop body | |
|
674 | if (chdir(argv[i]) == -1) { |
| 9 | | Assuming the condition is false | |
|
| |
| 15 | | Assuming the condition is false | |
|
| |
| 21 | | Assuming the condition is false | |
|
| |
| 27 | | Assuming the condition is false | |
|
| |
675 | fprintf(stderr, |
676 | "failed to change to directory %s: %s\n", |
677 | argv[i], strerror(errno)); |
678 | ret = 1; |
679 | continue; |
680 | } |
681 | ret |= certhash_directory(argv[i]); |
| 29 | | Calling 'certhash_directory' | |
|
682 | if (fchdir(cwdfd) == -1) { |
| 11 | | Assuming the condition is false | |
|
| |
| 17 | | Assuming the condition is false | |
|
| |
| 23 | | Assuming the condition is false | |
|
| |
683 | perror("failed to restore current directory"); |
684 | ret = 1; |
685 | break; |
686 | } |
687 | } |
688 | close(cwdfd); |
689 | |
690 | return (ret); |
691 | } |