1 /* SSL support via GnuTLS library.
2 Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software
5 This file is part of GNU Wget.
7 GNU Wget is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 GNU Wget is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Wget. If not, see <http://www.gnu.org/licenses/>.
20 Additional permission under GNU GPL version 3 section 7
22 If you modify this program, or any covered work, by linking or
23 combining it with the OpenSSL project's OpenSSL library (or a
24 modified version of that library), containing parts covered by the
25 terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
26 grants you additional permission to convey the resulting work.
27 Corresponding Source for a non-source form of such a combination
28 shall include the source code for the parts of OpenSSL used as well
29 as that of the covered work. */
41 #include <gnutls/gnutls.h>
42 #include <gnutls/x509.h>
43 #include <sys/ioctl.h>
52 #include <sys/fcntl.h>
61 key_type_to_gnutls_type (enum keyfile_type type)
66 return GNUTLS_X509_FMT_PEM;
68 return GNUTLS_X509_FMT_DER;
74 /* Note: some of the functions private to this file have names that
75 begin with "wgnutls_" (e.g. wgnutls_read) so that they wouldn't be
76 confused with actual gnutls functions -- such as the gnutls_read
77 preprocessor macro. */
79 static gnutls_certificate_credentials_t credentials;
83 /* Becomes true if GnuTLS is initialized. */
84 static bool ssl_initialized = false;
85 const char *ca_directory;
89 /* GnuTLS should be initialized only once. */
93 gnutls_global_init ();
94 gnutls_certificate_allocate_credentials (&credentials);
95 gnutls_certificate_set_verify_flags (credentials,
96 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
98 #if GNUTLS_VERSION_MAJOR >= 3
99 if (!opt.ca_directory)
100 ncerts = gnutls_certificate_set_x509_system_trust (credentials);
103 /* If GnuTLS version is too old or CA loading failed, fallback to old behaviour.
104 * Also use old behaviour if the CA directory is user-provided. */
107 ca_directory = opt.ca_directory ? opt.ca_directory : "/etc/ssl/certs";
108 if ((dir = opendir (ca_directory)) == NULL)
110 if (opt.ca_directory && *opt.ca_directory)
111 logprintf (LOG_NOTQUIET, _("ERROR: Cannot open directory %s.\n"),
116 struct hash_table *inode_map = hash_table_new (196, NULL, NULL);
118 size_t dirlen = strlen(ca_directory);
123 while ((dent = readdir (dir)) != NULL)
126 char ca_file[dirlen + strlen(dent->d_name) + 2];
128 snprintf (ca_file, sizeof(ca_file), "%s/%s", ca_directory, dent->d_name);
129 if (stat (ca_file, &st) != 0)
132 if (! S_ISREG (st.st_mode))
135 /* avoid loading the same file twice by checking the inode. */
136 if (hash_table_contains (inode_map, (void *)(intptr_t) st.st_ino))
139 hash_table_put (inode_map, (void *)(intptr_t) st.st_ino, NULL);
140 if ((rc = gnutls_certificate_set_x509_trust_file (credentials, ca_file,
141 GNUTLS_X509_FMT_PEM)) <= 0)
142 logprintf (LOG_NOTQUIET, _("ERROR: Failed to open cert %s: (%d).\n"),
148 hash_table_destroy (inode_map);
153 DEBUGP (("Certificates loaded: %d\n", ncerts));
155 /* Use the private key from the cert file unless otherwise specified. */
156 if (opt.cert_file && !opt.private_key)
158 opt.private_key = opt.cert_file;
159 opt.private_key_type = opt.cert_type;
161 /* Use the cert from the private key file unless otherwise specified. */
162 if (!opt.cert_file && opt.private_key)
164 opt.cert_file = opt.private_key;
165 opt.cert_type = opt.private_key_type;
168 if (opt.cert_file && opt.private_key)
171 if (opt.private_key_type != opt.cert_type)
173 /* GnuTLS can't handle this */
174 logprintf (LOG_NOTQUIET, _("ERROR: GnuTLS requires the key and the \
175 cert to be of the same type.\n"));
178 type = key_type_to_gnutls_type (opt.private_key_type);
180 gnutls_certificate_set_x509_key_file (credentials, opt.cert_file,
186 gnutls_certificate_set_x509_trust_file (credentials, opt.ca_cert,
187 GNUTLS_X509_FMT_PEM);
189 ssl_initialized = true;
194 struct wgnutls_transport_context
196 gnutls_session_t session; /* GnuTLS session handle */
197 int last_error; /* last error returned by read/write/... */
199 /* Since GnuTLS doesn't support the equivalent to recv(...,
200 MSG_PEEK) or SSL_peek(), we have to do it ourselves. Peeked data
201 is stored to PEEKBUF, and wgnutls_read checks that buffer before
208 # define MIN(i, j) ((i) <= (j) ? (i) : (j))
213 wgnutls_read_timeout (int fd, char *buf, int bufsize, void *arg, double timeout)
219 struct ptimer *timer = NULL;
220 struct wgnutls_transport_context *ctx = arg;
226 flags = fcntl (fd, F_GETFL, 0);
229 if (fcntl (fd, F_SETFL, flags | O_NONBLOCK))
232 /* XXX: Assume it was blocking before. */
234 if (ioctl (fd, FIONBIO, &one) < 0)
238 timer = ptimer_new ();
245 double next_timeout = 0;
248 next_timeout = timeout - ptimer_measure (timer);
249 if (next_timeout < 0)
253 ret = GNUTLS_E_AGAIN;
254 if (timeout == 0 || gnutls_record_check_pending (ctx->session)
255 || select_fd (fd, next_timeout, WAIT_FOR_READ))
257 ret = gnutls_record_recv (ctx->session, buf, bufsize);
258 timed_out = timeout && ptimer_measure (timer) >= timeout;
261 while (ret == GNUTLS_E_INTERRUPTED || (ret == GNUTLS_E_AGAIN && !timed_out));
265 ptimer_destroy (timer);
268 if (fcntl (fd, F_SETFL, flags) < 0)
272 if (ioctl (fd, FIONBIO, &zero) < 0)
276 if (timed_out && ret == GNUTLS_E_AGAIN)
284 wgnutls_read (int fd, char *buf, int bufsize, void *arg)
287 struct wgnutls_transport_context *ctx = arg;
291 /* If we have any peek data, simply return that. */
292 int copysize = MIN (bufsize, ctx->peeklen);
293 memcpy (buf, ctx->peekbuf, copysize);
294 ctx->peeklen -= copysize;
295 if (ctx->peeklen != 0)
296 memmove (ctx->peekbuf, ctx->peekbuf + copysize, ctx->peeklen);
301 ret = wgnutls_read_timeout (fd, buf, bufsize, arg, opt.read_timeout);
303 ctx->last_error = ret;
309 wgnutls_write (int fd _GL_UNUSED, char *buf, int bufsize, void *arg)
312 struct wgnutls_transport_context *ctx = arg;
314 ret = gnutls_record_send (ctx->session, buf, bufsize);
315 while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
317 ctx->last_error = ret;
322 wgnutls_poll (int fd, double timeout, int wait_for, void *arg)
324 struct wgnutls_transport_context *ctx = arg;
327 return ctx->peeklen || gnutls_record_check_pending (ctx->session)
328 || select_fd (fd, timeout, wait_for);
330 return ctx->peeklen || gnutls_record_check_pending (ctx->session);
334 wgnutls_peek (int fd, char *buf, int bufsize, void *arg)
337 struct wgnutls_transport_context *ctx = arg;
338 int offset = MIN (bufsize, ctx->peeklen);
342 memcpy (buf, ctx->peekbuf, offset);
346 if (bufsize > (int) sizeof ctx->peekbuf)
347 bufsize = sizeof ctx->peekbuf;
349 if (bufsize > offset)
351 if (opt.read_timeout && gnutls_record_check_pending (ctx->session) == 0
352 && select_fd (fd, 0.0, WAIT_FOR_READ) <= 0)
355 read = wgnutls_read_timeout (fd, buf + offset, bufsize - offset,
356 ctx, opt.read_timeout);
367 memcpy (ctx->peekbuf + offset, buf + offset,
369 ctx->peeklen += read;
373 return offset + read;
377 wgnutls_errstr (int fd _GL_UNUSED, void *arg)
379 struct wgnutls_transport_context *ctx = arg;
380 return gnutls_strerror (ctx->last_error);
384 wgnutls_close (int fd, void *arg)
386 struct wgnutls_transport_context *ctx = arg;
387 /*gnutls_bye (ctx->session, GNUTLS_SHUT_RDWR);*/
388 gnutls_deinit (ctx->session);
393 /* gnutls_transport is the singleton that describes the SSL transport
394 methods provided by this file. */
396 static struct transport_implementation wgnutls_transport =
398 wgnutls_read, wgnutls_write, wgnutls_poll,
399 wgnutls_peek, wgnutls_errstr, wgnutls_close
403 ssl_connect_wget (int fd, const char *hostname)
408 struct wgnutls_transport_context *ctx;
409 gnutls_session_t session;
411 gnutls_init (&session, GNUTLS_CLIENT);
414 /* We set the server name but only if it's not an IP address. */
415 if (! is_valid_ip_address (hostname))
417 gnutls_server_name_set (session, GNUTLS_NAME_DNS, hostname,
421 gnutls_set_default_priority (session);
422 gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, credentials);
424 # define FD_TO_SOCKET(X) (X)
427 gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) (intptr_t) FD_TO_SOCKET (fd));
429 gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) FD_TO_SOCKET (fd));
433 #if HAVE_GNUTLS_PRIORITY_SET_DIRECT
434 switch (opt.secure_protocol)
436 case secure_protocol_auto:
438 case secure_protocol_sslv2:
439 case secure_protocol_sslv3:
440 err = gnutls_priority_set_direct (session, "NORMAL:-VERS-TLS-ALL:+VERS-SSL3.0", NULL);
442 case secure_protocol_tlsv1:
443 err = gnutls_priority_set_direct (session, "NORMAL:-VERS-SSL3.0", NULL);
445 case secure_protocol_pfs:
446 #if defined (GNUTLS_VERSION_NUMBER) && GNUTLS_VERSION_NUMBER >= 0x030204
447 err = gnutls_priority_set_direct (session, "PFS", NULL);
449 err = gnutls_priority_set_direct (session, "NORMAL:-RSA", NULL);
456 int allowed_protocols[4] = {0, 0, 0, 0};
457 switch (opt.secure_protocol)
459 case secure_protocol_auto:
461 case secure_protocol_sslv2:
462 case secure_protocol_sslv3:
463 allowed_protocols[0] = GNUTLS_SSL3;
464 err = gnutls_protocol_set_priority (session, allowed_protocols);
467 case secure_protocol_tlsv1:
468 allowed_protocols[0] = GNUTLS_TLS1_0;
469 allowed_protocols[1] = GNUTLS_TLS1_1;
470 allowed_protocols[2] = GNUTLS_TLS1_2;
471 err = gnutls_protocol_set_priority (session, allowed_protocols);
481 logprintf (LOG_NOTQUIET, "GnuTLS: %s\n", gnutls_strerror (err));
482 gnutls_deinit (session);
486 if (opt.connect_timeout)
489 flags = fcntl (fd, F_GETFL, 0);
492 if (fcntl (fd, F_SETFL, flags | O_NONBLOCK))
495 /* XXX: Assume it was blocking before. */
497 if (ioctl (fd, FIONBIO, &one) < 0)
502 /* We don't stop the handshake process for non-fatal errors */
505 err = gnutls_handshake (session);
507 if (opt.connect_timeout && err == GNUTLS_E_AGAIN)
509 if (gnutls_record_get_direction (session))
511 /* wait for writeability */
512 err = select_fd (fd, opt.connect_timeout, WAIT_FOR_WRITE);
516 /* wait for readability */
517 err = select_fd (fd, opt.connect_timeout, WAIT_FOR_READ);
535 logprintf (LOG_NOTQUIET, "GnuTLS: %s\n", gnutls_strerror (err));
536 if (err == GNUTLS_E_WARNING_ALERT_RECEIVED ||
537 err == GNUTLS_E_FATAL_ALERT_RECEIVED)
539 alert = gnutls_alert_get (session);
540 str = gnutls_alert_get_name (alert);
543 logprintf (LOG_NOTQUIET, "GnuTLS: received alert [%d]: %s\n", alert, str);
547 while (err == GNUTLS_E_WARNING_ALERT_RECEIVED && gnutls_error_is_fatal (err) == 0);
549 if (opt.connect_timeout)
552 if (fcntl (fd, F_SETFL, flags) < 0)
556 if (ioctl (fd, FIONBIO, &zero) < 0)
563 gnutls_deinit (session);
567 ctx = xnew0 (struct wgnutls_transport_context);
568 ctx->session = session;
569 fd_register_transport (fd, &wgnutls_transport, ctx);
573 #define _CHECK_CERT(flag,msg) \
574 if (status & (flag))\
576 logprintf (LOG_NOTQUIET, (msg),\
577 severity, quote (host));\
582 ssl_check_certificate (int fd, const char *host)
584 struct wgnutls_transport_context *ctx = fd_transport_context (fd);
589 /* If the user has specified --no-check-cert, we still want to warn
590 him about problems with the server's certificate. */
591 const char *severity = opt.check_cert ? _("ERROR") : _("WARNING");
594 err = gnutls_certificate_verify_peers2 (ctx->session, &status);
597 logprintf (LOG_NOTQUIET, _("%s: No certificate presented by %s.\n"),
598 severity, quotearg_style (escape_quoting_style, host));
603 _CHECK_CERT (GNUTLS_CERT_INVALID, _("%s: The certificate of %s is not trusted.\n"));
604 _CHECK_CERT (GNUTLS_CERT_SIGNER_NOT_FOUND, _("%s: The certificate of %s hasn't got a known issuer.\n"));
605 _CHECK_CERT (GNUTLS_CERT_REVOKED, _("%s: The certificate of %s has been revoked.\n"));
606 _CHECK_CERT (GNUTLS_CERT_SIGNER_NOT_CA, _("%s: The certificate signer of %s was not a CA.\n"));
607 _CHECK_CERT (GNUTLS_CERT_INSECURE_ALGORITHM, _("%s: The certificate of %s was signed using an insecure algorithm.\n"));
608 _CHECK_CERT (GNUTLS_CERT_NOT_ACTIVATED, _("%s: The certificate of %s is not yet activated.\n"));
609 _CHECK_CERT (GNUTLS_CERT_EXPIRED, _("%s: The certificate of %s has expired.\n"));
611 if (gnutls_certificate_type_get (ctx->session) == GNUTLS_CRT_X509)
613 time_t now = time (NULL);
614 gnutls_x509_crt_t cert;
615 const gnutls_datum_t *cert_list;
616 unsigned int cert_list_size;
618 if ((err = gnutls_x509_crt_init (&cert)) < 0)
620 logprintf (LOG_NOTQUIET, _("Error initializing X509 certificate: %s\n"),
621 gnutls_strerror (err));
626 cert_list = gnutls_certificate_get_peers (ctx->session, &cert_list_size);
629 logprintf (LOG_NOTQUIET, _("No certificate found\n"));
633 err = gnutls_x509_crt_import (cert, cert_list, GNUTLS_X509_FMT_DER);
636 logprintf (LOG_NOTQUIET, _("Error parsing certificate: %s\n"),
637 gnutls_strerror (err));
641 if (now < gnutls_x509_crt_get_activation_time (cert))
643 logprintf (LOG_NOTQUIET, _("The certificate has not yet been activated\n"));
646 if (now >= gnutls_x509_crt_get_expiration_time (cert))
648 logprintf (LOG_NOTQUIET, _("The certificate has expired\n"));
651 if (!gnutls_x509_crt_check_hostname (cert, host))
653 logprintf (LOG_NOTQUIET,
654 _("The certificate's owner does not match hostname %s\n"),
659 gnutls_x509_crt_deinit (cert);
663 logprintf (LOG_NOTQUIET, _("Certificate must be X.509\n"));
668 return opt.check_cert ? success : true;