From 07f60f19a4ee99ddc343bb51568b0c474e9b853d Mon Sep 17 00:00:00 2001 From: hniksic Date: Sat, 10 Feb 2001 14:33:31 -0800 Subject: [PATCH] [svn] Applied Christian Fraenkel's patch "custom certificate patch for wget-1.7+dev; 2nd try", published in <200102082132220160.00474E73@pop.gmx.net>. It adds two options for custom certificates. --- src/ChangeLog | 16 ++++++++++++++++ src/gen_sslfunc.c | 37 +++++++++++++++++++++++++++++++------ src/gen_sslfunc.h | 1 + src/http.c | 39 ++++++++++++++++++++++++++++++++++++--- src/init.c | 8 ++++++++ src/main.c | 14 ++++++++++++++ src/options.h | 7 +++++++ src/wget.h | 3 ++- 8 files changed, 115 insertions(+), 10 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 7c9eeea9..d505b4c5 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,19 @@ +2001-02-08 Christian Fraenkel + + * gen_sslfunc.c: verify_callback is now static + + * gen_sslfunc.c (init_ssl): load certificate if specified + + * gen_sslfunc.c (ssl_printerr): new function + + * init.c: added new --sslcertfile and --sslcertkey switches + + * main.c: ditto + + * options.h: ditto + + * http.c (gethttp): abort when init_ssl fails + 2001-01-23 Herold Heiko * mswindows.h: Include ; it's needed for alloca(). diff --git a/src/gen_sslfunc.c b/src/gen_sslfunc.c index 8b64b581..c19cc66f 100644 --- a/src/gen_sslfunc.c +++ b/src/gen_sslfunc.c @@ -32,8 +32,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include -#define SSL_ERR_CTX_CREATION -2 - #include "wget.h" #include "connect.h" @@ -41,11 +39,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ extern int errno; #endif -/* #### Shouldn't this be static? --hniksic */ -int verify_callback PARAMS ((int, X509_STORE_CTX *)); +static int verify_callback PARAMS ((int, X509_STORE_CTX *)); /* Creates a SSL Context and sets some defaults for it */ -int +uerr_t init_ssl (SSL_CTX **ctx) { SSL_METHOD *meth = NULL; @@ -57,7 +54,18 @@ init_ssl (SSL_CTX **ctx) meth = SSLv23_client_method (); *ctx = SSL_CTX_new (meth); SSL_CTX_set_verify (*ctx, verify, verify_callback); - if (*ctx == NULL) return SSL_ERR_CTX_CREATION; + if (*ctx == NULL) return SSLERRCTXCREATE; + if (opt.sslcertfile) + { + if (SSL_CTX_use_certificate_file (*ctx, opt.sslcertfile, + SSL_FILETYPE_PEM) <= 0) + return SSLERRCERTFILE; + if (opt.sslcertkey == NULL) + opt.sslcertkey=opt.sslcertfile; + if (SSL_CTX_use_PrivateKey_file (*ctx, opt.sslcertkey, + SSL_FILETYPE_PEM) <= 0) + return SSLERRCERTKEY; + } return 0; /* Succeded */ } @@ -107,6 +115,23 @@ verify_callback (int ok, X509_STORE_CTX *ctx) return ok; } +/* pass all ssl errors to DEBUGP + returns the number of printed errors */ +int +ssl_printerrors (void) +{ + int ocerr = 0; + unsigned long curerr = 0; + char errbuff[1024]; + memset(errbuff, 0, sizeof(errbuff)); + for (curerr = ERR_get_error (); curerr; curerr = ERR_get_error ()) + { + DEBUGP (("OpenSSL: %s\n", ERR_error_string (curerr, errbuff))); + ++ocerr; + } + return ocerr; +} + /* SSL version of iread. Only exchanged read for SSL_read Read at most LEN bytes from FD, storing them to BUF. This is virtually the same as read(), but takes care of EINTR braindamage diff --git a/src/gen_sslfunc.h b/src/gen_sslfunc.h index 066ebfed..fdd3da1a 100644 --- a/src/gen_sslfunc.h +++ b/src/gen_sslfunc.h @@ -28,4 +28,5 @@ void free_ssl_ctx PARAMS ((SSL_CTX *)); int verify_callback PARAMS ((int, X509_STORE_CTX *)); int ssl_iread PARAMS ((SSL *, char *, int)); int ssl_iwrite PARAMS ((SSL *, char *, int)); +int ssl_printerrors PARAMS ((void)); diff --git a/src/http.c b/src/http.c index 0d81a30d..b8151ea2 100644 --- a/src/http.c +++ b/src/http.c @@ -536,9 +536,41 @@ gethttp (struct urlinfo *u, struct http_stat *hs, int *dt) int inhibit_keep_alive; #ifdef HAVE_SSL -/* initialize ssl_ctx on first run */ + /* initialize ssl_ctx on first run */ if (!ssl_ctx) - init_ssl (&ssl_ctx); + { + err=init_ssl (&ssl_ctx); + if (err != 0) + { + switch (err) + { + case SSLERRCTXCREATE: + /* this is fatal */ + logprintf (LOG_NOTQUIET, _("Failed to set up an SSL context\n")); + ssl_printerrors (); + return err; + case SSLERRCERTFILE: + /* try without certfile */ + logprintf (LOG_NOTQUIET, + _("Failed to load certificates from %s\n"), + opt.sslcertfile); + ssl_printerrors (); + logprintf (LOG_NOTQUIET, + _("Trying without the specified certificate\n")); + break; + case SSLERRCERTKEY: + logprintf (LOG_NOTQUIET, + _("Failed to get certificate key from %s\n"), + opt.sslcertkey); + ssl_printerrors (); + logprintf (LOG_NOTQUIET, + _("Trying without the specified certificate\n")); + break; + default: + break; + } + } + } #endif /* HAVE_SSL */ if (!(*dt & HEAD_ONLY)) @@ -1417,7 +1449,8 @@ File `%s' already there, will not retrieve.\n"), u->local); printwhat (count, opt.ntry); continue; break; - case HOSTERR: case CONREFUSED: case PROXERR: case AUTHFAILED: + case HOSTERR: case CONREFUSED: case PROXERR: case AUTHFAILED: + case SSLERRCTXCREATE: /* Fatal errors just return from the function. */ FREEHSTAT (hstat); xfree (filename_plus_orig_suffix); /* must precede every return! */ diff --git a/src/init.c b/src/init.c index 900f807d..321f50d4 100644 --- a/src/init.c +++ b/src/init.c @@ -161,6 +161,10 @@ static struct { { "simplehostcheck", &opt.simple_check, cmd_boolean }, { "spanhosts", &opt.spanhost, cmd_boolean }, { "spider", &opt.spider, cmd_boolean }, +#ifdef HAVE_SSL + { "sslcertfile", &opt.sslcertfile, cmd_string }, + { "sslcertkey", &opt.sslcertkey, cmd_string }, +#endif /* HAVE_SSL */ { "timeout", &opt.timeout, cmd_time }, { "timestamping", &opt.timestamping, cmd_boolean }, { "tries", &opt.ntry, cmd_number_inf }, @@ -1014,4 +1018,8 @@ cleanup (void) FREE_MAYBE (opt.http_user); FREE_MAYBE (opt.http_passwd); FREE_MAYBE (opt.user_header); +#ifdef HAVE_SSL + FREE_MAYBE (opt.sslcertkey); + FREE_MAYBE (opt.sslcertfile); +#endif /* HAVE_SSL */ } diff --git a/src/main.c b/src/main.c index d6a19bfd..275605ca 100644 --- a/src/main.c +++ b/src/main.c @@ -150,6 +150,8 @@ Logging and input file:\n\ -i, --input-file=FILE download URLs found in FILE.\n\ -F, --force-html treat input file as HTML.\n\ -B, --base=URL prepends URL to relative links in -F -i file.\n\ + --sslcertfile=FILE optional client certificate.\n\ + --sslcertkey=KEYFILE optional keyfile for this certificate.\n\ \n"), _("\ Download:\n\ --bind-address=ADDRESS bind to ADDRESS (hostname or IP) on local host.\n\ @@ -303,6 +305,10 @@ main (int argc, char *const *argv) { "user-agent", required_argument, NULL, 'U' }, { "referer", required_argument, NULL, 129 }, { "use-proxy", required_argument, NULL, 'Y' }, +#ifdef HAVE_SSL + { "sslcertfile", required_argument, NULL, 132}, + { "sslcertkey", required_argument, NULL, 133}, +#endif /* HAVE_SSL */ { "wait", required_argument, NULL, 'w' }, { "waitretry", required_argument, NULL, 24 }, { 0, 0, 0, 0 } @@ -506,6 +512,14 @@ GNU General Public License for more details.\n")); case 129: setval ("referer", optarg); break; +#ifdef HAVE_SSL + case 132: + setval ("sslcertfile", optarg); + break; + case 133: + setval ("sslcertkey", optarg); + break; +#endif /* HAVE_SSL */ case 'A': setval ("accept", optarg); break; diff --git a/src/options.h b/src/options.h index 7c1fac51..13b0bf20 100644 --- a/src/options.h +++ b/src/options.h @@ -153,6 +153,13 @@ struct options necessary to display a page properly. */ struct sockaddr_in *bind_address; /* What local IP address to bind to. */ + +#ifdef HAVE_SSL + char *sslcertfile; /* external client cert to use. */ + char *sslcertkey; /* the keyfile for this certificate + (if not internal) included in the + certfile. */ +#endif /* HAVE_SSL */ }; #ifndef OPTIONS_DEFINED_HERE diff --git a/src/wget.h b/src/wget.h index 42964411..86fa953d 100644 --- a/src/wget.h +++ b/src/wget.h @@ -257,7 +257,8 @@ typedef enum FTPINVPASV, FTPNOPASV, RETRFINISHED, READERR, TRYLIMEXC, URLBADPATTERN, FILEBADFILE, RANGEERR, RETRBADPATTERN, RETNOTSUP, - ROBOTSOK, NOROBOTS, PROXERR, AUTHFAILED, QUOTEXC, WRITEFAILED + ROBOTSOK, NOROBOTS, PROXERR, AUTHFAILED, QUOTEXC, WRITEFAILED, + SSLERRCERTFILE,SSLERRCERTKEY,SSLERRCTXCREATE } uerr_t; typedef unsigned char boolean;