From e4a8fe84e2b813b65d91aec29298eecabe4850a5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tim=20R=C3=BChsen?= <tim.ruehsen@gmx.de>
Date: Thu, 6 Nov 2014 17:53:44 +0100
Subject: [PATCH] Added --crl-file to load a Certificate Revocation List (CRL)
 file
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Reported-by: Noël Köthe <noel@debian.org>
---
 doc/ChangeLog |  4 ++++
 doc/wget.texi |  5 +++++
 src/ChangeLog |  8 ++++++++
 src/gnutls.c  | 34 ++++++++++++++++++++++++++++++----
 src/init.c    | 19 +++++++++++++++++++
 src/main.c    |  3 +++
 src/options.h |  1 +
 7 files changed, 70 insertions(+), 4 deletions(-)

diff --git a/doc/ChangeLog b/doc/ChangeLog
index d071efd1..4cd67ef3 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,7 @@
+2014-11-06  Tim Ruehsen  <tim.ruehsen@gmx.de>
+
+	* wget.texi: added description for --crl-file
+
 2014-10-28  Giuseppe Scrivano  <gscrivan@redhat.com>
 
 	* Makefile.am: Replace $FOO with @VAR@.
diff --git a/doc/wget.texi b/doc/wget.texi
index d7a4c949..a5fd285a 100644
--- a/doc/wget.texi
+++ b/doc/wget.texi
@@ -1725,6 +1725,11 @@ it allows Wget to fetch certificates on demand.
 Without this option Wget looks for CA certificates at the
 system-specified locations, chosen at OpenSSL installation time.
 
+@cindex SSL CRL, certificate revocation list
+@item --crl-file=@var{file}
+Specifies a CRL file in @var{file}.  This is needed for certificates
+that have been revocated by the CAs.
+
 @cindex entropy, specifying source of
 @cindex randomness, specifying source of
 @item --random-file=@var{file}
diff --git a/src/ChangeLog b/src/ChangeLog
index 0c41b1ed..8c58aeeb 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,11 @@
+2014-11-06  Tim Ruehsen  <tim.ruehsen@gmx.de>
+
+	* init.c, main.c, options.h: added new option --crl-file
+	 for specifying a CRL (Certificate Revocation List) file.
+	* gnutls.c: load CRL file given by --crl-file
+
+	Reported-by: Noël Köthe <noel@debian.org>
+
 2014-11-09  Darshit Shah  <darnir@gmail.com>
 
 	* http.c (gethttps): Honour keep-alive when server responds with a 416 Range
diff --git a/src/gnutls.c b/src/gnutls.c
index 230ae9aa..1744245b 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -149,6 +149,36 @@ ssl_init (void)
         }
     }
 
+  if (opt.ca_cert)
+    {
+      int rc;
+
+      ncerts = 0;
+
+      if ((rc = gnutls_certificate_set_x509_trust_file (credentials, opt.ca_cert,
+                                                        GNUTLS_X509_FMT_PEM)) <= 0)
+        logprintf (LOG_NOTQUIET, _ ("ERROR: Failed to open cert %s: (%d).\n"),
+                   opt.ca_cert, rc);
+      else
+        {
+          ncerts += rc;
+          logprintf (LOG_NOTQUIET, _ ("Loaded CA certificate '%s'\n"), opt.ca_cert);
+        }
+    }
+
+  if (opt.crl_file)
+    {
+      int rc;
+
+      if ((rc = gnutls_certificate_set_x509_crl_file (credentials, opt.crl_file, GNUTLS_X509_FMT_PEM)) <= 0)
+        {
+          logprintf (LOG_NOTQUIET, _("ERROR: Failed to load CRL file '%s': (%d)\n"), opt.crl_file, rc);
+          return false;
+        }
+
+      logprintf (LOG_NOTQUIET, _ ("Loaded CRL file '%s'\n"), opt.crl_file);
+    }
+
   DEBUGP (("Certificates loaded: %d\n", ncerts));
 
   /* Use the private key from the cert file unless otherwise specified. */
@@ -181,10 +211,6 @@ cert to be of the same type.\n"));
                                             type);
     }
 
-  if (opt.ca_cert)
-    gnutls_certificate_set_x509_trust_file (credentials, opt.ca_cert,
-                                            GNUTLS_X509_FMT_PEM);
-
   ssl_initialized = true;
 
   return true;
diff --git a/src/init.c b/src/init.c
index ef1dc8d7..6c09744f 100644
--- a/src/init.c
+++ b/src/init.c
@@ -91,6 +91,7 @@ CMD_DECLARE (cmd_number_inf);
 CMD_DECLARE (cmd_string);
 CMD_DECLARE (cmd_string_uppercase);
 CMD_DECLARE (cmd_file);
+CMD_DECLARE (cmd_file_once);
 CMD_DECLARE (cmd_directory);
 CMD_DECLARE (cmd_time);
 CMD_DECLARE (cmd_vector);
@@ -158,6 +159,9 @@ static const struct {
   { "continue",         &opt.always_rest,       cmd_boolean },
   { "convertlinks",     &opt.convert_links,     cmd_boolean },
   { "cookies",          &opt.cookies,           cmd_boolean },
+#ifdef HAVE_SSL
+  { "crlfile",      &opt.crl_file,          cmd_file_once },
+#endif
   { "cutdirs",          &opt.cut_dirs,          cmd_number },
   { "debug",            &opt.debug,             cmd_boolean },
   { "defaultpage",      &opt.default_page,      cmd_string },
@@ -1026,6 +1030,20 @@ cmd_file (const char *com _GL_UNUSED, const char *val, void *place)
   return true;
 }
 
+/* like cmd_file, but insist on just a single option usage */
+static bool
+cmd_file_once (const char *com _GL_UNUSED, const char *val, void *place)
+{
+  if (*(char **)place)
+    {
+      fprintf (stderr, _("%s: %s must only be used once\n"),
+               exec_name, com);
+      return false;
+    }
+
+  return cmd_file(com, val, place);
+}
+
 /* Like cmd_file, but strips trailing '/' characters.  */
 static bool
 cmd_directory (const char *com, const char *val, void *place)
@@ -1780,6 +1798,7 @@ cleanup (void)
   xfree_null (opt.private_key);
   xfree_null (opt.ca_directory);
   xfree_null (opt.ca_cert);
+  xfree_null (opt.crl_file);
   xfree_null (opt.random_file);
   xfree_null (opt.egd_file);
 # endif
diff --git a/src/main.c b/src/main.c
index 4fefe049..29788473 100644
--- a/src/main.c
+++ b/src/main.c
@@ -175,6 +175,7 @@ static struct cmdline_option option_data[] =
     { "content-disposition", 0, OPT_BOOLEAN, "contentdisposition", -1 },
     { "content-on-error", 0, OPT_BOOLEAN, "contentonerror", -1 },
     { "cookies", 0, OPT_BOOLEAN, "cookies", -1 },
+    { IF_SSL ("crl-file"), 0, OPT_VALUE, "crlfile", -1 },
     { "cut-dirs", 0, OPT_VALUE, "cutdirs", -1 },
     { "debug", 'd', OPT_BOOLEAN, "debug", -1 },
     { "default-page", 0, OPT_VALUE, "defaultpage", -1 },
@@ -652,6 +653,8 @@ HTTPS (SSL/TLS) options:\n"),
        --ca-certificate=FILE       file with the bundle of CA's.\n"),
     N_("\
        --ca-directory=DIR          directory where hash list of CA's is stored.\n"),
+    N_("\
+       --crl-file=FILE             file with bundle of CRL's.\n"),
     N_("\
        --random-file=FILE          file with random data for seeding the SSL PRNG.\n"),
     N_("\
diff --git a/src/options.h b/src/options.h
index 3346c91a..b9951265 100644
--- a/src/options.h
+++ b/src/options.h
@@ -218,6 +218,7 @@ struct options
 
   char *ca_directory;           /* CA directory (hash files) */
   char *ca_cert;                /* CA certificate file to use */
+  char *crl_file;               /* file with CRLs */
 
   char *random_file;            /* file with random data to seed the PRNG */
   char *egd_file;               /* file name of the egd daemon socket */