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 err = gnutls_priority_set_direct (session, "PFS", NULL);
447 if (err != GNUTLS_E_SUCCESS)
448 /* fallback if PFS is not available */
449 err = gnutls_priority_set_direct (session, "NORMAL:-RSA", NULL);
455 int allowed_protocols[4] = {0, 0, 0, 0};
456 switch (opt.secure_protocol)
458 case secure_protocol_auto:
460 case secure_protocol_sslv2:
461 case secure_protocol_sslv3:
462 allowed_protocols[0] = GNUTLS_SSL3;
463 err = gnutls_protocol_set_priority (session, allowed_protocols);
466 case secure_protocol_tlsv1:
467 allowed_protocols[0] = GNUTLS_TLS1_0;
468 allowed_protocols[1] = GNUTLS_TLS1_1;
469 allowed_protocols[2] = GNUTLS_TLS1_2;
470 err = gnutls_protocol_set_priority (session, allowed_protocols);
480 logprintf (LOG_NOTQUIET, "GnuTLS: %s\n", gnutls_strerror (err));
481 gnutls_deinit (session);
485 if (opt.connect_timeout)
488 flags = fcntl (fd, F_GETFL, 0);
491 if (fcntl (fd, F_SETFL, flags | O_NONBLOCK))
494 /* XXX: Assume it was blocking before. */
496 if (ioctl (fd, FIONBIO, &one) < 0)
501 /* We don't stop the handshake process for non-fatal errors */
504 err = gnutls_handshake (session);
506 if (opt.connect_timeout && err == GNUTLS_E_AGAIN)
508 if (gnutls_record_get_direction (session))
510 /* wait for writeability */
511 err = select_fd (fd, opt.connect_timeout, WAIT_FOR_WRITE);
515 /* wait for readability */
516 err = select_fd (fd, opt.connect_timeout, WAIT_FOR_READ);
529 err = GNUTLS_E_AGAIN;
533 logprintf (LOG_NOTQUIET, "GnuTLS: %s\n", gnutls_strerror (err));
534 if (err == GNUTLS_E_WARNING_ALERT_RECEIVED ||
535 err == GNUTLS_E_FATAL_ALERT_RECEIVED)
537 alert = gnutls_alert_get (session);
538 str = gnutls_alert_get_name (alert);
541 logprintf (LOG_NOTQUIET, "GnuTLS: received alert [%d]: %s\n", alert, str);
545 while (err && gnutls_error_is_fatal (err) == 0);
547 if (opt.connect_timeout)
550 if (fcntl (fd, F_SETFL, flags) < 0)
554 if (ioctl (fd, FIONBIO, &zero) < 0)
561 gnutls_deinit (session);
565 ctx = xnew0 (struct wgnutls_transport_context);
566 ctx->session = session;
567 fd_register_transport (fd, &wgnutls_transport, ctx);
571 #define _CHECK_CERT(flag,msg) \
572 if (status & (flag))\
574 logprintf (LOG_NOTQUIET, (msg),\
575 severity, quote (host));\
580 ssl_check_certificate (int fd, const char *host)
582 struct wgnutls_transport_context *ctx = fd_transport_context (fd);
587 /* If the user has specified --no-check-cert, we still want to warn
588 him about problems with the server's certificate. */
589 const char *severity = opt.check_cert ? _("ERROR") : _("WARNING");
592 err = gnutls_certificate_verify_peers2 (ctx->session, &status);
595 logprintf (LOG_NOTQUIET, _("%s: No certificate presented by %s.\n"),
596 severity, quotearg_style (escape_quoting_style, host));
601 _CHECK_CERT (GNUTLS_CERT_INVALID, _("%s: The certificate of %s is not trusted.\n"));
602 _CHECK_CERT (GNUTLS_CERT_SIGNER_NOT_FOUND, _("%s: The certificate of %s hasn't got a known issuer.\n"));
603 _CHECK_CERT (GNUTLS_CERT_REVOKED, _("%s: The certificate of %s has been revoked.\n"));
604 _CHECK_CERT (GNUTLS_CERT_SIGNER_NOT_CA, _("%s: The certificate signer of %s was not a CA.\n"));
605 _CHECK_CERT (GNUTLS_CERT_INSECURE_ALGORITHM, _("%s: The certificate of %s was signed using an insecure algorithm.\n"));
606 _CHECK_CERT (GNUTLS_CERT_NOT_ACTIVATED, _("%s: The certificate of %s is not yet activated.\n"));
607 _CHECK_CERT (GNUTLS_CERT_EXPIRED, _("%s: The certificate of %s has expired.\n"));
609 if (gnutls_certificate_type_get (ctx->session) == GNUTLS_CRT_X509)
611 time_t now = time (NULL);
612 gnutls_x509_crt_t cert;
613 const gnutls_datum_t *cert_list;
614 unsigned int cert_list_size;
616 if ((err = gnutls_x509_crt_init (&cert)) < 0)
618 logprintf (LOG_NOTQUIET, _("Error initializing X509 certificate: %s\n"),
619 gnutls_strerror (err));
624 cert_list = gnutls_certificate_get_peers (ctx->session, &cert_list_size);
627 logprintf (LOG_NOTQUIET, _("No certificate found\n"));
631 err = gnutls_x509_crt_import (cert, cert_list, GNUTLS_X509_FMT_DER);
634 logprintf (LOG_NOTQUIET, _("Error parsing certificate: %s\n"),
635 gnutls_strerror (err));
639 if (now < gnutls_x509_crt_get_activation_time (cert))
641 logprintf (LOG_NOTQUIET, _("The certificate has not yet been activated\n"));
644 if (now >= gnutls_x509_crt_get_expiration_time (cert))
646 logprintf (LOG_NOTQUIET, _("The certificate has expired\n"));
649 if (!gnutls_x509_crt_check_hostname (cert, host))
651 logprintf (LOG_NOTQUIET,
652 _("The certificate's owner does not match hostname %s\n"),
657 gnutls_x509_crt_deinit (cert);
661 logprintf (LOG_NOTQUIET, _("Certificate must be X.509\n"));
666 return opt.check_cert ? success : true;