extern int errno;
#endif
-void
+SSL_CTX *ssl_ctx;
+
+static void
ssl_init_prng (void)
{
/* It is likely that older versions of OpenSSL will fail on
unsigned char rnd = random_number (256);
RAND_seed (&rnd, sizeof (rnd));
}
-
- if (RAND_status () == 0)
- {
- logprintf (LOG_NOTQUIET,
- _("Could not seed OpenSSL PRNG; disabling SSL.\n"));
- scheme_disable (SCHEME_HTTPS);
- }
#endif /* SSLEAY_VERSION_NUMBER >= 0x00905100 */
}
-int
+static int
verify_callback (int ok, X509_STORE_CTX *ctx)
{
char *s, buf[256];
return ok;
}
-/* pass all ssl errors to DEBUGP
- returns the number of printed errors */
-int
-ssl_printerrors (void)
+/* Print SSL errors. */
+
+void
+ssl_print_errors (void)
{
- int ocerr = 0;
unsigned long curerr = 0;
char errbuff[1024];
xzero (errbuff);
while ((curerr = ERR_get_error ()) != 0)
- {
- DEBUGP (("OpenSSL: %s\n", ERR_error_string (curerr, errbuff)));
- ++ocerr;
- }
- return ocerr;
+ logprintf (LOG_NOTQUIET, "OpenSSL: %s\n",
+ ERR_error_string (curerr, errbuff));
}
/* Creates a SSL Context and sets some defaults for it */
uerr_t
-init_ssl (SSL_CTX **ctx)
+ssl_init ()
{
SSL_METHOD *meth = NULL;
int verify;
int can_validate;
+
+ if (ssl_ctx)
+ return 0;
+
+ /* Init the PRNG. If that fails, bail out. */
+ ssl_init_prng ();
+ if (RAND_status () == 0)
+ {
+ logprintf (LOG_NOTQUIET,
+ _("Could not seed OpenSSL PRNG; disabling SSL.\n"));
+ scheme_disable (SCHEME_HTTPS);
+ return SSLERRCTXCREATE;
+ }
+
SSL_library_init ();
SSL_load_error_strings ();
SSLeay_add_all_algorithms ();
}
if (meth == NULL)
{
- ssl_printerrors ();
+ ssl_print_errors ();
return SSLERRCTXCREATE;
}
- *ctx = SSL_CTX_new (meth);
+ ssl_ctx = SSL_CTX_new (meth);
if (meth == NULL)
{
- ssl_printerrors ();
+ ssl_print_errors ();
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);
+ SSL_CTX_load_verify_locations (ssl_ctx, opt.sslcafile, opt.sslcadir);
can_validate = 1;
}
else
}
}
- SSL_CTX_set_verify (*ctx, verify, verify_callback);
+ SSL_CTX_set_verify (ssl_ctx, verify, verify_callback);
if (opt.sslcertfile != NULL || opt.sslcertkey != NULL)
{
if (opt.sslcertfile == NULL)
opt.sslcertfile = opt.sslcertkey;
- if (SSL_CTX_use_certificate_file (*ctx, opt.sslcertfile, ssl_cert_type) <= 0)
+ if (SSL_CTX_use_certificate_file (ssl_ctx, opt.sslcertfile,
+ ssl_cert_type) <= 0)
{
- ssl_printerrors ();
+ ssl_print_errors ();
return SSLERRCERTFILE;
}
- if (SSL_CTX_use_PrivateKey_file (*ctx, opt.sslcertkey , ssl_cert_type) <= 0)
+ if (SSL_CTX_use_PrivateKey_file (ssl_ctx, opt.sslcertkey,
+ ssl_cert_type) <= 0)
{
- ssl_printerrors ();
+ ssl_print_errors ();
return SSLERRCERTKEY;
}
}
return 0; /* Succeded */
}
-static
-int ssl_read (int fd, char *buf, int bufsize, void *ctx)
+static int
+ssl_read (int fd, char *buf, int bufsize, void *ctx)
{
- int res;
+ int ret;
SSL *ssl = (SSL *) ctx;
- /* #### Does SSL_read actually set EINTR? */
do
- res = SSL_read (ssl, buf, bufsize);
- while (res == -1 && errno == EINTR);
- return res;
+ ret = SSL_read (ssl, buf, bufsize);
+ while (ret == -1
+ && SSL_get_error (ssl, ret) == SSL_ERROR_SYSCALL
+ && errno == EINTR);
+ return ret;
}
static int
ssl_write (int fd, char *buf, int bufsize, void *ctx)
{
- int res = 0;
+ int ret = 0;
SSL *ssl = (SSL *) ctx;
- /* #### Does SSL_write actually set EINTR? */
do
- res = SSL_write (ssl, buf, bufsize);
- while (res == -1 && errno == EINTR);
- return res;
+ ret = SSL_write (ssl, buf, bufsize);
+ while (ret == -1
+ && SSL_get_error (ssl, ret) == SSL_ERROR_SYSCALL
+ && errno == EINTR);
+ return ret;
}
static int
/* Sets up a SSL structure and performs the handshake on fd. */
SSL *
-connect_ssl (int fd, SSL_CTX *ctx)
+ssl_connect (int fd)
{
- SSL *ssl = SSL_new (ctx);
+ SSL *ssl;
+
+ assert (ssl_ctx != NULL);
+ ssl = SSL_new (ssl_ctx);
if (!ssl)
goto err;
if (!SSL_set_fd (ssl, fd))
return ssl;
err:
- ssl_printerrors ();
+ ssl_print_errors ();
if (ssl)
SSL_free (ssl);
return NULL;
}
-
-void
-free_ssl_ctx (SSL_CTX * ctx)
-{
- SSL_CTX_free (ctx);
-}
FILE *fp;
int auth_tried_already;
struct rbuf rbuf;
-#ifdef HAVE_SSL
- static SSL_CTX *ssl_ctx = NULL;
-#endif
int using_ssl = 0;
char *cookies = NULL;
long post_data_size = 0;
#ifdef HAVE_SSL
- /* initialize ssl_ctx on first run */
- if (!ssl_ctx)
+ /* Initialize the SSL context. After the first run, this is a
+ no-op. */
+ switch (ssl_init ())
{
- uerr_t 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;
- }
- }
+ case SSLERRCTXCREATE:
+ /* this is fatal */
+ logprintf (LOG_NOTQUIET, _("Failed to set up an SSL context\n"));
+ return SSLERRCTXCREATE;
+ case SSLERRCERTFILE:
+ /* try without certfile */
+ logprintf (LOG_NOTQUIET,
+ _("Failed to load certificates from %s\n"),
+ opt.sslcertfile);
+ 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);
+ logprintf (LOG_NOTQUIET,
+ _("Trying without the specified certificate\n"));
+ break;
+ default:
+ break;
}
#endif /* HAVE_SSL */
#ifdef HAVE_SSL
if (conn->scheme == SCHEME_HTTPS)
{
- if (!connect_ssl (sock, ssl_ctx))
+ if (!ssl_connect (sock))
{
logputs (LOG_VERBOSE, "\n");
logprintf (LOG_NOTQUIET,