xref: /openbsd-src/sbin/iked/ocsp.c (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1 /*
2  * Copyright (c) 2014 Markus Friedl
3  * Copyright (c) 2005 Marco Pfatschbacher
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 #include <sys/param.h>
18 #include <sys/queue.h>
19 #include <sys/socket.h>
20 #include <sys/uio.h>
21 #include <sys/stat.h>
22 
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <unistd.h>
29 #include <netdb.h>
30 
31 #include <openssl/pem.h>
32 #include <openssl/ocsp.h>
33 #include <openssl/err.h>
34 #include <openssl/ssl.h>
35 
36 #include <event.h>
37 
38 #include "iked.h"
39 
40 struct iked_ocsp {
41 	struct iked		*ocsp_env;	/* back pointer to env */
42 	struct iked_sahdr	 ocsp_sh;	/* ike sa */
43 	u_int8_t		 ocsp_type;	/* auth type */
44 	struct iked_socket	*ocsp_sock;	/* socket to ocsp responder */
45 	BIO			*ocsp_cbio;	/* matching OpenSSL obj */
46 	OCSP_CERTID		*ocsp_id;	/* ocsp-id for cert */
47 	OCSP_REQUEST		*ocsp_req;	/* ocsp-request */
48 	OCSP_REQ_CTX		*ocsp_req_ctx;	/* async ocsp-request */
49 };
50 
51 struct ocsp_connect {
52 	struct iked_socket	 oc_sock;
53 	char			*oc_path;
54 };
55 
56 /* priv */
57 void		 ocsp_connect_cb(int, short, void *);
58 int		 ocsp_connect_finish(struct iked *, int, struct ocsp_connect *);
59 
60 /* unpriv */
61 void		 ocsp_free(struct iked_ocsp *);
62 void		 ocsp_callback(int, short, void *);
63 void		 ocsp_parse_response(struct iked_ocsp *, OCSP_RESPONSE *);
64 STACK_OF(X509)	*ocsp_load_certs(const char *);
65 int		 ocsp_validate_finish(struct iked_ocsp *, int);
66 
67 
68 /* priv */
69 
70 /* async connect to configure ocsp-responder */
71 int
72 ocsp_connect(struct iked *env)
73 {
74 	struct ocsp_connect	*oc = NULL;
75 	struct addrinfo		 hints, *res0 = NULL, *res;
76 	char			*host = NULL, *port = NULL, *path = NULL;
77 	int			use_ssl, fd = -1, ret = -1, error;
78 
79 	if (env->sc_ocsp_url == 0) {
80 		log_warnx("%s: no ocsp url", __func__);
81 		goto done;
82 	}
83 	if (!OCSP_parse_url(env->sc_ocsp_url, &host, &port, &path, &use_ssl)) {
84 		log_warnx("%s: error parsing OCSP-request-URL: %s", __func__,
85 		    env->sc_ocsp_url);
86 		goto done;
87 	}
88 
89 	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
90 		log_debug("%s: socket failed", __func__);
91 		goto done;
92 	}
93 	if ((oc = calloc(1, sizeof(*oc))) == NULL) {
94 		log_debug("%s: calloc failed", __func__);
95 		goto done;
96 	}
97 
98 	bzero(&hints, sizeof(struct addrinfo));
99 	hints.ai_family = PF_UNSPEC;
100 	hints.ai_socktype = SOCK_STREAM;
101 	error = getaddrinfo(host, port, &hints, &res0);
102 	if (error) {
103 		log_debug("%s: getaddrinfo(%s, %s) failed",
104 		    __func__, host, port);
105 		goto done;
106 	}
107 	/* XXX just pick the first answer. we could loop instead */
108 	for (res = res0; res; res = res->ai_next)
109 		if (res->ai_family == AF_INET)
110 			break;
111 	if (res == NULL) {
112 		log_debug("%s: no addr to connect to for %s:%s",
113 		    __func__, host, port);
114 		goto done;
115 	}
116 
117 	oc->oc_sock.sock_fd = fd;
118 	oc->oc_sock.sock_env = env;
119 	oc->oc_path = path;
120 	path = NULL;
121 
122 	log_debug("%s: connect(%s, %s)", __func__, host, port);
123 	socket_set_blockmode(fd, BM_NONBLOCK);
124 	if (connect(fd, res->ai_addr, res->ai_addrlen) == -1) {
125 		/* register callback for ansync connect */
126 		if (errno == EINPROGRESS) {
127 			event_set(&oc->oc_sock.sock_ev, fd, EV_WRITE,
128 			    ocsp_connect_cb, oc);
129 			event_add(&oc->oc_sock.sock_ev, NULL);
130 			ret = 0;
131 		} else
132 			log_debug("%s: error while connecting: %s", __func__,
133 			    strerror(errno));
134 	} else {
135 		ocsp_connect_finish(env, fd, oc);
136 		ret = 0;
137 	}
138  done:
139 	if (res0)
140 		freeaddrinfo(res0);
141 	free(host);
142 	free(port);
143 	free(path);
144 	if (ret == -1) {
145 		ocsp_connect_finish(env, -1, oc);
146 		if (fd >= 0)
147 			close(fd);
148 	}
149 	return (ret);
150 }
151 
152 /* callback triggered if connection to ocsp-responder completes/fails */
153 void
154 ocsp_connect_cb(int fd, short event, void *arg)
155 {
156 	struct ocsp_connect	*oc = arg;
157 	int			 error, send_fd = -1;
158 	socklen_t		 len;
159 
160 	len = sizeof(error);
161 	if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
162 		log_warn("%s: getsockopt SOL_SOCKET SO_ERROR", __func__);
163 	} else if (error) {
164 		log_debug("%s: error while connecting: %s", __func__,
165 		    strerror(error));
166 	} else {
167 		send_fd = fd;
168 	}
169 	ocsp_connect_finish(oc->oc_sock.sock_env, send_fd, oc);
170 
171 	/* if we did not send the fd, we need to close it ourself */
172 	if (send_fd == -1)
173 		close(fd);
174 }
175 
176 /* send FD+path or error back to CA process */
177 int
178 ocsp_connect_finish(struct iked *env, int fd, struct ocsp_connect *oc)
179 {
180 	struct iovec		 iov[1];
181 	int			 iovcnt = 1, ret;
182 
183 	if (oc && fd >= 0) {
184 		/* the imsg framework will close the FD after send */
185 		iov[0].iov_base = oc->oc_path;
186 		iov[0].iov_len = strlen(oc->oc_path);
187 		ret = proc_composev_imsg(&env->sc_ps, PROC_CERT, -1,
188 		    IMSG_OCSP_FD, fd, iov, iovcnt);
189 	} else {
190 		ret = proc_compose_imsg(&env->sc_ps, PROC_CERT, -1,
191 		    IMSG_OCSP_FD, -1, NULL, 0);
192 		if (fd >= 0)
193 			close(fd);
194 	}
195 	if (oc) {
196 		free(oc->oc_path);
197 		free(oc);
198 	}
199 	return (ret);
200 }
201 
202 
203 /* unpriv */
204 
205 /* validate the certifcate stored in 'data' by querying the ocsp-responder */
206 int
207 ocsp_validate_cert(struct iked *env, struct iked_static_id *id,
208     void *data, size_t len, struct iked_sahdr sh, u_int8_t type)
209 {
210 	struct iked_ocsp_entry	*ioe;
211 	struct iked_ocsp	*ocsp;
212 	BIO			*rawcert = NULL, *bissuer = NULL;
213 	X509			*cert = NULL, *issuer = NULL;
214 
215 	if ((ioe = calloc(1, sizeof(*ioe))) == NULL)
216 		return (-1);
217 	if ((ocsp = calloc(1, sizeof(*ocsp))) == NULL) {
218 		free(ioe);
219 		return (-1);
220 	}
221 
222 	ocsp->ocsp_env = env;
223 	ocsp->ocsp_sh = sh;
224 	ocsp->ocsp_type = type;
225 
226 	if ((rawcert = BIO_new_mem_buf(data, len)) == NULL ||
227 	    (cert = d2i_X509_bio(rawcert, NULL)) == NULL ||
228 	    (bissuer = BIO_new_file(IKED_OCSP_ISSUER, "r")) == NULL ||
229 	    (issuer = PEM_read_bio_X509(bissuer, NULL, NULL, NULL)) == NULL ||
230 	    (ocsp->ocsp_cbio = BIO_new(BIO_s_socket())) == NULL ||
231 	    (ocsp->ocsp_req = OCSP_REQUEST_new()) == NULL ||
232 	    !(ocsp->ocsp_id = OCSP_cert_to_id(NULL, cert, issuer)) ||
233 	    !OCSP_request_add0_id(ocsp->ocsp_req, ocsp->ocsp_id))
234 		goto err;
235 
236 	BIO_free(rawcert);
237 	BIO_free(bissuer);
238 	X509_free(cert);
239 	X509_free(issuer);
240 
241 	ioe->ioe_ocsp = ocsp;
242 	TAILQ_INSERT_TAIL(&env->sc_ocsp, ioe, ioe_entry);
243 
244 	/* request connection to ocsp-responder */
245 	proc_compose_imsg(&env->sc_ps, PROC_PARENT, -1,
246 	    IMSG_OCSP_FD, -1, 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_imsg(&env->sc_ps, PROC_IKEV2, -1,
508 	    cmd, -1, iov, iovcnt);
509 
510 	ocsp_free(ocsp);
511 	return (ret);
512 }
513