]> sjero.net Git - wget/blobdiff - src/openssl.c
[svn] Remove K&R support.
[wget] / src / openssl.c
index 7a29167d5ca10ec543c272f3b672ceb430140fdb..5850b96f7733d3ba4d13acf82a5131719ba9b4c5 100644 (file)
@@ -35,11 +35,7 @@ so, delete this exception statement from your version.  */
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
 #endif
-#ifdef HAVE_STRING_H
-# include <string.h>
-#else
-# include <strings.h>
-#endif
+#include <string.h>
 
 #include <openssl/ssl.h>
 #include <openssl/x509.h>
@@ -52,10 +48,6 @@ so, delete this exception statement from your version.  */
 #include "url.h"
 #include "ssl.h"
 
-#ifndef errno
-extern int errno;
-#endif
-
 /* Application-wide SSL context.  This is common to all SSL
    connections.  */
 SSL_CTX *ssl_ctx;
@@ -214,7 +206,7 @@ ssl_init ()
 
   /* SSL_VERIFY_NONE instructs OpenSSL not to abort SSL_connect if the
      certificate is invalid.  We verify the certificate separately in
-     ssl_check_server_identity, which provides much better diagnostics
+     ssl_check_certificate, which provides much better diagnostics
      than examining the error stack after a failed SSL_connect.  */
   SSL_CTX_set_verify (ssl_ctx, SSL_VERIFY_NONE, NULL);
 
@@ -321,6 +313,8 @@ ssl_connect (int fd)
 {
   SSL *ssl;
 
+  DEBUGP (("Initiating SSL handshake.\n"));
+
   assert (ssl_ctx != NULL);
   ssl = SSL_new (ssl_ctx);
   if (!ssl)
@@ -335,17 +329,20 @@ ssl_connect (int fd)
      functions are used for reading, writing, and polling.  */
   fd_register_transport (fd, openssl_read, openssl_write, openssl_poll,
                         openssl_peek, openssl_close, ssl);
-  DEBUGP (("Connected %d to SSL 0x%0*lx\n", fd, 2 * sizeof (void *),
-          (unsigned long) ssl));
+  DEBUGP (("Handshake successful; connected socket %d to SSL handle 0x%0*lx\n",
+          fd, PTR_FORMAT (ssl)));
   return 1;
 
  error:
+  DEBUGP (("SSL handshake failed.\n"));
   print_errors ();
   if (ssl)
     SSL_free (ssl);
   return 0;
 }
 
+#define ASTERISK_EXCLUDES_DOT  /* mandated by rfc2818 */
+
 /* Return 1 is STRING (case-insensitively) matches PATTERN, 0
    otherwise.  The recognized wildcard character is "*", which matches
    any character in STRING except ".".  Any number of the "*" wildcard
@@ -355,7 +352,10 @@ ssl_connect (int fd)
    contain the wildcard character * which is considered to match any
    single domain name component or component fragment. E.g., *.a.com
    matches foo.a.com but not bar.foo.a.com. f*.com matches foo.com but
-   not bar.com."  */
+   not bar.com [or foo.bar.com]."
+
+   If the pattern contain no wildcards, pattern_match(a, b) is
+   equivalent to !strcasecmp(a, b).  */
 
 static int
 pattern_match (const char *pattern, const char *string)
@@ -370,8 +370,10 @@ pattern_match (const char *pattern, const char *string)
        for (; *n != '\0'; n++)
          if (TOLOWER (*n) == c && pattern_match (p, n))
            return 1;
+#ifdef ASTERISK_EXCLUDES_DOT
          else if (*n == '.')
            return 0;
+#endif
        return c == '\0';
       }
     else
@@ -402,7 +404,7 @@ ssl_check_certificate (int fd, const char *host)
   X509 *cert;
   char common_name[256];
   long vresult;
-  int success;
+  int success = 1;
 
   /* If the user has specified --no-check-cert, we still want to warn
      him about problems with the server's certificate.  */
@@ -417,7 +419,7 @@ ssl_check_certificate (int fd, const char *host)
       logprintf (LOG_NOTQUIET, _("%s: No certificate presented by %s.\n"),
                 severity, escnonprint (host));
       success = 0;
-      goto out;
+      goto no_cert;            /* must bail out since CERT is NULL */
     }
 
 #ifdef ENABLE_DEBUG
@@ -435,16 +437,26 @@ ssl_check_certificate (int fd, const char *host)
   vresult = SSL_get_verify_result (ssl);
   if (vresult != X509_V_OK)
     {
+      /* #### We might want to print saner (and translatable) error
+        messages for several frequently encountered errors.  The
+        candidates would include
+        X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY,
+        X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN,
+        X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT,
+        X509_V_ERR_CERT_NOT_YET_VALID, X509_V_ERR_CERT_HAS_EXPIRED,
+        and possibly others.  The current approach would still be
+        used for the less frequent failure cases.  */
       logprintf (LOG_NOTQUIET,
                 _("%s: Certificate verification error for %s: %s\n"),
                 severity, escnonprint (host),
                 X509_verify_cert_error_string (vresult));
       success = 0;
-      goto out;
+      /* Fall through, so that the user is warned about *all* issues
+        with the cert (important with --no-check-certificate.)  */
     }
 
-  /* Check that HOST matches the common name in the certificate.  ####
-     The remains to be done:
+  /* Check that HOST matches the common name in the certificate.
+     #### The following remains to be done:
 
      - It should use dNSName/ipAddress subjectAltName extensions if
        available; according to rfc2818: "If a subjectAltName extension
@@ -454,8 +466,8 @@ ssl_check_certificate (int fd, const char *host)
        common names and choose the most specific one, i.e. the last
        one, not the first one, which the current code picks.
 
-     - Make sure that the names are encoded as UTF-8 which, being
-       ASCII-compatible, can be easily compared against HOST.  */
+     - Ensure that ASN1 strings from the certificate are encoded as
+       UTF-8 which can be meaningfully compared to HOST.  */
 
   common_name[0] = '\0';
   X509_NAME_get_text_by_NID (X509_get_subject_name (cert),
@@ -466,16 +478,14 @@ ssl_check_certificate (int fd, const char *host)
 %s: certificate common name `%s' doesn't match requested host name `%s'.\n"),
                 severity, escnonprint (common_name), escnonprint (host));
       success = 0;
-      goto out;
     }
 
-  /* The certificate was found, verified, and matched HOST. */
-  success = 1;
-
- out:
-  if (cert)
-    X509_free (cert);
+  if (success)
+    DEBUGP (("X509 certificate successfully verified and matches host %s\n",
+            escnonprint (host)));
+  X509_free (cert);
 
+ no_cert:
   if (opt.check_cert && !success)
     logprintf (LOG_NOTQUIET, _("\
 To connect to %s insecurely, use `--no-check-certificate'.\n"),