Fix EXPIRE status message.
[pwmd.git] / src / tls.c
bloba77cb1334ef71caed0ad3fb3a61f81226bc2cc61
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015,
3 2016, 2017
4 Ben Kibbey <bjk@luxsci.net>
6 This file is part of pwmd.
8 Pwmd is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
13 Pwmd is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
25 #include <gnutls/x509.h>
26 #include <errno.h>
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <netdb.h>
31 #ifdef HAVE_STRINGS_H
32 #include <strings.h>
33 #endif
35 #include "pwmd-error.h"
36 #include <gcrypt.h>
37 #include "mem.h"
38 #include "util-misc.h"
39 #include "util-string.h"
40 #include "common.h"
41 #include "tls.h"
42 #include "mutex.h"
43 #include "rcfile.h"
45 #define WAIT_INTERVAL 50000
46 #define TEST_TIMEOUT(timeout, ret, start, rc) \
47 do { \
48 rc = 0; \
49 if (ret == GNUTLS_E_AGAIN) \
50 { \
51 time_t now = time (NULL); \
52 if (timeout && now - start >= timeout) \
53 { \
54 rc = gpg_error (GPG_ERR_ETIMEDOUT); \
55 ret = GNUTLS_E_TIMEDOUT; \
56 break; \
57 } \
58 struct timeval wtv = { 0, WAIT_INTERVAL }; \
59 select (0, NULL, NULL, NULL, &wtv); \
60 } \
61 if (ret != GNUTLS_E_INTERRUPTED) \
62 break; \
63 } \
64 while (0)
66 static gnutls_dh_params_t dh_params;
67 static gnutls_certificate_credentials_t x509_cred;
69 static char *
70 tls_fingerprint (gnutls_session_t ses)
72 gnutls_x509_crt_t crt;
73 const gnutls_datum_t *cert_list;
74 unsigned count;
75 unsigned char buf[32];
76 size_t len = sizeof (buf);
78 gnutls_x509_crt_init (&crt);
79 if (!crt)
81 log_write ("%s(%i): %s(): %s", __FILE__, __LINE__, __FUNCTION__,
82 gnutls_strerror (GNUTLS_E_MEMORY_ERROR));
83 return NULL;
86 cert_list = gnutls_certificate_get_peers (ses, &count);
87 if (count)
89 gnutls_x509_crt_import (crt, &cert_list[0], GNUTLS_X509_FMT_DER);
90 gnutls_x509_crt_get_fingerprint (crt, GNUTLS_DIG_SHA256, buf, &len);
91 gnutls_x509_crt_deinit (crt);
93 return len ? bin2hex (buf, len) : NULL;
96 gnutls_x509_crt_deinit (crt);
97 return NULL;
100 static int
101 verify_client_certificate (unsigned status)
103 if (!status)
104 return 0;
106 if (status & GNUTLS_CERT_REVOKED)
107 log_write (_("client certificate is revoked"));
109 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
110 log_write (_("client certificate has no signer"));
112 if (status & GNUTLS_CERT_SIGNATURE_FAILURE)
113 log_write (_("client certificate signature verification failed"));
115 if (status & GNUTLS_CERT_EXPIRED)
116 log_write (_("client certificate expired"));
118 if (status & GNUTLS_CERT_SIGNER_NOT_CA)
119 log_write (_("client certificate signer is not from CA"));
121 if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
122 log_write (_("client certificate has insecure algorithm"));
124 if (status & GNUTLS_CERT_INVALID)
125 log_write (_("client certificate is invalid"));
127 return GNUTLS_E_CERTIFICATE_ERROR;
130 struct tls_s *
131 tls_init_client (int fd, int timeout, const char *prio)
133 int ret;
134 unsigned status;
135 const char *prio_error;
136 gnutls_kx_algorithm_t kx;
137 gpg_error_t rc = 0;
138 struct tls_s *tls = xcalloc (1, sizeof (struct tls_s));
140 if (!tls)
142 log_write ("%s(%i): %s: %s", __FILE__, __LINE__, __FUNCTION__,
143 strerror (ENOMEM));
144 return NULL;
147 ret = gnutls_init (&tls->ses, GNUTLS_SERVER);
148 if (ret != GNUTLS_E_SUCCESS)
149 goto fail;
151 ret = gnutls_priority_set_direct (tls->ses, prio, &prio_error);
152 if (ret != GNUTLS_E_SUCCESS)
153 goto fail;
155 ret = gnutls_credentials_set (tls->ses, GNUTLS_CRD_CERTIFICATE, x509_cred);
156 if (ret != GNUTLS_E_SUCCESS)
157 goto fail;
159 gnutls_certificate_server_set_request (tls->ses, GNUTLS_CERT_REQUIRE);
160 gnutls_transport_set_ptr (tls->ses, (gnutls_transport_ptr_t) fd);
161 time_t start = time (NULL);
164 ret = gnutls_handshake (tls->ses);
165 TEST_TIMEOUT (timeout, ret, start, rc);
166 if (rc)
167 goto fail;
169 while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
171 if (ret != GNUTLS_E_SUCCESS)
172 goto fail;
174 ret = gnutls_certificate_verify_peers2 (tls->ses, &status);
175 if (ret)
176 goto fail;
178 kx = gnutls_kx_get (tls->ses);
179 tls->fp = tls_fingerprint (tls->ses);
180 log_write ("PROTO=%s CIPHER=%s MAC=%s KX=%s(%d) FP=%s",
181 gnutls_protocol_get_name (gnutls_protocol_get_version
182 (tls->ses)),
183 gnutls_cipher_get_name (gnutls_cipher_get (tls->ses)),
184 gnutls_mac_get_name (gnutls_mac_get (tls->ses)),
185 gnutls_kx_get_name (kx), gnutls_dh_get_prime_bits (tls->ses),
186 tls->fp ? tls->fp : "N/A");
187 ret = verify_client_certificate (status);
188 if (ret)
189 goto fail;
191 return tls;
193 fail:
194 log_write ("%s", rc ? pwmd_strerror(rc) : gnutls_strerror (ret));
195 gnutls_deinit (tls->ses);
196 xfree (tls->fp);
197 xfree (tls);
198 return NULL;
201 void
202 tls_log (int level, const char *msg)
204 log_write ("TLS: %i: %s", level, msg);
207 void
208 tls_audit_log (gnutls_session_t s, const char *msg)
210 (void)s;
211 log_write ("TLS: %s", msg);
214 ssize_t
215 tls_read_hook (assuan_context_t ctx, assuan_fd_t fd, void *data, size_t len)
217 struct client_s *client = assuan_get_pointer (ctx);
218 struct tls_s *tls = client->thd->tls;
219 time_t start = time (NULL);
220 ssize_t ret;
224 gpg_error_t rc = 0;
225 struct timeval tv = { 0, 0 };
226 fd_set fds;
227 int n;
229 FD_ZERO (&fds);
230 FD_SET (fd, &fds);
231 n = select (client->thd->fd+1, &fds, NULL, NULL, &tv);
232 if (n == 0 && tls->nl)
234 char c[] = "#\n";
236 memcpy (data, c, sizeof(c));
237 ret = strlen (c);
238 break;
241 ret = gnutls_record_recv (tls->ses, data, len);
242 if (ret == GNUTLS_E_REHANDSHAKE)
244 tls->rehandshake = 0;
248 ret = gnutls_handshake (tls->ses);
249 TEST_TIMEOUT (client->thd->timeout, ret, start, rc);
250 if (rc)
251 break;
253 while (ret < 0 && gnutls_error_is_fatal (ret) == 0);
255 if (!ret)
257 gnutls_kx_algorithm_t kx;
258 char c[] = "# \n";
260 if (tls->nl)
262 memcpy (data, c, sizeof (c));
263 ret = strlen (c);
265 else
266 ret = GNUTLS_E_AGAIN;
268 kx = gnutls_kx_get (tls->ses);
269 log_write ("PROTO=%s CIPHER=%s MAC=%s KX=%s(%d)",
270 gnutls_protocol_get_name (gnutls_protocol_get_version
271 (tls->ses)),
272 gnutls_cipher_get_name (gnutls_cipher_get (tls->ses)),
273 gnutls_mac_get_name (gnutls_mac_get (tls->ses)),
274 gnutls_kx_get_name (kx), gnutls_dh_get_prime_bits (tls->ses));
275 if (!tls->nl)
276 continue;
278 break;
281 TEST_TIMEOUT (client->thd->timeout, ret, start, rc);
282 if (rc)
283 break;
285 while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
287 if (ret < 0)
289 log_write ("TLS: %s", gnutls_strerror (ret));
290 ret = 0;
292 else if (ret > 0)
293 tls->nl = ((char *)data)[ret-1] == '\n';
295 return ret;
298 ssize_t
299 tls_write_hook (assuan_context_t ctx, assuan_fd_t fd, const void *data,
300 size_t len)
302 struct client_s *client = assuan_get_pointer (ctx);
303 ssize_t ret;
304 time_t start = time (NULL);
306 if (client->disco)
307 return -1;
309 (void)fd;
312 gpg_error_t rc = 0;
314 ret = gnutls_record_send (client->thd->tls->ses, data, len);
315 TEST_TIMEOUT (client->thd->timeout, ret, start, rc);
316 if (rc)
317 break;
319 while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
321 if (ret < 0)
322 log_write ("TLS: %s", gnutls_strerror (ret));
324 return ret;
327 static gpg_error_t
328 tls_init_params ()
330 int n;
331 char *tmp, *tmp2;
332 gpg_error_t rc = GPG_ERR_GENERAL;
333 static pthread_mutex_t tls_mutex = PTHREAD_MUTEX_INITIALIZER;
335 if (x509_cred)
336 return 0;
338 MUTEX_LOCK(&tls_mutex);
339 pthread_cleanup_push (release_mutex_cb, &tls_mutex);
340 tls_deinit_params ();
341 n = gnutls_certificate_allocate_credentials (&x509_cred);
342 if (n != GNUTLS_E_SUCCESS)
344 log_write ("%s", gnutls_strerror (n));
345 x509_cred = NULL;
346 goto fail;
349 tmp = str_asprintf ("%s/ca-cert.pem", homedir);
350 if (!tmp)
352 rc = GPG_ERR_ENOMEM;
353 log_write ("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror (rc));
354 goto fail;
357 n = gnutls_certificate_set_x509_trust_file (x509_cred, tmp,
358 GNUTLS_X509_FMT_PEM);
359 if (n < 0)
361 log_write ("%s: %s", tmp, gnutls_strerror (n));
362 xfree (tmp);
363 goto fail;
366 xfree (tmp);
367 tmp = str_asprintf ("%s/server-cert.pem", homedir);
368 if (!tmp)
370 rc = GPG_ERR_ENOMEM;
371 log_write ("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror (rc));
372 goto fail;
375 tmp2 = str_asprintf ("%s/server-key.pem", homedir);
376 if (!tmp2)
378 xfree (tmp);
379 rc = GPG_ERR_ENOMEM;
380 log_write ("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror (rc));
381 goto fail;
384 n = gnutls_certificate_set_x509_key_file (x509_cred, tmp, tmp2,
385 GNUTLS_X509_FMT_PEM);
386 xfree (tmp);
387 xfree (tmp2);
388 if (n != GNUTLS_E_SUCCESS)
390 log_write ("%s", gnutls_strerror (n));
391 goto fail;
394 tmp = config_get_string ("global", "tls_dh_params_file");
395 if (tmp)
397 tmp2 = expand_homedir (tmp);
398 if (!tmp2)
400 log_write ("%s: %s", tmp, pwmd_strerror (GPG_ERR_ENOMEM));
401 xfree (tmp);
402 rc = GPG_ERR_ENOMEM;
403 goto fail;
406 xfree (tmp);
407 tmp = tmp2;
408 n = gnutls_dh_params_init (&dh_params);
409 if (!n)
411 gnutls_datum_t data;
413 n = gnutls_load_file (tmp, &data);
414 if (!n)
416 n = gnutls_dh_params_import_pkcs3 (dh_params, &data,
417 GNUTLS_X509_FMT_PEM);
418 if (!n)
419 gnutls_certificate_set_dh_params (x509_cred, dh_params);
421 wipememory (data.data, 0, data.size);
422 free (data.data);
426 if (n != GNUTLS_E_SUCCESS)
428 log_write ("%s: %s", tmp, gnutls_strerror (n));
429 xfree (tmp);
430 goto fail;
432 xfree (tmp);
435 rc = 0;
437 fail:
438 if (rc)
439 tls_deinit_params ();
441 pthread_cleanup_pop (1);
442 return rc;
445 void
446 tls_deinit_params ()
448 if (dh_params)
450 gnutls_dh_params_deinit (dh_params);
451 dh_params = NULL;
454 if (x509_cred)
456 gnutls_certificate_free_credentials (x509_cred);
457 x509_cred = NULL;
461 static gpg_error_t
462 do_tls_validate_access (struct client_s *client, const char *section)
464 char **access = config_get_list (section, "allowed");
465 char **p;
466 int allowed = 0;
468 if (!access || !*access)
469 return GPG_ERR_EACCES;
471 for (p = access; p && *p; p++)
473 int not = 0;
474 char *fp = *p;
476 if (*fp && *fp == '+' && *(fp + 1) == 0) // allow all connections
478 allowed = 1;
479 continue;
482 if (*fp == '!' || *fp == '-')
484 not = 1;
485 fp++;
486 if (!*fp)
487 break;
490 if (*fp++ != '#')
491 continue;
493 if (!strcasecmp (client->thd->tls->fp, fp))
494 allowed = not ? 0 : 1;
497 strv_free (access);
498 return allowed ? 0 : GPG_ERR_EACCES;
501 gpg_error_t
502 tls_validate_access (struct client_s *client, const char *filename)
504 gpg_error_t rc = do_tls_validate_access (client, "global");
506 if (!rc && filename)
507 rc = do_tls_validate_access (client, filename);
509 return rc;
512 void
513 tls_rehandshake ()
515 unsigned t, i;
517 MUTEX_LOCK (&cn_mutex);
518 t = slist_length (cn_thread_list);
519 for (i = 0; i < t; i++)
521 struct client_thread_s *thd = slist_nth_data (cn_thread_list, i);
523 if (thd->remote && thd->tls)
524 thd->tls->rehandshake = 1;
526 MUTEX_UNLOCK (&cn_mutex);
529 static int
530 start_stop_tls_with_protocol (int ipv6, int term)
532 struct addrinfo hints, *servinfo, *p;
533 int port = config_get_integer ("global", "tcp_port");
534 char buf[7];
535 int n;
536 int *fd = ipv6 ? &tls6_fd : &tls_fd;
538 if (term || config_get_boolean ("global", "enable_tcp") == 0)
540 if (tls6_fd != -1)
542 shutdown (tls6_fd, SHUT_RDWR);
543 close (tls6_fd);
544 tls6_fd = -1;
547 if (tls_fd != -1)
549 shutdown (tls_fd, SHUT_RDWR);
550 close (tls_fd);
551 tls_fd = -1;
554 return 0;
557 memset (&hints, 0, sizeof (hints));
558 hints.ai_family = ipv6 ? AF_INET6 : AF_INET;
559 hints.ai_socktype = SOCK_STREAM;
560 hints.ai_flags = AI_PASSIVE;
561 snprintf (buf, sizeof (buf), "%i", port);
563 if ((n = getaddrinfo (NULL, buf, &hints, &servinfo)) == -1)
565 log_write ("getaddrinfo(): %s", gai_strerror (n));
566 return 0;
569 for (n = 0, p = servinfo; p != NULL; p = p->ai_next)
571 int r = 1;
573 if ((ipv6 && p->ai_family != AF_INET6)
574 || (!ipv6 && p->ai_family != AF_INET))
575 continue;
577 if ((*fd = socket (p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
579 log_write ("socket(): %s", strerror (errno));
580 continue;
583 if (setsockopt (*fd, SOL_SOCKET, SO_REUSEADDR, &r, sizeof (int)) == -1)
585 log_write ("setsockopt(): %s",
586 pwmd_strerror (gpg_error_from_errno (errno)));
587 freeaddrinfo (servinfo);
588 goto fail;
591 if (bind (*fd, p->ai_addr, p->ai_addrlen) == -1)
593 close (*fd);
594 log_write ("bind(): %s",
595 pwmd_strerror (gpg_error_from_errno (errno)));
596 continue;
599 n++;
600 break;
603 freeaddrinfo (servinfo);
605 if (!n)
606 goto fail;
608 #if HAVE_DECL_SO_BINDTODEVICE != 0
609 char *tmp = config_get_string ("global", "tcp_interface");
610 if (tmp && setsockopt (*fd, SOL_SOCKET, SO_BINDTODEVICE, tmp,
611 strlen (tmp)) == -1)
613 log_write ("setsockopt(): %s",
614 pwmd_strerror (gpg_error_from_errno (errno)));
615 xfree (tmp);
616 goto fail;
619 xfree (tmp);
620 #endif
622 if (listen (*fd, 128) == -1)
624 log_write ("listen(): %s", strerror (errno));
625 goto fail;
628 return 1;
630 fail:
631 start_stop_tls_with_protocol (0, 1);
632 if (tls_fd != -1)
633 close (tls_fd);
635 if (tls6_fd != -1)
636 close (tls6_fd);
638 tls_fd = -1;
639 tls6_fd = -1;
640 return 0;
644 tls_start_stop (int term)
646 char *s = config_get_string ("global", "tcp_bind");
647 int b;
649 if (!s)
650 return 0;
652 if (!strcmp (s, "any"))
654 b = start_stop_tls_with_protocol (0, term);
655 if (b)
656 b = start_stop_tls_with_protocol (1, term);
658 else if (!strcmp (s, "ipv4"))
659 b = start_stop_tls_with_protocol (0, term);
660 else if (!strcmp (s, "ipv6"))
661 b = start_stop_tls_with_protocol (1, term);
662 else
663 b = 0;
665 xfree (s);
666 if (!term && b)
668 gpg_error_t rc = tls_init_params ();
669 if (rc)
671 start_stop_tls_with_protocol (0, 1);
672 return 0;
676 return b;