BULK: Change syntax to drop "7:command ".
[pwmd.git] / src / tls.c
blob2a16120885b9db1c7b7eb3d54bbd0d6fb490a7a4
1 /*
2 Copyright (C) 2006-2018 Ben Kibbey <bjk@luxsci.net>
4 This file is part of pwmd.
6 Pwmd is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 2 of the License, or
9 (at your option) any later version.
11 Pwmd is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
23 #include <gnutls/x509.h>
24 #include <errno.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <netdb.h>
29 #ifdef HAVE_STRINGS_H
30 #include <strings.h>
31 #endif
33 #include "pwmd-error.h"
34 #include <gcrypt.h>
35 #include "mem.h"
36 #include "util-misc.h"
37 #include "util-string.h"
38 #include "common.h"
39 #include "tls.h"
40 #include "mutex.h"
41 #include "rcfile.h"
43 #define WAIT_INTERVAL 50000
44 #define TEST_TIMEOUT(timeout, ret, start, rc) \
45 do { \
46 rc = 0; \
47 if (ret == GNUTLS_E_AGAIN) \
48 { \
49 time_t now = time (NULL); \
50 if (timeout && now - start >= timeout) \
51 { \
52 rc = gpg_error (GPG_ERR_ETIMEDOUT); \
53 ret = GNUTLS_E_TIMEDOUT; \
54 break; \
55 } \
56 struct timeval wtv = { 0, WAIT_INTERVAL }; \
57 select (0, NULL, NULL, NULL, &wtv); \
58 } \
59 if (ret != GNUTLS_E_INTERRUPTED) \
60 break; \
61 } \
62 while (0)
64 static gnutls_dh_params_t dh_params;
65 static gnutls_certificate_credentials_t x509_cred;
67 static char *
68 tls_fingerprint (gnutls_session_t ses)
70 gnutls_x509_crt_t crt;
71 const gnutls_datum_t *cert_list;
72 unsigned count;
73 unsigned char buf[32];
74 size_t len = sizeof (buf);
76 gnutls_x509_crt_init (&crt);
77 if (!crt)
79 log_write ("%s(%i): %s(): %s", __FILE__, __LINE__, __FUNCTION__,
80 gnutls_strerror (GNUTLS_E_MEMORY_ERROR));
81 return NULL;
84 cert_list = gnutls_certificate_get_peers (ses, &count);
85 if (count)
87 gnutls_x509_crt_import (crt, &cert_list[0], GNUTLS_X509_FMT_DER);
88 gnutls_x509_crt_get_fingerprint (crt, GNUTLS_DIG_SHA256, buf, &len);
89 gnutls_x509_crt_deinit (crt);
91 return len ? bin2hex (buf, len) : NULL;
94 gnutls_x509_crt_deinit (crt);
95 return NULL;
98 static int
99 verify_client_certificate (unsigned status)
101 if (!status)
102 return 0;
104 if (status & GNUTLS_CERT_REVOKED)
105 log_write (_("client certificate is revoked"));
107 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
108 log_write (_("client certificate has no signer"));
110 if (status & GNUTLS_CERT_SIGNATURE_FAILURE)
111 log_write (_("client certificate signature verification failed"));
113 if (status & GNUTLS_CERT_EXPIRED)
114 log_write (_("client certificate expired"));
116 if (status & GNUTLS_CERT_SIGNER_NOT_CA)
117 log_write (_("client certificate signer is not from CA"));
119 if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
120 log_write (_("client certificate has insecure algorithm"));
122 if (status & GNUTLS_CERT_INVALID)
123 log_write (_("client certificate is invalid"));
125 return GNUTLS_E_CERTIFICATE_ERROR;
128 struct tls_s *
129 tls_init_client (int fd, int timeout, const char *prio)
131 int ret;
132 unsigned status;
133 const char *prio_error;
134 gnutls_kx_algorithm_t kx;
135 gpg_error_t rc = 0;
136 struct tls_s *tls = xcalloc (1, sizeof (struct tls_s));
138 if (!tls)
140 log_write ("%s(%i): %s: %s", __FILE__, __LINE__, __FUNCTION__,
141 strerror (ENOMEM));
142 return NULL;
145 ret = gnutls_init (&tls->ses, GNUTLS_SERVER);
146 if (ret != GNUTLS_E_SUCCESS)
147 goto fail;
149 ret = gnutls_priority_set_direct (tls->ses, prio, &prio_error);
150 if (ret != GNUTLS_E_SUCCESS)
151 goto fail;
153 ret = gnutls_credentials_set (tls->ses, GNUTLS_CRD_CERTIFICATE, x509_cred);
154 if (ret != GNUTLS_E_SUCCESS)
155 goto fail;
157 gnutls_certificate_server_set_request (tls->ses, GNUTLS_CERT_REQUIRE);
158 gnutls_transport_set_ptr (tls->ses, (gnutls_transport_ptr_t) fd);
159 time_t start = time (NULL);
162 ret = gnutls_handshake (tls->ses);
163 TEST_TIMEOUT (timeout, ret, start, rc);
164 if (rc)
165 goto fail;
167 while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
169 if (ret != GNUTLS_E_SUCCESS)
170 goto fail;
172 ret = gnutls_certificate_verify_peers2 (tls->ses, &status);
173 if (ret)
174 goto fail;
176 kx = gnutls_kx_get (tls->ses);
177 tls->fp = tls_fingerprint (tls->ses);
178 log_write ("PROTO=%s CIPHER=%s MAC=%s KX=%s(%d) FP=%s",
179 gnutls_protocol_get_name (gnutls_protocol_get_version
180 (tls->ses)),
181 gnutls_cipher_get_name (gnutls_cipher_get (tls->ses)),
182 gnutls_mac_get_name (gnutls_mac_get (tls->ses)),
183 gnutls_kx_get_name (kx), gnutls_dh_get_prime_bits (tls->ses),
184 tls->fp ? tls->fp : "N/A");
185 ret = verify_client_certificate (status);
186 if (ret)
187 goto fail;
189 return tls;
191 fail:
192 log_write ("%s", rc ? pwmd_strerror(rc) : gnutls_strerror (ret));
193 gnutls_deinit (tls->ses);
194 xfree (tls->fp);
195 xfree (tls);
196 return NULL;
199 void
200 tls_log (int level, const char *msg)
202 log_write ("TLS: %i: %s", level, msg);
205 void
206 tls_audit_log (gnutls_session_t s, const char *msg)
208 (void)s;
209 log_write ("TLS: %s", msg);
212 ssize_t
213 tls_read_hook (assuan_context_t ctx, assuan_fd_t fd, void *data, size_t len)
215 struct client_s *client = assuan_get_pointer (ctx);
216 struct tls_s *tls = client->thd->tls;
217 time_t start = time (NULL);
218 ssize_t ret;
222 gpg_error_t rc = 0;
223 struct timeval tv = { 0, 0 };
224 fd_set fds;
225 int n;
227 FD_ZERO (&fds);
228 FD_SET (fd, &fds);
229 n = select (client->thd->fd+1, &fds, NULL, NULL, &tv);
230 if (n == 0 && tls->nl)
232 char c[] = "#\n";
234 memcpy (data, c, sizeof(c));
235 ret = strlen (c);
236 break;
239 ret = gnutls_record_recv (tls->ses, data, len);
240 if (ret == GNUTLS_E_REHANDSHAKE)
242 tls->rehandshake = 0;
246 ret = gnutls_handshake (tls->ses);
247 TEST_TIMEOUT (client->thd->timeout, ret, start, rc);
248 if (rc)
249 break;
251 while (ret < 0 && gnutls_error_is_fatal (ret) == 0);
253 if (!ret)
255 gnutls_kx_algorithm_t kx;
256 char c[] = "# \n";
258 if (tls->nl)
260 memcpy (data, c, sizeof (c));
261 ret = strlen (c);
263 else
264 ret = GNUTLS_E_AGAIN;
266 kx = gnutls_kx_get (tls->ses);
267 log_write ("PROTO=%s CIPHER=%s MAC=%s KX=%s(%d)",
268 gnutls_protocol_get_name (gnutls_protocol_get_version
269 (tls->ses)),
270 gnutls_cipher_get_name (gnutls_cipher_get (tls->ses)),
271 gnutls_mac_get_name (gnutls_mac_get (tls->ses)),
272 gnutls_kx_get_name (kx), gnutls_dh_get_prime_bits (tls->ses));
273 if (!tls->nl)
274 continue;
276 break;
279 TEST_TIMEOUT (client->thd->timeout, ret, start, rc);
280 if (rc)
281 break;
283 while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
285 if (ret < 0)
287 log_write ("TLS: %s", gnutls_strerror (ret));
288 ret = 0;
290 else if (ret > 0)
291 tls->nl = ((char *)data)[ret-1] == '\n';
293 return ret;
296 ssize_t
297 tls_write_hook (assuan_context_t ctx, assuan_fd_t fd, const void *data,
298 size_t len)
300 struct client_s *client = assuan_get_pointer (ctx);
301 ssize_t ret;
302 time_t start = time (NULL);
304 if (client->disco)
305 return -1;
307 (void)fd;
310 gpg_error_t rc = 0;
312 ret = gnutls_record_send (client->thd->tls->ses, data, len);
313 TEST_TIMEOUT (client->thd->timeout, ret, start, rc);
314 if (rc)
315 break;
317 while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
319 if (ret < 0)
320 log_write ("TLS: %s", gnutls_strerror (ret));
322 return ret;
325 static gpg_error_t
326 tls_init_params ()
328 int n;
329 char *tmp, *tmp2;
330 gpg_error_t rc = GPG_ERR_GENERAL;
331 static pthread_mutex_t tls_mutex = PTHREAD_MUTEX_INITIALIZER;
333 if (x509_cred)
334 return 0;
336 MUTEX_LOCK(&tls_mutex);
337 pthread_cleanup_push (release_mutex_cb, &tls_mutex);
338 tls_deinit_params ();
339 n = gnutls_certificate_allocate_credentials (&x509_cred);
340 if (n != GNUTLS_E_SUCCESS)
342 log_write ("%s", gnutls_strerror (n));
343 x509_cred = NULL;
344 goto fail;
347 MUTEX_LOCK (&rcfile_mutex);
348 if (config_get_boolean ("global", "tls_use_crl"))
350 MUTEX_UNLOCK (&rcfile_mutex);
351 tmp = str_asprintf ("%s/crl.pem", homedir);
352 if (!tmp)
354 rc = GPG_ERR_ENOMEM;
355 goto fail;
358 if (access (tmp, R_OK) == -1 && errno == ENOENT)
360 rc = gpg_error_from_errno (errno);
361 log_write ("%s: %s", tmp, pwmd_strerror (rc));
362 goto fail;
364 else
366 n = gnutls_certificate_set_x509_crl_file (x509_cred, tmp,
367 GNUTLS_X509_FMT_PEM);
368 if (n < 0)
370 log_write ("%s: %s", tmp, gnutls_strerror (n));
371 xfree (tmp);
372 goto fail;
376 xfree (tmp);
378 else
379 MUTEX_UNLOCK (&rcfile_mutex);
381 tmp = str_asprintf ("%s/ca-cert.pem", homedir);
382 if (!tmp)
384 rc = GPG_ERR_ENOMEM;
385 log_write ("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror (rc));
386 goto fail;
389 n = gnutls_certificate_set_x509_trust_file (x509_cred, tmp,
390 GNUTLS_X509_FMT_PEM);
391 if (n < 0)
393 log_write ("%s: %s", tmp, gnutls_strerror (n));
394 xfree (tmp);
395 goto fail;
398 xfree (tmp);
399 tmp = str_asprintf ("%s/server-cert.pem", homedir);
400 if (!tmp)
402 rc = GPG_ERR_ENOMEM;
403 log_write ("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror (rc));
404 goto fail;
407 tmp2 = str_asprintf ("%s/server-key.pem", homedir);
408 if (!tmp2)
410 xfree (tmp);
411 rc = GPG_ERR_ENOMEM;
412 log_write ("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror (rc));
413 goto fail;
416 n = gnutls_certificate_set_x509_key_file (x509_cred, tmp, tmp2,
417 GNUTLS_X509_FMT_PEM);
418 xfree (tmp);
419 xfree (tmp2);
420 if (n != GNUTLS_E_SUCCESS)
422 log_write ("%s", gnutls_strerror (n));
423 goto fail;
426 tmp = config_get_string ("global", "tls_dh_params_file");
427 if (tmp)
429 tmp2 = expand_homedir (tmp);
430 if (!tmp2)
432 log_write ("%s: %s", tmp, pwmd_strerror (GPG_ERR_ENOMEM));
433 xfree (tmp);
434 rc = GPG_ERR_ENOMEM;
435 goto fail;
438 xfree (tmp);
439 tmp = tmp2;
440 n = gnutls_dh_params_init (&dh_params);
441 if (!n)
443 gnutls_datum_t data;
445 n = gnutls_load_file (tmp, &data);
446 if (!n)
448 n = gnutls_dh_params_import_pkcs3 (dh_params, &data,
449 GNUTLS_X509_FMT_PEM);
450 if (!n)
451 gnutls_certificate_set_dh_params (x509_cred, dh_params);
453 wipememory (data.data, 0, data.size);
454 free (data.data);
458 if (n != GNUTLS_E_SUCCESS)
460 log_write ("%s: %s", tmp, gnutls_strerror (n));
461 xfree (tmp);
462 goto fail;
464 xfree (tmp);
467 rc = 0;
469 fail:
470 if (rc)
471 tls_deinit_params ();
473 pthread_cleanup_pop (1);
474 return rc;
477 void
478 tls_deinit_params ()
480 if (dh_params)
482 gnutls_dh_params_deinit (dh_params);
483 dh_params = NULL;
486 if (x509_cred)
488 gnutls_certificate_free_credentials (x509_cred);
489 x509_cred = NULL;
493 static gpg_error_t
494 do_tls_validate_access (struct client_s *client, const char *section)
496 char **access = config_get_list (section, "allowed");
497 char **p;
498 int allowed = 0;
500 if (!access || !*access)
501 return GPG_ERR_EACCES;
503 for (p = access; p && *p; p++)
505 int not = 0;
506 char *fp = *p;
508 if (*fp && *fp == '+' && *(fp + 1) == 0) // allow all connections
510 allowed = 1;
511 continue;
514 if (*fp == '!' || *fp == '-')
516 not = 1;
517 fp++;
518 if (!*fp)
519 break;
522 if (*fp++ != '#')
523 continue;
525 if (!strcasecmp (client->thd->tls->fp, fp))
526 allowed = not ? 0 : 1;
529 strv_free (access);
530 return allowed ? 0 : GPG_ERR_EACCES;
533 gpg_error_t
534 tls_validate_access (struct client_s *client, const char *filename)
536 gpg_error_t rc = do_tls_validate_access (client, "global");
538 if (!rc && filename)
539 rc = do_tls_validate_access (client, filename);
541 return rc;
544 void
545 tls_rehandshake ()
547 unsigned t, i;
549 MUTEX_LOCK (&cn_mutex);
550 t = slist_length (cn_thread_list);
551 for (i = 0; i < t; i++)
553 struct client_thread_s *thd = slist_nth_data (cn_thread_list, i);
555 if (thd->remote && thd->tls)
556 thd->tls->rehandshake = 1;
558 MUTEX_UNLOCK (&cn_mutex);
561 static int
562 start_stop_tls_with_protocol (int ipv6, int term)
564 struct addrinfo hints, *servinfo, *p;
565 int port = config_get_integer ("global", "tcp_port");
566 char buf[7];
567 int n;
568 int *fd = ipv6 ? &tls6_fd : &tls_fd;
570 if (term || config_get_boolean ("global", "enable_tcp") == 0)
572 if (tls6_fd != -1)
574 shutdown (tls6_fd, SHUT_RDWR);
575 close (tls6_fd);
576 tls6_fd = -1;
579 if (tls_fd != -1)
581 shutdown (tls_fd, SHUT_RDWR);
582 close (tls_fd);
583 tls_fd = -1;
586 return 0;
589 memset (&hints, 0, sizeof (hints));
590 hints.ai_family = ipv6 ? AF_INET6 : AF_INET;
591 hints.ai_socktype = SOCK_STREAM;
592 hints.ai_flags = AI_PASSIVE;
593 snprintf (buf, sizeof (buf), "%i", port);
595 if ((n = getaddrinfo (NULL, buf, &hints, &servinfo)) == -1)
597 log_write ("getaddrinfo(): %s", gai_strerror (n));
598 return 0;
601 for (n = 0, p = servinfo; p != NULL; p = p->ai_next)
603 int r = 1;
605 if ((ipv6 && p->ai_family != AF_INET6)
606 || (!ipv6 && p->ai_family != AF_INET))
607 continue;
609 if ((*fd = socket (p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
611 log_write ("socket(): %s", strerror (errno));
612 continue;
615 if (setsockopt (*fd, SOL_SOCKET, SO_REUSEADDR, &r, sizeof (int)) == -1)
617 log_write ("setsockopt(): %s",
618 pwmd_strerror (gpg_error_from_errno (errno)));
619 freeaddrinfo (servinfo);
620 goto fail;
623 if (bind (*fd, p->ai_addr, p->ai_addrlen) == -1)
625 close (*fd);
626 log_write ("bind(): port %u: %s", port,
627 pwmd_strerror (gpg_error_from_errno (errno)));
628 continue;
631 n++;
632 break;
635 freeaddrinfo (servinfo);
637 if (!n)
638 goto fail;
640 #if HAVE_DECL_SO_BINDTODEVICE != 0
641 char *tmp = config_get_string ("global", "tcp_interface");
642 if (tmp && setsockopt (*fd, SOL_SOCKET, SO_BINDTODEVICE, tmp,
643 strlen (tmp)) == -1)
645 log_write ("setsockopt(): %s",
646 pwmd_strerror (gpg_error_from_errno (errno)));
647 xfree (tmp);
648 goto fail;
651 xfree (tmp);
652 #endif
654 if (listen (*fd, 128) == -1)
656 log_write ("listen(): %s", strerror (errno));
657 goto fail;
660 return 1;
662 fail:
663 start_stop_tls_with_protocol (0, 1);
664 if (tls_fd != -1)
665 close (tls_fd);
667 if (tls6_fd != -1)
668 close (tls6_fd);
670 tls_fd = -1;
671 tls6_fd = -1;
672 return 0;
676 tls_start_stop (int term)
678 char *s = config_get_string ("global", "tcp_bind");
679 int b;
681 if (!s)
682 return 0;
684 if (!strcmp (s, "any"))
686 b = start_stop_tls_with_protocol (0, term);
687 if (b)
688 b = start_stop_tls_with_protocol (1, term);
690 else if (!strcmp (s, "ipv4"))
691 b = start_stop_tls_with_protocol (0, term);
692 else if (!strcmp (s, "ipv6"))
693 b = start_stop_tls_with_protocol (1, term);
694 else
695 b = 0;
697 xfree (s);
698 if (!term && b)
700 gpg_error_t rc = tls_init_params ();
701 if (rc)
703 start_stop_tls_with_protocol (0, 1);
704 return 0;
708 return b;