]> sjero.net Git - wget/blob - src/openssl.c
[svn] Separate SSL error messages with "; ".
[wget] / src / openssl.c
1 /* SSL support via OpenSSL library.
2    Copyright (C) 2000-2005 Free Software Foundation, Inc.
3    Originally contributed by Christian Fraenkel.
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 2 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, write to the Free Software Foundation, Inc.,
19 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
21 In addition, as a special exception, the Free Software Foundation
22 gives permission to link the code of its release of Wget with the
23 OpenSSL project's "OpenSSL" library (or with modified versions of it
24 that use the same license as the "OpenSSL" library), and distribute
25 the linked executables.  You must obey the GNU General Public License
26 in all respects for all of the code used other than "OpenSSL".  If you
27 modify this file, you may extend this exception to your version of the
28 file, but you are not obligated to do so.  If you do not wish to do
29 so, delete this exception statement from your version.  */
30
31 #include <config.h>
32
33 #include <assert.h>
34 #include <errno.h>
35 #ifdef HAVE_UNISTD_H
36 # include <unistd.h>
37 #endif
38 #include <string.h>
39
40 #include <openssl/ssl.h>
41 #include <openssl/x509.h>
42 #include <openssl/err.h>
43 #include <openssl/rand.h>
44
45 #include "wget.h"
46 #include "utils.h"
47 #include "connect.h"
48 #include "url.h"
49 #include "ssl.h"
50
51 /* Application-wide SSL context.  This is common to all SSL
52    connections.  */
53 static SSL_CTX *ssl_ctx;
54
55 /* Initialize the SSL's PRNG using various methods. */
56
57 static void
58 init_prng (void)
59 {
60   char namebuf[256];
61   const char *random_file;
62
63   if (RAND_status ())
64     /* The PRNG has been seeded; no further action is necessary. */
65     return;
66
67   /* Seed from a file specified by the user.  This will be the file
68      specified with --random-file, $RANDFILE, if set, or ~/.rnd, if it
69      exists.  */
70   if (opt.random_file)
71     random_file = opt.random_file;
72   else
73     {
74       /* Get the random file name using RAND_file_name. */
75       namebuf[0] = '\0';
76       random_file = RAND_file_name (namebuf, sizeof (namebuf));
77     }
78
79   if (random_file && *random_file)
80     /* Seed at most 16k (apparently arbitrary value borrowed from
81        curl) from random file. */
82     RAND_load_file (random_file, 16384);
83
84   if (RAND_status ())
85     return;
86
87   /* Get random data from EGD if opt.egd_file was used.  */
88   if (opt.egd_file && *opt.egd_file)
89     RAND_egd (opt.egd_file);
90
91   if (RAND_status ())
92     return;
93
94 #ifdef WINDOWS
95   /* Under Windows, we can try to seed the PRNG using screen content.
96      This may or may not work, depending on whether we'll calling Wget
97      interactively.  */
98
99   RAND_screen ();
100   if (RAND_status ())
101     return;
102 #endif
103
104 #if 0 /* don't do this by default */
105   {
106     int maxrand = 500;
107
108     /* Still not random enough, presumably because neither /dev/random
109        nor EGD were available.  Try to seed OpenSSL's PRNG with libc
110        PRNG.  This is cryptographically weak and defeats the purpose
111        of using OpenSSL, which is why it is highly discouraged.  */
112
113     logprintf (LOG_NOTQUIET, _("WARNING: using a weak random seed.\n"));
114
115     while (RAND_status () == 0 && maxrand-- > 0)
116       {
117         unsigned char rnd = random_number (256);
118         RAND_seed (&rnd, sizeof (rnd));
119       }
120   }
121 #endif
122 }
123
124 /* Print errors in the OpenSSL error stack. */
125
126 static void
127 print_errors (void) 
128 {
129   unsigned long err;
130   while ((err = ERR_get_error ()) != 0)
131     logprintf (LOG_NOTQUIET, "OpenSSL: %s\n", ERR_error_string (err, NULL));
132 }
133
134 /* Convert keyfile type as used by options.h to a type as accepted by
135    SSL_CTX_use_certificate_file and SSL_CTX_use_PrivateKey_file.
136
137    (options.h intentionally doesn't use values from openssl/ssl.h so
138    it doesn't depend specifically on OpenSSL for SSL functionality.)  */
139
140 static int
141 key_type_to_ssl_type (enum keyfile_type type)
142 {
143   switch (type)
144     {
145     case keyfile_pem:
146       return SSL_FILETYPE_PEM;
147     case keyfile_asn1:
148       return SSL_FILETYPE_ASN1;
149     default:
150       abort ();
151     }
152 }
153
154 /* Create an SSL Context and set default paths etc.  Called the first
155    time an HTTP download is attempted.
156
157    Returns true on success, false otherwise.  */
158
159 bool
160 ssl_init ()
161 {
162   SSL_METHOD *meth;
163
164   if (ssl_ctx)
165     /* The SSL has already been initialized. */
166     return true;
167
168   /* Init the PRNG.  If that fails, bail out.  */
169   init_prng ();
170   if (RAND_status () != 1)
171     {
172       logprintf (LOG_NOTQUIET,
173                  _("Could not seed PRNG; consider using --random-file.\n"));
174       goto error;
175     }
176
177   SSL_library_init ();
178   SSL_load_error_strings ();
179   SSLeay_add_all_algorithms ();
180   SSLeay_add_ssl_algorithms ();
181
182   switch (opt.secure_protocol)
183     {
184     case secure_protocol_auto:
185       meth = SSLv23_client_method ();
186       break;
187     case secure_protocol_sslv2:
188       meth = SSLv2_client_method ();
189       break;
190     case secure_protocol_sslv3:
191       meth = SSLv3_client_method ();
192       break;
193     case secure_protocol_tlsv1:
194       meth = TLSv1_client_method ();
195       break;
196     default:
197       abort ();
198     }
199
200   ssl_ctx = SSL_CTX_new (meth);
201   if (!ssl_ctx)
202     goto error;
203
204   SSL_CTX_set_default_verify_paths (ssl_ctx);
205   SSL_CTX_load_verify_locations (ssl_ctx, opt.ca_cert, opt.ca_directory);
206
207   /* SSL_VERIFY_NONE instructs OpenSSL not to abort SSL_connect if the
208      certificate is invalid.  We verify the certificate separately in
209      ssl_check_certificate, which provides much better diagnostics
210      than examining the error stack after a failed SSL_connect.  */
211   SSL_CTX_set_verify (ssl_ctx, SSL_VERIFY_NONE, NULL);
212
213   if (opt.cert_file)
214     if (SSL_CTX_use_certificate_file (ssl_ctx, opt.cert_file,
215                                       key_type_to_ssl_type (opt.cert_type))
216         != 1)
217       goto error;
218   if (opt.private_key)
219     if (SSL_CTX_use_PrivateKey_file (ssl_ctx, opt.private_key,
220                                      key_type_to_ssl_type (opt.private_key_type))
221         != 1)
222       goto error;
223
224   /* Since fd_write unconditionally assumes partial writes (and
225      handles them correctly), allow them in OpenSSL.  */
226   SSL_CTX_set_mode (ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
227
228   return true;
229
230  error:
231   if (ssl_ctx)
232     SSL_CTX_free (ssl_ctx);
233   print_errors ();
234   return false;
235 }
236
237 static int
238 openssl_read (int fd, char *buf, int bufsize, void *ctx)
239 {
240   int ret;
241   SSL *ssl = ctx;
242   do
243     ret = SSL_read (ssl, buf, bufsize);
244   while (ret == -1
245          && SSL_get_error (ssl, ret) == SSL_ERROR_SYSCALL
246          && errno == EINTR);
247   return ret;
248 }
249
250 static int
251 openssl_write (int fd, char *buf, int bufsize, void *ctx)
252 {
253   int ret = 0;
254   SSL *ssl = ctx;
255   do
256     ret = SSL_write (ssl, buf, bufsize);
257   while (ret == -1
258          && SSL_get_error (ssl, ret) == SSL_ERROR_SYSCALL
259          && errno == EINTR);
260   return ret;
261 }
262
263 static int
264 openssl_poll (int fd, double timeout, int wait_for, void *ctx)
265 {
266   SSL *ssl = ctx;
267   if (timeout == 0)
268     return 1;
269   if (SSL_pending (ssl))
270     return 1;
271   return select_fd (fd, timeout, wait_for);
272 }
273
274 static int
275 openssl_peek (int fd, char *buf, int bufsize, void *ctx)
276 {
277   int ret;
278   SSL *ssl = ctx;
279   do
280     ret = SSL_peek (ssl, buf, bufsize);
281   while (ret == -1
282          && SSL_get_error (ssl, ret) == SSL_ERROR_SYSCALL
283          && errno == EINTR);
284   return ret;
285 }
286
287 static const char *
288 openssl_errstr (int fd, void *ctx)
289 {
290   /* Unfortunately we cannot use ERR_error_string's internal buffer
291      because we must be prepared to print more than one error.  */
292   static char errbuf[512];
293   char *p = errbuf, *end = errbuf + sizeof errbuf;
294   unsigned long err;
295
296   if ((err = ERR_get_error ()) == 0)
297     /* Inform the caller that there have been no errors */
298     return NULL;
299
300   /* Iterate over OpenSSL's error stack and print errors to ERRBUF,
301      separated by "; ", while being careful not to overrun ERRBUF.  */
302   do
303     {
304       ERR_error_string_n (err, p, end - p);
305       p = strchr (p, '\0');
306       err = ERR_get_error ();
307       if (err == 0)
308         break;
309       if (p < end) *p++ = ';';
310       if (p < end) *p++ = ' ';
311     }
312   while (p < end);
313
314   if (p < end)
315     *p++ = '\0';
316   else
317     end[-1] = '\0';
318   return errbuf;
319 }
320
321 static void
322 openssl_close (int fd, void *ctx)
323 {
324   SSL *ssl = ctx;
325   SSL_shutdown (ssl);
326   SSL_free (ssl);
327
328 #ifdef WINDOWS
329   closesocket (fd);
330 #else
331   close (fd);
332 #endif
333
334   DEBUGP (("Closed %d/SSL 0x%0lx\n", fd, (unsigned long) ssl));
335 }
336
337 /* openssl_transport is the singleton that describes the SSL transport
338    methods provided by this file.  */
339
340 static struct transport_implementation openssl_transport = {
341   openssl_read, openssl_write, openssl_poll,
342   openssl_peek, openssl_errstr, openssl_close
343 };
344
345 /* Perform the SSL handshake on file descriptor FD, which is assumed
346    to be connected to an SSL server.  The SSL handle provided by
347    OpenSSL is registered with the file descriptor FD using
348    fd_register_transport, so that subsequent calls to fd_read,
349    fd_write, etc., will use the corresponding SSL functions.
350
351    Returns true on success, false on failure.  */
352
353 bool
354 ssl_connect (int fd) 
355 {
356   SSL *ssl;
357
358   DEBUGP (("Initiating SSL handshake.\n"));
359
360   assert (ssl_ctx != NULL);
361   ssl = SSL_new (ssl_ctx);
362   if (!ssl)
363     goto error;
364   if (!SSL_set_fd (ssl, fd))
365     goto error;
366   SSL_set_connect_state (ssl);
367   if (SSL_connect (ssl) <= 0 || ssl->state != SSL_ST_OK)
368     goto error;
369
370   /* Register FD with Wget's transport layer, i.e. arrange that our
371      functions are used for reading, writing, and polling.  */
372   fd_register_transport (fd, &openssl_transport, ssl);
373   DEBUGP (("Handshake successful; connected socket %d to SSL handle 0x%0*lx\n",
374            fd, PTR_FORMAT (ssl)));
375   return true;
376
377  error:
378   DEBUGP (("SSL handshake failed.\n"));
379   print_errors ();
380   if (ssl)
381     SSL_free (ssl);
382   return false;
383 }
384
385 #define ASTERISK_EXCLUDES_DOT   /* mandated by rfc2818 */
386
387 /* Return true is STRING (case-insensitively) matches PATTERN, false
388    otherwise.  The recognized wildcard character is "*", which matches
389    any character in STRING except ".".  Any number of the "*" wildcard
390    may be present in the pattern.
391
392    This is used to match of hosts as indicated in rfc2818: "Names may
393    contain the wildcard character * which is considered to match any
394    single domain name component or component fragment. E.g., *.a.com
395    matches foo.a.com but not bar.foo.a.com. f*.com matches foo.com but
396    not bar.com [or foo.bar.com]."
397
398    If the pattern contain no wildcards, pattern_match(a, b) is
399    equivalent to !strcasecmp(a, b).  */
400
401 static bool
402 pattern_match (const char *pattern, const char *string)
403 {
404   const char *p = pattern, *n = string;
405   char c;
406   for (; (c = TOLOWER (*p++)) != '\0'; n++)
407     if (c == '*')
408       {
409         for (c = TOLOWER (*p); c == '*'; c = TOLOWER (*++p))
410           ;
411         for (; *n != '\0'; n++)
412           if (TOLOWER (*n) == c && pattern_match (p, n))
413             return true;
414 #ifdef ASTERISK_EXCLUDES_DOT
415           else if (*n == '.')
416             return false;
417 #endif
418         return c == '\0';
419       }
420     else
421       {
422         if (c != TOLOWER (*n))
423           return false;
424       }
425   return *n == '\0';
426 }
427
428 /* Verify the validity of the certificate presented by the server.
429    Also check that the "common name" of the server, as presented by
430    its certificate, corresponds to HOST.  (HOST typically comes from
431    the URL and is what the user thinks he's connecting to.)
432
433    This assumes that ssl_connect has successfully finished, i.e. that
434    the SSL handshake has been performed and that FD is connected to an
435    SSL handle.
436
437    If opt.check_cert is true (the default), this returns 1 if the
438    certificate is valid, 0 otherwise.  If opt.check_cert is 0, the
439    function always returns 1, but should still be called because it
440    warns the user about any problems with the certificate.  */
441
442 bool
443 ssl_check_certificate (int fd, const char *host)
444 {
445   X509 *cert;
446   char common_name[256];
447   long vresult;
448   bool success = true;
449
450   /* If the user has specified --no-check-cert, we still want to warn
451      him about problems with the server's certificate.  */
452   const char *severity = opt.check_cert ? _("ERROR") : _("WARNING");
453
454   SSL *ssl = (SSL *) fd_transport_context (fd);
455   assert (ssl != NULL);
456
457   cert = SSL_get_peer_certificate (ssl);
458   if (!cert)
459     {
460       logprintf (LOG_NOTQUIET, _("%s: No certificate presented by %s.\n"),
461                  severity, escnonprint (host));
462       success = false;
463       goto no_cert;             /* must bail out since CERT is NULL */
464     }
465
466   IF_DEBUG
467     {
468       char *subject = X509_NAME_oneline (X509_get_subject_name (cert), 0, 0);
469       char *issuer = X509_NAME_oneline (X509_get_issuer_name (cert), 0, 0);
470       DEBUGP (("certificate:\n  subject: %s\n  issuer:  %s\n",
471                escnonprint (subject), escnonprint (issuer)));
472       OPENSSL_free (subject);
473       OPENSSL_free (issuer);
474     }
475
476   vresult = SSL_get_verify_result (ssl);
477   if (vresult != X509_V_OK)
478     {
479       /* #### We might want to print saner (and translatable) error
480          messages for several frequently encountered errors.  The
481          candidates would include
482          X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY,
483          X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN,
484          X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT,
485          X509_V_ERR_CERT_NOT_YET_VALID, X509_V_ERR_CERT_HAS_EXPIRED,
486          and possibly others.  The current approach would still be
487          used for the less frequent failure cases.  */
488       logprintf (LOG_NOTQUIET,
489                  _("%s: Certificate verification error for %s: %s\n"),
490                  severity, escnonprint (host),
491                  X509_verify_cert_error_string (vresult));
492       success = false;
493       /* Fall through, so that the user is warned about *all* issues
494          with the cert (important with --no-check-certificate.)  */
495     }
496
497   /* Check that HOST matches the common name in the certificate.
498      #### The following remains to be done:
499
500      - It should use dNSName/ipAddress subjectAltName extensions if
501        available; according to rfc2818: "If a subjectAltName extension
502        of type dNSName is present, that MUST be used as the identity."
503
504      - When matching against common names, it should loop over all
505        common names and choose the most specific one, i.e. the last
506        one, not the first one, which the current code picks.
507
508      - Ensure that ASN1 strings from the certificate are encoded as
509        UTF-8 which can be meaningfully compared to HOST.  */
510
511   common_name[0] = '\0';
512   X509_NAME_get_text_by_NID (X509_get_subject_name (cert),
513                              NID_commonName, common_name, sizeof (common_name));
514   if (!pattern_match (common_name, host))
515     {
516       logprintf (LOG_NOTQUIET, _("\
517 %s: certificate common name `%s' doesn't match requested host name `%s'.\n"),
518                  severity, escnonprint (common_name), escnonprint (host));
519       success = false;
520     }
521
522   if (success)
523     DEBUGP (("X509 certificate successfully verified and matches host %s\n",
524              escnonprint (host)));
525   X509_free (cert);
526
527  no_cert:
528   if (opt.check_cert && !success)
529     logprintf (LOG_NOTQUIET, _("\
530 To connect to %s insecurely, use `--no-check-certificate'.\n"),
531                escnonprint (host));
532
533   /* Allow --no-check-cert to disable certificate checking. */
534   return opt.check_cert ? success : true;
535 }