GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/iked/ocsp.c Lines: 0 245 0.0 %
Date: 2017-11-07 Branches: 0 154 0.0 %

Line Branch Exec Source
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
}