1 /* SSL support via OpenSSL library.
2 Copyright (C) 2000-2005 Free Software Foundation, Inc.
3 Originally contributed by Christian Fraenkel.
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 2 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, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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. */
44 #include <openssl/ssl.h>
45 #include <openssl/x509.h>
46 #include <openssl/err.h>
47 #include <openssl/rand.h>
59 /* Application-wide SSL context. This is common to all SSL
63 /* Initialize the SSL's PRNG using various methods. */
69 const char *random_file;
72 /* The PRNG has been seeded; no further action is necessary. */
75 /* Seed from a file specified by the user. This will be the file
76 specified with --random-file, $RANDFILE, if set, or ~/.rnd, if it
79 random_file = opt.random_file;
82 /* Get the random file name using RAND_file_name. */
84 random_file = RAND_file_name (namebuf, sizeof (namebuf));
87 if (random_file && *random_file)
88 /* Seed at most 16k (apparently arbitrary value borrowed from
89 curl) from random file. */
90 RAND_load_file (random_file, 16384);
95 /* Get random data from EGD if opt.egd_file was used. */
96 if (opt.egd_file && *opt.egd_file)
97 RAND_egd (opt.egd_file);
103 /* Under Windows, we can try to seed the PRNG using screen content.
104 This may or may not work, depending on whether we'll calling Wget
112 #if 0 /* don't do this by default */
116 /* Still not random enough, presumably because neither /dev/random
117 nor EGD were available. Try to seed OpenSSL's PRNG with libc
118 PRNG. This is cryptographically weak and defeats the purpose
119 of using OpenSSL, which is why it is highly discouraged. */
121 logprintf (LOG_NOTQUIET, _("WARNING: using a weak random seed.\n"));
123 while (RAND_status () == 0 && maxrand-- > 0)
125 unsigned char rnd = random_number (256);
126 RAND_seed (&rnd, sizeof (rnd));
132 /* Print errors in the OpenSSL error stack. */
137 unsigned long curerr = 0;
138 while ((curerr = ERR_get_error ()) != 0)
139 logprintf (LOG_NOTQUIET, "OpenSSL: %s\n", ERR_error_string (curerr, NULL));
142 /* Convert keyfile type as used by options.h to a type as accepted by
143 SSL_CTX_use_certificate_file and SSL_CTX_use_PrivateKey_file.
145 (options.h intentionally doesn't use values from openssl/ssl.h so
146 it doesn't depend specifically on OpenSSL for SSL functionality.) */
149 key_type_to_ssl_type (enum keyfile_type type)
154 return SSL_FILETYPE_PEM;
156 return SSL_FILETYPE_ASN1;
162 /* Create an SSL Context and set default paths etc. Called the first
163 time an HTTP download is attempted.
165 Returns 1 on success, 0 otherwise. */
173 /* The SSL has already been initialized. */
176 /* Init the PRNG. If that fails, bail out. */
178 if (RAND_status () != 1)
180 logprintf (LOG_NOTQUIET,
181 _("Could not seed PRNG; consider using --random-file.\n"));
186 SSL_load_error_strings ();
187 SSLeay_add_all_algorithms ();
188 SSLeay_add_ssl_algorithms ();
190 switch (opt.secure_protocol)
192 case secure_protocol_auto:
193 meth = SSLv23_client_method ();
195 case secure_protocol_sslv2:
196 meth = SSLv2_client_method ();
198 case secure_protocol_sslv3:
199 meth = SSLv3_client_method ();
201 case secure_protocol_tlsv1:
202 meth = TLSv1_client_method ();
208 ssl_ctx = SSL_CTX_new (meth);
212 SSL_CTX_set_default_verify_paths (ssl_ctx);
213 SSL_CTX_load_verify_locations (ssl_ctx, opt.ca_cert, opt.ca_directory);
215 /* SSL_VERIFY_NONE instructs OpenSSL not to abort SSL_connect if the
216 certificate is invalid. We verify the certificate separately in
217 ssl_check_server_identity, which provides much better diagnostics
218 than examining the error stack after a failed SSL_connect. */
219 SSL_CTX_set_verify (ssl_ctx, SSL_VERIFY_NONE, NULL);
222 if (SSL_CTX_use_certificate_file (ssl_ctx, opt.cert_file,
223 key_type_to_ssl_type (opt.cert_type))
227 if (SSL_CTX_use_PrivateKey_file (ssl_ctx, opt.private_key,
228 key_type_to_ssl_type (opt.private_key_type))
232 /* Since fd_write unconditionally assumes partial writes (and
233 handles them correctly), allow them in OpenSSL. */
234 SSL_CTX_set_mode (ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
240 SSL_CTX_free (ssl_ctx);
246 openssl_read (int fd, char *buf, int bufsize, void *ctx)
249 SSL *ssl = (SSL *) ctx;
251 ret = SSL_read (ssl, buf, bufsize);
253 && SSL_get_error (ssl, ret) == SSL_ERROR_SYSCALL
259 openssl_write (int fd, char *buf, int bufsize, void *ctx)
262 SSL *ssl = (SSL *) ctx;
264 ret = SSL_write (ssl, buf, bufsize);
266 && SSL_get_error (ssl, ret) == SSL_ERROR_SYSCALL
272 openssl_poll (int fd, double timeout, int wait_for, void *ctx)
274 SSL *ssl = (SSL *) ctx;
277 if (SSL_pending (ssl))
279 return select_fd (fd, timeout, wait_for);
283 openssl_peek (int fd, char *buf, int bufsize, void *ctx)
286 SSL *ssl = (SSL *) ctx;
288 ret = SSL_peek (ssl, buf, bufsize);
290 && SSL_get_error (ssl, ret) == SSL_ERROR_SYSCALL
296 openssl_close (int fd, void *ctx)
298 SSL *ssl = (SSL *) ctx;
308 DEBUGP (("Closed %d/SSL 0x%0lx\n", fd, (unsigned long) ssl));
311 /* Perform the SSL handshake on file descriptor FD, which is assumed
312 to be connected to an SSL server. The SSL handle provided by
313 OpenSSL is registered with the file descriptor FD using
314 fd_register_transport, so that subsequent calls to fd_read,
315 fd_write, etc., will use the corresponding SSL functions.
317 Returns 1 on success, 0 on failure. */
324 assert (ssl_ctx != NULL);
325 ssl = SSL_new (ssl_ctx);
328 if (!SSL_set_fd (ssl, fd))
330 SSL_set_connect_state (ssl);
331 if (SSL_connect (ssl) <= 0 || ssl->state != SSL_ST_OK)
334 /* Register FD with Wget's transport layer, i.e. arrange that our
335 functions are used for reading, writing, and polling. */
336 fd_register_transport (fd, openssl_read, openssl_write, openssl_poll,
337 openssl_peek, openssl_close, ssl);
338 DEBUGP (("Connected %d to SSL 0x%0*lx\n", fd, 2 * sizeof (void *),
339 (unsigned long) ssl));
349 /* Return 1 is STRING (case-insensitively) matches PATTERN, 0
350 otherwise. The recognized wildcard character is "*", which matches
351 any character in STRING except ".". Any number of the "*" wildcard
352 may be present in the pattern.
354 This is used to match of hosts as indicated in rfc2818: "Names may
355 contain the wildcard character * which is considered to match any
356 single domain name component or component fragment. E.g., *.a.com
357 matches foo.a.com but not bar.foo.a.com. f*.com matches foo.com but
361 pattern_match (const char *pattern, const char *string)
363 const char *p = pattern, *n = string;
365 for (; (c = TOLOWER (*p++)) != '\0'; n++)
368 for (c = TOLOWER (*p); c == '*'; c = TOLOWER (*++p))
370 for (; *n != '\0'; n++)
371 if (TOLOWER (*n) == c && pattern_match (p, n))
379 if (c != TOLOWER (*n))
385 /* Verify the validity of the certificate presented by the server.
386 Also check that the "common name" of the server, as presented by
387 its certificate, corresponds to HOST. (HOST typically comes from
388 the URL and is what the user thinks he's connecting to.)
390 This assumes that ssl_connect has successfully finished, i.e. that
391 the SSL handshake has been performed and that FD is connected to an
394 If opt.check_cert is non-zero (the default), this returns 1 if the
395 certificate is valid, 0 otherwise. If opt.check_cert is 0, the
396 function always returns 1, but should still be called because it
397 warns the user about any problems with the certificate. */
400 ssl_check_certificate (int fd, const char *host)
403 char common_name[256];
407 /* If the user has specified --no-check-cert, we still want to warn
408 him about problems with the server's certificate. */
409 const char *severity = opt.check_cert ? _("ERROR") : _("WARNING");
411 SSL *ssl = (SSL *) fd_transport_context (fd);
412 assert (ssl != NULL);
414 cert = SSL_get_peer_certificate (ssl);
417 logprintf (LOG_NOTQUIET, _("%s: No certificate presented by %s.\n"),
418 severity, escnonprint (host));
426 char *subject = X509_NAME_oneline (X509_get_subject_name (cert), 0, 0);
427 char *issuer = X509_NAME_oneline (X509_get_issuer_name (cert), 0, 0);
428 DEBUGP (("certificate:\n subject: %s\n issuer: %s\n",
429 escnonprint (subject), escnonprint (issuer)));
430 OPENSSL_free (subject);
431 OPENSSL_free (issuer);
435 vresult = SSL_get_verify_result (ssl);
436 if (vresult != X509_V_OK)
438 logprintf (LOG_NOTQUIET,
439 _("%s: Certificate verification error for %s: %s\n"),
440 severity, escnonprint (host),
441 X509_verify_cert_error_string (vresult));
446 /* Check that HOST matches the common name in the certificate. ####
447 The remains to be done:
449 - It should use dNSName/ipAddress subjectAltName extensions if
450 available; according to rfc2818: "If a subjectAltName extension
451 of type dNSName is present, that MUST be used as the identity."
453 - When matching against common names, it should loop over all
454 common names and choose the most specific one, i.e. the last
455 one, not the first one, which the current code picks.
457 - Make sure that the names are encoded as UTF-8 which, being
458 ASCII-compatible, can be easily compared against HOST. */
460 common_name[0] = '\0';
461 X509_NAME_get_text_by_NID (X509_get_subject_name (cert),
462 NID_commonName, common_name, sizeof (common_name));
463 if (!pattern_match (common_name, host))
465 logprintf (LOG_NOTQUIET, _("\
466 %s: certificate common name `%s' doesn't match requested host name `%s'.\n"),
467 severity, escnonprint (common_name), escnonprint (host));
472 /* The certificate was found, verified, and matched HOST. */
479 if (opt.check_cert && !success)
480 logprintf (LOG_NOTQUIET, _("\
481 To connect to %s insecurely, use `--no-check-certificate'.\n"),
484 /* Allow --no-check-cert to disable certificate checking. */
485 return opt.check_cert ? success : 1;