1 /* $OpenBSD: ocsp.c,v 1.25 2024/01/17 08:25:02 claudio 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", SPI_SH(&sh, __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", 110 SPI_SH(&sh, __func__), url); 111 goto done; 112 } 113 if (use_ssl) { 114 log_warnx("%s: OCSP over SSL not supported: %s", 115 SPI_SH(&sh, __func__), url); 116 goto done; 117 } 118 119 if ((fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0)) == -1) { 120 log_debug("%s: socket failed", SPI_SH(&sh, __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 SPI_SH(&sh, __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 if (oc->oc_url == NULL) { 153 log_warn("%s: strdup failed", SPI_SH(&sh, __func__)); 154 goto done; 155 } 156 path = NULL; 157 158 log_debug("%s: connect(%s, %s)", __func__, host, port); 159 if (connect(fd, res->ai_addr, res->ai_addrlen) == -1) { 160 /* register callback for ansync connect */ 161 if (errno == EINPROGRESS) { 162 tv.tv_sec = OCSP_TIMEOUT; 163 tv.tv_usec = 0; 164 event_set(&oc->oc_sock.sock_ev, fd, EV_WRITE, 165 ocsp_connect_cb, oc); 166 event_add(&oc->oc_sock.sock_ev, &tv); 167 ret = 0; 168 } else 169 log_warn("%s: connect(%s, %s)", 170 SPI_SH(&oc->oc_sh, __func__), host, port); 171 } else { 172 ocsp_connect_finish(env, fd, oc); 173 ret = 0; 174 } 175 done: 176 if (res0) 177 freeaddrinfo(res0); 178 free(freeme); 179 free(host); 180 free(port); 181 free(path); 182 if (ret == -1) { 183 ocsp_connect_finish(env, -1, oc); 184 if (fd >= 0) 185 close(fd); 186 } 187 return (ret); 188 } 189 190 /* callback triggered if connection to ocsp-responder completes/fails */ 191 void 192 ocsp_connect_cb(int fd, short event, void *arg) 193 { 194 struct ocsp_connect *oc = arg; 195 int error, send_fd = -1; 196 socklen_t len; 197 198 if (event == EV_TIMEOUT) { 199 log_info("%s: timeout, giving up", 200 SPI_SH(&oc->oc_sh, __func__)); 201 goto done; 202 } 203 204 len = sizeof(error); 205 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) == -1) { 206 log_warn("%s: getsockopt SOL_SOCKET SO_ERROR", 207 SPI_SH(&oc->oc_sh, __func__)); 208 } else if (error) { 209 log_warnx("%s: error while connecting: %s", 210 SPI_SH(&oc->oc_sh, __func__), strerror(error)); 211 } else { 212 send_fd = fd; 213 } 214 done: 215 ocsp_connect_finish(oc->oc_sock.sock_env, send_fd, oc); 216 217 /* if we did not send the fd, we need to close it ourself */ 218 if (send_fd == -1) 219 close(fd); 220 } 221 222 /* send FD+path or error back to CA process */ 223 int 224 ocsp_connect_finish(struct iked *env, int fd, struct ocsp_connect *oc) 225 { 226 struct iovec iov[2]; 227 int iovcnt = 0, ret; 228 229 iov[iovcnt].iov_base = &oc->oc_sh; 230 iov[iovcnt].iov_len = sizeof(oc->oc_sh); 231 iovcnt++; 232 233 if (oc && fd >= 0) { 234 /* the imsg framework will close the FD after send */ 235 iov[iovcnt].iov_base = oc->oc_path; 236 iov[iovcnt].iov_len = strlen(oc->oc_path); 237 iovcnt++; 238 ret = proc_composev_imsg(&env->sc_ps, PROC_CERT, -1, 239 IMSG_OCSP_FD, -1, fd, iov, iovcnt); 240 } else { 241 if (oc) 242 log_info("%s: connect failed for %s", 243 SPI_SH(&oc->oc_sh, __func__), 244 oc->oc_url ? oc->oc_url : "unknown"); 245 else 246 log_info("%s: connect failed", __func__); 247 ret = proc_composev_imsg(&env->sc_ps, PROC_CERT, -1, 248 IMSG_OCSP_FD, -1, -1, iov, iovcnt); 249 if (fd >= 0) 250 close(fd); 251 } 252 if (oc) { 253 free(oc->oc_url); 254 free(oc->oc_path); 255 free(oc); 256 } 257 return (ret); 258 } 259 260 261 /* unpriv */ 262 263 /* validate the certifcate stored in 'data' by querying the ocsp-responder */ 264 int 265 ocsp_validate_cert(struct iked *env, void *data, size_t len, 266 struct iked_sahdr sh, uint8_t type, X509 *issuer) 267 { 268 struct iovec iov[2]; 269 STACK_OF(OPENSSL_STRING) *aia; /* Authority Information Access */ 270 struct iked_ocsp_entry *ioe; 271 struct iked_ocsp *ocsp; 272 OCSP_CERTID *id = NULL; 273 char *url; 274 BIO *rawcert = NULL; 275 X509 *cert = NULL; 276 int ret, iovcnt = 0; 277 278 if (issuer == NULL) 279 return (-1); 280 if ((ioe = calloc(1, sizeof(*ioe))) == NULL) 281 return (-1); 282 if ((ocsp = calloc(1, sizeof(*ocsp))) == NULL) { 283 free(ioe); 284 return (-1); 285 } 286 287 ocsp->ocsp_env = env; 288 ocsp->ocsp_sh = sh; 289 ocsp->ocsp_type = type; 290 291 if ((rawcert = BIO_new_mem_buf(data, len)) == NULL || 292 (cert = d2i_X509_bio(rawcert, NULL)) == NULL || 293 (ocsp->ocsp_cbio = BIO_new(BIO_s_socket())) == NULL || 294 (ocsp->ocsp_req = OCSP_REQUEST_new()) == NULL || 295 (id = OCSP_cert_to_id(NULL, cert, issuer)) == NULL || 296 !OCSP_request_add0_id(ocsp->ocsp_req, id)) 297 goto err; 298 299 /* id is owned by and freed together with ocsp_req */ 300 ocsp->ocsp_id = id; 301 302 BIO_free(rawcert); 303 X509_free(cert); 304 305 ioe->ioe_ocsp = ocsp; 306 TAILQ_INSERT_TAIL(&env->sc_ocsp, ioe, ioe_entry); 307 308 /* pass SA header */ 309 iov[iovcnt].iov_base = &ocsp->ocsp_sh; 310 iov[iovcnt].iov_len = sizeof(ocsp->ocsp_sh); 311 iovcnt++; 312 313 /* pass optional ocsp-url from issuer */ 314 if ((aia = X509_get1_ocsp(issuer)) != NULL) { 315 url = sk_OPENSSL_STRING_value(aia, 0); 316 log_debug("%s: aia %s", __func__, url); 317 iov[iovcnt].iov_base = url; 318 iov[iovcnt].iov_len = strlen(url); 319 iovcnt++; 320 } 321 /* request connection to ocsp-responder */ 322 ret = proc_composev(&env->sc_ps, PROC_PARENT, IMSG_OCSP_FD, 323 iov, iovcnt); 324 325 X509_email_free(aia); /* free stack of openssl strings */ 326 327 return (ret); 328 329 err: 330 ca_sslerror(__func__); 331 free(ioe); 332 BIO_free(rawcert); 333 X509_free(cert); 334 OCSP_CERTID_free(id); 335 ocsp_validate_finish(ocsp, 0); /* failed */ 336 return (-1); 337 } 338 339 /* free ocsp query context */ 340 void 341 ocsp_free(struct iked_ocsp *ocsp) 342 { 343 if (ocsp != NULL) { 344 if (ocsp->ocsp_sock != NULL) { 345 close(ocsp->ocsp_sock->sock_fd); 346 free(ocsp->ocsp_sock); 347 } 348 BIO_free_all(ocsp->ocsp_cbio); 349 OCSP_REQ_CTX_free(ocsp->ocsp_req_ctx); 350 OCSP_REQUEST_free(ocsp->ocsp_req); 351 free(ocsp); 352 } 353 } 354 355 /* we got a connection to the ocsp responder */ 356 int 357 ocsp_receive_fd(struct iked *env, struct imsg *imsg) 358 { 359 struct iked_ocsp_entry *ioe = NULL; 360 struct iked_ocsp *ocsp = NULL, *ocsp_tmp; 361 struct iked_socket *sock; 362 struct iked_sahdr sh; 363 struct timeval tv; 364 uint8_t *ptr; 365 char *path = NULL; 366 size_t len; 367 int fd, ret = -1; 368 369 IMSG_SIZE_CHECK(imsg, &sh); 370 371 ptr = (uint8_t *)imsg->data; 372 len = IMSG_DATA_SIZE(imsg); 373 374 memcpy(&sh, ptr, sizeof(sh)); 375 376 ptr += sizeof(sh); 377 len -= sizeof(sh); 378 379 TAILQ_FOREACH(ioe, &env->sc_ocsp, ioe_entry) { 380 ocsp_tmp = ioe->ioe_ocsp; 381 if (memcmp(&ocsp_tmp->ocsp_sh, &sh, sizeof(sh)) == 0) 382 break; 383 } 384 if (ioe == NULL) { 385 log_debug("%s: no pending request found", __func__); 386 if ((fd = imsg_get_fd(imsg)) != -1) /* XXX */ 387 close(fd); 388 return (-1); 389 } 390 TAILQ_REMOVE(&env->sc_ocsp, ioe, ioe_entry); 391 ocsp = ioe->ioe_ocsp; 392 free(ioe); 393 394 if ((fd = imsg_get_fd(imsg)) == -1) 395 goto done; 396 397 if ((sock = calloc(1, sizeof(*sock))) == NULL) 398 fatal("ocsp_receive_fd: calloc sock"); 399 400 /* note that sock_addr is not set */ 401 sock->sock_fd = fd; 402 sock->sock_env = env; 403 ocsp->ocsp_sock = sock; 404 405 log_debug("%s: received socket fd %d", __func__, sock->sock_fd); 406 407 /* fetch 'path' and 'fd' from imsg */ 408 if ((path = get_string(ptr, len)) == NULL) 409 goto done; 410 411 BIO_set_fd(ocsp->ocsp_cbio, sock->sock_fd, BIO_NOCLOSE); 412 413 if ((ocsp->ocsp_req_ctx = OCSP_sendreq_new(ocsp->ocsp_cbio, 414 path, NULL, -1)) == NULL) 415 goto done; 416 if (!OCSP_REQ_CTX_set1_req(ocsp->ocsp_req_ctx, ocsp->ocsp_req)) 417 goto done; 418 419 tv.tv_sec = OCSP_TIMEOUT; 420 tv.tv_usec = 0; 421 event_set(&sock->sock_ev, sock->sock_fd, EV_WRITE, ocsp_callback, ocsp); 422 event_add(&sock->sock_ev, &tv); 423 ret = 0; 424 done: 425 if (ret == -1) 426 ocsp_validate_finish(ocsp, 0); /* failed */ 427 free(path); 428 return (ret); 429 } 430 431 /* load a stack of x509 certificates */ 432 STACK_OF(X509)* 433 ocsp_load_certs(const char *file) 434 { 435 BIO *bio = NULL; 436 STACK_OF(X509) *certs = NULL; 437 STACK_OF(X509_INFO) *xis = NULL; 438 X509_INFO *xi; 439 int i; 440 441 if ((bio = BIO_new_file(file, "r")) == NULL) { 442 log_warn("%s: BIO_new_file failed for %s", 443 __func__, file); 444 return (NULL); 445 } 446 if ((xis = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL)) == NULL) { 447 ca_sslerror(__func__); 448 goto done; 449 } 450 if ((certs = sk_X509_new_null()) == NULL) { 451 log_debug("%s: sk_X509_new_null failed for %s", __func__, file); 452 goto done; 453 } 454 for (i = 0; i < sk_X509_INFO_num(xis); i++) { 455 xi = sk_X509_INFO_value(xis, i); 456 if (xi->x509) { 457 if (!sk_X509_push(certs, xi->x509)) 458 goto done; 459 xi->x509 = NULL; 460 } 461 } 462 463 done: 464 BIO_free(bio); 465 sk_X509_INFO_pop_free(xis, X509_INFO_free); 466 if (sk_X509_num(certs) <= 0) { 467 sk_X509_free(certs); 468 certs = NULL; 469 } 470 return (certs); 471 } 472 473 /* read/write callback that sends the requests and reads the ocsp response */ 474 void 475 ocsp_callback(int fd, short event, void *arg) 476 { 477 struct iked_ocsp *ocsp = arg; 478 struct iked_socket *sock = ocsp->ocsp_sock; 479 struct timeval tv; 480 OCSP_RESPONSE *resp = NULL; 481 482 if (event == EV_TIMEOUT) { 483 log_info("%s: timeout, giving up", 484 SPI_SH(&ocsp->ocsp_sh, __func__)); 485 ocsp_validate_finish(ocsp, 0); 486 return; 487 } 488 /* 489 * Only call OCSP_sendreq_nbio() if should_read/write is 490 * either not requested or read/write can be called. 491 */ 492 if ((!BIO_should_read(ocsp->ocsp_cbio) || (event & EV_READ)) && 493 (!BIO_should_write(ocsp->ocsp_cbio) || (event & EV_WRITE)) && 494 OCSP_sendreq_nbio(&resp, ocsp->ocsp_req_ctx) != -1 ) { 495 ocsp_parse_response(ocsp, resp); 496 return; 497 } 498 if (BIO_should_read(ocsp->ocsp_cbio)) 499 event_set(&sock->sock_ev, sock->sock_fd, EV_READ, 500 ocsp_callback, ocsp); 501 else if (BIO_should_write(ocsp->ocsp_cbio)) 502 event_set(&sock->sock_ev, sock->sock_fd, EV_WRITE, 503 ocsp_callback, ocsp); 504 tv.tv_sec = OCSP_TIMEOUT; 505 tv.tv_usec = 0; 506 event_add(&sock->sock_ev, &tv); 507 } 508 509 /* parse the actual OCSP response */ 510 void 511 ocsp_parse_response(struct iked_ocsp *ocsp, OCSP_RESPONSE *resp) 512 { 513 struct iked *env = ocsp->ocsp_env; 514 X509_STORE *store = NULL; 515 STACK_OF(X509) *verify_other = NULL; 516 OCSP_BASICRESP *bs = NULL; 517 ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; 518 const char *errstr; 519 int reason = 0, valid = 0, verify_flags = 0; 520 int status; 521 522 if (!resp) { 523 errstr = "error querying OCSP responder"; 524 goto done; 525 } 526 527 status = OCSP_response_status(resp); 528 if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { 529 errstr = OCSP_response_status_str(status); 530 goto done; 531 } 532 533 verify_other = ocsp_load_certs(IKED_OCSP_RESPCERT); 534 verify_flags |= OCSP_TRUSTOTHER; 535 if (!verify_other) { 536 errstr = "no verify_other"; 537 goto done; 538 } 539 540 bs = OCSP_response_get1_basic(resp); 541 if (!bs) { 542 errstr = "error parsing response"; 543 goto done; 544 } 545 546 status = OCSP_check_nonce(ocsp->ocsp_req, bs); 547 if (status <= 0) { 548 if (status == -1) 549 log_warnx("%s: no nonce in response", 550 SPI_SH(&ocsp->ocsp_sh, __func__)); 551 else { 552 errstr = "nonce verify error"; 553 goto done; 554 } 555 } 556 557 store = X509_STORE_new(); 558 status = OCSP_basic_verify(bs, verify_other, store, verify_flags); 559 if (status < 0) 560 status = OCSP_basic_verify(bs, NULL, store, 0); 561 if (status <= 0) { 562 ca_sslerror(__func__); 563 errstr = "response verify failure"; 564 goto done; 565 } 566 log_debug("%s: response verify ok", SPI_SH(&ocsp->ocsp_sh, __func__)); 567 568 if (!OCSP_resp_find_status(bs, ocsp->ocsp_id, &status, &reason, 569 &rev, &thisupd, &nextupd)) { 570 errstr = "no status found"; 571 goto done; 572 } 573 if (env->sc_ocsp_tolerate && 574 !OCSP_check_validity(thisupd, nextupd, env->sc_ocsp_tolerate, 575 env->sc_ocsp_maxage)) { 576 ca_sslerror(SPI_SH(&ocsp->ocsp_sh, __func__)); 577 errstr = "status times invalid"; 578 goto done; 579 } 580 errstr = OCSP_cert_status_str(status); 581 if (status == V_OCSP_CERTSTATUS_GOOD) { 582 log_debug("%s: status: %s", SPI_SH(&ocsp->ocsp_sh, __func__), 583 errstr); 584 valid = 1; 585 } 586 done: 587 if (!valid) { 588 log_debug("%s: status: %s", __func__, errstr); 589 } 590 X509_STORE_free(store); 591 sk_X509_pop_free(verify_other, X509_free); 592 OCSP_RESPONSE_free(resp); 593 OCSP_BASICRESP_free(bs); 594 595 ocsp_validate_finish(ocsp, valid); 596 } 597 598 /* 599 * finish the ocsp_validate_cert() RPC by sending the appropriate 600 * message back to the IKEv2 process 601 */ 602 int 603 ocsp_validate_finish(struct iked_ocsp *ocsp, int valid) 604 { 605 struct iked *env = ocsp->ocsp_env; 606 struct iovec iov[2]; 607 int iovcnt = 2, ret, cmd; 608 609 iov[0].iov_base = &ocsp->ocsp_sh; 610 iov[0].iov_len = sizeof(ocsp->ocsp_sh); 611 iov[1].iov_base = &ocsp->ocsp_type; 612 iov[1].iov_len = sizeof(ocsp->ocsp_type); 613 614 cmd = valid ? IMSG_CERTVALID : IMSG_CERTINVALID; 615 ret = proc_composev(&env->sc_ps, PROC_IKEV2, cmd, iov, iovcnt); 616 617 ocsp_free(ocsp); 618 return (ret); 619 } 620