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