diff options
Diffstat (limited to 'src')
-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, |