Published in <sxs7ks1noc4.fsf@florida.arsdigita.de>.
+2001-12-06 Hrvoje Niksic <hniksic@arsdigita.com>
+
+ * url.c (scheme_disable): New function.
+
+ * main.c (main): Call ssl_init_prng from here rather than from
+ init_ssl, so that it has a chance to disable support for https
+ before a URL has been resolved.
+
+ * gen_sslfunc.c (ssl_init_prng): Seed with rand() if all else
+ failed.
+ (ssl_init_prng): Disable support for https if seeding the PRNG
+ fails.
+
2001-12-06 Hrvoje Niksic <hniksic@arsdigita.com>
* utils.c (read_whole_line): Handle lines beginning with \0.
#include "wget.h"
#include "connect.h"
+#include "url.h"
#ifndef errno
extern int errno;
static int verify_callback PARAMS ((int, X509_STORE_CTX *));
-static void
+void
ssl_init_prng (void)
{
+ /* It is likely that older versions of OpenSSL will fail on
+ non-Linux machines because this code is unable to seed the PRNG
+ on older versions of the library. */
+
#if SSLEAY_VERSION_NUMBER >= 0x00905100
+ char rand_file[256];
+ int maxrand = 500;
+
+ /* First, seed from a file specified by the user. This will be
+ $RANDFILE, if set, or ~/.rnd. */
+ RAND_file_name (rand_file, sizeof (rand_file));
+ if (rand_file)
+ /* Seed at most 16k (value borrowed from curl) from random file. */
+ RAND_load_file (rand_file, 16384);
+
+ if (RAND_status ())
+ return;
+
+ /* Get random data from EGD if opt.sslegdsock was set. */
+ if (opt.sslegdsock)
+ RAND_egd (opt.sslegdsock);
+
+ if (RAND_status ())
+ return;
+
+#ifdef WINDOWS
+ /* Under Windows, we can try to seed the PRNG using screen content.
+ This may or may not work, depending on whether we'll calling Wget
+ interactively. */
+
+ RAND_screen ();
+ if (RAND_status ())
+ return;
+#endif
+
+ /* Still not enough randomness, presumably because neither random
+ file nor EGD have been available. Use the stupidest possible
+ method -- seed OpenSSL's PRNG with the system's PRNG. This is
+ insecure in the cryptographic sense, but people who care about
+ security will use /dev/random or their own source of randomness
+ anyway. */
+
+ srand (time (NULL));
+ while (RAND_status () == 0 && maxrand-- > 0)
+ {
+ int rnd = rand ();
+ RAND_seed ((unsigned char *)&rnd, sizeof (rnd));
+ }
+
if (RAND_status () == 0)
{
- char rand_file[256];
- time_t t;
- long l,seed;
-
- t = time(NULL);
- /* gets random data from egd if opt.sslegdsock was set */
- if (opt.sslegdsock != NULL)
- RAND_egd(opt.sslegdsock);
- /* gets the file ~/.rnd or $RANDFILE if set */
- RAND_file_name(rand_file, 256);
- if (rand_file != NULL)
- {
- /* Seed as much as 1024 bytes from RAND_file_name */
- RAND_load_file(rand_file, 1024);
- }
- /* Seed in time (mod_ssl does this) */
- RAND_seed((unsigned char *)&t, sizeof(time_t));
- /* Initialize system's random number generator */
- RAND_bytes((unsigned char *)&seed, sizeof(long));
-#ifndef WINDOWS
- srand48(seed);
- while (RAND_status () == 0)
- {
- /* Repeatedly seed the PRNG using the system's random number
- generator until it has been seeded with enough data. */
- l = lrand48();
- RAND_seed((unsigned char *)&l, sizeof(long));
- }
-#else /* WINDOWS */
- RAND_screen();
- if (RAND_status() == 0)
- /* Here we should probably disable the whole ssl protocol ? HEH */
- DEBUGP (("SSL random data generator not seeded correctly, %i",RAND_status()));
-#endif /* WINDOWS */
- if (rand_file != NULL)
- {
- /* Write a rand_file */
- RAND_write_file(rand_file);
- }
+ logprintf (LOG_NOTQUIET, "Could not seed OpenSSL PRNG; disabling SSL.\n");
+ scheme_disable (SCHEME_HTTPS);
}
#endif /* SSLEAY_VERSION_NUMBER >= 0x00905100 */
- return;
}
-
/* Creates a SSL Context and sets some defaults for it */
uerr_t
init_ssl (SSL_CTX **ctx)
SSL_FILETYPE_PEM) <= 0)
return SSLERRCERTKEY;
}
- ssl_init_prng();
return 0; /* Succeded */
}
# include <openssl/ssl.h>
#endif
+void ssl_init_prng PARAMS ((void));
int init_ssl PARAMS ((SSL_CTX **));
+
int connect_ssl PARAMS ((SSL **, SSL_CTX *, int));
void shutdown_ssl PARAMS ((SSL*));
void free_ssl_ctx PARAMS ((SSL_CTX *));
#include "url.h"
#include "progress.h" /* for progress_handle_sigwinch */
+#ifdef HAVE_SSL
+# include "gen_sslfunc.h"
+#endif
+
/* On GNU system this will include system-wide getopt.h. */
#include "getopt.h"
#endif
#endif /* HAVE_SIGNAL */
+#ifdef HAVE_SSL
+ /* Must call this before resolving any URLs because it has the power
+ to disable `https'. */
+ ssl_init_prng ();
+#endif
+
status = RETROK; /* initialize it, just-in-case */
- /*recursive_reset ();*/
/* Retrieve the URLs from argument list. */
for (t = url; *t; t++)
{
{
char *leading_string;
int default_port;
+ int enabled;
};
/* Supported schemes: */
static struct scheme_data supported_schemes[] =
{
- { "http://", DEFAULT_HTTP_PORT },
+ { "http://", DEFAULT_HTTP_PORT, 1 },
#ifdef HAVE_SSL
- { "https://", DEFAULT_HTTPS_PORT },
+ { "https://", DEFAULT_HTTPS_PORT, 1 },
#endif
- { "ftp://", DEFAULT_FTP_PORT },
+ { "ftp://", DEFAULT_FTP_PORT, 1 },
/* SCHEME_INVALID */
- { NULL, -1 }
+ { NULL, -1, 0 }
};
static char *construct_relative PARAMS ((const char *, const char *));
int i;
for (i = 0; supported_schemes[i].leading_string; i++)
- if (!strncasecmp (url, supported_schemes[i].leading_string,
- strlen (supported_schemes[i].leading_string)))
- return (enum url_scheme)i;
+ if (0 == strncasecmp (url, supported_schemes[i].leading_string,
+ strlen (supported_schemes[i].leading_string)))
+ {
+ if (supported_schemes[i].enabled)
+ return (enum url_scheme) i;
+ else
+ return SCHEME_INVALID;
+ }
+
return SCHEME_INVALID;
}
return supported_schemes[scheme].default_port;
}
+void
+scheme_disable (enum url_scheme scheme)
+{
+ supported_schemes[scheme].enabled = 0;
+}
+
/* Skip the username and password, if present here. The function
should be called *not* with the complete URL, but with the part
right after the scheme.
static char *parse_errors[] = {
#define PE_NO_ERROR 0
"No error",
-#define PE_UNRECOGNIZED_SCHEME 1
- "Unrecognized scheme",
+#define PE_UNSUPPORTED_SCHEME 1
+ "Unsupported scheme",
#define PE_EMPTY_HOST 2
"Empty host",
#define PE_BAD_PORT_NUMBER 3
scheme = url_scheme (url);
if (scheme == SCHEME_INVALID)
{
- SETERR (error, PE_UNRECOGNIZED_SCHEME);
+ SETERR (error, PE_UNSUPPORTED_SCHEME);
return NULL;
}
int url_skip_scheme PARAMS ((const char *));
int url_has_scheme PARAMS ((const char *));
int scheme_default_port PARAMS ((enum url_scheme));
+void scheme_disable PARAMS ((enum url_scheme));
int url_skip_uname PARAMS ((const char *));