diff options
author | inoguchi <> | 2022-03-24 11:27:45 +0000 |
---|---|---|
committer | inoguchi <> | 2022-03-24 11:27:45 +0000 |
commit | 76013a51bc66b3329f74a077b07c5c10f876736a (patch) | |
tree | 5a2c1b53461d3f733e0a928c35d85886fd48d726 /src/usr.bin/openssl/ts.c | |
parent | 4ab9607bafc39e3112c831efcc8db6382fb735ba (diff) | |
download | openbsd-76013a51bc66b3329f74a077b07c5c10f876736a.tar.gz openbsd-76013a51bc66b3329f74a077b07c5c10f876736a.tar.bz2 openbsd-76013a51bc66b3329f74a077b07c5c10f876736a.zip |
Convert openssl(1) ts option handling
Apply new option handling to openssl(1) ts, and there is no functional
changes here.
usage strings are comes from manual page.
comments and ok jsing@
Diffstat (limited to 'src/usr.bin/openssl/ts.c')
-rw-r--r-- | src/usr.bin/openssl/ts.c | 438 |
1 files changed, 285 insertions, 153 deletions
diff --git a/src/usr.bin/openssl/ts.c b/src/usr.bin/openssl/ts.c index 40c1a49b23..e4d299d726 100644 --- a/src/usr.bin/openssl/ts.c +++ b/src/usr.bin/openssl/ts.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ts.c,v 1.17 2021/12/12 20:22:59 tb Exp $ */ | 1 | /* $OpenBSD: ts.c,v 1.18 2022/03/24 11:27:45 inoguchi Exp $ */ |
2 | /* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL | 2 | /* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL |
3 | * project 2002. | 3 | * project 2002. |
4 | */ | 4 | */ |
@@ -116,38 +116,271 @@ static TS_VERIFY_CTX *create_verify_ctx(char *data, char *digest, | |||
116 | static X509_STORE *create_cert_store(char *ca_path, char *ca_file); | 116 | static X509_STORE *create_cert_store(char *ca_path, char *ca_file); |
117 | static int verify_cb(int ok, X509_STORE_CTX * ctx); | 117 | static int verify_cb(int ok, X509_STORE_CTX * ctx); |
118 | 118 | ||
119 | enum mode { | ||
120 | CMD_NONE, CMD_QUERY, CMD_REPLY, CMD_VERIFY | ||
121 | }; | ||
122 | |||
123 | static struct { | ||
124 | char *ca_file; | ||
125 | char *ca_path; | ||
126 | int cert; | ||
127 | char *chain; | ||
128 | char *configfile; | ||
129 | char *data; | ||
130 | char *digest; | ||
131 | char *in; | ||
132 | char *inkey; | ||
133 | const EVP_MD *md; | ||
134 | int mode; | ||
135 | int no_nonce; | ||
136 | char *out; | ||
137 | char *passin; | ||
138 | char *policy; | ||
139 | char *queryfile; | ||
140 | char *section; | ||
141 | char *signer; | ||
142 | int text; | ||
143 | int token_in; | ||
144 | int token_out; | ||
145 | char *untrusted; | ||
146 | } ts_config; | ||
147 | |||
148 | static int | ||
149 | ts_opt_md(int argc, char **argv, int *argsused) | ||
150 | { | ||
151 | char *name = argv[0]; | ||
152 | |||
153 | if (*name++ != '-') | ||
154 | return (1); | ||
155 | |||
156 | if ((ts_config.md = EVP_get_digestbyname(name)) == NULL) | ||
157 | return (1); | ||
158 | |||
159 | *argsused = 1; | ||
160 | return (0); | ||
161 | } | ||
162 | |||
163 | static int | ||
164 | ts_opt_query(void) | ||
165 | { | ||
166 | if (ts_config.mode != CMD_NONE) | ||
167 | return (1); | ||
168 | ts_config.mode = CMD_QUERY; | ||
169 | return (0); | ||
170 | } | ||
171 | |||
172 | static int | ||
173 | ts_opt_reply(void) | ||
174 | { | ||
175 | if (ts_config.mode != CMD_NONE) | ||
176 | return (1); | ||
177 | ts_config.mode = CMD_REPLY; | ||
178 | return (0); | ||
179 | } | ||
180 | |||
181 | static int | ||
182 | ts_opt_verify(void) | ||
183 | { | ||
184 | if (ts_config.mode != CMD_NONE) | ||
185 | return (1); | ||
186 | ts_config.mode = CMD_VERIFY; | ||
187 | return (0); | ||
188 | } | ||
189 | |||
190 | static const struct option ts_options[] = { | ||
191 | { | ||
192 | .name = "CAfile", | ||
193 | .argname = "file", | ||
194 | .desc = "Certificate Authority file", | ||
195 | .type = OPTION_ARG, | ||
196 | .opt.arg = &ts_config.ca_file, | ||
197 | }, | ||
198 | { | ||
199 | .name = "CApath", | ||
200 | .argname = "path", | ||
201 | .desc = "Certificate Authority path", | ||
202 | .type = OPTION_ARG, | ||
203 | .opt.arg = &ts_config.ca_path, | ||
204 | }, | ||
205 | { | ||
206 | .name = "cert", | ||
207 | .desc = "Include signing certificate in the response", | ||
208 | .type = OPTION_FLAG, | ||
209 | .opt.flag = &ts_config.cert, | ||
210 | }, | ||
211 | { | ||
212 | .name = "chain", | ||
213 | .argname = "file", | ||
214 | .desc = "PEM certificates that will be included in the response", | ||
215 | .type = OPTION_ARG, | ||
216 | .opt.arg = &ts_config.chain, | ||
217 | }, | ||
218 | { | ||
219 | .name = "config", | ||
220 | .argname = "file", | ||
221 | .desc = "Specify an alternative configuration file", | ||
222 | .type = OPTION_ARG, | ||
223 | .opt.arg = &ts_config.configfile, | ||
224 | }, | ||
225 | { | ||
226 | .name = "data", | ||
227 | .argname = "file", | ||
228 | .desc = "Data file for which the time stamp request needs to be created", | ||
229 | .type = OPTION_ARG, | ||
230 | .opt.arg = &ts_config.data, | ||
231 | }, | ||
232 | { | ||
233 | .name = "digest", | ||
234 | .argname = "arg", | ||
235 | .desc = "Specify the message imprint explicitly without the data file", | ||
236 | .type = OPTION_ARG, | ||
237 | .opt.arg = &ts_config.digest, | ||
238 | }, | ||
239 | { | ||
240 | .name = "in", | ||
241 | .argname = "file", | ||
242 | .desc = "Input file", | ||
243 | .type = OPTION_ARG, | ||
244 | .opt.arg = &ts_config.in, | ||
245 | }, | ||
246 | { | ||
247 | .name = "inkey", | ||
248 | .argname = "file", | ||
249 | .desc = "Input key file", | ||
250 | .type = OPTION_ARG, | ||
251 | .opt.arg = &ts_config.inkey, | ||
252 | }, | ||
253 | { | ||
254 | .name = "no_nonce", | ||
255 | .desc = "Specify no nonce in the request", | ||
256 | .type = OPTION_FLAG, | ||
257 | .opt.flag = &ts_config.no_nonce, | ||
258 | }, | ||
259 | { | ||
260 | .name = "out", | ||
261 | .argname = "file", | ||
262 | .desc = "Output file", | ||
263 | .type = OPTION_ARG, | ||
264 | .opt.arg = &ts_config.out, | ||
265 | }, | ||
266 | { | ||
267 | .name = "passin", | ||
268 | .argname = "src", | ||
269 | .desc = "Private key password source", | ||
270 | .type = OPTION_ARG, | ||
271 | .opt.arg = &ts_config.passin, | ||
272 | }, | ||
273 | { | ||
274 | .name = "policy", | ||
275 | .argname = "object_id", | ||
276 | .desc = "Policy for the TSA to use when creating the time stamp token", | ||
277 | .type = OPTION_ARG, | ||
278 | .opt.arg = &ts_config.policy, | ||
279 | }, | ||
280 | { | ||
281 | .name = "query", | ||
282 | .desc = "Create and print a time stamp request", | ||
283 | .type = OPTION_FUNC, | ||
284 | .opt.func = ts_opt_query, | ||
285 | }, | ||
286 | { | ||
287 | .name = "queryfile", | ||
288 | .argname = "file", | ||
289 | .desc = "File containing a DER-encoded time stamp request", | ||
290 | .type = OPTION_ARG, | ||
291 | .opt.arg = &ts_config.queryfile, | ||
292 | }, | ||
293 | { | ||
294 | .name = "reply", | ||
295 | .desc = "Create a time stamp response", | ||
296 | .type = OPTION_FUNC, | ||
297 | .opt.func = ts_opt_reply, | ||
298 | }, | ||
299 | { | ||
300 | .name = "section", | ||
301 | .argname = "arg", | ||
302 | .desc = "TSA section containing the settings for response generation", | ||
303 | .type = OPTION_ARG, | ||
304 | .opt.arg = &ts_config.section, | ||
305 | }, | ||
306 | { | ||
307 | .name = "signer", | ||
308 | .argname = "file", | ||
309 | .desc = "Signer certificate file", | ||
310 | .type = OPTION_ARG, | ||
311 | .opt.arg = &ts_config.signer, | ||
312 | }, | ||
313 | { | ||
314 | .name = "text", | ||
315 | .desc = "Output in human-readable text format", | ||
316 | .type = OPTION_FLAG, | ||
317 | .opt.flag = &ts_config.text, | ||
318 | }, | ||
319 | { | ||
320 | .name = "token_in", | ||
321 | .desc = "Input is a DER-encoded time stamp token", | ||
322 | .type = OPTION_FLAG, | ||
323 | .opt.flag = &ts_config.token_in, | ||
324 | }, | ||
325 | { | ||
326 | .name = "token_out", | ||
327 | .desc = "Output is a DER-encoded time stamp token", | ||
328 | .type = OPTION_FLAG, | ||
329 | .opt.flag = &ts_config.token_out, | ||
330 | }, | ||
331 | { | ||
332 | .name = "untrusted", | ||
333 | .argname = "file", | ||
334 | .desc = "File containing untrusted certificates", | ||
335 | .type = OPTION_ARG, | ||
336 | .opt.arg = &ts_config.untrusted, | ||
337 | }, | ||
338 | { | ||
339 | .name = "verify", | ||
340 | .desc = "Verify a time stamp response", | ||
341 | .type = OPTION_FUNC, | ||
342 | .opt.func = ts_opt_verify, | ||
343 | }, | ||
344 | { | ||
345 | .name = NULL, | ||
346 | .desc = "", | ||
347 | .type = OPTION_ARGV_FUNC, | ||
348 | .opt.argvfunc = ts_opt_md, | ||
349 | }, | ||
350 | { NULL }, | ||
351 | }; | ||
352 | |||
353 | static void | ||
354 | ts_usage(void) | ||
355 | { | ||
356 | fprintf(stderr, "usage:\n" | ||
357 | "ts -query [-md4 | -md5 | -ripemd160 | -sha1] [-cert]\n" | ||
358 | " [-config configfile] [-data file_to_hash]\n" | ||
359 | " [-digest digest_bytes] [-in request.tsq] [-no_nonce]\n" | ||
360 | " [-out request.tsq] [-policy object_id] [-text]\n"); | ||
361 | fprintf(stderr, "\n" | ||
362 | "ts -reply [-chain certs_file.pem] [-config configfile]\n" | ||
363 | " [-in response.tsr] [-inkey private.pem] [-out response.tsr]\n" | ||
364 | " [-passin arg] [-policy object_id] [-queryfile request.tsq]\n" | ||
365 | " [-section tsa_section] [-signer tsa_cert.pem] [-text]\n" | ||
366 | " [-token_in] [-token_out]\n"); | ||
367 | fprintf(stderr, "\n" | ||
368 | "ts -verify [-CAfile trusted_certs.pem]\n" | ||
369 | " [-CApath trusted_cert_path] [-data file_to_hash]\n" | ||
370 | " [-digest digest_bytes] [-in response.tsr]\n" | ||
371 | " [-queryfile request.tsq] [-token_in]\n" | ||
372 | " [-untrusted cert_file.pem]\n"); | ||
373 | fprintf(stderr, "\n"); | ||
374 | options_usage(ts_options); | ||
375 | fprintf(stderr, "\n"); | ||
376 | } | ||
377 | |||
119 | int | 378 | int |
120 | ts_main(int argc, char **argv) | 379 | ts_main(int argc, char **argv) |
121 | { | 380 | { |
122 | int ret = 1; | 381 | int ret = 1; |
123 | char *configfile = NULL; | ||
124 | char *section = NULL; | ||
125 | CONF *conf = NULL; | 382 | CONF *conf = NULL; |
126 | enum mode { | ||
127 | CMD_NONE, CMD_QUERY, CMD_REPLY, CMD_VERIFY | ||
128 | } mode = CMD_NONE; | ||
129 | char *data = NULL; | ||
130 | char *digest = NULL; | ||
131 | const EVP_MD *md = NULL; | ||
132 | char *policy = NULL; | ||
133 | int no_nonce = 0; | ||
134 | int cert = 0; | ||
135 | char *in = NULL; | ||
136 | char *out = NULL; | ||
137 | int text = 0; | ||
138 | char *queryfile = NULL; | ||
139 | char *passin = NULL; /* Password source. */ | ||
140 | char *password = NULL; /* Password itself. */ | 383 | char *password = NULL; /* Password itself. */ |
141 | char *inkey = NULL; | ||
142 | char *signer = NULL; | ||
143 | char *chain = NULL; | ||
144 | char *ca_path = NULL; | ||
145 | char *ca_file = NULL; | ||
146 | char *untrusted = NULL; | ||
147 | /* Input is ContentInfo instead of TimeStampResp. */ | ||
148 | int token_in = 0; | ||
149 | /* Output is ContentInfo instead of TimeStampResp. */ | ||
150 | int token_out = 0; | ||
151 | 384 | ||
152 | if (single_execution) { | 385 | if (single_execution) { |
153 | if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { | 386 | if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { |
@@ -156,98 +389,15 @@ ts_main(int argc, char **argv) | |||
156 | } | 389 | } |
157 | } | 390 | } |
158 | 391 | ||
159 | for (argc--, argv++; argc > 0; argc--, argv++) { | 392 | memset(&ts_config, 0, sizeof(ts_config)); |
160 | if (strcmp(*argv, "-config") == 0) { | 393 | ts_config.mode = CMD_NONE; |
161 | if (argc-- < 1) | 394 | |
162 | goto usage; | 395 | if (options_parse(argc, argv, ts_options, NULL, NULL) != 0) |
163 | configfile = *++argv; | 396 | goto usage; |
164 | } else if (strcmp(*argv, "-section") == 0) { | ||
165 | if (argc-- < 1) | ||
166 | goto usage; | ||
167 | section = *++argv; | ||
168 | } else if (strcmp(*argv, "-query") == 0) { | ||
169 | if (mode != CMD_NONE) | ||
170 | goto usage; | ||
171 | mode = CMD_QUERY; | ||
172 | } else if (strcmp(*argv, "-data") == 0) { | ||
173 | if (argc-- < 1) | ||
174 | goto usage; | ||
175 | data = *++argv; | ||
176 | } else if (strcmp(*argv, "-digest") == 0) { | ||
177 | if (argc-- < 1) | ||
178 | goto usage; | ||
179 | digest = *++argv; | ||
180 | } else if (strcmp(*argv, "-policy") == 0) { | ||
181 | if (argc-- < 1) | ||
182 | goto usage; | ||
183 | policy = *++argv; | ||
184 | } else if (strcmp(*argv, "-no_nonce") == 0) { | ||
185 | no_nonce = 1; | ||
186 | } else if (strcmp(*argv, "-cert") == 0) { | ||
187 | cert = 1; | ||
188 | } else if (strcmp(*argv, "-in") == 0) { | ||
189 | if (argc-- < 1) | ||
190 | goto usage; | ||
191 | in = *++argv; | ||
192 | } else if (strcmp(*argv, "-token_in") == 0) { | ||
193 | token_in = 1; | ||
194 | } else if (strcmp(*argv, "-out") == 0) { | ||
195 | if (argc-- < 1) | ||
196 | goto usage; | ||
197 | out = *++argv; | ||
198 | } else if (strcmp(*argv, "-token_out") == 0) { | ||
199 | token_out = 1; | ||
200 | } else if (strcmp(*argv, "-text") == 0) { | ||
201 | text = 1; | ||
202 | } else if (strcmp(*argv, "-reply") == 0) { | ||
203 | if (mode != CMD_NONE) | ||
204 | goto usage; | ||
205 | mode = CMD_REPLY; | ||
206 | } else if (strcmp(*argv, "-queryfile") == 0) { | ||
207 | if (argc-- < 1) | ||
208 | goto usage; | ||
209 | queryfile = *++argv; | ||
210 | } else if (strcmp(*argv, "-passin") == 0) { | ||
211 | if (argc-- < 1) | ||
212 | goto usage; | ||
213 | passin = *++argv; | ||
214 | } else if (strcmp(*argv, "-inkey") == 0) { | ||
215 | if (argc-- < 1) | ||
216 | goto usage; | ||
217 | inkey = *++argv; | ||
218 | } else if (strcmp(*argv, "-signer") == 0) { | ||
219 | if (argc-- < 1) | ||
220 | goto usage; | ||
221 | signer = *++argv; | ||
222 | } else if (strcmp(*argv, "-chain") == 0) { | ||
223 | if (argc-- < 1) | ||
224 | goto usage; | ||
225 | chain = *++argv; | ||
226 | } else if (strcmp(*argv, "-verify") == 0) { | ||
227 | if (mode != CMD_NONE) | ||
228 | goto usage; | ||
229 | mode = CMD_VERIFY; | ||
230 | } else if (strcmp(*argv, "-CApath") == 0) { | ||
231 | if (argc-- < 1) | ||
232 | goto usage; | ||
233 | ca_path = *++argv; | ||
234 | } else if (strcmp(*argv, "-CAfile") == 0) { | ||
235 | if (argc-- < 1) | ||
236 | goto usage; | ||
237 | ca_file = *++argv; | ||
238 | } else if (strcmp(*argv, "-untrusted") == 0) { | ||
239 | if (argc-- < 1) | ||
240 | goto usage; | ||
241 | untrusted = *++argv; | ||
242 | } else if ((md = EVP_get_digestbyname(*argv + 1)) != NULL) { | ||
243 | /* empty. */ | ||
244 | } else | ||
245 | goto usage; | ||
246 | } | ||
247 | 397 | ||
248 | /* Get the password if required. */ | 398 | /* Get the password if required. */ |
249 | if (mode == CMD_REPLY && passin && | 399 | if (ts_config.mode == CMD_REPLY && ts_config.passin && |
250 | !app_passwd(bio_err, passin, NULL, &password, NULL)) { | 400 | !app_passwd(bio_err, ts_config.passin, NULL, &password, NULL)) { |
251 | BIO_printf(bio_err, "Error getting password.\n"); | 401 | BIO_printf(bio_err, "Error getting password.\n"); |
252 | goto cleanup; | 402 | goto cleanup; |
253 | } | 403 | } |
@@ -255,7 +405,7 @@ ts_main(int argc, char **argv) | |||
255 | * Check consistency of parameters and execute the appropriate | 405 | * Check consistency of parameters and execute the appropriate |
256 | * function. | 406 | * function. |
257 | */ | 407 | */ |
258 | switch (mode) { | 408 | switch (ts_config.mode) { |
259 | case CMD_NONE: | 409 | case CMD_NONE: |
260 | goto usage; | 410 | goto usage; |
261 | case CMD_QUERY: | 411 | case CMD_QUERY: |
@@ -263,64 +413,46 @@ ts_main(int argc, char **argv) | |||
263 | * Data file and message imprint cannot be specified at the | 413 | * Data file and message imprint cannot be specified at the |
264 | * same time. | 414 | * same time. |
265 | */ | 415 | */ |
266 | ret = data != NULL && digest != NULL; | 416 | ret = ts_config.data != NULL && ts_config.digest != NULL; |
267 | if (ret) | 417 | if (ret) |
268 | goto usage; | 418 | goto usage; |
269 | /* Load the config file for possible policy OIDs. */ | 419 | /* Load the config file for possible policy OIDs. */ |
270 | conf = load_config_file(configfile); | 420 | conf = load_config_file(ts_config.configfile); |
271 | ret = !query_command(data, digest, md, policy, no_nonce, cert, | 421 | ret = !query_command(ts_config.data, ts_config.digest, ts_config.md, ts_config.policy, ts_config.no_nonce, ts_config.cert, |
272 | in, out, text); | 422 | ts_config.in, ts_config.out, ts_config.text); |
273 | break; | 423 | break; |
274 | case CMD_REPLY: | 424 | case CMD_REPLY: |
275 | conf = load_config_file(configfile); | 425 | conf = load_config_file(ts_config.configfile); |
276 | if (in == NULL) { | 426 | if (ts_config.in == NULL) { |
277 | ret = !(queryfile != NULL && conf != NULL && !token_in); | 427 | ret = !(ts_config.queryfile != NULL && conf != NULL && !ts_config.token_in); |
278 | if (ret) | 428 | if (ret) |
279 | goto usage; | 429 | goto usage; |
280 | } else { | 430 | } else { |
281 | /* 'in' and 'queryfile' are exclusive. */ | 431 | /* 'in' and 'queryfile' are exclusive. */ |
282 | ret = !(queryfile == NULL); | 432 | ret = !(ts_config.queryfile == NULL); |
283 | if (ret) | 433 | if (ret) |
284 | goto usage; | 434 | goto usage; |
285 | } | 435 | } |
286 | 436 | ||
287 | ret = !reply_command(conf, section, queryfile, | 437 | ret = !reply_command(conf, ts_config.section, ts_config.queryfile, |
288 | password, inkey, signer, chain, policy, | 438 | password, ts_config.inkey, ts_config.signer, ts_config.chain, ts_config.policy, |
289 | in, token_in, out, token_out, text); | 439 | ts_config.in, ts_config.token_in, ts_config.out, ts_config.token_out, ts_config.text); |
290 | break; | 440 | break; |
291 | case CMD_VERIFY: | 441 | case CMD_VERIFY: |
292 | ret = !(((queryfile && !data && !digest) || | 442 | ret = !(((ts_config.queryfile && !ts_config.data && !ts_config.digest) || |
293 | (!queryfile && data && !digest) || | 443 | (!ts_config.queryfile && ts_config.data && !ts_config.digest) || |
294 | (!queryfile && !data && digest)) && in != NULL); | 444 | (!ts_config.queryfile && !ts_config.data && ts_config.digest)) && ts_config.in != NULL); |
295 | if (ret) | 445 | if (ret) |
296 | goto usage; | 446 | goto usage; |
297 | 447 | ||
298 | ret = !verify_command(data, digest, queryfile, in, token_in, | 448 | ret = !verify_command(ts_config.data, ts_config.digest, ts_config.queryfile, ts_config.in, ts_config.token_in, |
299 | ca_path, ca_file, untrusted); | 449 | ts_config.ca_path, ts_config.ca_file, ts_config.untrusted); |
300 | } | 450 | } |
301 | 451 | ||
302 | goto cleanup; | 452 | goto cleanup; |
303 | 453 | ||
304 | usage: | 454 | usage: |
305 | BIO_printf(bio_err, "usage:\n" | 455 | ts_usage(); |
306 | "ts -query [-config configfile] " | ||
307 | "[-data file_to_hash] [-digest digest_bytes]" | ||
308 | "[-md4|-md5|-sha1|-ripemd160] " | ||
309 | "[-policy object_id] [-no_nonce] [-cert] " | ||
310 | "[-in request.tsq] [-out request.tsq] [-text]\n"); | ||
311 | BIO_printf(bio_err, "or\n" | ||
312 | "ts -reply [-config configfile] [-section tsa_section] " | ||
313 | "[-queryfile request.tsq] [-passin password] " | ||
314 | "[-signer tsa_cert.pem] [-inkey private_key.pem] " | ||
315 | "[-chain certs_file.pem] [-policy object_id] " | ||
316 | "[-in response.tsr] [-token_in] " | ||
317 | "[-out response.tsr] [-token_out] [-text]\n"); | ||
318 | BIO_printf(bio_err, "or\n" | ||
319 | "ts -verify [-data file_to_hash] [-digest digest_bytes] " | ||
320 | "[-queryfile request.tsq] " | ||
321 | "-in response.tsr [-token_in] " | ||
322 | "-CApath ca_path -CAfile ca_file.pem " | ||
323 | "-untrusted cert_file.pem\n"); | ||
324 | 456 | ||
325 | cleanup: | 457 | cleanup: |
326 | /* Clean up. */ | 458 | /* Clean up. */ |