1 /* $OpenBSD: ocsp.c,v 1.8 2015/12/07 12:46:37 reyk 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_socket oc_sock; 55 char *oc_path; 56 }; 57 58 /* priv */ 59 void ocsp_connect_cb(int, short, void *); 60 int ocsp_connect_finish(struct iked *, int, struct ocsp_connect *); 61 62 /* unpriv */ 63 void ocsp_free(struct iked_ocsp *); 64 void ocsp_callback(int, short, void *); 65 void ocsp_parse_response(struct iked_ocsp *, OCSP_RESPONSE *); 66 STACK_OF(X509) *ocsp_load_certs(const char *); 67 int ocsp_validate_finish(struct iked_ocsp *, int); 68 69 70 /* priv */ 71 72 /* async connect to configure ocsp-responder */ 73 int 74 ocsp_connect(struct iked *env) 75 { 76 struct ocsp_connect *oc = NULL; 77 struct addrinfo hints, *res0 = NULL, *res; 78 char *host = NULL, *port = NULL, *path = NULL; 79 int use_ssl, fd = -1, ret = -1, error; 80 81 if (env->sc_ocsp_url == 0) { 82 log_warnx("%s: no ocsp url", __func__); 83 goto done; 84 } 85 if (!OCSP_parse_url(env->sc_ocsp_url, &host, &port, &path, &use_ssl)) { 86 log_warnx("%s: error parsing OCSP-request-URL: %s", __func__, 87 env->sc_ocsp_url); 88 goto done; 89 } 90 91 if ((fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0)) < 0) { 92 log_debug("%s: socket failed", __func__); 93 goto done; 94 } 95 if ((oc = calloc(1, sizeof(*oc))) == NULL) { 96 log_debug("%s: calloc failed", __func__); 97 goto done; 98 } 99 100 bzero(&hints, sizeof(struct addrinfo)); 101 hints.ai_family = PF_UNSPEC; 102 hints.ai_socktype = SOCK_STREAM; 103 error = getaddrinfo(host, port, &hints, &res0); 104 if (error) { 105 log_debug("%s: getaddrinfo(%s, %s) failed", 106 __func__, host, port); 107 goto done; 108 } 109 /* XXX just pick the first answer. we could loop instead */ 110 for (res = res0; res; res = res->ai_next) 111 if (res->ai_family == AF_INET) 112 break; 113 if (res == NULL) { 114 log_debug("%s: no addr to connect to for %s:%s", 115 __func__, host, port); 116 goto done; 117 } 118 119 oc->oc_sock.sock_fd = fd; 120 oc->oc_sock.sock_env = env; 121 oc->oc_path = path; 122 path = NULL; 123 124 log_debug("%s: connect(%s, %s)", __func__, host, port); 125 if (connect(fd, res->ai_addr, res->ai_addrlen) == -1) { 126 /* register callback for ansync connect */ 127 if (errno == EINPROGRESS) { 128 event_set(&oc->oc_sock.sock_ev, fd, EV_WRITE, 129 ocsp_connect_cb, oc); 130 event_add(&oc->oc_sock.sock_ev, NULL); 131 ret = 0; 132 } else 133 log_debug("%s: error while connecting: %s", __func__, 134 strerror(errno)); 135 } else { 136 ocsp_connect_finish(env, fd, oc); 137 ret = 0; 138 } 139 done: 140 if (res0) 141 freeaddrinfo(res0); 142 free(host); 143 free(port); 144 free(path); 145 if (ret == -1) { 146 ocsp_connect_finish(env, -1, oc); 147 if (fd >= 0) 148 close(fd); 149 } 150 return (ret); 151 } 152 153 /* callback triggered if connection to ocsp-responder completes/fails */ 154 void 155 ocsp_connect_cb(int fd, short event, void *arg) 156 { 157 struct ocsp_connect *oc = arg; 158 int error, send_fd = -1; 159 socklen_t len; 160 161 len = sizeof(error); 162 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { 163 log_warn("%s: getsockopt SOL_SOCKET SO_ERROR", __func__); 164 } else if (error) { 165 log_debug("%s: error while connecting: %s", __func__, 166 strerror(error)); 167 } else { 168 send_fd = fd; 169 } 170 ocsp_connect_finish(oc->oc_sock.sock_env, send_fd, oc); 171 172 /* if we did not send the fd, we need to close it ourself */ 173 if (send_fd == -1) 174 close(fd); 175 } 176 177 /* send FD+path or error back to CA process */ 178 int 179 ocsp_connect_finish(struct iked *env, int fd, struct ocsp_connect *oc) 180 { 181 struct iovec iov[1]; 182 int iovcnt = 1, ret; 183 184 if (oc && fd >= 0) { 185 /* the imsg framework will close the FD after send */ 186 iov[0].iov_base = oc->oc_path; 187 iov[0].iov_len = strlen(oc->oc_path); 188 ret = proc_composev_imsg(&env->sc_ps, PROC_CERT, -1, 189 IMSG_OCSP_FD, -1, fd, iov, iovcnt); 190 } else { 191 ret = proc_compose_imsg(&env->sc_ps, PROC_CERT, -1, 192 IMSG_OCSP_FD, -1, -1, NULL, 0); 193 if (fd >= 0) 194 close(fd); 195 } 196 if (oc) { 197 free(oc->oc_path); 198 free(oc); 199 } 200 return (ret); 201 } 202 203 204 /* unpriv */ 205 206 /* validate the certifcate stored in 'data' by querying the ocsp-responder */ 207 int 208 ocsp_validate_cert(struct iked *env, struct iked_static_id *id, 209 void *data, size_t len, struct iked_sahdr sh, uint8_t type) 210 { 211 struct iked_ocsp_entry *ioe; 212 struct iked_ocsp *ocsp; 213 BIO *rawcert = NULL, *bissuer = NULL; 214 X509 *cert = NULL, *issuer = NULL; 215 216 if ((ioe = calloc(1, sizeof(*ioe))) == NULL) 217 return (-1); 218 if ((ocsp = calloc(1, sizeof(*ocsp))) == NULL) { 219 free(ioe); 220 return (-1); 221 } 222 223 ocsp->ocsp_env = env; 224 ocsp->ocsp_sh = sh; 225 ocsp->ocsp_type = type; 226 227 if ((rawcert = BIO_new_mem_buf(data, len)) == NULL || 228 (cert = d2i_X509_bio(rawcert, NULL)) == NULL || 229 (bissuer = BIO_new_file(IKED_OCSP_ISSUER, "r")) == NULL || 230 (issuer = PEM_read_bio_X509(bissuer, NULL, NULL, NULL)) == NULL || 231 (ocsp->ocsp_cbio = BIO_new(BIO_s_socket())) == NULL || 232 (ocsp->ocsp_req = OCSP_REQUEST_new()) == NULL || 233 !(ocsp->ocsp_id = OCSP_cert_to_id(NULL, cert, issuer)) || 234 !OCSP_request_add0_id(ocsp->ocsp_req, ocsp->ocsp_id)) 235 goto err; 236 237 BIO_free(rawcert); 238 BIO_free(bissuer); 239 X509_free(cert); 240 X509_free(issuer); 241 242 ioe->ioe_ocsp = ocsp; 243 TAILQ_INSERT_TAIL(&env->sc_ocsp, ioe, ioe_entry); 244 245 /* request connection to ocsp-responder */ 246 proc_compose(&env->sc_ps, PROC_PARENT, IMSG_OCSP_FD, NULL, 0); 247 return (0); 248 249 err: 250 ca_sslerror(__func__); 251 free(ioe); 252 if (rawcert != NULL) 253 BIO_free(rawcert); 254 if (cert != NULL) 255 X509_free(cert); 256 if (bissuer != NULL) 257 BIO_free(bissuer); 258 if (issuer != NULL) 259 X509_free(issuer); 260 ocsp_validate_finish(ocsp, 0); /* failed */ 261 return (-1); 262 } 263 264 /* free ocsp query context */ 265 void 266 ocsp_free(struct iked_ocsp *ocsp) 267 { 268 if (ocsp != NULL) { 269 if (ocsp->ocsp_sock != NULL) { 270 close(ocsp->ocsp_sock->sock_fd); 271 free(ocsp->ocsp_sock); 272 } 273 if (ocsp->ocsp_cbio != NULL) 274 BIO_free_all(ocsp->ocsp_cbio); 275 if (ocsp->ocsp_id != NULL) 276 OCSP_CERTID_free(ocsp->ocsp_id); 277 278 /* XXX not sure about ownership XXX */ 279 if (ocsp->ocsp_req_ctx != NULL) 280 OCSP_REQ_CTX_free(ocsp->ocsp_req_ctx); 281 else if (ocsp->ocsp_req != NULL) 282 OCSP_REQUEST_free(ocsp->ocsp_req); 283 284 free(ocsp); 285 } 286 } 287 288 /* we got a connection to the ocsp responder */ 289 int 290 ocsp_receive_fd(struct iked *env, struct imsg *imsg) 291 { 292 struct iked_ocsp_entry *ioe = NULL; 293 struct iked_ocsp *ocsp = NULL; 294 struct iked_socket *sock; 295 char *path = NULL; 296 int ret = -1; 297 298 log_debug("%s: received socket fd %d", __func__, imsg->fd); 299 if ((ioe = TAILQ_FIRST(&env->sc_ocsp)) == NULL) { 300 log_debug("%s: oops, no request for", __func__); 301 close(imsg->fd); 302 return (-1); 303 } 304 TAILQ_REMOVE(&env->sc_ocsp, ioe, ioe_entry); 305 ocsp = ioe->ioe_ocsp; 306 free(ioe); 307 308 if ((sock = calloc(1, sizeof(*sock))) == NULL) 309 fatal("ocsp_receive_fd: calloc sock"); 310 311 /* note that sock_addr is not set */ 312 sock->sock_fd = imsg->fd; 313 sock->sock_env = env; 314 ocsp->ocsp_sock = sock; 315 316 /* fetch 'path' and 'fd' from imsg */ 317 if ((path = get_string(imsg->data, IMSG_DATA_SIZE(imsg))) == NULL) 318 goto done; 319 320 BIO_set_fd(ocsp->ocsp_cbio, imsg->fd, BIO_NOCLOSE); 321 322 if ((ocsp->ocsp_req_ctx = OCSP_sendreq_new(ocsp->ocsp_cbio, 323 path, NULL, -1)) == NULL) 324 goto done; 325 if (!OCSP_REQ_CTX_set1_req(ocsp->ocsp_req_ctx, ocsp->ocsp_req)) 326 goto done; 327 328 event_set(&sock->sock_ev, sock->sock_fd, EV_WRITE, ocsp_callback, ocsp); 329 event_add(&sock->sock_ev, NULL); 330 ret = 0; 331 done: 332 if (ret == -1) 333 ocsp_validate_finish(ocsp, 0); /* failed */ 334 free(path); 335 return (ret); 336 } 337 338 /* load a stack of x509 certificates */ 339 STACK_OF(X509)* 340 ocsp_load_certs(const char *file) 341 { 342 BIO *bio = NULL; 343 STACK_OF(X509) *certs = NULL; 344 STACK_OF(X509_INFO) *xis = NULL; 345 X509_INFO *xi; 346 int i; 347 348 if ((bio = BIO_new_file(file, "r")) == NULL) { 349 log_warn("%s: BIO_new_file failed for %s", 350 __func__, file); 351 return (NULL); 352 } 353 if ((xis = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL)) == NULL) { 354 ca_sslerror(__func__); 355 goto done; 356 } 357 if ((certs = sk_X509_new_null()) == NULL) { 358 log_debug("%s: sk_X509_new_null failed for %s", __func__, file); 359 goto done; 360 } 361 for (i = 0; i < sk_X509_INFO_num(xis); i++) { 362 xi = sk_X509_INFO_value(xis, i); 363 if (xi->x509) { 364 if (!sk_X509_push(certs, xi->x509)) 365 goto done; 366 xi->x509 = NULL; 367 } 368 } 369 370 done: 371 if (bio) 372 BIO_free(bio); 373 if (xis) 374 sk_X509_INFO_pop_free(xis, X509_INFO_free); 375 if (certs && sk_X509_num(certs) <= 0) { 376 sk_X509_pop_free(certs, X509_free); 377 certs = NULL; 378 } 379 return (certs); 380 } 381 382 /* read/write callback that sends the requests and reads the ocsp response */ 383 void 384 ocsp_callback(int fd, short event, void *arg) 385 { 386 struct iked_ocsp *ocsp = arg; 387 struct iked_socket *sock = ocsp->ocsp_sock; 388 OCSP_RESPONSE *resp = NULL; 389 390 /* 391 * Only call OCSP_sendreq_nbio() if should_read/write is 392 * either not requested or read/write can be called. 393 */ 394 if ((!BIO_should_read(ocsp->ocsp_cbio) || (event & EV_READ)) && 395 (!BIO_should_write(ocsp->ocsp_cbio) || (event & EV_WRITE)) && 396 OCSP_sendreq_nbio(&resp, ocsp->ocsp_req_ctx) != -1 ) { 397 ocsp_parse_response(ocsp, resp); 398 return; 399 } 400 if (BIO_should_read(ocsp->ocsp_cbio)) 401 event_set(&sock->sock_ev, sock->sock_fd, EV_READ, 402 ocsp_callback, ocsp); 403 else if (BIO_should_write(ocsp->ocsp_cbio)) 404 event_set(&sock->sock_ev, sock->sock_fd, EV_WRITE, 405 ocsp_callback, ocsp); 406 event_add(&sock->sock_ev, NULL); 407 } 408 409 /* parse the actual OCSP response */ 410 void 411 ocsp_parse_response(struct iked_ocsp *ocsp, OCSP_RESPONSE *resp) 412 { 413 int status; 414 X509_STORE *store = NULL; 415 STACK_OF(X509) *verify_other = NULL; 416 OCSP_BASICRESP *bs = NULL; 417 int verify_flags = 0; 418 ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; 419 int reason = 0; 420 int error = 1; 421 422 if (!resp) { 423 log_warnx("%s: error querying OCSP responder", __func__); 424 goto done; 425 } 426 427 status = OCSP_response_status(resp); 428 if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { 429 log_warnx("%s: responder error: %s (%i)\n", __func__, 430 OCSP_response_status_str(status), status); 431 goto done; 432 } 433 434 verify_other = ocsp_load_certs(IKED_OCSP_RESPCERT); 435 verify_flags |= OCSP_TRUSTOTHER; 436 if (!verify_other) 437 goto done; 438 439 bs = OCSP_response_get1_basic(resp); 440 if (!bs) { 441 log_warnx("%s: error parsing response", __func__); 442 goto done; 443 } 444 445 status = OCSP_check_nonce(ocsp->ocsp_req, bs); 446 if (status <= 0) { 447 if (status == -1) 448 log_warnx("%s: no nonce in response", __func__); 449 else { 450 log_warnx("%s: nonce verify error", __func__); 451 goto done; 452 } 453 } 454 455 store = X509_STORE_new(); 456 status = OCSP_basic_verify(bs, verify_other, store, verify_flags); 457 if (status < 0) 458 status = OCSP_basic_verify(bs, NULL, store, 0); 459 460 if (status <= 0) { 461 ca_sslerror(__func__); 462 log_warnx("%s: response verify failure", __func__); 463 goto done; 464 } else 465 log_debug("%s: response verify ok", __func__); 466 467 if (!OCSP_resp_find_status(bs, ocsp->ocsp_id, &status, &reason, 468 &rev, &thisupd, &nextupd)) { 469 log_warnx("%s: no status found", __func__); 470 goto done; 471 } 472 log_debug("%s: status: %s", __func__, OCSP_cert_status_str(status)); 473 474 if (status == V_OCSP_CERTSTATUS_GOOD) 475 error = 0; 476 477 done: 478 if (store) 479 X509_STORE_free(store); 480 if (verify_other) 481 sk_X509_pop_free(verify_other, X509_free); 482 if (resp) 483 OCSP_RESPONSE_free(resp); 484 if (bs) 485 OCSP_BASICRESP_free(bs); 486 487 ocsp_validate_finish(ocsp, error == 0); 488 } 489 490 /* 491 * finish the ocsp_validate_cert() RPC by sending the appropriate 492 * message back to the IKEv2 process 493 */ 494 int 495 ocsp_validate_finish(struct iked_ocsp *ocsp, int valid) 496 { 497 struct iked *env = ocsp->ocsp_env; 498 struct iovec iov[2]; 499 int iovcnt = 2, ret, cmd; 500 501 iov[0].iov_base = &ocsp->ocsp_sh; 502 iov[0].iov_len = sizeof(ocsp->ocsp_sh); 503 iov[1].iov_base = &ocsp->ocsp_type; 504 iov[1].iov_len = sizeof(ocsp->ocsp_type); 505 506 cmd = valid ? IMSG_CERTVALID : IMSG_CERTINVALID; 507 ret = proc_composev(&env->sc_ps, PROC_IKEV2, cmd, iov, iovcnt); 508 509 ocsp_free(ocsp); 510 return (ret); 511 } 512