]> sjero.net Git - wget/blob - src/gnutls.c
NEWS: cite --start-pos
[wget] / src / gnutls.c
1 /* SSL support via GnuTLS library.
2    Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software
3    Foundation, Inc.
4
5 This file is part of GNU Wget.
6
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.
11
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.
16
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/>.
19
20 Additional permission under GNU GPL version 3 section 7
21
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.  */
30
31 #include "wget.h"
32
33 #include <assert.h>
34 #include <errno.h>
35 #include <unistd.h>
36 #include <string.h>
37 #include <stdio.h>
38 #include <dirent.h>
39 #include <stdlib.h>
40
41 #include <gnutls/gnutls.h>
42 #include <gnutls/x509.h>
43 #include <sys/ioctl.h>
44
45 #include "utils.h"
46 #include "connect.h"
47 #include "url.h"
48 #include "ptimer.h"
49 #include "hash.h"
50 #include "ssl.h"
51
52 #include <sys/fcntl.h>
53
54 #ifdef WIN32
55 # include "w32sock.h"
56 #endif
57
58 #include "host.h"
59
60 static int
61 key_type_to_gnutls_type (enum keyfile_type type)
62 {
63   switch (type)
64     {
65     case keyfile_pem:
66       return GNUTLS_X509_FMT_PEM;
67     case keyfile_asn1:
68       return GNUTLS_X509_FMT_DER;
69     default:
70       abort ();
71     }
72 }
73
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.  */
78
79 static gnutls_certificate_credentials_t credentials;
80 bool
81 ssl_init (void)
82 {
83   /* Becomes true if GnuTLS is initialized. */
84   static bool ssl_initialized = false;
85   const char *ca_directory;
86   DIR *dir;
87   int ncerts = -1;
88
89   /* GnuTLS should be initialized only once. */
90   if (ssl_initialized)
91     return true;
92
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);
97
98 #if GNUTLS_VERSION_MAJOR >= 3
99   if (!opt.ca_directory)
100     ncerts = gnutls_certificate_set_x509_system_trust (credentials);
101 #endif
102
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.  */
105   if (ncerts <= 0)
106     {
107       ca_directory = opt.ca_directory ? opt.ca_directory : "/etc/ssl/certs";
108       if ((dir = opendir (ca_directory)) == NULL)
109         {
110           if (opt.ca_directory && *opt.ca_directory)
111             logprintf (LOG_NOTQUIET, _("ERROR: Cannot open directory %s.\n"),
112                        opt.ca_directory);
113         }
114       else
115         {
116           struct hash_table *inode_map = hash_table_new (196, NULL, NULL);
117           struct dirent *dent;
118           size_t dirlen = strlen(ca_directory);
119           int rc;
120
121           ncerts = 0;
122
123           while ((dent = readdir (dir)) != NULL)
124             {
125               struct stat st;
126               char ca_file[dirlen + strlen(dent->d_name) + 2];
127
128               snprintf (ca_file, sizeof(ca_file), "%s/%s", ca_directory, dent->d_name);
129               if (stat (ca_file, &st) != 0)
130                 continue;
131
132               if (! S_ISREG (st.st_mode))
133                 continue;
134
135               /* avoid loading the same file twice by checking the inode.  */
136               if (hash_table_contains (inode_map, (void *)(intptr_t) st.st_ino))
137                 continue;
138
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"),
143                            ca_file, rc);
144               else
145                 ncerts += rc;
146             }
147
148           hash_table_destroy (inode_map);
149           closedir (dir);
150         }
151     }
152
153   DEBUGP (("Certificates loaded: %d\n", ncerts));
154
155   /* Use the private key from the cert file unless otherwise specified. */
156   if (opt.cert_file && !opt.private_key)
157     {
158       opt.private_key = opt.cert_file;
159       opt.private_key_type = opt.cert_type;
160     }
161   /* Use the cert from the private key file unless otherwise specified. */
162   if (!opt.cert_file && opt.private_key)
163     {
164       opt.cert_file = opt.private_key;
165       opt.cert_type = opt.private_key_type;
166     }
167
168   if (opt.cert_file && opt.private_key)
169     {
170       int type;
171       if (opt.private_key_type != opt.cert_type)
172         {
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"));
176         }
177
178       type = key_type_to_gnutls_type (opt.private_key_type);
179
180       gnutls_certificate_set_x509_key_file (credentials, opt.cert_file,
181                                             opt.private_key,
182                                             type);
183     }
184
185   if (opt.ca_cert)
186     gnutls_certificate_set_x509_trust_file (credentials, opt.ca_cert,
187                                             GNUTLS_X509_FMT_PEM);
188
189   ssl_initialized = true;
190
191   return true;
192 }
193
194 struct wgnutls_transport_context
195 {
196   gnutls_session_t session;       /* GnuTLS session handle */
197   int last_error;               /* last error returned by read/write/... */
198
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
202      actually reading.  */
203   char peekbuf[512];
204   int peeklen;
205 };
206
207 #ifndef MIN
208 # define MIN(i, j) ((i) <= (j) ? (i) : (j))
209 #endif
210
211
212 static int
213 wgnutls_read_timeout (int fd, char *buf, int bufsize, void *arg, double timeout)
214 {
215 #ifdef F_GETFL
216   int flags = 0;
217 #endif
218   int ret = 0;
219   struct ptimer *timer = NULL;
220   struct wgnutls_transport_context *ctx = arg;
221   int timed_out = 0;
222
223   if (timeout)
224     {
225 #ifdef F_GETFL
226       flags = fcntl (fd, F_GETFL, 0);
227       if (flags < 0)
228         return flags;
229       if (fcntl (fd, F_SETFL, flags | O_NONBLOCK))
230         return -1;
231 #else
232       /* XXX: Assume it was blocking before.  */
233       const int one = 1;
234       if (ioctl (fd, FIONBIO, &one) < 0)
235         return -1;
236 #endif
237
238       timer = ptimer_new ();
239       if (timer == NULL)
240         return -1;
241     }
242
243   do
244     {
245       double next_timeout = 0;
246       if (timeout)
247         {
248           next_timeout = timeout - ptimer_measure (timer);
249           if (next_timeout < 0)
250             break;
251         }
252
253       ret = GNUTLS_E_AGAIN;
254       if (timeout == 0 || gnutls_record_check_pending (ctx->session)
255           || select_fd (fd, next_timeout, WAIT_FOR_READ))
256         {
257           ret = gnutls_record_recv (ctx->session, buf, bufsize);
258           timed_out = timeout && ptimer_measure (timer) >= timeout;
259         }
260     }
261   while (ret == GNUTLS_E_INTERRUPTED || (ret == GNUTLS_E_AGAIN && !timed_out));
262
263   if (timeout)
264     {
265       ptimer_destroy (timer);
266
267 #ifdef F_GETFL
268       if (fcntl (fd, F_SETFL, flags) < 0)
269         return -1;
270 #else
271       const int zero = 0;
272       if (ioctl (fd, FIONBIO, &zero) < 0)
273         return -1;
274 #endif
275
276       if (timed_out && ret == GNUTLS_E_AGAIN)
277         errno = ETIMEDOUT;
278     }
279
280   return ret;
281 }
282
283 static int
284 wgnutls_read (int fd, char *buf, int bufsize, void *arg)
285 {
286   int ret = 0;
287   struct wgnutls_transport_context *ctx = arg;
288
289   if (ctx->peeklen)
290     {
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);
297
298       return copysize;
299     }
300
301   ret = wgnutls_read_timeout (fd, buf, bufsize, arg, opt.read_timeout);
302   if (ret < 0)
303     ctx->last_error = ret;
304
305   return ret;
306 }
307
308 static int
309 wgnutls_write (int fd _GL_UNUSED, char *buf, int bufsize, void *arg)
310 {
311   int ret;
312   struct wgnutls_transport_context *ctx = arg;
313   do
314     ret = gnutls_record_send (ctx->session, buf, bufsize);
315   while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
316   if (ret < 0)
317     ctx->last_error = ret;
318   return ret;
319 }
320
321 static int
322 wgnutls_poll (int fd, double timeout, int wait_for, void *arg)
323 {
324   struct wgnutls_transport_context *ctx = arg;
325
326   if (timeout)
327     return ctx->peeklen || gnutls_record_check_pending (ctx->session)
328       || select_fd (fd, timeout, wait_for);
329   else
330     return ctx->peeklen || gnutls_record_check_pending (ctx->session);
331 }
332
333 static int
334 wgnutls_peek (int fd, char *buf, int bufsize, void *arg)
335 {
336   int read = 0;
337   struct wgnutls_transport_context *ctx = arg;
338   int offset = MIN (bufsize, ctx->peeklen);
339
340   if (ctx->peeklen)
341     {
342       memcpy (buf, ctx->peekbuf, offset);
343       return offset;
344     }
345
346   if (bufsize > (int) sizeof ctx->peekbuf)
347     bufsize = sizeof ctx->peekbuf;
348
349   if (bufsize > offset)
350     {
351       if (opt.read_timeout && gnutls_record_check_pending (ctx->session) == 0
352           && select_fd (fd, 0.0, WAIT_FOR_READ) <= 0)
353         read = 0;
354       else
355         read = wgnutls_read_timeout (fd, buf + offset, bufsize - offset,
356                                      ctx, opt.read_timeout);
357       if (read < 0)
358         {
359           if (offset)
360             read = 0;
361           else
362             return read;
363         }
364
365       if (read > 0)
366         {
367           memcpy (ctx->peekbuf + offset, buf + offset,
368                   read);
369           ctx->peeklen += read;
370         }
371     }
372
373   return offset + read;
374 }
375
376 static const char *
377 wgnutls_errstr (int fd _GL_UNUSED, void *arg)
378 {
379   struct wgnutls_transport_context *ctx = arg;
380   return gnutls_strerror (ctx->last_error);
381 }
382
383 static void
384 wgnutls_close (int fd, void *arg)
385 {
386   struct wgnutls_transport_context *ctx = arg;
387   /*gnutls_bye (ctx->session, GNUTLS_SHUT_RDWR);*/
388   gnutls_deinit (ctx->session);
389   xfree (ctx);
390   close (fd);
391 }
392
393 /* gnutls_transport is the singleton that describes the SSL transport
394    methods provided by this file.  */
395
396 static struct transport_implementation wgnutls_transport =
397 {
398   wgnutls_read, wgnutls_write, wgnutls_poll,
399   wgnutls_peek, wgnutls_errstr, wgnutls_close
400 };
401
402 bool
403 ssl_connect_wget (int fd, const char *hostname)
404 {
405 #ifdef F_GETFL
406   int flags = 0;
407 #endif
408   struct wgnutls_transport_context *ctx;
409   gnutls_session_t session;
410   int err,alert;
411   gnutls_init (&session, GNUTLS_CLIENT);
412   const char *str;
413
414   /* We set the server name but only if it's not an IP address. */
415   if (! is_valid_ip_address (hostname))
416     {
417       gnutls_server_name_set (session, GNUTLS_NAME_DNS, hostname,
418                               strlen (hostname));
419     }
420
421   gnutls_set_default_priority (session);
422   gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, credentials);
423 #ifndef FD_TO_SOCKET
424 # define FD_TO_SOCKET(X) (X)
425 #endif
426 #ifdef HAVE_INTPTR_T
427   gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) (intptr_t) FD_TO_SOCKET (fd));
428 #else
429   gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) FD_TO_SOCKET (fd));
430 #endif
431
432   err = 0;
433 #if HAVE_GNUTLS_PRIORITY_SET_DIRECT
434   switch (opt.secure_protocol)
435     {
436     case secure_protocol_auto:
437       break;
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);
441       break;
442     case secure_protocol_tlsv1:
443       err = gnutls_priority_set_direct (session, "NORMAL:-VERS-SSL3.0", NULL);
444       break;
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);
450       break;
451     default:
452       abort ();
453     }
454 #else
455   int allowed_protocols[4] = {0, 0, 0, 0};
456   switch (opt.secure_protocol)
457     {
458     case secure_protocol_auto:
459       break;
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);
464       break;
465
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);
471       break;
472
473     default:
474       abort ();
475     }
476 #endif
477
478   if (err < 0)
479     {
480       logprintf (LOG_NOTQUIET, "GnuTLS: %s\n", gnutls_strerror (err));
481       gnutls_deinit (session);
482       return false;
483     }
484
485   if (opt.connect_timeout)
486     {
487 #ifdef F_GETFL
488       flags = fcntl (fd, F_GETFL, 0);
489       if (flags < 0)
490         return flags;
491       if (fcntl (fd, F_SETFL, flags | O_NONBLOCK))
492         return -1;
493 #else
494       /* XXX: Assume it was blocking before.  */
495       const int one = 1;
496       if (ioctl (fd, FIONBIO, &one) < 0)
497         return -1;
498 #endif
499     }
500
501   /* We don't stop the handshake process for non-fatal errors */
502   do
503     {
504       err = gnutls_handshake (session);
505
506       if (opt.connect_timeout && err == GNUTLS_E_AGAIN)
507         {
508           if (gnutls_record_get_direction (session))
509             {
510               /* wait for writeability */
511               err = select_fd (fd, opt.connect_timeout, WAIT_FOR_WRITE);
512             }
513           else
514             {
515               /* wait for readability */
516               err = select_fd (fd, opt.connect_timeout, WAIT_FOR_READ);
517             }
518
519           if (err <= 0)
520             {
521               if (err == 0)
522                 {
523                   errno = ETIMEDOUT;
524                   err = -1;
525                 }
526               break;
527             }
528
529            err = GNUTLS_E_AGAIN;
530         }
531       else if (err < 0)
532         {
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)
536             {
537               alert = gnutls_alert_get (session);
538               str = gnutls_alert_get_name (alert);
539               if (str == NULL)
540                 str = "(unknown)";
541               logprintf (LOG_NOTQUIET, "GnuTLS: received alert [%d]: %s\n", alert, str);
542             }
543         }
544     }
545   while (err && gnutls_error_is_fatal (err) == 0);
546
547   if (opt.connect_timeout)
548     {
549 #ifdef F_GETFL
550       if (fcntl (fd, F_SETFL, flags) < 0)
551         return -1;
552 #else
553       const int zero = 0;
554       if (ioctl (fd, FIONBIO, &zero) < 0)
555         return -1;
556 #endif
557     }
558
559   if (err < 0)
560     {
561       gnutls_deinit (session);
562       return false;
563     }
564
565   ctx = xnew0 (struct wgnutls_transport_context);
566   ctx->session = session;
567   fd_register_transport (fd, &wgnutls_transport, ctx);
568   return true;
569 }
570
571 #define _CHECK_CERT(flag,msg) \
572   if (status & (flag))\
573     {\
574       logprintf (LOG_NOTQUIET, (msg),\
575                  severity, quote (host));\
576       success = false;\
577     }
578
579 bool
580 ssl_check_certificate (int fd, const char *host)
581 {
582   struct wgnutls_transport_context *ctx = fd_transport_context (fd);
583
584   unsigned int status;
585   int err;
586
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");
590   bool success = true;
591
592   err = gnutls_certificate_verify_peers2 (ctx->session, &status);
593   if (err < 0)
594     {
595       logprintf (LOG_NOTQUIET, _("%s: No certificate presented by %s.\n"),
596                  severity, quotearg_style (escape_quoting_style, host));
597       success = false;
598       goto out;
599     }
600
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"));
608
609   if (gnutls_certificate_type_get (ctx->session) == GNUTLS_CRT_X509)
610     {
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;
615
616       if ((err = gnutls_x509_crt_init (&cert)) < 0)
617         {
618           logprintf (LOG_NOTQUIET, _("Error initializing X509 certificate: %s\n"),
619                      gnutls_strerror (err));
620           success = false;
621           goto out;
622         }
623
624       cert_list = gnutls_certificate_get_peers (ctx->session, &cert_list_size);
625       if (!cert_list)
626         {
627           logprintf (LOG_NOTQUIET, _("No certificate found\n"));
628           success = false;
629           goto crt_deinit;
630         }
631       err = gnutls_x509_crt_import (cert, cert_list, GNUTLS_X509_FMT_DER);
632       if (err < 0)
633         {
634           logprintf (LOG_NOTQUIET, _("Error parsing certificate: %s\n"),
635                      gnutls_strerror (err));
636           success = false;
637           goto crt_deinit;
638         }
639       if (now < gnutls_x509_crt_get_activation_time (cert))
640         {
641           logprintf (LOG_NOTQUIET, _("The certificate has not yet been activated\n"));
642           success = false;
643         }
644       if (now >= gnutls_x509_crt_get_expiration_time (cert))
645         {
646           logprintf (LOG_NOTQUIET, _("The certificate has expired\n"));
647           success = false;
648         }
649       if (!gnutls_x509_crt_check_hostname (cert, host))
650         {
651           logprintf (LOG_NOTQUIET,
652                      _("The certificate's owner does not match hostname %s\n"),
653                      quote (host));
654           success = false;
655         }
656  crt_deinit:
657       gnutls_x509_crt_deinit (cert);
658     }
659   else
660     {
661       logprintf (LOG_NOTQUIET, _("Certificate must be X.509\n"));
662       success = false;
663     }
664
665  out:
666   return opt.check_cert ? success : true;
667 }