1 /*
2  * Copyright (C) 2013-2018 Nikos Mavrogiannopoulos
3  * Copyright (C) 2015-2016 Red Hat, Inc.
4  *
5  * This file is part of ocserv.
6  *
7  * ocserv is free software: you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * ocserv is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #include <config.h>
22 
23 #include <gnutls/gnutls.h>
24 #include <gnutls/crypto.h>
25 #include <gnutls/pkcs11.h>
26 #include <gnutls/abstract.h>
27 #include <errno.h>
28 #include <stdlib.h>
29 #include <stdarg.h>
30 #ifndef _GNU_SOURCE
31 # define _GNU_SOURCE /* for vasprintf() */
32 #endif
33 #include <stdio.h>
34 #include <string.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38 #include <unistd.h>
39 #include <limits.h>
40 #include <tlslib.h>
41 #include <ccan/hash/hash.h>
42 #include <vpn.h>
43 #include <main.h>
44 #include <worker.h>
45 #include <common.h>
46 #include <sys/un.h>
47 #include <sys/uio.h>
48 #include <sys/types.h>
49 #include <sys/socket.h>
50 #include <netinet/in.h>
51 #include <netinet/tcp.h>
52 #include <c-ctype.h>
53 
54 static void tls_reload_ocsp(main_server_st* s, struct vhost_cfg_st *vhost);
55 
cstp_cork(worker_st * ws)56 void cstp_cork(worker_st *ws)
57 {
58 	if (ws->session) {
59 		gnutls_record_cork(ws->session);
60 	} else {
61 		int state = 1, ret = 0;
62 #if defined(__linux__)
63 		ret = setsockopt(ws->conn_fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
64 #elif defined(TCP_NOPUSH)
65 		ret = setsockopt(ws->conn_fd, IPPROTO_TCP, TCP_NOPUSH, &state, sizeof(state));
66 #endif
67 		if (ret == -1) {
68 			oclog(ws, LOG_ERR, "setsockopt(IPPROTO_TCP(TCP_CORK) failed");
69 		}
70 	}
71 }
72 
cstp_uncork(worker_st * ws)73 int cstp_uncork(worker_st *ws)
74 {
75 	if (ws->session) {
76 		return gnutls_record_uncork(ws->session, GNUTLS_RECORD_WAIT);
77 	} else {
78 		int state = 0, ret = 0;
79 #if defined(__linux__)
80 		ret = setsockopt(ws->conn_fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
81 #elif defined(TCP_NOPUSH)
82 		ret = setsockopt(ws->conn_fd, IPPROTO_TCP, TCP_NOPUSH, &state, sizeof(state));
83 #endif
84 		if (ret == -1) {
85 			oclog(ws, LOG_ERR, "setsockopt(IPPROTO_TCP(TCP_UNCORK) failed");
86 		}
87 		return 0;
88 	}
89 }
90 
91 
cstp_send(worker_st * ws,const void * data,size_t data_size)92 ssize_t cstp_send(worker_st *ws, const void *data,
93 			size_t data_size)
94 {
95 	int ret;
96 	int left = data_size;
97 	const uint8_t* p = data;
98 
99 	if (ws->session != NULL) {
100 		while(left > 0) {
101 			ret = gnutls_record_send(ws->session, p, data_size);
102 			if (ret < 0) {
103 				if (ret != GNUTLS_E_AGAIN && ret != GNUTLS_E_INTERRUPTED) {
104 					return ret;
105 				} else {
106 					/* do not cause mayhem */
107 					ms_sleep(20);
108 				}
109 			}
110 
111 			if (ret > 0) {
112 				left -= ret;
113 				p += ret;
114 			}
115 		}
116 		return data_size;
117 	} else {
118 		return force_write(ws->conn_fd, data, data_size);
119 	}
120 }
121 
cstp_send_file(worker_st * ws,const char * file)122 ssize_t cstp_send_file(worker_st *ws, const char *file)
123 {
124 	int fd;
125 	char buf[1024];
126 	int counter = 100; /* allow 10 seconds for a full packet */
127 	ssize_t len, total = 0;
128 	int ret;
129 
130 	fd = open(file, O_RDONLY);
131 	if (fd == -1)
132 		return GNUTLS_E_FILE_ERROR;
133 
134 	while (	(len = read( fd, buf, sizeof(buf))) > 0 ||
135 		(len == -1 && counter > 0 && (errno == EINTR || errno == EAGAIN))) {
136 
137 		if (len == -1) {
138 			counter--;
139 			ms_sleep(100);
140 			continue;
141 		}
142 
143 		ret = cstp_send(ws, buf, len);
144 		CSTP_FATAL_ERR(ws, ret);
145 
146 		total += ret;
147 	}
148 
149 	close(fd);
150 
151 	return total;
152 }
153 
154 static
recv_remaining(int fd,uint8_t * p,int left)155 int recv_remaining(int fd, uint8_t *p, int left)
156 {
157 	int counter = 100; /* allow 10 seconds for a full packet */
158 	unsigned total = 0;
159 	int ret;
160 
161 	while(left > 0) {
162 		ret = recv(fd, p, left, 0);
163 		if (ret == -1 && counter > 0 && (errno == EINTR || errno == EAGAIN)) {
164 			counter--;
165 			ms_sleep(100);
166 			continue;
167 		}
168 		if (ret == 0)
169 			ret = GNUTLS_E_PREMATURE_TERMINATION;
170 		if (ret < 0)
171 			break;
172 
173 		left -= ret;
174 		p += ret;
175 		total += ret;
176 	}
177 
178 	return total;
179 }
180 
181 /* Receives CSTP packet, after the channel is established.
182  * It makes sure that CSTP packet boundaries are respected in
183  * case we do not read over TLS - e.g., when TLS is done by
184  * a proxy. */
_cstp_recv_packet(worker_st * ws,void * data,size_t data_size)185 static ssize_t _cstp_recv_packet(worker_st *ws, void *data, size_t data_size)
186 {
187 	int ret;
188 
189 	/* socket is in non-blocking mode already */
190 
191 	if (ws->session != NULL) {
192 		return gnutls_record_recv(ws->session, data, data_size);
193 	} else {
194 		/* It can happen in UNIX sockets case that we receive an
195 		 * incomplete CSTP packet. In that case we attempt to read
196 		 * a full CSTP packet.
197 		 */
198 		unsigned pktlen;
199 		uint8_t *p = data;
200 
201 		/* read the header */
202 		ret = recv_remaining(ws->conn_fd, p, 8);
203 		if (ret <= 0)
204 			return ret;
205 
206 		/* get the actual length from headers */
207 		pktlen = (p[4] << 8) + p[5];
208 		if (pktlen+8 > data_size) {
209 			oclog(ws, LOG_ERR, "error in CSTP packet length");
210 			return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
211 		}
212 
213 		if (pktlen > 0) {
214 			ret = recv_remaining(ws->conn_fd, p+8, pktlen);
215 			if (ret <= 0)
216 				return ret;
217 		}
218 
219 		return 8+pktlen;
220 	}
221 }
222 
cstp_recv_packet(worker_st * ws,gnutls_datum_t * data,void ** p)223 ssize_t cstp_recv_packet(worker_st *ws, gnutls_datum_t *data, void **p)
224 {
225 	int ret;
226 #ifdef ZERO_COPY
227 	gnutls_packet_t packet = NULL;
228 
229 	if (ws->session != NULL) {
230 		ret = gnutls_record_recv_packet(ws->session, &packet);
231 		if (ret > 0) {
232 			*p = packet;
233 			gnutls_packet_get(packet, data, NULL);
234 		}
235 	} else {
236 		ret = _cstp_recv_packet(ws, ws->buffer, ws->buffer_size);
237 		data->data = ws->buffer;
238 		data->size = ret;
239 	}
240 
241 #else
242 	ret = _cstp_recv_packet(ws, ws->buffer, ws->buffer_size);
243 	data->data = ws->buffer;
244 	data->size = ret;
245 #endif
246 	return ret;
247 }
248 
249 /* Restores gnutls_record_recv() on EAGAIN */
cstp_recv(worker_st * ws,void * data,size_t data_size)250 ssize_t cstp_recv(worker_st *ws, void *data, size_t data_size)
251 {
252 	int ret;
253 	int counter = 5;
254 
255 	if (ws->session != NULL) {
256 		do {
257 			ret = gnutls_record_recv(ws->session, data, data_size);
258 			if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) {
259 				counter--;
260 				ms_sleep(20);
261 			}
262 		} while ((ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) && counter > 0);
263 	} else {
264 		do {
265 			ret = recv(ws->conn_fd, data, data_size, 0);
266 			if (ret == -1 && (errno == EAGAIN || errno == EINTR)) {
267 				counter--;
268 				ms_sleep(20);
269 			}
270 		} while(ret == -1 && (errno == EINTR || errno == EAGAIN) && counter > 0);
271 	}
272 
273 	return ret;
274 }
275 
276 
277 /* Typically used in a resumed session. It will return
278  * true if a certificate has been used.
279  */
tls_has_session_cert(struct worker_st * ws)280 unsigned tls_has_session_cert(struct worker_st * ws)
281 {
282 	unsigned int list_size = 0;
283 	const gnutls_datum_t * certs;
284 
285 	if (ws->session == NULL)
286 		return 0;
287 
288 	if (ws->cert_auth_ok)
289 		return 1;
290 
291 	if (WSCONFIG(ws)->cisco_client_compat == 0) {
292 		return 0;
293 	}
294 
295 	certs = gnutls_certificate_get_peers(ws->session, &list_size);
296 	if (certs != NULL)
297 		return 1;
298 
299 	return 0;
300 }
301 
302 int __attribute__ ((format(printf, 2, 3)))
cstp_printf(worker_st * ws,const char * fmt,...)303     cstp_printf(worker_st *ws, const char *fmt, ...)
304 {
305 	char *buf;
306 	va_list args;
307 	int ret, s;
308 
309 	va_start(args, fmt);
310 	s = vasprintf(&buf, fmt, args);
311 	va_end(args);
312 
313 	if (s == -1)
314 		return -1;
315 
316 	ret = cstp_send(ws, buf, s);
317 	free(buf);
318 	return ret;
319 }
320 
cstp_close(worker_st * ws)321 void cstp_close(worker_st *ws)
322 {
323 	if (ws->session) {
324 		gnutls_bye(ws->session, GNUTLS_SHUT_WR);
325 		gnutls_deinit(ws->session);
326 	} else {
327 		close(ws->conn_fd);
328 	}
329 }
330 
cstp_fatal_close(worker_st * ws,gnutls_alert_description_t a)331 void cstp_fatal_close(worker_st *ws,
332 			    gnutls_alert_description_t a)
333 {
334 	if (ws->session) {
335 		gnutls_alert_send(ws->session, GNUTLS_AL_FATAL, a);
336 		gnutls_deinit(ws->session);
337 	} else {
338 		close(ws->conn_fd);
339 	}
340 }
341 
dtls_recv_packet(struct dtls_st * dtls,gnutls_datum_t * data,void ** p)342 ssize_t dtls_recv_packet(struct dtls_st *dtls, gnutls_datum_t *data, void **p)
343 {
344 	int ret;
345 #ifdef ZERO_COPY
346 	gnutls_packet_t packet = NULL;
347 
348 	ret = gnutls_record_recv_packet(dtls->dtls_session, &packet);
349 	if (ret > 0) {
350 		gnutls_packet_get(packet, data, NULL);
351 		*p = packet;
352 	} else {
353 		data->size = 0;
354 	}
355 #else
356 	ret =
357 	    gnutls_record_recv(dtls->dtls_session, ws->buffer, ws->buffer_size);
358 	data->data = ws->buffer;
359 	data->size = ret;
360 #endif
361 
362 	return ret;
363 }
364 
dtls_send(struct dtls_st * dtls,const void * data,size_t data_size)365 ssize_t dtls_send(struct dtls_st *dtls, const void *data,
366 			size_t data_size)
367 {
368 	int ret;
369 	int left = data_size;
370 	const uint8_t* p = data;
371 
372 	while(left > 0) {
373 		ret = gnutls_record_send(dtls->dtls_session, p, data_size);
374 		if (ret < 0) {
375 			if (ret != GNUTLS_E_AGAIN && ret != GNUTLS_E_INTERRUPTED) {
376 				return ret;
377 			} else {
378 				/* do not cause mayhem */
379 				ms_sleep(20);
380 			}
381 		}
382 
383 		if (ret > 0) {
384 			left -= ret;
385 			p += ret;
386 		}
387 	}
388 
389 	return data_size;
390 }
391 
dtls_close(struct dtls_st * dtls)392 void dtls_close(struct dtls_st *dtls)
393 {
394 	gnutls_bye(dtls->dtls_session, GNUTLS_SHUT_WR);
395 	gnutls_deinit(dtls->dtls_session);
396 }
397 
rehash(const void * _e,void * unused)398 static size_t rehash(const void *_e, void *unused)
399 {
400 	const tls_cache_st *e = _e;
401 
402 	return hash_any(e->session_id, e->session_id_size, 0);
403 }
404 
tls_cache_init(void * pool,tls_sess_db_st * db)405 void tls_cache_init(void *pool, tls_sess_db_st* db)
406 {
407 	db->ht = talloc(pool, struct htable);
408 	if (db->ht == NULL)
409 		exit(1);
410 
411 	htable_init(db->ht, rehash, NULL);
412 	db->entries = 0;
413 }
414 
tls_cache_deinit(tls_sess_db_st * db)415 void tls_cache_deinit(tls_sess_db_st* db)
416 {
417 	tls_cache_st* cache;
418 	struct htable_iter iter;
419 
420 	cache = htable_first(db->ht, &iter);
421 	while(cache != NULL) {
422 		if (cache->session_data_size > 0) {
423 			safe_memset(cache->session_data, 0, cache->session_data_size);
424 			cache->session_data_size = 0;
425 			cache->session_id_size = 0;
426 		}
427 		talloc_free(cache);
428 
429 		cache = htable_next(db->ht, &iter);
430         }
431         htable_clear(db->ht);
432 	db->entries = 0;
433 	talloc_free(db->ht);
434 
435         return;
436 }
437 
tls_log_func(int level,const char * str)438 static void tls_log_func(int level, const char *str)
439 {
440 	syslog(LOG_DEBUG, "TLS[<%d>]: %s", level, str);
441 }
442 
tls_audit_log_func(gnutls_session_t session,const char * str)443 static void tls_audit_log_func(gnutls_session_t session, const char *str)
444 {
445 	worker_st * ws;
446 
447 	(void)(ws);
448 
449 	if (session == NULL)
450 		syslog(LOG_NOTICE, "warning: %s", str);
451 	else {
452 		ws = gnutls_session_get_ptr(session);
453 
454 		oclog(ws, LOG_NOTICE, "warning: %s", str);
455 	}
456 }
457 
verify_certificate_cb(gnutls_session_t session)458 static int verify_certificate_cb(gnutls_session_t session)
459 {
460 	unsigned int status;
461 	int ret;
462 	worker_st * ws;
463 
464 	ws = gnutls_session_get_ptr(session);
465 	if (ws == NULL) {
466 		syslog(LOG_ERR, "%s:%d: could not obtain worker state", __func__, __LINE__);
467 		return -1;
468 	}
469 
470 	if ((session == DTLS_ACTIVE(ws)->dtls_session) ||
471 		(session == DTLS_INACTIVE(ws)->dtls_session)) {
472 		oclog(ws, LOG_ERR, "unexpected issue; client shouldn't have offered a certificate in DTLS");
473 		return GNUTLS_E_CERTIFICATE_ERROR;
474 	}
475 
476 	ws->cert_auth_ok = 0;
477 
478 	/* now verify whether the username in the certificate matches the username of the session */
479 	if (ws->cert_username[0] != 0) {
480 		char prev_username[MAX_USERNAME_SIZE];
481 		const gnutls_datum_t *cert;
482 		unsigned cert_size;
483 
484 		cert = gnutls_certificate_get_peers(session, &cert_size);
485 		if (cert != NULL) { /* it's ok for the user not to send any certificate on renegotiation */
486 			memcpy(prev_username, ws->cert_username, MAX_USERNAME_SIZE);
487 			ret = get_cert_names(ws, &cert[0]);
488 			if (ret < 0) {
489 				oclog(ws, LOG_ERR, "cannot parse certificate");
490 				return GNUTLS_E_CERTIFICATE_ERROR;
491 			}
492 
493 			if (strcmp(prev_username, ws->cert_username) != 0) {
494 				oclog(ws, LOG_ERR, "user switched during renegotiation!");
495 				return GNUTLS_E_CERTIFICATE_ERROR;
496 			}
497 		}
498 	}
499 
500 	/* This verification function uses the trusted CAs in the credentials
501 	 * structure. So you must have installed one or more CA certificates.
502 	 */
503 	ret = gnutls_certificate_verify_peers2(session, &status);
504 	if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND) {
505 		oclog(ws, LOG_ERR, "no certificate was found");
506 		goto no_cert;
507 	}
508 	if (ret < 0) {
509 		oclog(ws, LOG_ERR, "error verifying client certificate: %s", gnutls_strerror(ret));
510 		goto fail;
511 	}
512 
513 	if (status != 0) {
514 		gnutls_datum_t out;
515 		int type = gnutls_certificate_type_get(session);
516 
517 		ret =
518 		    gnutls_certificate_verification_status_print(status, type,
519 							 &out, 0);
520 		if (ret < 0)
521 			goto fail;
522 
523 		oclog(ws, LOG_INFO, "client certificate verification failed: %s", out.data);
524 
525 		gnutls_free(out.data);
526 
527 		goto fail;
528 	} else {
529 		ws->cert_auth_ok = 1;
530 		oclog(ws, LOG_INFO, "client certificate verification succeeded");
531 	}
532 
533 	/* notify gnutls to continue handshake normally */
534 	return 0;
535 no_cert:
536 	if (WSCONFIG(ws)->cisco_client_compat != 0 || WSCONFIG(ws)->cert_req != GNUTLS_CERT_REQUIRE)
537 		return 0;
538 fail:
539 	return GNUTLS_E_CERTIFICATE_ERROR;
540 }
541 
tls_global_init(void)542 void tls_global_init(void)
543 {
544 	gnutls_global_set_audit_log_function(tls_audit_log_func);
545 }
546 
tls_vhost_init(struct vhost_cfg_st * vhost)547 void tls_vhost_init(struct vhost_cfg_st *vhost)
548 {
549 	int ret;
550 
551 	ret = gnutls_psk_allocate_server_credentials(&vhost->creds.pskcred);
552 	GNUTLS_FATAL_ERR(ret);
553 }
554 
tls_vhost_deinit(struct vhost_cfg_st * vhost)555 void tls_vhost_deinit(struct vhost_cfg_st *vhost)
556 {
557 #ifndef GNUTLS_BROKEN_CERTIFICATE_SET_KEY
558 	if (vhost->creds.xcred != NULL)
559 		gnutls_certificate_free_credentials(vhost->creds.xcred);
560 #endif
561 
562 	if (vhost->creds.pskcred != NULL)
563 		gnutls_psk_free_server_credentials(vhost->creds.pskcred);
564 	if (vhost->creds.cprio != NULL)
565 		gnutls_priority_deinit(vhost->creds.cprio);
566 
567 	gnutls_free(vhost->creds.ocsp_response.data);
568 	vhost->creds.ocsp_response.data = NULL;
569 	vhost->creds.xcred = NULL;
570 	vhost->creds.pskcred = NULL;
571 	vhost->creds.cprio = NULL;
572 
573 	return;
574 }
575 
576 /* Checks, if there is a single certificate specified, whether it
577  * is compatible with all ciphersuites */
certificate_check(main_server_st * s,const char * vhostname,gnutls_pcert_st * pcert)578 static void certificate_check(main_server_st *s, const char *vhostname, gnutls_pcert_st *pcert)
579 {
580 	gnutls_datum_t data = {NULL, 0};
581 	gnutls_x509_crt_t crt = NULL;
582 	int ret;
583 	unsigned usage;
584 	gnutls_datum_t dn = {NULL, 0};
585 	const char *cert_name = "unnamed";
586 	time_t t;
587 
588 	(void)cert_name;
589 
590 	ret = gnutls_x509_crt_init(&crt);
591 	GNUTLS_FATAL_ERR(ret);
592 
593 	ret = gnutls_x509_crt_import(crt, &pcert->cert, GNUTLS_X509_FMT_DER);
594 	GNUTLS_FATAL_ERR(ret);
595 
596 	ret = gnutls_x509_crt_get_pk_algorithm(crt, NULL);
597 	if (ret != GNUTLS_PK_RSA)
598 		goto cleanup;
599 
600 #if GNUTLS_VERSION_NUMBER >= 0x030507
601 	ret = gnutls_x509_crt_get_dn3(crt, &dn, 0);
602 #else
603 	ret = gnutls_x509_crt_get_dn2(crt, &dn);
604 #endif
605 	if (ret >= 0) {
606 		cert_name = (char*)dn.data;
607 	}
608 
609 	ret = gnutls_x509_crt_get_key_usage(crt, &usage, NULL);
610 	if (ret >= 0) {
611 		if (!(usage & GNUTLS_KEY_KEY_ENCIPHERMENT)) {
612 			mslog(s, NULL, LOG_WARNING, "%s certificate key usage prevents key encipherment; unable to support the RSA ciphersuites; "
613 				"if that is not intentional, regenerate the server certificate with the key usage flag 'key encipherment' set.",
614 				cert_name);
615 		}
616 	}
617 
618 	if (vhostname) {
619 		/* check whether the hostname matches our vhost */
620 		if (!gnutls_x509_crt_check_hostname(crt, vhostname)) {
621 			mslog(s, NULL, LOG_WARNING, "The %s certificate's name doesn't match for vhost %s",
622 			      cert_name, vhostname);
623 		}
624 	}
625 
626 	t = gnutls_x509_crt_get_expiration_time(crt);
627 	if (t < time(0)) {
628 		mslog(s, NULL, LOG_WARNING, "The %s certificate set is expired!", cert_name);
629 	}
630 
631 	t = gnutls_x509_crt_get_activation_time(crt);
632 	if (t > time(0)) {
633 		mslog(s, NULL, LOG_WARNING, "The %s certificate set is not yet active!", cert_name);
634 	}
635 
636 cleanup:
637 	if (crt != NULL)
638 		gnutls_x509_crt_deinit(crt);
639 	gnutls_free(data.data);
640 	gnutls_free(dn.data);
641 	return;
642 }
643 
set_dh_params(main_server_st * s,struct vhost_cfg_st * vhost)644 static void set_dh_params(main_server_st* s, struct vhost_cfg_st *vhost)
645 {
646 	gnutls_datum_t data;
647 	int ret;
648 
649 	if (vhost->perm_config.dh_params_file != NULL) {
650 		ret = gnutls_dh_params_init (&vhost->creds.dh_params);
651 		GNUTLS_FATAL_ERR(ret);
652 
653 		ret = gnutls_load_file(vhost->perm_config.dh_params_file, &data);
654 		GNUTLS_FATAL_ERR(ret);
655 
656 		ret = gnutls_dh_params_import_pkcs3(vhost->creds.dh_params, &data, GNUTLS_X509_FMT_PEM);
657 		GNUTLS_FATAL_ERR(ret);
658 
659 		gnutls_free(data.data);
660 
661 		gnutls_certificate_set_dh_params(vhost->creds.xcred, vhost->creds.dh_params);
662 	} else {
663 #if GNUTLS_VERSION_NUMBER >= 0x030506
664 		/* use pre-generated parameters */
665 		gnutls_certificate_set_known_dh_params(vhost->creds.xcred, GNUTLS_SEC_PARAM_MEDIUM);
666 #endif
667 	}
668 }
669 
670 #ifndef UNDER_TEST
671 struct key_cb_data {
672 	unsigned pk;
673 	unsigned bits;
674 	unsigned idx; /* the index of the key */
675 	struct sockaddr_un sa;
676 	unsigned sa_len;
677 	const char *vhost;
678 };
679 
680 static
key_cb_common_func(gnutls_privkey_t key,void * userdata,const gnutls_datum_t * raw_data,gnutls_datum_t * output,unsigned sigalgo,unsigned type)681 int key_cb_common_func (gnutls_privkey_t key, void* userdata, const gnutls_datum_t * raw_data,
682 	gnutls_datum_t * output, unsigned sigalgo, unsigned type)
683 {
684 	struct key_cb_data* cdata = userdata;
685 	int sd = -1, ret, e;
686 	SecOpMsg msg = SEC_OP_MSG__INIT;
687 	SecOpMsg *reply = NULL;
688 	PROTOBUF_ALLOCATOR(pa, userdata);
689 
690 	output->data = NULL;
691 
692 	sd = socket(AF_UNIX, SOCK_STREAM, 0);
693 	if (sd == -1) {
694 		e = errno;
695 		syslog(LOG_ERR, "error opening socket: %s", strerror(e));
696 		return GNUTLS_E_INTERNAL_ERROR;
697 	}
698 
699 	ret = connect(sd, (struct sockaddr *)&cdata->sa, cdata->sa_len);
700 	if (ret == -1) {
701 		e = errno;
702 		syslog(LOG_ERR, "error connecting to sec-mod socket '%s': %s",
703 			cdata->sa.sun_path, strerror(e));
704 		goto error;
705 	}
706 
707 	msg.has_key_idx = 1;
708 	msg.key_idx = cdata->idx;
709 	msg.sig = sigalgo;
710 	msg.data.data = raw_data->data;
711 	msg.data.len = raw_data->size;
712 	msg.vhost = (char*)cdata->vhost;
713 
714 	ret = send_msg(userdata, sd, type, &msg,
715 			(pack_size_func)sec_op_msg__get_packed_size,
716 			(pack_func)sec_op_msg__pack);
717 	if (ret < 0) {
718 		goto error;
719 	}
720 
721 	ret = recv_msg(userdata, sd, type, (void*)&reply,
722 		       (unpack_func)sec_op_msg__unpack,
723 		       DEFAULT_SOCKET_TIMEOUT);
724 	if (ret < 0) {
725 		e = errno;
726 		syslog(LOG_ERR, "error receiving sec-mod reply: %s",
727 				strerror(e));
728 		goto error;
729 	}
730 	close(sd);
731 	sd = -1;
732 
733 	output->size = reply->data.len;
734 	output->data = gnutls_malloc(reply->data.len);
735 	if (output->data == NULL) {
736 		syslog(LOG_ERR, "error allocating memory");
737 		goto error;
738 	}
739 
740 	memcpy(output->data, reply->data.data, reply->data.len);
741 
742 	sec_op_msg__free_unpacked(reply, &pa);
743 	return 0;
744 
745 error:
746 	if (sd != -1)
747 		close(sd);
748 	gnutls_free(output->data);
749 	if (reply != NULL)
750 		sec_op_msg__free_unpacked(reply, &pa);
751 	return GNUTLS_E_INTERNAL_ERROR;
752 }
753 
754 #if GNUTLS_VERSION_NUMBER >= 0x030600
key_cb_info_func(gnutls_privkey_t key,unsigned int flags,void * userdata)755 static int key_cb_info_func(gnutls_privkey_t key, unsigned int flags, void *userdata)
756 {
757 	struct key_cb_data *p = userdata;
758 
759 	if (flags & GNUTLS_PRIVKEY_INFO_PK_ALGO) {
760 		return p->pk;
761 #if GNUTLS_VERSION_NUMBER >= 0x030603
762 	} else if (flags & GNUTLS_PRIVKEY_INFO_PK_ALGO_BITS) {
763 		return p->bits;
764 #endif
765 	} else if (flags & GNUTLS_PRIVKEY_INFO_HAVE_SIGN_ALGO) {
766 		unsigned sig = GNUTLS_FLAGS_TO_SIGN_ALGO(flags);
767 
768 		if (gnutls_sign_supports_pk_algorithm(sig, p->pk))
769 			return 1;
770 
771 		return 0;
772 	}
773 
774 	return -1;
775 }
776 
777 static
key_cb_sign_data_func(gnutls_privkey_t key,gnutls_sign_algorithm_t sig,void * userdata,unsigned int flags,const gnutls_datum_t * data,gnutls_datum_t * signature)778 int key_cb_sign_data_func (gnutls_privkey_t key, gnutls_sign_algorithm_t sig,
779 			   void* userdata, unsigned int flags, const gnutls_datum_t *data,
780 			   gnutls_datum_t *signature)
781 {
782 	return key_cb_common_func(key, userdata, data, signature, sig, CMD_SEC_SIGN_DATA);
783 }
784 
785 static
key_cb_sign_hash_func(gnutls_privkey_t key,gnutls_sign_algorithm_t sig,void * userdata,unsigned int flags,const gnutls_datum_t * data,gnutls_datum_t * signature)786 int key_cb_sign_hash_func (gnutls_privkey_t key, gnutls_sign_algorithm_t sig,
787 			   void* userdata, unsigned int flags, const gnutls_datum_t *data,
788 			   gnutls_datum_t *signature)
789 {
790 	if (sig == GNUTLS_SIGN_RSA_RAW)
791 		return key_cb_common_func(key, userdata, data, signature, 0, CMD_SEC_SIGN);
792 
793 	return key_cb_common_func(key, userdata, data, signature, sig, CMD_SEC_SIGN_HASH);
794 }
795 
796 #else
797 static
key_cb_sign_func(gnutls_privkey_t key,void * userdata,const gnutls_datum_t * raw_data,gnutls_datum_t * signature)798 int key_cb_sign_func (gnutls_privkey_t key, void* userdata, const gnutls_datum_t * raw_data,
799 	gnutls_datum_t * signature)
800 {
801 	return key_cb_common_func(key, userdata, raw_data, signature, 0, CMD_SEC_SIGN);
802 }
803 #endif
804 
key_cb_decrypt_func(gnutls_privkey_t key,void * userdata,const gnutls_datum_t * ciphertext,gnutls_datum_t * plaintext)805 static int key_cb_decrypt_func(gnutls_privkey_t key, void* userdata, const gnutls_datum_t * ciphertext,
806 	gnutls_datum_t * plaintext)
807 {
808 	return key_cb_common_func(key, userdata, ciphertext, plaintext, 0, CMD_SEC_DECRYPT);
809 }
810 
key_cb_deinit_func(gnutls_privkey_t key,void * userdata)811 static void key_cb_deinit_func(gnutls_privkey_t key, void* userdata)
812 {
813 	talloc_free(userdata);
814 }
815 
816 static
load_cert_files(main_server_st * s,struct vhost_cfg_st * vhost)817 int load_cert_files(main_server_st *s, struct vhost_cfg_st *vhost)
818 {
819 	int ret;
820 	gnutls_pcert_st *pcert_list;
821 	unsigned pcert_list_size, i;
822 	gnutls_privkey_t key;
823 	gnutls_datum_t data;
824 	struct key_cb_data *cdata;
825 	unsigned flags;
826 
827 	for (i=0;i<vhost->perm_config.key_size;i++) {
828 		/* load the certificate */
829 
830 		if (gnutls_url_is_supported(vhost->perm_config.cert[i]) != 0) {
831 			mslog(s, NULL, LOG_ERR, "Loading a certificate from '%s' is unsupported", vhost->perm_config.cert[i]);
832 			return -1;
833 		} else {
834 			ret = gnutls_load_file(vhost->perm_config.cert[i], &data);
835 			if (ret < 0) {
836 				mslog(s, NULL, LOG_ERR, "error loading file[%d] '%s'", i, vhost->perm_config.cert[i]);
837 				return -1;
838 			}
839 
840 			pcert_list_size = 8;
841 			pcert_list = talloc_size(vhost->pool, sizeof(pcert_list[0])*pcert_list_size);
842 			if (pcert_list == NULL) {
843 				mslog(s, NULL, LOG_ERR, "error allocating memory");
844 				return -1;
845 			}
846 
847 			flags = GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED|GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED;
848 #if GNUTLS_VERSION_NUMBER > 0x030409
849 			flags |= GNUTLS_X509_CRT_LIST_SORT;
850 #endif
851 
852 			ret = gnutls_pcert_list_import_x509_raw(pcert_list, &pcert_list_size,
853 								&data, GNUTLS_X509_FMT_PEM, flags);
854 			GNUTLS_FATAL_ERR(ret);
855 
856 			gnutls_free(data.data);
857 		}
858 
859 		/* sanity checks on the loaded certificate and key */
860 		certificate_check(s, vhost->name, &pcert_list[0]);
861 
862 		ret = gnutls_privkey_init(&key);
863 		GNUTLS_FATAL_ERR(ret);
864 
865 		/* use use the vhost/config pool rather than main, to allow usage of the credentials
866 		 * after freeing s.
867 		 */
868 		cdata = talloc_zero(vhost->pool, struct key_cb_data);
869 		if (cdata == NULL) {
870 			mslog(s, NULL, LOG_ERR, "error allocating memory");
871 			return -1;
872 		}
873 
874 		cdata->idx = i;
875 		cdata->vhost = vhost->name;
876 
877 		/* when called here configuration may not be populated, so avoid using it */
878 		cdata->sa.sun_family = AF_UNIX;
879 		strlcpy(cdata->sa.sun_path, secmod_socket_file_name(&vhost->perm_config), sizeof(cdata->sa.sun_path));
880 		cdata->sa_len = SUN_LEN(&cdata->sa);
881 
882 
883 		/* load the private key */
884 
885 #if GNUTLS_VERSION_NUMBER >= 0x030600
886 		cdata->pk = gnutls_pubkey_get_pk_algorithm(pcert_list[0].pubkey, &cdata->bits);
887 		ret = gnutls_privkey_import_ext4(key, cdata, key_cb_sign_data_func,
888 			key_cb_sign_hash_func,key_cb_decrypt_func,
889 			key_cb_deinit_func, key_cb_info_func,
890 			GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
891 #else
892 		ret = gnutls_privkey_import_ext2(key, gnutls_pubkey_get_pk_algorithm(pcert_list[0].pubkey, NULL),
893 			cdata, key_cb_sign_func, key_cb_decrypt_func,
894 			key_cb_deinit_func, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
895 #endif
896 		GNUTLS_FATAL_ERR(ret);
897 
898 		ret = gnutls_certificate_set_key(vhost->creds.xcred, NULL, 0, pcert_list,
899 				pcert_list_size, key);
900 		GNUTLS_FATAL_ERR(ret);
901 	}
902 
903 	return 0;
904 }
905 
need_file_reload(const char * file,time_t last_access)906 unsigned need_file_reload(const char *file, time_t last_access)
907 {
908 	struct stat st;
909 	int ret, e;
910 
911 	if (file == NULL || file[0] == 0)
912 		return 0;
913 
914 	if (last_access == 0)
915 		return 1;
916 
917 	ret = stat(file, &st);
918 	if (ret == -1) {
919 		e = errno;
920 		syslog(LOG_INFO, "file %s (to be reloaded) was not found: %s",
921 		      file, strerror(e));
922 		return 0;
923 	}
924 
925 	/* reload only if it is a newer file */
926 	if (st.st_mtime > last_access)
927 		return 1;
928 	return 0;
929 }
930 
931 /* reload key files etc.
932  * @s may be %NULL, and should be used for mslog() purposes only.
933  */
tls_load_files(main_server_st * s,struct vhost_cfg_st * vhost)934 void tls_load_files(main_server_st *s, struct vhost_cfg_st *vhost)
935 {
936 	int ret;
937 	unsigned i;
938 	unsigned need_reload = 0;
939 
940 	if (vhost->params_last_access != 0) {
941 		for (i=0;i<vhost->perm_config.key_size;i++) {
942 			if (need_file_reload(vhost->perm_config.cert[i], vhost->params_last_access) != 0) {
943 				need_reload = 1;
944 				break;
945 			}
946 		}
947 
948 		if (need_file_reload(vhost->perm_config.ca, vhost->params_last_access) ||
949 		    need_file_reload(vhost->perm_config.config->ocsp_response, vhost->params_last_access) ||
950 		    need_file_reload(vhost->perm_config.dh_params_file, vhost->params_last_access)) {
951 			need_reload = 1;
952 		}
953 
954 		if (need_reload == 0)
955 			return;
956 
957 		mslog(s, NULL, LOG_INFO, "reloading server certificates");
958 	}
959 
960 	if (vhost->perm_config.debug >= DEBUG_TLS) {
961 		gnutls_global_set_log_function(tls_log_func);
962 		gnutls_global_set_log_level(9);
963 	}
964 
965 	vhost->params_last_access = time(0);
966 
967 #ifndef GNUTLS_BROKEN_CERTIFICATE_SET_KEY
968 	if (vhost->creds.xcred != NULL)
969 		gnutls_certificate_free_credentials(vhost->creds.xcred);
970 #endif
971 
972 	ret = gnutls_certificate_allocate_credentials(&vhost->creds.xcred);
973 	GNUTLS_FATAL_ERR(ret);
974 
975 	set_dh_params(s, vhost);
976 
977 	if (vhost->perm_config.key_size == 0 || vhost->perm_config.cert_size == 0) {
978 		mslog(s, NULL, LOG_ERR, "no certificate or key files were specified");
979 		exit(1);
980 	}
981 
982 	/* on reload reduce any checks done */
983 	if (need_reload) {
984 #if GNUTLS_VERSION_NUMBER >= 0x030407
985 		gnutls_certificate_set_flags(vhost->creds.xcred, GNUTLS_CERTIFICATE_SKIP_KEY_CERT_MATCH);
986 #endif
987 	}
988 
989 	ret = load_cert_files(s, vhost);
990 	if (ret < 0) {
991 		mslog(s, NULL, LOG_ERR, "error loading the certificate or key file");
992 		exit(1);
993 	}
994 
995 	if (vhost->perm_config.config->cert_req != GNUTLS_CERT_IGNORE) {
996 		if (vhost->perm_config.ca != NULL) {
997 			ret =
998 			    gnutls_certificate_set_x509_trust_file(vhost->creds.xcred,
999 								   vhost->perm_config.ca,
1000 								   GNUTLS_X509_FMT_PEM);
1001 			if (ret < 0) {
1002 				mslog(s, NULL, LOG_ERR, "error setting the CA (%s) file",
1003 					vhost->perm_config.ca);
1004 				exit(1);
1005 			}
1006 
1007 			mslog(s, NULL, LOG_INFO, "processed %d CA certificate(s)", ret);
1008 		}
1009 
1010 		tls_reload_crl(s, vhost, 1);
1011 
1012 		gnutls_certificate_set_verify_function(vhost->creds.xcred,
1013 						       verify_certificate_cb);
1014 	}
1015 
1016 	tls_reload_ocsp(s, vhost);
1017 
1018 	return;
1019 }
1020 
ocsp_get_func(gnutls_session_t session,void * ptr,gnutls_datum_t * response)1021 static int ocsp_get_func(gnutls_session_t session, void *ptr, gnutls_datum_t *response)
1022 {
1023 	struct vhost_cfg_st *vhost = ptr;
1024 
1025 	if (ptr == NULL || vhost->creds.ocsp_response.size == 0)
1026 		return GNUTLS_E_NO_CERTIFICATE_STATUS;
1027 
1028 	response->data = gnutls_malloc(vhost->creds.ocsp_response.size);
1029 	if (response->data == NULL)
1030 		return GNUTLS_E_NO_CERTIFICATE_STATUS;
1031 
1032 	memcpy(response->data, vhost->creds.ocsp_response.data, vhost->creds.ocsp_response.size);
1033 	response->size = vhost->creds.ocsp_response.size;
1034 
1035 	return 0;
1036 }
1037 
tls_reload_ocsp(main_server_st * s,struct vhost_cfg_st * vhost)1038 static void tls_reload_ocsp(main_server_st* s, struct vhost_cfg_st *vhost)
1039 {
1040 	int ret;
1041 
1042 	gnutls_free(vhost->creds.ocsp_response.data);
1043 	vhost->creds.ocsp_response.data = NULL;
1044 
1045 	if (vhost->perm_config.config->ocsp_response != NULL) {
1046 		ret = gnutls_load_file(vhost->perm_config.config->ocsp_response, &vhost->creds.ocsp_response);
1047 		if (ret < 0)
1048 			return;
1049 
1050 		gnutls_certificate_set_ocsp_status_request_function(vhost->creds.xcred,
1051 								    ocsp_get_func, vhost);
1052 	} else {
1053 		gnutls_certificate_set_ocsp_status_request_function(vhost->creds.xcred, NULL, 0);
1054 	}
1055 }
1056 
1057 /*
1058  * @s may be %NULL, and should be used for mslog() purposes only.
1059  */
tls_load_prio(main_server_st * s,struct vhost_cfg_st * vhost)1060 void tls_load_prio(main_server_st *s, struct vhost_cfg_st *vhost)
1061 {
1062 	int ret;
1063 	const char* perr;
1064 
1065 	if (vhost->creds.cprio != NULL)
1066 		gnutls_priority_deinit(vhost->creds.cprio);
1067 
1068 	ret = gnutls_priority_init(&vhost->creds.cprio, vhost->perm_config.config->priorities, &perr);
1069 	if (ret == GNUTLS_E_PARSING_ERROR)
1070 		mslog(s, NULL, LOG_ERR, "error in TLS priority string: %s", perr);
1071 	GNUTLS_FATAL_ERR(ret);
1072 
1073 	return;
1074 }
1075 
1076 /*
1077  * @s may be %NULL, and should be used for mslog() purposes only.
1078  */
tls_reload_crl(main_server_st * s,struct vhost_cfg_st * vhost,unsigned force)1079 void tls_reload_crl(main_server_st* s, struct vhost_cfg_st *vhost, unsigned force)
1080 {
1081 	int ret, saved_ret;
1082 	static unsigned crl_type = GNUTLS_X509_FMT_PEM;
1083 
1084 	if (force)
1085 		vhost->crl_last_access = 0;
1086 
1087 	if (vhost->perm_config.config->cert_req != GNUTLS_CERT_IGNORE && vhost->perm_config.config->crl != NULL) {
1088 		if (need_file_reload(vhost->perm_config.config->crl, vhost->crl_last_access) == 0) {
1089 			mslog(s, NULL, LOG_DEBUG, "skipping already loaded CRL: %s", vhost->perm_config.config->crl);
1090 			return;
1091 		}
1092 
1093 		vhost->crl_last_access = time(0);
1094 
1095 		ret =
1096 		    gnutls_certificate_set_x509_crl_file(vhost->creds.xcred,
1097 							 vhost->perm_config.config->crl,
1098 							 crl_type);
1099 		if (ret == GNUTLS_E_BASE64_DECODING_ERROR && crl_type == GNUTLS_X509_FMT_PEM) {
1100 			crl_type = GNUTLS_X509_FMT_DER;
1101 			saved_ret = ret;
1102 			ret =
1103 			    gnutls_certificate_set_x509_crl_file(vhost->creds.xcred,
1104 								 vhost->perm_config.config->crl,
1105 								 crl_type);
1106 			if (ret < 0)
1107 				ret = saved_ret;
1108 		}
1109 		if (ret < 0) {
1110 			/* ignore the CRL file when empty */
1111 			mslog(s, NULL, LOG_ERR, "error reading the CRL (%s) file: %s",
1112 				vhost->perm_config.config->crl, gnutls_strerror(ret));
1113 			exit(1);
1114 		}
1115 		mslog(s, NULL, LOG_INFO, "loaded CRL: %s", vhost->perm_config.config->crl);
1116 	}
1117 }
1118 #endif
1119 
tls_cork(gnutls_session_t session)1120 void tls_cork(gnutls_session_t session)
1121 {
1122 	gnutls_record_cork(session);
1123 }
1124 
tls_uncork(gnutls_session_t session)1125 int tls_uncork(gnutls_session_t session)
1126 {
1127 	return gnutls_record_uncork(session, GNUTLS_RECORD_WAIT);
1128 }
1129 
calc_sha1_hash(void * pool,char * file,unsigned cert)1130 void *calc_sha1_hash(void *pool, char* file, unsigned cert)
1131 {
1132 	int ret;
1133 	gnutls_datum_t data;
1134 	uint8_t digest[20];
1135 	char * retval;
1136 	gnutls_x509_crt_t crt;
1137 	unsigned i;
1138 
1139 	ret = gnutls_load_file(file, &data);
1140 	if (ret < 0) {
1141 		return NULL;
1142 	}
1143 
1144 	if (cert != 0) {
1145 		ret = gnutls_x509_crt_init(&crt);
1146 		GNUTLS_FATAL_ERR(ret);
1147 
1148 		ret = gnutls_x509_crt_import(crt, &data, GNUTLS_X509_FMT_PEM);
1149 		if (ret == GNUTLS_E_BASE64_DECODING_ERROR)
1150 			ret = gnutls_x509_crt_import(crt, &data, GNUTLS_X509_FMT_DER);
1151 		GNUTLS_FATAL_ERR(ret);
1152 
1153 		gnutls_free(data.data);
1154 
1155 		ret = gnutls_x509_crt_export2(crt, GNUTLS_X509_FMT_DER, &data);
1156 		GNUTLS_FATAL_ERR(ret);
1157 		gnutls_x509_crt_deinit(crt);
1158 	}
1159 
1160 	ret = gnutls_hash_fast(GNUTLS_DIG_SHA1, data.data, data.size, digest);
1161 	gnutls_free(data.data);
1162 
1163 	if (ret < 0) {
1164 		fprintf(stderr, "error calculating hash of '%s': %s", file, gnutls_strerror(ret));
1165 		exit(1);
1166 	}
1167 
1168 	size_t ret_size = sizeof(digest)*2+1;
1169 	retval = talloc_size(pool, ret_size);
1170 	if (retval == NULL) {
1171 		fprintf(stderr, "memory error");
1172 		exit(1);
1173 	}
1174 
1175 	data.data = digest;
1176 	data.size = sizeof(digest);
1177 	ret = gnutls_hex_encode(&data, retval, &ret_size);
1178 	if (ret < 0) {
1179 		fprintf(stderr, "error in hex encode: %s", gnutls_strerror(ret));
1180 		exit(1);
1181 	}
1182 	if (retval[ret_size-1] == 0) ret_size--; /* remove the null terminator */
1183 
1184 	/* convert to all caps */
1185 	for (i=0;i<ret_size;i++)
1186 	        retval[i] = c_toupper(retval[i]);
1187 
1188 	return retval;
1189 }
1190 
1191 
tls_get_overhead(gnutls_protocol_t version,gnutls_cipher_algorithm_t cipher,gnutls_mac_algorithm_t mac)1192 size_t tls_get_overhead(gnutls_protocol_t version, gnutls_cipher_algorithm_t cipher, gnutls_mac_algorithm_t mac)
1193 {
1194 	return gnutls_est_record_overhead_size(version, cipher, mac, GNUTLS_COMP_NULL, 0);
1195 }
1196