mirror of
https://github.com/moparisthebest/wget
synced 2024-07-03 16:38:41 -04:00
[svn] Implement several SSL features.
- allow checking of server cert - allow defining client cert type - allow limit of ssl protocol - check more return values - added debug message on break Published by Thomas Lussnig in <3CC09969.5000607@bewegungsmelder.de>.
This commit is contained in:
parent
bf018d5721
commit
91a190a770
@ -1,3 +1,12 @@
|
||||
2002-04-21 Thomas Lussnig <thomas.lussnig@bewegungsmelder.de>
|
||||
|
||||
* gen_ssl.c:
|
||||
- allow checking of server cert
|
||||
- allow defining client cert type
|
||||
- allow limit of ssl protocol
|
||||
- check more return values
|
||||
- added debug message on break
|
||||
|
||||
2002-04-21 Hrvoje Niksic <hniksic@arsdigita.com>
|
||||
|
||||
* recur.c (download_child_p): Revert order of items in check
|
||||
|
@ -50,8 +50,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
static int verify_callback PARAMS ((int, X509_STORE_CTX *));
|
||||
|
||||
void
|
||||
ssl_init_prng (void)
|
||||
{
|
||||
@ -112,68 +110,6 @@ ssl_init_prng (void)
|
||||
#endif /* SSLEAY_VERSION_NUMBER >= 0x00905100 */
|
||||
}
|
||||
|
||||
/* Creates a SSL Context and sets some defaults for it */
|
||||
uerr_t
|
||||
init_ssl (SSL_CTX **ctx)
|
||||
{
|
||||
SSL_METHOD *meth = NULL;
|
||||
int verify = SSL_VERIFY_NONE;
|
||||
SSL_library_init ();
|
||||
SSL_load_error_strings ();
|
||||
SSLeay_add_all_algorithms ();
|
||||
SSLeay_add_ssl_algorithms ();
|
||||
meth = SSLv23_client_method ();
|
||||
*ctx = SSL_CTX_new (meth);
|
||||
SSL_CTX_set_verify (*ctx, verify, verify_callback);
|
||||
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 */
|
||||
}
|
||||
|
||||
/* Sets up a SSL structure and performs the handshake on fd
|
||||
Returns 0 if everything went right
|
||||
Returns 1 if something went wrong ----- TODO: More exit codes
|
||||
*/
|
||||
int
|
||||
connect_ssl (SSL **con, SSL_CTX *ctx, int fd)
|
||||
{
|
||||
*con = (SSL *)SSL_new (ctx);
|
||||
SSL_set_fd (*con, fd);
|
||||
SSL_set_connect_state (*con);
|
||||
SSL_connect (*con);
|
||||
if ((*con)->state != SSL_ST_OK)
|
||||
return 1;
|
||||
/*while((SSLerror=ERR_get_error())!=0)
|
||||
printf("%s\n", ERR_error_string(SSLerror,NULL));*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
shutdown_ssl (SSL* con)
|
||||
{
|
||||
SSL_shutdown (con);
|
||||
if (con != NULL)
|
||||
SSL_free (con);
|
||||
}
|
||||
|
||||
void
|
||||
free_ssl_ctx (SSL_CTX * ctx)
|
||||
{
|
||||
SSL_CTX_free (ctx);
|
||||
}
|
||||
|
||||
int
|
||||
verify_callback (int ok, X509_STORE_CTX *ctx)
|
||||
{
|
||||
@ -183,8 +119,13 @@ verify_callback (int ok, X509_STORE_CTX *ctx)
|
||||
switch (ctx->error) {
|
||||
case X509_V_ERR_CERT_NOT_YET_VALID:
|
||||
case X509_V_ERR_CERT_HAS_EXPIRED:
|
||||
/* This mean the CERT is not valid !!! */
|
||||
ok = 0;
|
||||
break;
|
||||
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
|
||||
/* Unsure if we should handle that this way */
|
||||
ok = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
@ -199,7 +140,7 @@ ssl_printerrors (void)
|
||||
unsigned long curerr = 0;
|
||||
char errbuff[1024];
|
||||
memset(errbuff, 0, sizeof(errbuff));
|
||||
for (curerr = ERR_get_error (); curerr; curerr = ERR_get_error ())
|
||||
while ( 0 != (curerr = ERR_get_error ()))
|
||||
{
|
||||
DEBUGP (("OpenSSL: %s\n", ERR_error_string (curerr, errbuff)));
|
||||
++ocerr;
|
||||
@ -207,6 +148,156 @@ ssl_printerrors (void)
|
||||
return ocerr;
|
||||
}
|
||||
|
||||
/* Creates a SSL Context and sets some defaults for it */
|
||||
uerr_t
|
||||
init_ssl (SSL_CTX **ctx)
|
||||
{
|
||||
SSL_METHOD *meth = NULL;
|
||||
int verify;
|
||||
int can_validate;
|
||||
SSL_library_init ();
|
||||
SSL_load_error_strings ();
|
||||
SSLeay_add_all_algorithms ();
|
||||
SSLeay_add_ssl_algorithms ();
|
||||
switch (opt.sslprotocol)
|
||||
{
|
||||
default:
|
||||
meth = SSLv23_client_method ();
|
||||
break;
|
||||
case 1 :
|
||||
meth = SSLv2_client_method ();
|
||||
break;
|
||||
case 2 :
|
||||
meth = SSLv3_client_method ();
|
||||
break;
|
||||
case 3 :
|
||||
meth = TLSv1_client_method ();
|
||||
break;
|
||||
}
|
||||
if (meth == NULL)
|
||||
{
|
||||
ssl_printerrors ();
|
||||
return SSLERRCTXCREATE;
|
||||
}
|
||||
|
||||
*ctx = SSL_CTX_new (meth);
|
||||
if (meth == NULL)
|
||||
{
|
||||
ssl_printerrors ();
|
||||
return SSLERRCTXCREATE;
|
||||
}
|
||||
/* Can we validate the server Cert ? */
|
||||
if (opt.sslcadir != NULL || opt.sslcafile != NULL)
|
||||
{
|
||||
SSL_CTX_load_verify_locations (*ctx, opt.sslcafile, opt.sslcadir);
|
||||
can_validate = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
can_validate = 0;
|
||||
}
|
||||
|
||||
if (!opt.sslcheckcert)
|
||||
{
|
||||
/* check cert but ignore error, do not break handshake on error */
|
||||
verify = SSL_VERIFY_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!can_validate)
|
||||
{
|
||||
logprintf (LOG_NOTQUIET, "Warrining validation of Server Cert not possible!\n");
|
||||
verify = SSL_VERIFY_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* break handshake if server cert is not valid but allow NO-Cert mode */
|
||||
verify = SSL_VERIFY_PEER;
|
||||
}
|
||||
}
|
||||
|
||||
SSL_CTX_set_verify (*ctx, verify, verify_callback);
|
||||
|
||||
if (opt.sslcertfile != NULL || opt.sslcertkey != NULL)
|
||||
{
|
||||
int ssl_cert_type;
|
||||
if (!opt.sslcerttype)
|
||||
ssl_cert_type = SSL_FILETYPE_PEM;
|
||||
else
|
||||
ssl_cert_type = SSL_FILETYPE_ASN1;
|
||||
|
||||
if (opt.sslcertkey == NULL)
|
||||
opt.sslcertkey = opt.sslcertfile;
|
||||
if (opt.sslcertfile == NULL)
|
||||
opt.sslcertfile = opt.sslcertkey;
|
||||
|
||||
if (SSL_CTX_use_certificate_file (*ctx, opt.sslcertfile, ssl_cert_type) <= 0)
|
||||
{
|
||||
ssl_printerrors ();
|
||||
return SSLERRCERTFILE;
|
||||
}
|
||||
if (SSL_CTX_use_PrivateKey_file (*ctx, opt.sslcertkey , ssl_cert_type) <= 0)
|
||||
{
|
||||
ssl_printerrors ();
|
||||
return SSLERRCERTKEY;
|
||||
}
|
||||
}
|
||||
|
||||
return 0; /* Succeded */
|
||||
}
|
||||
|
||||
void
|
||||
shutdown_ssl (SSL* con)
|
||||
{
|
||||
if (con == NULL)
|
||||
return;
|
||||
if (0==SSL_shutdown (con))
|
||||
SSL_shutdown (con);
|
||||
SSL_free (con);
|
||||
}
|
||||
|
||||
/* Sets up a SSL structure and performs the handshake on fd
|
||||
Returns 0 if everything went right
|
||||
Returns 1 if something went wrong ----- TODO: More exit codes
|
||||
*/
|
||||
int
|
||||
connect_ssl (SSL **con, SSL_CTX *ctx, int fd)
|
||||
{
|
||||
if (NULL == (*con = SSL_new (ctx)))
|
||||
{
|
||||
ssl_printerrors ();
|
||||
return 1;
|
||||
}
|
||||
if (!SSL_set_fd (*con, fd))
|
||||
{
|
||||
ssl_printerrors ();
|
||||
return 1;
|
||||
}
|
||||
SSL_set_connect_state (*con);
|
||||
switch (SSL_connect (*con))
|
||||
{
|
||||
case 1 :
|
||||
return (*con)->state != SSL_ST_OK;
|
||||
default:
|
||||
ssl_printerrors ();
|
||||
shutdown_ssl (*con);
|
||||
*con = NULL;
|
||||
return 1;
|
||||
case 0 :
|
||||
ssl_printerrors ();
|
||||
SSL_free (*con);
|
||||
*con = NULL;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
free_ssl_ctx (SSL_CTX * ctx)
|
||||
{
|
||||
SSL_CTX_free (ctx);
|
||||
}
|
||||
|
||||
/* SSL version of iread. Only exchanged read for SSL_read Read at
|
||||
most LEN bytes from FD, storing them to BUF. */
|
||||
|
||||
|
@ -185,8 +185,13 @@ static struct {
|
||||
{ "spanhosts", &opt.spanhost, cmd_boolean },
|
||||
{ "spider", &opt.spider, cmd_boolean },
|
||||
#ifdef HAVE_SSL
|
||||
{ "sslcadir", &opt.sslcadir, cmd_directory },
|
||||
{ "sslcafile", &opt.sslcafile, cmd_file },
|
||||
{ "sslcertfile", &opt.sslcertfile, cmd_file },
|
||||
{ "sslcertkey", &opt.sslcertkey, cmd_file },
|
||||
{ "sslcerttype", &opt.sslcerttype, cmd_number },
|
||||
{ "sslcheckcert", &opt.sslcheckcert, cmd_number },
|
||||
{ "sslprotocol", &opt.sslprotocol, cmd_number },
|
||||
#endif /* HAVE_SSL */
|
||||
{ "timeout", &opt.timeout, cmd_time },
|
||||
{ "timestamping", &opt.timestamping, cmd_boolean },
|
||||
|
45
src/main.c
45
src/main.c
@ -1,5 +1,5 @@
|
||||
/* Command line parsing.
|
||||
Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001
|
||||
Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Wget.
|
||||
@ -148,13 +148,9 @@ 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\
|
||||
--egd-file=FILE file name of the EGD socket.\n\
|
||||
\n"), stdout);
|
||||
\n"),stdout);
|
||||
fputs (_("\
|
||||
Download:\n\
|
||||
--bind-address=ADDRESS bind to ADDRESS (hostname or IP) on local host.\n\
|
||||
-t, --tries=NUMBER set number of retries to NUMBER (0 unlimits).\n\
|
||||
-O --output-document=FILE write documents to FILE.\n\
|
||||
-nc, --no-clobber don\'t clobber existing files or use .# suffixes.\n\
|
||||
@ -169,6 +165,7 @@ Download:\n\
|
||||
--random-wait wait from 0...2*WAIT secs between retrievals.\n\
|
||||
-Y, --proxy=on/off turn proxy on or off.\n\
|
||||
-Q, --quota=NUMBER set retrieval quota to NUMBER.\n\
|
||||
--bind-address=ADDRESS bind to ADDRESS (hostname or IP) on local host.\n\
|
||||
--limit-rate=RATE limit download rate to RATE.\n\
|
||||
\n"), stdout);
|
||||
fputs (_("\
|
||||
@ -199,6 +196,20 @@ HTTP options:\n\
|
||||
--post-data=STRING use the POST method; send STRING as the data.\n\
|
||||
--post-file=FILE use the POST method; send contents of FILE.\n\
|
||||
\n"), stdout);
|
||||
#ifdef HAVE_SSL
|
||||
fputs (_("\
|
||||
HTTPS (SSL) options:\n\
|
||||
--sslcertfile=FILE optional client certificate.\n\
|
||||
--sslcertkey=KEYFILE optional keyfile for this certificate.\n\
|
||||
--egd-file=FILE file name of the EGD socket.\n\
|
||||
--sslcadir=DIR dir where hash list of CA's are stured.\n\
|
||||
--sslcafile=FILE file with bundle of CA's\n\
|
||||
--sslcerttype=0/1 Client-Cert type 0=PEM (default) / 1=ASN1 (DER)\n\
|
||||
--sslcheckcert=0/1 Check the server cert agenst given CA\n\
|
||||
--sslprotocol=0-3 choose SSL protocol; 0=automatic,\n\
|
||||
1=SSLv2 2=SSLv3 3=TLSv1\n\
|
||||
\n"), stdout);
|
||||
#endif
|
||||
fputs (_("\
|
||||
FTP options:\n\
|
||||
-nr, --dont-remove-listing don\'t remove `.listing\' files.\n\
|
||||
@ -208,7 +219,7 @@ FTP options:\n\
|
||||
\n"), stdout);
|
||||
fputs (_("\
|
||||
Recursive retrieval:\n\
|
||||
-r, --recursive recursive web-suck -- use with care!\n\
|
||||
-r, --recursive recursive download.\n\
|
||||
-l, --level=NUMBER maximum recursion depth (inf or 0 for infinite).\n\
|
||||
--delete-after delete files locally after downloading them.\n\
|
||||
-k, --convert-links convert non-relative links to relative.\n\
|
||||
@ -329,6 +340,11 @@ main (int argc, char *const *argv)
|
||||
{ "sslcertfile", required_argument, NULL, 158 },
|
||||
{ "sslcertkey", required_argument, NULL, 159 },
|
||||
{ "egd-file", required_argument, NULL, 166 },
|
||||
{ "sslcadir", required_argument, NULL, 169},
|
||||
{ "sslcafile", required_argument, NULL, 170},
|
||||
{ "sslcerttype", required_argument, NULL, 171},
|
||||
{ "sslcheckcert", required_argument, NULL, 172},
|
||||
{ "sslprotocol", required_argument, NULL, 173},
|
||||
#endif /* HAVE_SSL */
|
||||
{ "wait", required_argument, NULL, 'w' },
|
||||
{ "waitretry", required_argument, NULL, 152 },
|
||||
@ -552,6 +568,21 @@ GNU General Public License for more details.\n"));
|
||||
case 166:
|
||||
setval ("egdfile", optarg);
|
||||
break;
|
||||
case 169:
|
||||
setval ("sslcadir", optarg);
|
||||
break;
|
||||
case 170:
|
||||
setval ("sslcafile", optarg);
|
||||
break;
|
||||
case 171:
|
||||
setval ("sslcerttype", optarg);
|
||||
break;
|
||||
case 172:
|
||||
setval ("sslcheckcert", optarg);
|
||||
break;
|
||||
case 173:
|
||||
setval ("sslprotocol", optarg);
|
||||
break;
|
||||
#endif /* HAVE_SSL */
|
||||
case 167:
|
||||
setval ("postdata", optarg);
|
||||
|
@ -154,11 +154,16 @@ struct options
|
||||
necessary to display a page properly. */
|
||||
char *bind_address; /* What local IP address to bind to. */
|
||||
#ifdef HAVE_SSL
|
||||
char *sslcadir; /* CA directory (hash files) */
|
||||
char *sslcafile; /* CA File to use */
|
||||
char *sslcertfile; /* external client cert to use. */
|
||||
char *sslcertkey; /* the keyfile for this certificate
|
||||
(if not internal) included in the
|
||||
certfile. */
|
||||
int sslcerttype; /* 0 = PEM / 1=ASN1 (DER) */
|
||||
int sslcheckcert; /* 0 do not check / 1 check server cert */
|
||||
char *sslegdsock; /* optional socket of the egd daemon */
|
||||
int sslprotocol; /* 0 = auto / 1 = v2 / 2 = v3 / 3 = TLSv1 */
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
int cookies;
|
||||
|
Loading…
Reference in New Issue
Block a user