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);
449 int allowed_protocols[4] = {0, 0, 0, 0};
450 switch (opt.secure_protocol)
452 case secure_protocol_auto:
454 case secure_protocol_sslv2:
455 case secure_protocol_sslv3:
456 allowed_protocols[0] = GNUTLS_SSL3;
457 err = gnutls_protocol_set_priority (session, allowed_protocols);
460 case secure_protocol_tlsv1:
461 allowed_protocols[0] = GNUTLS_TLS1_0;
462 allowed_protocols[1] = GNUTLS_TLS1_1;
463 allowed_protocols[2] = GNUTLS_TLS1_2;
464 err = gnutls_protocol_set_priority (session, allowed_protocols);
474 logprintf (LOG_NOTQUIET, "GnuTLS: %s\n", gnutls_strerror (err));
475 gnutls_deinit (session);
479 if (opt.connect_timeout)
482 flags = fcntl (fd, F_GETFL, 0);
485 if (fcntl (fd, F_SETFL, flags | O_NONBLOCK))
488 /* XXX: Assume it was blocking before. */
490 if (ioctl (fd, FIONBIO, &one) < 0)
495 /* We don't stop the handshake process for non-fatal errors */
498 err = gnutls_handshake (session);
500 if (opt.connect_timeout && err == GNUTLS_E_AGAIN)
502 if (gnutls_record_get_direction (session))
504 /* wait for writeability */
505 err = select_fd (fd, opt.connect_timeout, WAIT_FOR_WRITE);
509 /* wait for readability */
510 err = select_fd (fd, opt.connect_timeout, WAIT_FOR_READ);
528 logprintf (LOG_NOTQUIET, "GnuTLS: %s\n", gnutls_strerror (err));
529 if (err == GNUTLS_E_WARNING_ALERT_RECEIVED ||
530 err == GNUTLS_E_FATAL_ALERT_RECEIVED)
532 alert = gnutls_alert_get (session);
533 str = gnutls_alert_get_name (alert);
536 logprintf (LOG_NOTQUIET, "GnuTLS: received alert [%d]: %s\n", alert, str);
540 while (err == GNUTLS_E_WARNING_ALERT_RECEIVED && gnutls_error_is_fatal (err) == 0);
542 if (opt.connect_timeout)
545 if (fcntl (fd, F_SETFL, flags) < 0)
549 if (ioctl (fd, FIONBIO, &zero) < 0)
556 gnutls_deinit (session);
560 ctx = xnew0 (struct wgnutls_transport_context);
561 ctx->session = session;
562 fd_register_transport (fd, &wgnutls_transport, ctx);
566 #define _CHECK_CERT(flag,msg) \
567 if (status & (flag))\
569 logprintf (LOG_NOTQUIET, (msg),\
570 severity, quote (host));\
575 ssl_check_certificate (int fd, const char *host)
577 struct wgnutls_transport_context *ctx = fd_transport_context (fd);
582 /* If the user has specified --no-check-cert, we still want to warn
583 him about problems with the server's certificate. */
584 const char *severity = opt.check_cert ? _("ERROR") : _("WARNING");
587 err = gnutls_certificate_verify_peers2 (ctx->session, &status);
590 logprintf (LOG_NOTQUIET, _("%s: No certificate presented by %s.\n"),
591 severity, quotearg_style (escape_quoting_style, host));
596 _CHECK_CERT (GNUTLS_CERT_INVALID, _("%s: The certificate of %s is not trusted.\n"));
597 _CHECK_CERT (GNUTLS_CERT_SIGNER_NOT_FOUND, _("%s: The certificate of %s hasn't got a known issuer.\n"));
598 _CHECK_CERT (GNUTLS_CERT_REVOKED, _("%s: The certificate of %s has been revoked.\n"));
599 _CHECK_CERT (GNUTLS_CERT_SIGNER_NOT_CA, _("%s: The certificate signer of %s was not a CA.\n"));
600 _CHECK_CERT (GNUTLS_CERT_INSECURE_ALGORITHM, _("%s: The certificate of %s was signed using an insecure algorithm.\n"));
601 _CHECK_CERT (GNUTLS_CERT_NOT_ACTIVATED, _("%s: The certificate of %s is not yet activated.\n"));
602 _CHECK_CERT (GNUTLS_CERT_EXPIRED, _("%s: The certificate of %s has expired.\n"));
604 if (gnutls_certificate_type_get (ctx->session) == GNUTLS_CRT_X509)
606 time_t now = time (NULL);
607 gnutls_x509_crt_t cert;
608 const gnutls_datum_t *cert_list;
609 unsigned int cert_list_size;
611 if ((err = gnutls_x509_crt_init (&cert)) < 0)
613 logprintf (LOG_NOTQUIET, _("Error initializing X509 certificate: %s\n"),
614 gnutls_strerror (err));
619 cert_list = gnutls_certificate_get_peers (ctx->session, &cert_list_size);
622 logprintf (LOG_NOTQUIET, _("No certificate found\n"));
626 err = gnutls_x509_crt_import (cert, cert_list, GNUTLS_X509_FMT_DER);
629 logprintf (LOG_NOTQUIET, _("Error parsing certificate: %s\n"),
630 gnutls_strerror (err));
634 if (now < gnutls_x509_crt_get_activation_time (cert))
636 logprintf (LOG_NOTQUIET, _("The certificate has not yet been activated\n"));
639 if (now >= gnutls_x509_crt_get_expiration_time (cert))
641 logprintf (LOG_NOTQUIET, _("The certificate has expired\n"));
644 if (!gnutls_x509_crt_check_hostname (cert, host))
646 logprintf (LOG_NOTQUIET,
647 _("The certificate's owner does not match hostname %s\n"),
652 gnutls_x509_crt_deinit (cert);
656 logprintf (LOG_NOTQUIET, _("Certificate must be X.509\n"));
661 return opt.check_cert ? success : true;