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>
51 #include <sys/fcntl.h>
60 key_type_to_gnutls_type (enum keyfile_type type)
65 return GNUTLS_X509_FMT_PEM;
67 return GNUTLS_X509_FMT_DER;
73 /* Note: some of the functions private to this file have names that
74 begin with "wgnutls_" (e.g. wgnutls_read) so that they wouldn't be
75 confused with actual gnutls functions -- such as the gnutls_read
76 preprocessor macro. */
78 static gnutls_certificate_credentials_t credentials;
82 /* Becomes true if GnuTLS is initialized. */
83 static bool ssl_initialized = false;
85 /* GnuTLS should be initialized only once. */
89 const char *ca_directory;
92 gnutls_global_init ();
93 gnutls_certificate_allocate_credentials (&credentials);
94 gnutls_certificate_set_verify_flags(credentials,
95 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
97 ca_directory = opt.ca_directory ? opt.ca_directory : "/etc/ssl/certs";
99 dir = opendir (ca_directory);
102 if (opt.ca_directory && *opt.ca_directory)
103 logprintf (LOG_NOTQUIET, _("ERROR: Cannot open directory %s.\n"),
109 while ((dent = readdir (dir)) != NULL)
113 asprintf (&ca_file, "%s/%s", ca_directory, dent->d_name);
117 if (S_ISREG (st.st_mode))
118 gnutls_certificate_set_x509_trust_file (credentials, ca_file,
119 GNUTLS_X509_FMT_PEM);
127 /* Use the private key from the cert file unless otherwise specified. */
128 if (opt.cert_file && !opt.private_key)
130 opt.private_key = opt.cert_file;
131 opt.private_key_type = opt.cert_type;
133 /* Use the cert from the private key file unless otherwise specified. */
134 if (!opt.cert_file && opt.private_key)
136 opt.cert_file = opt.private_key;
137 opt.cert_type = opt.private_key_type;
140 if (opt.cert_file && opt.private_key)
143 if (opt.private_key_type != opt.cert_type)
145 /* GnuTLS can't handle this */
146 logprintf (LOG_NOTQUIET, _("ERROR: GnuTLS requires the key and the \
147 cert to be of the same type.\n"));
150 type = key_type_to_gnutls_type (opt.private_key_type);
152 gnutls_certificate_set_x509_key_file (credentials, opt.cert_file,
158 gnutls_certificate_set_x509_trust_file (credentials, opt.ca_cert,
159 GNUTLS_X509_FMT_PEM);
161 ssl_initialized = true;
166 struct wgnutls_transport_context
168 gnutls_session_t session; /* GnuTLS session handle */
169 int last_error; /* last error returned by read/write/... */
171 /* Since GnuTLS doesn't support the equivalent to recv(...,
172 MSG_PEEK) or SSL_peek(), we have to do it ourselves. Peeked data
173 is stored to PEEKBUF, and wgnutls_read checks that buffer before
180 # define MIN(i, j) ((i) <= (j) ? (i) : (j))
185 wgnutls_read_timeout (int fd, char *buf, int bufsize, void *arg, double timeout)
191 struct ptimer *timer = NULL;
192 struct wgnutls_transport_context *ctx = arg;
198 flags = fcntl (fd, F_GETFL, 0);
201 if (fcntl (fd, F_SETFL, flags | O_NONBLOCK))
204 /* XXX: Assume it was blocking before. */
206 if (ioctl (fd, FIONBIO, &one) < 0)
210 timer = ptimer_new ();
217 double next_timeout = 0;
220 next_timeout = timeout - ptimer_measure (timer);
221 if (next_timeout < 0)
225 ret = GNUTLS_E_AGAIN;
226 if (timeout == 0 || gnutls_record_check_pending (ctx->session)
227 || select_fd (fd, next_timeout, WAIT_FOR_READ))
229 ret = gnutls_record_recv (ctx->session, buf, bufsize);
230 timed_out = timeout && ptimer_measure (timer) >= timeout;
233 while (ret == GNUTLS_E_INTERRUPTED || (ret == GNUTLS_E_AGAIN && !timed_out));
237 ptimer_destroy (timer);
240 if (fcntl (fd, F_SETFL, flags) < 0)
244 if (ioctl (fd, FIONBIO, &zero) < 0)
248 if (timed_out && ret == GNUTLS_E_AGAIN)
256 wgnutls_read (int fd, char *buf, int bufsize, void *arg)
259 struct wgnutls_transport_context *ctx = arg;
263 /* If we have any peek data, simply return that. */
264 int copysize = MIN (bufsize, ctx->peeklen);
265 memcpy (buf, ctx->peekbuf, copysize);
266 ctx->peeklen -= copysize;
267 if (ctx->peeklen != 0)
268 memmove (ctx->peekbuf, ctx->peekbuf + copysize, ctx->peeklen);
273 ret = wgnutls_read_timeout (fd, buf, bufsize, arg, opt.read_timeout);
275 ctx->last_error = ret;
281 wgnutls_write (int fd, char *buf, int bufsize, void *arg)
284 struct wgnutls_transport_context *ctx = arg;
286 ret = gnutls_record_send (ctx->session, buf, bufsize);
287 while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
289 ctx->last_error = ret;
294 wgnutls_poll (int fd, double timeout, int wait_for, void *arg)
296 struct wgnutls_transport_context *ctx = arg;
299 return ctx->peeklen || gnutls_record_check_pending (ctx->session)
300 || select_fd (fd, timeout, wait_for);
302 return ctx->peeklen || gnutls_record_check_pending (ctx->session);
306 wgnutls_peek (int fd, char *buf, int bufsize, void *arg)
309 struct wgnutls_transport_context *ctx = arg;
310 int offset = MIN (bufsize, ctx->peeklen);
314 memcpy (buf, ctx->peekbuf, offset);
318 if (bufsize > sizeof ctx->peekbuf)
319 bufsize = sizeof ctx->peekbuf;
321 if (bufsize > offset)
323 if (opt.read_timeout && gnutls_record_check_pending (ctx->session) == 0
324 && select_fd (fd, 0.0, WAIT_FOR_READ) <= 0)
327 read = wgnutls_read_timeout (fd, buf + offset, bufsize - offset,
328 ctx, opt.read_timeout);
339 memcpy (ctx->peekbuf + offset, buf + offset,
341 ctx->peeklen += read;
345 return offset + read;
349 wgnutls_errstr (int fd, void *arg)
351 struct wgnutls_transport_context *ctx = arg;
352 return gnutls_strerror (ctx->last_error);
356 wgnutls_close (int fd, void *arg)
358 struct wgnutls_transport_context *ctx = arg;
359 /*gnutls_bye (ctx->session, GNUTLS_SHUT_RDWR);*/
360 gnutls_deinit (ctx->session);
365 /* gnutls_transport is the singleton that describes the SSL transport
366 methods provided by this file. */
368 static struct transport_implementation wgnutls_transport =
370 wgnutls_read, wgnutls_write, wgnutls_poll,
371 wgnutls_peek, wgnutls_errstr, wgnutls_close
375 ssl_connect_wget (int fd, const char *hostname)
380 struct wgnutls_transport_context *ctx;
381 gnutls_session_t session;
383 gnutls_init (&session, GNUTLS_CLIENT);
386 /* We set the server name but only if it's not an IP address. */
387 if (! is_valid_ip_address (hostname))
389 gnutls_server_name_set (session, GNUTLS_NAME_DNS, hostname,
393 gnutls_set_default_priority (session);
394 gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, credentials);
396 # define FD_TO_SOCKET(X) (X)
398 gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) FD_TO_SOCKET (fd));
401 #if HAVE_GNUTLS_PRIORITY_SET_DIRECT
402 switch (opt.secure_protocol)
404 case secure_protocol_auto:
406 case secure_protocol_sslv2:
407 case secure_protocol_sslv3:
408 err = gnutls_priority_set_direct (session, "NORMAL:-VERS-TLS-ALL:+VERS-SSL3.0", NULL);
410 case secure_protocol_tlsv1:
411 err = gnutls_priority_set_direct (session, "NORMAL:-VERS-SSL3.0", NULL);
417 int allowed_protocols[4] = {0, 0, 0, 0};
418 switch (opt.secure_protocol)
420 case secure_protocol_auto:
422 case secure_protocol_sslv2:
423 case secure_protocol_sslv3:
424 allowed_protocols[0] = GNUTLS_SSL3;
425 err = gnutls_protocol_set_priority (session, allowed_protocols);
428 case secure_protocol_tlsv1:
429 allowed_protocols[0] = GNUTLS_TLS1_0;
430 allowed_protocols[1] = GNUTLS_TLS1_1;
431 allowed_protocols[2] = GNUTLS_TLS1_2;
432 err = gnutls_protocol_set_priority (session, allowed_protocols);
442 logprintf (LOG_NOTQUIET, "GnuTLS: %s\n", gnutls_strerror (err));
443 gnutls_deinit (session);
447 if (opt.connect_timeout)
450 flags = fcntl (fd, F_GETFL, 0);
453 if (fcntl (fd, F_SETFL, flags | O_NONBLOCK))
456 /* XXX: Assume it was blocking before. */
458 if (ioctl (fd, FIONBIO, &one) < 0)
463 /* We don't stop the handshake process for non-fatal errors */
466 err = gnutls_handshake (session);
468 if (opt.connect_timeout && err == GNUTLS_E_AGAIN)
470 if (gnutls_record_get_direction (session))
472 /* wait for writeability */
473 err = select_fd (fd, opt.connect_timeout, WAIT_FOR_WRITE);
477 /* wait for readability */
478 err = select_fd (fd, opt.connect_timeout, WAIT_FOR_READ);
496 logprintf (LOG_NOTQUIET, "GnuTLS: %s\n", gnutls_strerror (err));
497 if (err == GNUTLS_E_WARNING_ALERT_RECEIVED ||
498 err == GNUTLS_E_FATAL_ALERT_RECEIVED)
500 alert = gnutls_alert_get (session);
501 str = gnutls_alert_get_name (alert);
504 logprintf (LOG_NOTQUIET, "GnuTLS: received alert [%d]: %s\n", alert, str);
508 while (err == GNUTLS_E_WARNING_ALERT_RECEIVED && gnutls_error_is_fatal (err) == 0);
510 if (opt.connect_timeout)
513 if (fcntl (fd, F_SETFL, flags) < 0)
517 if (ioctl (fd, FIONBIO, &zero) < 0)
524 gnutls_deinit (session);
528 ctx = xnew0 (struct wgnutls_transport_context);
529 ctx->session = session;
530 fd_register_transport (fd, &wgnutls_transport, ctx);
535 ssl_check_certificate (int fd, const char *host)
537 struct wgnutls_transport_context *ctx = fd_transport_context (fd);
542 /* If the user has specified --no-check-cert, we still want to warn
543 him about problems with the server's certificate. */
544 const char *severity = opt.check_cert ? _("ERROR") : _("WARNING");
547 err = gnutls_certificate_verify_peers2 (ctx->session, &status);
550 logprintf (LOG_NOTQUIET, _("%s: No certificate presented by %s.\n"),
551 severity, quotearg_style (escape_quoting_style, host));
556 if (status & GNUTLS_CERT_INVALID)
558 logprintf (LOG_NOTQUIET, _("%s: The certificate of %s is not trusted.\n"),
559 severity, quote (host));
562 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
564 logprintf (LOG_NOTQUIET, _("%s: The certificate of %s hasn't got a known issuer.\n"),
565 severity, quote (host));
568 if (status & GNUTLS_CERT_REVOKED)
570 logprintf (LOG_NOTQUIET, _("%s: The certificate of %s has been revoked.\n"),
571 severity, quote (host));
575 if (gnutls_certificate_type_get (ctx->session) == GNUTLS_CRT_X509)
577 time_t now = time (NULL);
578 gnutls_x509_crt_t cert;
579 const gnutls_datum_t *cert_list;
580 unsigned int cert_list_size;
582 if ((err = gnutls_x509_crt_init (&cert)) < 0)
584 logprintf (LOG_NOTQUIET, _("Error initializing X509 certificate: %s\n"),
585 gnutls_strerror (err));
590 cert_list = gnutls_certificate_get_peers (ctx->session, &cert_list_size);
593 logprintf (LOG_NOTQUIET, _("No certificate found\n"));
597 err = gnutls_x509_crt_import (cert, cert_list, GNUTLS_X509_FMT_DER);
600 logprintf (LOG_NOTQUIET, _("Error parsing certificate: %s\n"),
601 gnutls_strerror (err));
605 if (now < gnutls_x509_crt_get_activation_time (cert))
607 logprintf (LOG_NOTQUIET, _("The certificate has not yet been activated\n"));
610 if (now >= gnutls_x509_crt_get_expiration_time (cert))
612 logprintf (LOG_NOTQUIET, _("The certificate has expired\n"));
615 if (!gnutls_x509_crt_check_hostname (cert, host))
617 logprintf (LOG_NOTQUIET,
618 _("The certificate's owner does not match hostname %s\n"),
623 gnutls_x509_crt_deinit (cert);
627 return opt.check_cert ? success : true;