X-Git-Url: http://sjero.net/git/?p=wget;a=blobdiff_plain;f=src%2Fgnutls.c;h=06f90200c514ca303c8dd3739c7c59c7cbcafe52;hp=32c6d174548ba2e3ffc69b9168648dd03a10506d;hb=b8f036d16c508efde5bacfab9a96d8b6c6aeeeb2;hpb=370f96d36cac952a52f71cb2a2b03f4a64a6d93e diff --git a/src/gnutls.c b/src/gnutls.c index 32c6d174..06f90200 100644 --- a/src/gnutls.c +++ b/src/gnutls.c @@ -99,7 +99,7 @@ ssl_init (void) dir = opendir (ca_directory); if (dir == NULL) { - if (opt.ca_directory) + if (opt.ca_directory && *opt.ca_directory) logprintf (LOG_NOTQUIET, _("ERROR: Cannot open directory %s.\n"), opt.ca_directory); } @@ -374,10 +374,14 @@ static struct transport_implementation wgnutls_transport = bool ssl_connect_wget (int fd, const char *hostname) { +#ifdef F_GETFL + int flags = 0; +#endif struct wgnutls_transport_context *ctx; gnutls_session_t session; - int err; + int err,alert; gnutls_init (&session, GNUTLS_CLIENT); + const char *str; /* We set the server name but only if it's not an IP address. */ if (! is_valid_ip_address (hostname)) @@ -401,7 +405,7 @@ ssl_connect_wget (int fd, const char *hostname) break; case secure_protocol_sslv2: case secure_protocol_sslv3: - err = gnutls_priority_set_direct (session, "NORMAL:-VERS-TLS-ALL", NULL); + err = gnutls_priority_set_direct (session, "NORMAL:-VERS-TLS-ALL:+VERS-SSL3.0", NULL); break; case secure_protocol_tlsv1: err = gnutls_priority_set_direct (session, "NORMAL:-VERS-SSL3.0", NULL); @@ -440,10 +444,83 @@ ssl_connect_wget (int fd, const char *hostname) return false; } - err = gnutls_handshake (session); + if (opt.connect_timeout) + { +#ifdef F_GETFL + flags = fcntl (fd, F_GETFL, 0); + if (flags < 0) + return flags; + if (fcntl (fd, F_SETFL, flags | O_NONBLOCK)) + return -1; +#else + /* XXX: Assume it was blocking before. */ + const int one = 1; + if (ioctl (fd, FIONBIO, &one) < 0) + return -1; +#endif + } + + /* We don't stop the handshake process for non-fatal errors */ + do + { + err = gnutls_handshake (session); + + if (opt.connect_timeout && err == GNUTLS_E_AGAIN) + { + if (gnutls_record_get_direction (session)) + { + /* wait for writeability */ + err = select_fd (fd, opt.connect_timeout, WAIT_FOR_WRITE); + } + else + { + /* wait for readability */ + err = select_fd (fd, opt.connect_timeout, WAIT_FOR_READ); + } + + if (err <= 0) + { + if (err == 0) + { + errno = ETIMEDOUT; + err = -1; + } + break; + } + + if (err <= 0) + break; + } + else if (err < 0) + { + logprintf (LOG_NOTQUIET, "GnuTLS: %s\n", gnutls_strerror (err)); + if (err == GNUTLS_E_WARNING_ALERT_RECEIVED || + err == GNUTLS_E_FATAL_ALERT_RECEIVED) + { + alert = gnutls_alert_get (session); + str = gnutls_alert_get_name (alert); + if (str == NULL) + str = "(unknown)"; + logprintf (LOG_NOTQUIET, "GnuTLS: received alert [%d]: %s\n", alert, str); + } + } + } + while (err == GNUTLS_E_WARNING_ALERT_RECEIVED && gnutls_error_is_fatal (err) == 0); + + if (opt.connect_timeout) + { +#ifdef F_GETFL + if (fcntl (fd, F_SETFL, flags) < 0) + return -1; +#else + const int zero = 0; + if (ioctl (fd, FIONBIO, &zero) < 0) + return -1; +#endif + } + if (err < 0) { - logprintf (LOG_NOTQUIET, "GnuTLS: %s\n", gnutls_strerror (err)); gnutls_deinit (session); return false; } @@ -515,7 +592,7 @@ ssl_check_certificate (int fd, const char *host) { logprintf (LOG_NOTQUIET, _("No certificate found\n")); success = false; - goto out; + goto crt_deinit; } err = gnutls_x509_crt_import (cert, cert_list, GNUTLS_X509_FMT_DER); if (err < 0) @@ -523,7 +600,7 @@ ssl_check_certificate (int fd, const char *host) logprintf (LOG_NOTQUIET, _("Error parsing certificate: %s\n"), gnutls_strerror (err)); success = false; - goto out; + goto crt_deinit; } if (now < gnutls_x509_crt_get_activation_time (cert)) { @@ -542,6 +619,7 @@ ssl_check_certificate (int fd, const char *host) quote (host)); success = false; } + crt_deinit: gnutls_x509_crt_deinit (cert); }