-
Notifications
You must be signed in to change notification settings - Fork 6
/
clrtrust-helper.c
164 lines (137 loc) · 4.42 KB
/
clrtrust-helper.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*
* Copyright © 2018 Intel Corporation.
*
* See COPYING for terms.
*/
/* This is a helper application which is meant to be used with clrtrust, the
* Clear Linux Trust Store management tool. It is created for performance
* reasons, to process certificates in bulk as opposed to running openssl for
* each certificate file.
*
* It reads the list of files, one filename per line, from the standard input
* and produces output in form of: <filename>\t<fingerprint or hash>.
*
* Two modes are supported. If '-f' switch is specified on the command line, for
* each file a SHA-1 fingerprint is calculated. If '-s' is specified, then
* subject hash is produced.
*/
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
/* process return codes */
#define CTH_EOK 0 /* success. */
#define CTH_EERR 1 /* incorrect invocation, cannot start. */
#define CTH_EINV 2 /* invalid input, cannot produce result. */
typedef enum {
MODE_FINGER = 1, /* output fingerprint */
MODE_HASH, /* output subject hash */
MODE_INVALID = 100
} runmode_t;
void print_help() {
char *help = "clrtrust-helper [-f|-s]\n"
"Helper utility for clrtrust. Reads the list of files from"
" stdin, one per line, and produces either fingerprint or"
" subject hash for each file on stdout in form:\n"
" <filename><TAB><fingerprint or subject hash>\n";
puts(help);
}
int main(int argc, char **argv) {
runmode_t runmode = MODE_INVALID; /* global switch: whether to produce fingerprint
or subject hash. */
BIO *inbio = NULL;
/* fingerprint-related variables */
const EVP_MD *finger_type = NULL;
unsigned int finger_sz;
unsigned char finger[EVP_MAX_MD_SIZE];
/* subjecthash-related variables */
unsigned long subject_hash;
unsigned int i;
int c;
char *fname = NULL;
size_t sz = 0;
/* return code */
int ret = CTH_EOK;
while ((c = getopt(argc, argv, "fs")) != -1) {
switch (c) {
case 'f':
if (runmode == MODE_INVALID) {
runmode = MODE_FINGER;
} else {
print_help();
return CTH_EERR;
}
break;
case 's':
if (runmode == MODE_INVALID) {
runmode = MODE_HASH;
} else {
print_help();
return CTH_EERR;
}
break;
default:
printf("Unrecognized option -%c.\n", c);
print_help();
return CTH_EERR;
}
}
if (runmode == MODE_INVALID) {
print_help();
return CTH_EERR;
}
OpenSSL_add_all_algorithms();
finger_type = EVP_sha1();
inbio = BIO_new(BIO_s_file());
while (getline(&fname, &sz, stdin) != -1) {
int fname_len = strlen(fname);
int err = 1;
FILE *fp = NULL;
X509 *cert = NULL;
if (fname_len < 1) continue;
if (fname[fname_len-1] == '\n') {
fname[fname_len-1] = '\0';
}
if (!(fp = fopen(fname, "r"))) {
goto wrap_up;
}
if (!BIO_set_fp(inbio, fp, BIO_NOCLOSE)) {
goto wrap_up;
}
if (!(cert = PEM_read_bio_X509(inbio, NULL, 0, NULL))) {
goto wrap_up;
}
switch (runmode) {
case MODE_FINGER:
if (!X509_digest(cert, finger_type, finger, &finger_sz)) {
goto wrap_up;
}
printf("%s\t", fname);
for (i=0; i < finger_sz; i++) {
printf("%02X", finger[i]);
if (i < finger_sz-1) printf(":");
}
putc('\n', stdout);
err = 0;
break;
case MODE_HASH:
subject_hash = X509_subject_name_hash(cert);
printf("%s\t%08lx\n", fname, subject_hash);
err = 0;
break;
default:
return CTH_EERR;
}
wrap_up:
if (fp) fclose(fp);
if (cert) X509_free(cert);
if (err) {
printf("%s\tERROR\n", fname);
ret = CTH_EINV;
}
}
if (fname) free(fname);
return ret;
}