diff options
author | beck <> | 2020-10-16 01:16:55 +0000 |
---|---|---|
committer | beck <> | 2020-10-16 01:16:55 +0000 |
commit | 02e3c352953d6092e9148dfaca026fa935952d0f (patch) | |
tree | 2ffe48089f785e7609d4d6310fa64084c64f5129 | |
parent | 7c6ffc946324eead9f89ecc9ac680e2c861f8741 (diff) | |
download | openbsd-02e3c352953d6092e9148dfaca026fa935952d0f.tar.gz openbsd-02e3c352953d6092e9148dfaca026fa935952d0f.tar.bz2 openbsd-02e3c352953d6092e9148dfaca026fa935952d0f.zip |
Refactor a bunch of oscpcheck for single return to clean it up,
and add the ability to parse a port in the specified ocsp url.
Since this will now pass them, enable regress tests previously
committed for ocspcheck.
mostly by me with some cleanup by tb after an obvious yak was found
to shave in the OCSP routines in libcrypto
ok tb@
-rw-r--r-- | src/usr.sbin/ocspcheck/ocspcheck.c | 158 |
1 files changed, 95 insertions, 63 deletions
diff --git a/src/usr.sbin/ocspcheck/ocspcheck.c b/src/usr.sbin/ocspcheck/ocspcheck.c index d9f7104bec..dec548e0b2 100644 --- a/src/usr.sbin/ocspcheck/ocspcheck.c +++ b/src/usr.sbin/ocspcheck/ocspcheck.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* $OpenBSD: ocspcheck.c,v 1.27 2020/09/04 04:17:46 tb Exp $ */ | 1 | /* $OpenBSD: ocspcheck.c,v 1.28 2020/10/16 01:16:55 beck Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2017 Bob Beck <beck@openbsd.org> | 4 | * Copyright (c) 2017,2020 Bob Beck <beck@openbsd.org> |
5 | * | 5 | * |
6 | * Permission to use, copy, modify, and distribute this software for any | 6 | * Permission to use, copy, modify, and distribute this software for any |
7 | * purpose with or without fee is hereby granted, provided that the above | 7 | * purpose with or without fee is hereby granted, provided that the above |
@@ -155,7 +155,7 @@ url2host(const char *host, short *port, char **path) | |||
155 | *path = strdup(ep); | 155 | *path = strdup(ep); |
156 | *ep = '\0'; | 156 | *ep = '\0'; |
157 | } else | 157 | } else |
158 | *path = strdup(""); | 158 | *path = strdup("/"); |
159 | 159 | ||
160 | if (*path == NULL) { | 160 | if (*path == NULL) { |
161 | warn("strdup"); | 161 | warn("strdup"); |
@@ -163,6 +163,21 @@ url2host(const char *host, short *port, char **path) | |||
163 | return (NULL); | 163 | return (NULL); |
164 | } | 164 | } |
165 | 165 | ||
166 | /* Check to see if there is a port in the url */ | ||
167 | if ((ep = strchr(url, ':')) != NULL) { | ||
168 | const char *errstr; | ||
169 | short pp; | ||
170 | pp = strtonum(ep + 1, 1, SHRT_MAX, &errstr); | ||
171 | if (errstr != NULL) { | ||
172 | warnx("error parsing port from '%s': %s", url, errstr); | ||
173 | free(url); | ||
174 | free(*path); | ||
175 | return NULL; | ||
176 | } | ||
177 | *port = pp; | ||
178 | *ep = '\0'; | ||
179 | } | ||
180 | |||
166 | return (url); | 181 | return (url); |
167 | } | 182 | } |
168 | 183 | ||
@@ -221,7 +236,7 @@ read_cacerts(const char *file, const char *dir) | |||
221 | } | 236 | } |
222 | return store; | 237 | return store; |
223 | 238 | ||
224 | end: | 239 | end: |
225 | X509_STORE_free(store); | 240 | X509_STORE_free(store); |
226 | return NULL; | 241 | return NULL; |
227 | } | 242 | } |
@@ -239,14 +254,12 @@ read_fullchain(const char *file, int *count) | |||
239 | 254 | ||
240 | if ((bio = BIO_new_file(file, "r")) == NULL) { | 255 | if ((bio = BIO_new_file(file, "r")) == NULL) { |
241 | warn("Unable to read a certificate from %s", file); | 256 | warn("Unable to read a certificate from %s", file); |
242 | return NULL; | 257 | goto end; |
243 | } | 258 | } |
244 | if ((xis = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL)) == NULL) { | 259 | if ((xis = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL)) == NULL) { |
245 | warnx("Unable to read PEM format from %s", file); | 260 | warnx("Unable to read PEM format from %s", file); |
246 | return NULL; | 261 | goto end; |
247 | } | 262 | } |
248 | BIO_free(bio); | ||
249 | |||
250 | if (sk_X509_INFO_num(xis) <= 0) { | 263 | if (sk_X509_INFO_num(xis) <= 0) { |
251 | warnx("No certificates in file %s", file); | 264 | warnx("No certificates in file %s", file); |
252 | goto end; | 265 | goto end; |
@@ -269,7 +282,8 @@ read_fullchain(const char *file, int *count) | |||
269 | xi->x509 = NULL; | 282 | xi->x509 = NULL; |
270 | (*count)++; | 283 | (*count)++; |
271 | } | 284 | } |
272 | end: | 285 | end: |
286 | BIO_free(bio); | ||
273 | sk_X509_INFO_pop_free(xis, X509_INFO_free); | 287 | sk_X509_INFO_pop_free(xis, X509_INFO_free); |
274 | return rv; | 288 | return rv; |
275 | } | 289 | } |
@@ -280,38 +294,37 @@ cert_from_chain(STACK_OF(X509) *fullchain) | |||
280 | return sk_X509_value(fullchain, 0); | 294 | return sk_X509_value(fullchain, 0); |
281 | } | 295 | } |
282 | 296 | ||
283 | static X509 * | 297 | static const X509 * |
284 | issuer_from_chain(STACK_OF(X509) *fullchain) | 298 | issuer_from_chain(STACK_OF(X509) *fullchain) |
285 | { | 299 | { |
286 | X509 *cert, *issuer; | 300 | const X509 *cert; |
287 | X509_NAME *issuer_name; | 301 | X509_NAME *issuer_name; |
288 | 302 | ||
289 | cert = cert_from_chain(fullchain); | 303 | cert = cert_from_chain(fullchain); |
290 | if ((issuer_name = X509_get_issuer_name(cert)) == NULL) | 304 | if ((issuer_name = X509_get_issuer_name(cert)) == NULL) |
291 | return NULL; | 305 | return NULL; |
292 | 306 | ||
293 | issuer = X509_find_by_subject(fullchain, issuer_name); | 307 | return X509_find_by_subject(fullchain, issuer_name); |
294 | return issuer; | ||
295 | } | 308 | } |
296 | 309 | ||
297 | static ocsp_request * | 310 | static ocsp_request * |
298 | ocsp_request_new_from_cert(const char *cadir, char *file, int nonce) | 311 | ocsp_request_new_from_cert(const char *cadir, char *file, int nonce) |
299 | { | 312 | { |
300 | X509 *cert = NULL; | 313 | X509 *cert; |
301 | int count = 0; | 314 | int count = 0; |
302 | OCSP_CERTID *id; | 315 | OCSP_CERTID *id = NULL; |
303 | ocsp_request *request; | 316 | ocsp_request *request = NULL; |
304 | const EVP_MD *cert_id_md = NULL; | 317 | const EVP_MD *cert_id_md = NULL; |
305 | X509 *issuer = NULL; | 318 | const X509 *issuer; |
306 | STACK_OF(OPENSSL_STRING) *urls; | 319 | STACK_OF(OPENSSL_STRING) *urls = NULL; |
307 | 320 | ||
308 | if ((request = calloc(1, sizeof(ocsp_request))) == NULL) { | 321 | if ((request = calloc(1, sizeof(ocsp_request))) == NULL) { |
309 | warn("malloc"); | 322 | warn("malloc"); |
310 | return NULL; | 323 | goto err; |
311 | } | 324 | } |
312 | 325 | ||
313 | if ((request->req = OCSP_REQUEST_new()) == NULL) | 326 | if ((request->req = OCSP_REQUEST_new()) == NULL) |
314 | return NULL; | 327 | goto err; |
315 | 328 | ||
316 | request->fullchain = read_fullchain(file, &count); | 329 | request->fullchain = read_fullchain(file, &count); |
317 | if (cadir == NULL) { | 330 | if (cadir == NULL) { |
@@ -319,39 +332,43 @@ ocsp_request_new_from_cert(const char *cadir, char *file, int nonce) | |||
319 | if (pledge("stdio inet dns", NULL) == -1) | 332 | if (pledge("stdio inet dns", NULL) == -1) |
320 | err(1, "pledge"); | 333 | err(1, "pledge"); |
321 | } | 334 | } |
322 | if (request->fullchain == NULL) | 335 | if (request->fullchain == NULL) { |
323 | return NULL; | 336 | warnx("Unable to read cert chain from file %s", file); |
337 | goto err; | ||
338 | } | ||
324 | if (count <= 1) { | 339 | if (count <= 1) { |
325 | warnx("File %s does not contain a cert chain", file); | 340 | warnx("File %s does not contain a cert chain", file); |
326 | return NULL; | 341 | goto err; |
327 | } | 342 | } |
328 | if ((cert = cert_from_chain(request->fullchain)) == NULL) { | 343 | if ((cert = cert_from_chain(request->fullchain)) == NULL) { |
329 | warnx("No certificate found in %s", file); | 344 | warnx("No certificate found in %s", file); |
330 | return NULL; | 345 | goto err; |
331 | } | 346 | } |
332 | if ((issuer = issuer_from_chain(request->fullchain)) == NULL) { | 347 | if ((issuer = issuer_from_chain(request->fullchain)) == NULL) { |
333 | warnx("Unable to find issuer for cert in %s", file); | 348 | warnx("Unable to find issuer for cert in %s", file); |
334 | return NULL; | 349 | goto err; |
335 | } | 350 | } |
336 | 351 | ||
337 | urls = X509_get1_ocsp(cert); | 352 | urls = X509_get1_ocsp(cert); |
338 | if (urls == NULL || sk_OPENSSL_STRING_num(urls) <= 0) { | 353 | if (urls == NULL || sk_OPENSSL_STRING_num(urls) <= 0) { |
339 | warnx("Certificate in %s contains no OCSP url", file); | 354 | warnx("Certificate in %s contains no OCSP url", file); |
340 | return NULL; | 355 | goto err; |
341 | } | 356 | } |
342 | if ((request->url = strdup(sk_OPENSSL_STRING_value(urls, 0))) == NULL) | 357 | if ((request->url = strdup(sk_OPENSSL_STRING_value(urls, 0))) == NULL) |
343 | return NULL; | 358 | goto err; |
344 | X509_email_free(urls); | 359 | X509_email_free(urls); |
360 | urls = NULL; | ||
345 | 361 | ||
346 | cert_id_md = EVP_sha1(); /* XXX. This sucks but OCSP is poopy */ | 362 | cert_id_md = EVP_sha1(); /* XXX. This sucks but OCSP is poopy */ |
347 | if ((id = OCSP_cert_to_id(cert_id_md, cert, issuer)) == NULL) { | 363 | if ((id = OCSP_cert_to_id(cert_id_md, cert, issuer)) == NULL) { |
348 | warnx("Unable to get certificate id from cert in %s", file); | 364 | warnx("Unable to get certificate id from cert in %s", file); |
349 | return NULL; | 365 | goto err; |
350 | } | 366 | } |
351 | if (OCSP_request_add0_id(request->req, id) == NULL) { | 367 | if (OCSP_request_add0_id(request->req, id) == NULL) { |
352 | warnx("Unable to add certificate id to request"); | 368 | warnx("Unable to add certificate id to request"); |
353 | return NULL; | 369 | goto err; |
354 | } | 370 | } |
371 | id = NULL; | ||
355 | 372 | ||
356 | request->nonce = nonce; | 373 | request->nonce = nonce; |
357 | if (request->nonce) | 374 | if (request->nonce) |
@@ -360,13 +377,25 @@ ocsp_request_new_from_cert(const char *cadir, char *file, int nonce) | |||
360 | if ((request->size = i2d_OCSP_REQUEST(request->req, | 377 | if ((request->size = i2d_OCSP_REQUEST(request->req, |
361 | &request->data)) <= 0) { | 378 | &request->data)) <= 0) { |
362 | warnx("Unable to encode ocsp request"); | 379 | warnx("Unable to encode ocsp request"); |
363 | return NULL; | 380 | goto err; |
364 | } | 381 | } |
365 | if (request->data == NULL) { | 382 | if (request->data == NULL) { |
366 | warnx("Unable to allocte memory"); | 383 | warnx("Unable to allocte memory"); |
367 | return NULL; | 384 | goto err; |
385 | } | ||
386 | return request; | ||
387 | |||
388 | err: | ||
389 | if (request != NULL) { | ||
390 | sk_X509_pop_free(request->fullchain, X509_free); | ||
391 | free(request->url); | ||
392 | OCSP_REQUEST_free(request->req); | ||
393 | free(request->data); | ||
368 | } | 394 | } |
369 | return (request); | 395 | X509_email_free(urls); |
396 | OCSP_CERTID_free(id); | ||
397 | free(request); | ||
398 | return NULL; | ||
370 | } | 399 | } |
371 | 400 | ||
372 | 401 | ||
@@ -376,40 +405,41 @@ validate_response(char *buf, size_t size, ocsp_request *request, | |||
376 | { | 405 | { |
377 | ASN1_GENERALIZEDTIME *revtime = NULL, *thisupd = NULL, *nextupd = NULL; | 406 | ASN1_GENERALIZEDTIME *revtime = NULL, *thisupd = NULL, *nextupd = NULL; |
378 | const unsigned char **p = (const unsigned char **)&buf; | 407 | const unsigned char **p = (const unsigned char **)&buf; |
379 | int status, cert_status=0, crl_reason=0; | 408 | int status, cert_status = 0, crl_reason = 0; |
380 | time_t now, rev_t = -1, this_t, next_t; | 409 | time_t now, rev_t = -1, this_t, next_t; |
381 | OCSP_RESPONSE *resp; | 410 | OCSP_RESPONSE *resp = NULL; |
382 | OCSP_BASICRESP *bresp; | 411 | OCSP_BASICRESP *bresp = NULL; |
383 | OCSP_CERTID *cid; | 412 | OCSP_CERTID *cid = NULL; |
384 | X509 *cert, *issuer; | 413 | const X509 *cert, *issuer; |
414 | int ret = 0; | ||
385 | 415 | ||
386 | if ((cert = cert_from_chain(request->fullchain)) == NULL) { | 416 | if ((cert = cert_from_chain(request->fullchain)) == NULL) { |
387 | warnx("No certificate found in %s", file); | 417 | warnx("No certificate found in %s", file); |
388 | return 0; | 418 | goto err; |
389 | } | 419 | } |
390 | if ((issuer = issuer_from_chain(request->fullchain)) == NULL) { | 420 | if ((issuer = issuer_from_chain(request->fullchain)) == NULL) { |
391 | warnx("Unable to find certificate issuer for cert in %s", file); | 421 | warnx("Unable to find certificate issuer for cert in %s", file); |
392 | return 0; | 422 | goto err; |
393 | } | 423 | } |
394 | if ((cid = OCSP_cert_to_id(NULL, cert, issuer)) == NULL) { | 424 | if ((cid = OCSP_cert_to_id(NULL, cert, issuer)) == NULL) { |
395 | warnx("Unable to get issuer cert/CID in %s", file); | 425 | warnx("Unable to get issuer cert/CID in %s", file); |
396 | return 0; | 426 | goto err; |
397 | } | 427 | } |
398 | 428 | ||
399 | if ((resp = d2i_OCSP_RESPONSE(NULL, p, size)) == NULL) { | 429 | if ((resp = d2i_OCSP_RESPONSE(NULL, p, size)) == NULL) { |
400 | warnx("OCSP response unserializable from host %s", host); | 430 | warnx("OCSP response unserializable from host %s", host); |
401 | return 0; | 431 | goto err; |
402 | } | 432 | } |
403 | 433 | ||
404 | if ((bresp = OCSP_response_get1_basic(resp)) == NULL) { | 434 | if ((bresp = OCSP_response_get1_basic(resp)) == NULL) { |
405 | warnx("Failed to load OCSP response from %s", host); | 435 | warnx("Failed to load OCSP response from %s", host); |
406 | return 0; | 436 | goto err; |
407 | } | 437 | } |
408 | 438 | ||
409 | if (OCSP_basic_verify(bresp, request->fullchain, store, | 439 | if (OCSP_basic_verify(bresp, request->fullchain, store, |
410 | OCSP_TRUSTOTHER) != 1) { | 440 | OCSP_TRUSTOTHER) != 1) { |
411 | warnx("OCSP verify failed from %s", host); | 441 | warnx("OCSP verify failed from %s", host); |
412 | return 0; | 442 | goto err; |
413 | } | 443 | } |
414 | dspew("OCSP response signature validated from %s\n", host); | 444 | dspew("OCSP response signature validated from %s\n", host); |
415 | 445 | ||
@@ -417,7 +447,7 @@ validate_response(char *buf, size_t size, ocsp_request *request, | |||
417 | if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { | 447 | if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { |
418 | warnx("OCSP Failure: code %d (%s) from host %s", | 448 | warnx("OCSP Failure: code %d (%s) from host %s", |
419 | status, OCSP_response_status_str(status), host); | 449 | status, OCSP_response_status_str(status), host); |
420 | return 0; | 450 | goto err; |
421 | } | 451 | } |
422 | dspew("OCSP response status %d from host %s\n", status, host); | 452 | dspew("OCSP response status %d from host %s\n", status, host); |
423 | 453 | ||
@@ -426,19 +456,19 @@ validate_response(char *buf, size_t size, ocsp_request *request, | |||
426 | if (request->nonce) { | 456 | if (request->nonce) { |
427 | if (OCSP_check_nonce(request->req, bresp) <= 0) { | 457 | if (OCSP_check_nonce(request->req, bresp) <= 0) { |
428 | warnx("No OCSP nonce, or mismatch, from host %s", host); | 458 | warnx("No OCSP nonce, or mismatch, from host %s", host); |
429 | return 0; | 459 | goto err; |
430 | } | 460 | } |
431 | } | 461 | } |
432 | 462 | ||
433 | if (OCSP_resp_find_status(bresp, cid, &cert_status, &crl_reason, | 463 | if (OCSP_resp_find_status(bresp, cid, &cert_status, &crl_reason, |
434 | &revtime, &thisupd, &nextupd) != 1) { | 464 | &revtime, &thisupd, &nextupd) != 1) { |
435 | warnx("OCSP verify failed: no result for cert"); | 465 | warnx("OCSP verify failed: no result for cert"); |
436 | return 0; | 466 | goto err; |
437 | } | 467 | } |
438 | 468 | ||
439 | if (revtime && (rev_t = parse_ocsp_time(revtime)) == -1) { | 469 | if (revtime && (rev_t = parse_ocsp_time(revtime)) == -1) { |
440 | warnx("Unable to parse revocation time in OCSP reply"); | 470 | warnx("Unable to parse revocation time in OCSP reply"); |
441 | return 0; | 471 | goto err; |
442 | } | 472 | } |
443 | /* | 473 | /* |
444 | * Belt and suspenders, Treat it as revoked if there is either | 474 | * Belt and suspenders, Treat it as revoked if there is either |
@@ -448,21 +478,21 @@ validate_response(char *buf, size_t size, ocsp_request *request, | |||
448 | warnx("Invalid OCSP reply: certificate is revoked"); | 478 | warnx("Invalid OCSP reply: certificate is revoked"); |
449 | if (rev_t != -1) | 479 | if (rev_t != -1) |
450 | warnx("Certificate revoked at: %s", ctime(&rev_t)); | 480 | warnx("Certificate revoked at: %s", ctime(&rev_t)); |
451 | return 0; | 481 | goto err; |
452 | } | 482 | } |
453 | if ((this_t = parse_ocsp_time(thisupd)) == -1) { | 483 | if ((this_t = parse_ocsp_time(thisupd)) == -1) { |
454 | warnx("unable to parse this update time in OCSP reply"); | 484 | warnx("unable to parse this update time in OCSP reply"); |
455 | return 0; | 485 | goto err; |
456 | } | 486 | } |
457 | if ((next_t = parse_ocsp_time(nextupd)) == -1) { | 487 | if ((next_t = parse_ocsp_time(nextupd)) == -1) { |
458 | warnx("unable to parse next update time in OCSP reply"); | 488 | warnx("unable to parse next update time in OCSP reply"); |
459 | return 0; | 489 | goto err; |
460 | } | 490 | } |
461 | 491 | ||
462 | /* Don't allow this update to precede next update */ | 492 | /* Don't allow this update to precede next update */ |
463 | if (this_t >= next_t) { | 493 | if (this_t >= next_t) { |
464 | warnx("Invalid OCSP reply: this update >= next update"); | 494 | warnx("Invalid OCSP reply: this update >= next update"); |
465 | return 0; | 495 | goto err; |
466 | } | 496 | } |
467 | 497 | ||
468 | now = time(NULL); | 498 | now = time(NULL); |
@@ -471,9 +501,9 @@ validate_response(char *buf, size_t size, ocsp_request *request, | |||
471 | * in the future. | 501 | * in the future. |
472 | */ | 502 | */ |
473 | if (this_t > now + JITTER_SEC) { | 503 | if (this_t > now + JITTER_SEC) { |
474 | warnx("Invalid OCSP reply: this update is in the future (%s)", | 504 | warnx("Invalid OCSP reply: this update is in the future at %s", |
475 | ctime(&this_t)); | 505 | ctime(&this_t)); |
476 | return 0; | 506 | goto err; |
477 | } | 507 | } |
478 | 508 | ||
479 | /* | 509 | /* |
@@ -481,24 +511,29 @@ validate_response(char *buf, size_t size, ocsp_request *request, | |||
481 | * in the past. | 511 | * in the past. |
482 | */ | 512 | */ |
483 | if (this_t < now - MAXAGE_SEC) { | 513 | if (this_t < now - MAXAGE_SEC) { |
484 | warnx("Invalid OCSP reply: this update is too old (%s)", | 514 | warnx("Invalid OCSP reply: this update is too old %s", |
485 | ctime(&this_t)); | 515 | ctime(&this_t)); |
486 | return 0; | 516 | goto err; |
487 | } | 517 | } |
488 | 518 | ||
489 | /* | 519 | /* |
490 | * Check that next update is still valid | 520 | * Check that next update is still valid |
491 | */ | 521 | */ |
492 | if (next_t < now - JITTER_SEC) { | 522 | if (next_t < now - JITTER_SEC) { |
493 | warnx("Invalid OCSP reply: reply has expired (%s)", | 523 | warnx("Invalid OCSP reply: reply has expired at %s", |
494 | ctime(&next_t)); | 524 | ctime(&next_t)); |
495 | return 0; | 525 | goto err; |
496 | } | 526 | } |
497 | 527 | ||
498 | vspew("OCSP response validated from %s\n", host); | 528 | vspew("OCSP response validated from %s\n", host); |
499 | vspew(" This Update: %s", ctime(&this_t)); | 529 | vspew(" This Update: %s", ctime(&this_t)); |
500 | vspew(" Next Update: %s", ctime(&next_t)); | 530 | vspew(" Next Update: %s", ctime(&next_t)); |
501 | return 1; | 531 | ret = 1; |
532 | err: | ||
533 | OCSP_RESPONSE_free(resp); | ||
534 | OCSP_BASICRESP_free(bresp); | ||
535 | OCSP_CERTID_free(cid); | ||
536 | return ret; | ||
502 | } | 537 | } |
503 | 538 | ||
504 | static void | 539 | static void |
@@ -514,7 +549,7 @@ int | |||
514 | main(int argc, char **argv) | 549 | main(int argc, char **argv) |
515 | { | 550 | { |
516 | const char *cafile = NULL, *cadir = NULL; | 551 | const char *cafile = NULL, *cadir = NULL; |
517 | char *host = NULL, *path = "/", *certfile = NULL, *outfile = NULL, | 552 | char *host = NULL, *path = NULL, *certfile = NULL, *outfile = NULL, |
518 | *instaple = NULL, *infile = NULL; | 553 | *instaple = NULL, *infile = NULL; |
519 | struct addr addrs[MAX_SERVERS_DNS] = {{0}}; | 554 | struct addr addrs[MAX_SERVERS_DNS] = {{0}}; |
520 | struct source sources[MAX_SERVERS_DNS]; | 555 | struct source sources[MAX_SERVERS_DNS]; |
@@ -551,7 +586,7 @@ main(int argc, char **argv) | |||
551 | argc -= optind; | 586 | argc -= optind; |
552 | argv += optind; | 587 | argv += optind; |
553 | 588 | ||
554 | if ((certfile = argv[0]) == NULL) | 589 | if (argc != 1 || (certfile = argv[0]) == NULL) |
555 | usage(); | 590 | usage(); |
556 | 591 | ||
557 | if (outfile != NULL) { | 592 | if (outfile != NULL) { |
@@ -611,8 +646,6 @@ main(int argc, char **argv) | |||
611 | if ((host = url2host(request->url, &port, &path)) == NULL) | 646 | if ((host = url2host(request->url, &port, &path)) == NULL) |
612 | errx(1, "Invalid OCSP url %s from %s", request->url, | 647 | errx(1, "Invalid OCSP url %s from %s", request->url, |
613 | certfile); | 648 | certfile); |
614 | if (*path == '\0') | ||
615 | path = "/"; | ||
616 | 649 | ||
617 | if (infd == -1) { | 650 | if (infd == -1) { |
618 | /* Get a new OCSP response from the indicated server */ | 651 | /* Get a new OCSP response from the indicated server */ |
@@ -713,7 +746,6 @@ main(int argc, char **argv) | |||
713 | if (errno != EINTR && errno != EAGAIN) | 746 | if (errno != EINTR && errno != EAGAIN) |
714 | err(1, "Write of OCSP response failed"); | 747 | err(1, "Write of OCSP response failed"); |
715 | } | 748 | } |
716 | w = 0; | ||
717 | written = 0; | 749 | written = 0; |
718 | while (written < instaplesz) { | 750 | while (written < instaplesz) { |
719 | w = write(staplefd, instaple + written, | 751 | w = write(staplefd, instaple + written, |