1 /* $OpenBSD: ocsp.c,v 1.20 2020/09/03 14:50:40 tobhe Exp $ */ 2 3 /* 4 * Copyright (c) 2014 Markus Friedl 5 * Copyright (c) 2005 Marco Pfatschbacher 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/queue.h> 21 #include <sys/socket.h> 22 #include <sys/uio.h> 23 #include <sys/stat.h> 24 25 #include <stdio.h> 26 #include <string.h> 27 #include <stdlib.h> 28 #include <errno.h> 29 #include <fcntl.h> 30 #include <unistd.h> 31 #include <netdb.h> 32 33 #include <openssl/pem.h> 34 #include <openssl/ocsp.h> 35 #include <openssl/err.h> 36 #include <openssl/ssl.h> 37 38 #include <event.h> 39 40 #include "iked.h" 41 42 struct iked_ocsp { 43 struct iked *ocsp_env; /* back pointer to env */ 44 struct iked_sahdr ocsp_sh; /* ike sa */ 45 uint8_t ocsp_type; /* auth type */ 46 struct iked_socket *ocsp_sock; /* socket to ocsp responder */ 47 BIO *ocsp_cbio; /* matching OpenSSL obj */ 48 OCSP_CERTID *ocsp_id; /* ocsp-id for cert */ 49 OCSP_REQUEST *ocsp_req; /* ocsp-request */ 50 OCSP_REQ_CTX *ocsp_req_ctx; /* async ocsp-request */ 51 }; 52 53 struct ocsp_connect { 54 struct iked_sahdr oc_sh; 55 struct iked_socket oc_sock; 56 char *oc_path; 57 char *oc_url; 58 }; 59 60 #define OCSP_TIMEOUT 30 61 62 /* priv */ 63 void ocsp_connect_cb(int, short, void *); 64 int ocsp_connect_finish(struct iked *, int, struct ocsp_connect *); 65 66 /* unpriv */ 67 void ocsp_free(struct iked_ocsp *); 68 void ocsp_callback(int, short, void *); 69 void ocsp_parse_response(struct iked_ocsp *, OCSP_RESPONSE *); 70 STACK_OF(X509) *ocsp_load_certs(const char *); 71 int ocsp_validate_finish(struct iked_ocsp *, int); 72 73 74 /* priv */ 75 76 /* async connect to configure ocsp-responder */ 77 int 78 ocsp_connect(struct iked *env, struct imsg *imsg) 79 { 80 struct ocsp_connect *oc = NULL; 81 struct iked_sahdr sh; 82 struct addrinfo hints, *res0 = NULL, *res; 83 struct timeval tv; 84 uint8_t *ptr; 85 size_t len; 86 char *host = NULL, *port = NULL, *path = NULL; 87 char *url, *freeme = NULL; 88 int use_ssl, fd = -1, ret = -1, error; 89 90 IMSG_SIZE_CHECK(imsg, &sh); 91 92 ptr = (uint8_t *)imsg->data; 93 len = IMSG_DATA_SIZE(imsg); 94 95 memcpy(&sh, ptr, sizeof(sh)); 96 97 ptr += sizeof(sh); 98 len -= sizeof(sh); 99 100 if (len > 0) 101 url = freeme = get_string(ptr, len); 102 else if (env->sc_ocsp_url) 103 url = env->sc_ocsp_url; 104 else { 105 log_warnx("%s: no ocsp url", __func__); 106 goto done; 107 } 108 if (!OCSP_parse_url(url, &host, &port, &path, &use_ssl)) { 109 log_warnx("%s: error parsing OCSP-request-URL: %s", __func__, 110 url); 111 goto done; 112 } 113 if (use_ssl) { 114 log_warnx("%s: OCSP over SSL not supported: %s", __func__, 115 url); 116 goto done; 117 } 118 119 if ((fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0)) == -1) { 120 log_debug("%s: socket failed", __func__); 121 goto done; 122 } 123 if ((oc = calloc(1, sizeof(*oc))) == NULL) { 124 log_debug("%s: calloc failed", __func__); 125 goto done; 126 } 127 128 bzero(&hints, sizeof(struct addrinfo)); 129 hints.ai_family = PF_UNSPEC; 130 hints.ai_socktype = SOCK_STREAM; 131 error = getaddrinfo(host, port, &hints, &res0); 132 if (error) { 133 log_warn("%s: getaddrinfo(%s, %s) failed", 134 SPI_SH(&sh, __func__), host, port); 135 goto done; 136 } 137 /* XXX just pick the first answer. we could loop instead */ 138 for (res = res0; res; res = res->ai_next) 139 if (res->ai_family == AF_INET) 140 break; 141 if (res == NULL) { 142 log_debug("%s: no addr to connect to for %s:%s", 143 __func__, host, port); 144 goto done; 145 } 146 147 oc->oc_sock.sock_fd = fd; 148 oc->oc_sock.sock_env = env; 149 oc->oc_sh = sh; 150 oc->oc_path = path; 151 oc->oc_url = strdup(url); 152 path = NULL; 153 154 log_debug("%s: connect(%s, %s)", __func__, host, port); 155 if (connect(fd, res->ai_addr, res->ai_addrlen) == -1) { 156 /* register callback for ansync connect */ 157 if (errno == EINPROGRESS) { 158 tv.tv_sec = OCSP_TIMEOUT; 159 tv.tv_usec = 0; 160 event_set(&oc->oc_sock.sock_ev, fd, EV_WRITE, 161 ocsp_connect_cb, oc); 162 event_add(&oc->oc_sock.sock_ev, &tv); 163 ret = 0; 164 } else 165 log_warn("%s: connect(%s, %s)", 166 SPI_SH(&oc->oc_sh, __func__), host, port); 167 } else { 168 ocsp_connect_finish(env, fd, oc); 169 ret = 0; 170 } 171 done: 172 if (res0) 173 freeaddrinfo(res0); 174 free(freeme); 175 free(host); 176 free(port); 177 free(path); 178 if (ret == -1) { 179 ocsp_connect_finish(env, -1, oc); 180 if (fd >= 0) 181 close(fd); 182 } 183 return (ret); 184 } 185 186 /* callback triggered if connection to ocsp-responder completes/fails */ 187 void 188 ocsp_connect_cb(int fd, short event, void *arg) 189 { 190 struct ocsp_connect *oc = arg; 191 int error, send_fd = -1; 192 socklen_t len; 193 194 if (event == EV_TIMEOUT) { 195 log_info("%s: timeout, giving up", 196 SPI_SH(&oc->oc_sh, __func__)); 197 goto done; 198 } 199 200 len = sizeof(error); 201 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) == -1) { 202 log_warn("%s: getsockopt SOL_SOCKET SO_ERROR", __func__); 203 } else if (error) { 204 log_warnx("%s: error while connecting: %s", 205 SPI_SH(&oc->oc_sh, __func__), strerror(error)); 206 } else { 207 send_fd = fd; 208 } 209 done: 210 ocsp_connect_finish(oc->oc_sock.sock_env, send_fd, oc); 211 212 /* if we did not send the fd, we need to close it ourself */ 213 if (send_fd == -1) 214 close(fd); 215 } 216 217 /* send FD+path or error back to CA process */ 218 int 219 ocsp_connect_finish(struct iked *env, int fd, struct ocsp_connect *oc) 220 { 221 struct iovec iov[2]; 222 int iovcnt = 0, ret; 223 224 iov[iovcnt].iov_base = &oc->oc_sh; 225 iov[iovcnt].iov_len = sizeof(oc->oc_sh); 226 iovcnt++; 227 228 if (oc && fd >= 0) { 229 /* the imsg framework will close the FD after send */ 230 iov[iovcnt].iov_base = oc->oc_path; 231 iov[iovcnt].iov_len = strlen(oc->oc_path); 232 iovcnt++; 233 ret = proc_composev_imsg(&env->sc_ps, PROC_CERT, -1, 234 IMSG_OCSP_FD, -1, fd, iov, iovcnt); 235 } else { 236 if (oc) 237 log_info("%s: connect failed for %s", 238 SPI_SH(&oc->oc_sh, __func__), 239 oc->oc_url ? oc->oc_url : "unknown"); 240 else 241 log_info("%s: connect failed", __func__); 242 ret = proc_composev_imsg(&env->sc_ps, PROC_CERT, -1, 243 IMSG_OCSP_FD, -1, -1, iov, iovcnt); 244 if (fd >= 0) 245 close(fd); 246 } 247 if (oc) { 248 free(oc->oc_url); 249 free(oc->oc_path); 250 free(oc); 251 } 252 return (ret); 253 } 254 255 256 /* unpriv */ 257 258 /* validate the certifcate stored in 'data' by querying the ocsp-responder */ 259 int 260 ocsp_validate_cert(struct iked *env, void *data, size_t len, 261 struct iked_sahdr sh, u_int8_t type, X509 *issuer) 262 { 263 struct iovec iov[2]; 264 STACK_OF(OPENSSL_STRING) *aia; /* Authority Information Access */ 265 struct iked_ocsp_entry *ioe; 266 struct iked_ocsp *ocsp; 267 OCSP_CERTID *id = NULL; 268 char *url; 269 BIO *rawcert = NULL; 270 X509 *cert = NULL; 271 int ret, iovcnt = 0; 272 273 if (issuer == NULL) 274 return (-1); 275 if ((ioe = calloc(1, sizeof(*ioe))) == NULL) 276 return (-1); 277 if ((ocsp = calloc(1, sizeof(*ocsp))) == NULL) { 278 free(ioe); 279 return (-1); 280 } 281 282 ocsp->ocsp_env = env; 283 ocsp->ocsp_sh = sh; 284 ocsp->ocsp_type = type; 285 286 if ((rawcert = BIO_new_mem_buf(data, len)) == NULL || 287 (cert = d2i_X509_bio(rawcert, NULL)) == NULL || 288 (ocsp->ocsp_cbio = BIO_new(BIO_s_socket())) == NULL || 289 (ocsp->ocsp_req = OCSP_REQUEST_new()) == NULL || 290 (id = OCSP_cert_to_id(NULL, cert, issuer)) == NULL || 291 !OCSP_request_add0_id(ocsp->ocsp_req, id)) 292 goto err; 293 294 /* id is owned by and freed together with ocsp_req */ 295 ocsp->ocsp_id = id; 296 297 BIO_free(rawcert); 298 X509_free(cert); 299 300 ioe->ioe_ocsp = ocsp; 301 TAILQ_INSERT_TAIL(&env->sc_ocsp, ioe, ioe_entry); 302 303 /* pass SA header */ 304 iov[iovcnt].iov_base = &ocsp->ocsp_sh; 305 iov[iovcnt].iov_len = sizeof(ocsp->ocsp_sh); 306 iovcnt++; 307 308 /* pass optional ocsp-url from issuer */ 309 if ((aia = X509_get1_ocsp(issuer)) != NULL) { 310 url = sk_OPENSSL_STRING_value(aia, 0); 311 log_debug("%s: aia %s", __func__, url); 312 iov[iovcnt].iov_base = url; 313 iov[iovcnt].iov_len = strlen(url); 314 iovcnt++; 315 } 316 /* request connection to ocsp-responder */ 317 ret = proc_composev(&env->sc_ps, PROC_PARENT, IMSG_OCSP_FD, 318 iov, iovcnt); 319 320 if (aia) 321 X509_email_free(aia); /* free stack of openssl strings */ 322 323 return (ret); 324 325 err: 326 ca_sslerror(__func__); 327 free(ioe); 328 if (rawcert != NULL) 329 BIO_free(rawcert); 330 if (cert != NULL) 331 X509_free(cert); 332 if (id != NULL) 333 OCSP_CERTID_free(id); 334 ocsp_validate_finish(ocsp, 0); /* failed */ 335 return (-1); 336 } 337 338 /* free ocsp query context */ 339 void 340 ocsp_free(struct iked_ocsp *ocsp) 341 { 342 if (ocsp != NULL) { 343 if (ocsp->ocsp_sock != NULL) { 344 close(ocsp->ocsp_sock->sock_fd); 345 free(ocsp->ocsp_sock); 346 } 347 if (ocsp->ocsp_cbio != NULL) 348 BIO_free_all(ocsp->ocsp_cbio); 349 350 if (ocsp->ocsp_req_ctx != NULL) 351 OCSP_REQ_CTX_free(ocsp->ocsp_req_ctx); 352 353 if (ocsp->ocsp_req != NULL) 354 OCSP_REQUEST_free(ocsp->ocsp_req); 355 356 free(ocsp); 357 } 358 } 359 360 /* we got a connection to the ocsp responder */ 361 int 362 ocsp_receive_fd(struct iked *env, struct imsg *imsg) 363 { 364 struct iked_ocsp_entry *ioe = NULL; 365 struct iked_ocsp *ocsp = NULL, *ocsp_tmp; 366 struct iked_socket *sock; 367 struct iked_sahdr sh; 368 struct timeval tv; 369 uint8_t *ptr; 370 char *path = NULL; 371 size_t len; 372 int ret = -1; 373 374 log_debug("%s: received socket fd %d", __func__, imsg->fd); 375 376 IMSG_SIZE_CHECK(imsg, &sh); 377 378 ptr = (uint8_t *)imsg->data; 379 len = IMSG_DATA_SIZE(imsg); 380 381 memcpy(&sh, ptr, sizeof(sh)); 382 383 ptr += sizeof(sh); 384 len -= sizeof(sh); 385 386 TAILQ_FOREACH(ioe, &env->sc_ocsp, ioe_entry) { 387 ocsp_tmp = ioe->ioe_ocsp; 388 if (memcmp(&ocsp_tmp->ocsp_sh, &sh, sizeof(sh)) == 0) 389 break; 390 } 391 if (ioe == NULL) { 392 log_debug("%s: no pending request found", __func__); 393 if (imsg->fd != -1) 394 close(imsg->fd); 395 return (-1); 396 } 397 TAILQ_REMOVE(&env->sc_ocsp, ioe, ioe_entry); 398 ocsp = ioe->ioe_ocsp; 399 free(ioe); 400 401 if (imsg->fd == -1) 402 goto done; 403 404 if ((sock = calloc(1, sizeof(*sock))) == NULL) 405 fatal("ocsp_receive_fd: calloc sock"); 406 407 /* note that sock_addr is not set */ 408 sock->sock_fd = imsg->fd; 409 sock->sock_env = env; 410 ocsp->ocsp_sock = sock; 411 412 /* fetch 'path' and 'fd' from imsg */ 413 if ((path = get_string(ptr, len)) == NULL) 414 goto done; 415 416 BIO_set_fd(ocsp->ocsp_cbio, imsg->fd, BIO_NOCLOSE); 417 418 if ((ocsp->ocsp_req_ctx = OCSP_sendreq_new(ocsp->ocsp_cbio, 419 path, NULL, -1)) == NULL) 420 goto done; 421 if (!OCSP_REQ_CTX_set1_req(ocsp->ocsp_req_ctx, ocsp->ocsp_req)) 422 goto done; 423 424 tv.tv_sec = OCSP_TIMEOUT; 425 tv.tv_usec = 0; 426 event_set(&sock->sock_ev, sock->sock_fd, EV_WRITE, ocsp_callback, ocsp); 427 event_add(&sock->sock_ev, &tv); 428 ret = 0; 429 done: 430 if (ret == -1) 431 ocsp_validate_finish(ocsp, 0); /* failed */ 432 free(path); 433 return (ret); 434 } 435 436 /* load a stack of x509 certificates */ 437 STACK_OF(X509)* 438 ocsp_load_certs(const char *file) 439 { 440 BIO *bio = NULL; 441 STACK_OF(X509) *certs = NULL; 442 STACK_OF(X509_INFO) *xis = NULL; 443 X509_INFO *xi; 444 int i; 445 446 if ((bio = BIO_new_file(file, "r")) == NULL) { 447 log_warn("%s: BIO_new_file failed for %s", 448 __func__, file); 449 return (NULL); 450 } 451 if ((xis = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL)) == NULL) { 452 ca_sslerror(__func__); 453 goto done; 454 } 455 if ((certs = sk_X509_new_null()) == NULL) { 456 log_debug("%s: sk_X509_new_null failed for %s", __func__, file); 457 goto done; 458 } 459 for (i = 0; i < sk_X509_INFO_num(xis); i++) { 460 xi = sk_X509_INFO_value(xis, i); 461 if (xi->x509) { 462 if (!sk_X509_push(certs, xi->x509)) 463 goto done; 464 xi->x509 = NULL; 465 } 466 } 467 468 done: 469 if (bio) 470 BIO_free(bio); 471 if (xis) 472 sk_X509_INFO_pop_free(xis, X509_INFO_free); 473 if (certs && sk_X509_num(certs) <= 0) { 474 sk_X509_pop_free(certs, X509_free); 475 certs = NULL; 476 } 477 return (certs); 478 } 479 480 /* read/write callback that sends the requests and reads the ocsp response */ 481 void 482 ocsp_callback(int fd, short event, void *arg) 483 { 484 struct iked_ocsp *ocsp = arg; 485 struct iked_socket *sock = ocsp->ocsp_sock; 486 struct timeval tv; 487 OCSP_RESPONSE *resp = NULL; 488 489 if (event == EV_TIMEOUT) { 490 log_info("%s: timeout, giving up", 491 SPI_SH(&ocsp->ocsp_sh, __func__)); 492 ocsp_validate_finish(ocsp, 0); 493 return; 494 } 495 /* 496 * Only call OCSP_sendreq_nbio() if should_read/write is 497 * either not requested or read/write can be called. 498 */ 499 if ((!BIO_should_read(ocsp->ocsp_cbio) || (event & EV_READ)) && 500 (!BIO_should_write(ocsp->ocsp_cbio) || (event & EV_WRITE)) && 501 OCSP_sendreq_nbio(&resp, ocsp->ocsp_req_ctx) != -1 ) { 502 ocsp_parse_response(ocsp, resp); 503 return; 504 } 505 if (BIO_should_read(ocsp->ocsp_cbio)) 506 event_set(&sock->sock_ev, sock->sock_fd, EV_READ, 507 ocsp_callback, ocsp); 508 else if (BIO_should_write(ocsp->ocsp_cbio)) 509 event_set(&sock->sock_ev, sock->sock_fd, EV_WRITE, 510 ocsp_callback, ocsp); 511 tv.tv_sec = OCSP_TIMEOUT; 512 tv.tv_usec = 0; 513 event_add(&sock->sock_ev, &tv); 514 } 515 516 /* parse the actual OCSP response */ 517 void 518 ocsp_parse_response(struct iked_ocsp *ocsp, OCSP_RESPONSE *resp) 519 { 520 struct iked *env = ocsp->ocsp_env; 521 X509_STORE *store = NULL; 522 STACK_OF(X509) *verify_other = NULL; 523 OCSP_BASICRESP *bs = NULL; 524 ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; 525 const char *errstr; 526 int reason = 0, valid = 0, verify_flags = 0; 527 int status; 528 529 if (!resp) { 530 errstr = "error querying OCSP responder"; 531 goto done; 532 } 533 534 status = OCSP_response_status(resp); 535 if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { 536 errstr = OCSP_response_status_str(status); 537 goto done; 538 } 539 540 verify_other = ocsp_load_certs(IKED_OCSP_RESPCERT); 541 verify_flags |= OCSP_TRUSTOTHER; 542 if (!verify_other) { 543 errstr = "no verify_other"; 544 goto done; 545 } 546 547 bs = OCSP_response_get1_basic(resp); 548 if (!bs) { 549 errstr = "error parsing response"; 550 goto done; 551 } 552 553 status = OCSP_check_nonce(ocsp->ocsp_req, bs); 554 if (status <= 0) { 555 if (status == -1) 556 log_warnx("%s: no nonce in response", 557 SPI_SH(&ocsp->ocsp_sh, __func__)); 558 else { 559 errstr = "nonce verify error"; 560 goto done; 561 } 562 } 563 564 store = X509_STORE_new(); 565 status = OCSP_basic_verify(bs, verify_other, store, verify_flags); 566 if (status < 0) 567 status = OCSP_basic_verify(bs, NULL, store, 0); 568 if (status <= 0) { 569 ca_sslerror(__func__); 570 errstr = "response verify failure"; 571 goto done; 572 } 573 log_debug("%s: response verify ok", SPI_SH(&ocsp->ocsp_sh, __func__)); 574 575 if (!OCSP_resp_find_status(bs, ocsp->ocsp_id, &status, &reason, 576 &rev, &thisupd, &nextupd)) { 577 errstr = "no status found"; 578 goto done; 579 } 580 if (env->sc_ocsp_tolerate && 581 !OCSP_check_validity(thisupd, nextupd, env->sc_ocsp_tolerate, 582 env->sc_ocsp_maxage)) { 583 ca_sslerror(SPI_SH(&ocsp->ocsp_sh, __func__)); 584 errstr = "status times invalid"; 585 goto done; 586 } 587 errstr = OCSP_cert_status_str(status); 588 if (status == V_OCSP_CERTSTATUS_GOOD) { 589 log_debug("%s: status: %s", SPI_SH(&ocsp->ocsp_sh, __func__), 590 errstr); 591 valid = 1; 592 } 593 done: 594 if (!valid) { 595 log_debug("%s: status: %s", __func__, errstr); 596 } 597 if (store) 598 X509_STORE_free(store); 599 if (verify_other) 600 sk_X509_pop_free(verify_other, X509_free); 601 if (resp) 602 OCSP_RESPONSE_free(resp); 603 if (bs) 604 OCSP_BASICRESP_free(bs); 605 606 ocsp_validate_finish(ocsp, valid); 607 } 608 609 /* 610 * finish the ocsp_validate_cert() RPC by sending the appropriate 611 * message back to the IKEv2 process 612 */ 613 int 614 ocsp_validate_finish(struct iked_ocsp *ocsp, int valid) 615 { 616 struct iked *env = ocsp->ocsp_env; 617 struct iovec iov[2]; 618 int iovcnt = 2, ret, cmd; 619 620 iov[0].iov_base = &ocsp->ocsp_sh; 621 iov[0].iov_len = sizeof(ocsp->ocsp_sh); 622 iov[1].iov_base = &ocsp->ocsp_type; 623 iov[1].iov_len = sizeof(ocsp->ocsp_type); 624 625 cmd = valid ? IMSG_CERTVALID : IMSG_CERTINVALID; 626 ret = proc_composev(&env->sc_ps, PROC_IKEV2, cmd, iov, iovcnt); 627 628 ocsp_free(ocsp); 629 return (ret); 630 } 631