Links SSL Error

6,078

What version of links does the user called "bytepool" have that he's able to find this workaround? Refer to link below.

Unknown.


He writes "I quickly peeked into the code, and it seems that the relevant function is verify_cert in https.c. .... So as a quick fix for my problem I just built myself a custom version in which verify_cert always returns true, i.e. the cert check is just completely bypassed."

Bad idea.


The following code should do the trick if all you want to do is succeed for an expired certificate.

In essence, you add the function https_verify_cb and then you tell the context to use the callback. Then, when OpenSSL encounters a certificate, it will invoke your callback after doing some processing of its own.

The code below allows any certificate to be expired, including the CA and intermediates. You can restrict it to end entity certificates (i.e., server certificates) by using depth == 0.

$ diff -u https.c.orig https.c
--- https.c.orig    2013-09-20 17:17:00.000000000 -0400
+++ https.c 2014-11-13 17:42:40.000000000 -0500
@@ -23,10 +23,34 @@
 #define PATH_MAX 255
 #endif

+#ifndef NDEBUG
+# include <stdio.h>
+#endif
+
 #ifdef HAVE_SSL

+#include <openssl/ssl.h>
+#include <openssl/x509_vfy.h>
+
 static SSL_CTX *context = NULL;

+int https_verify_cb(int preverify, X509_STORE_CTX* x509_ctx)
+{
+    /* For error codes, see http://www.openssl.org/docs/apps/verify.html  */
+    
+    const int depth = X509_STORE_CTX_get_error_depth(x509_ctx);
+    const int err = X509_STORE_CTX_get_error(x509_ctx);
+    
+#ifndef NDEBUG
+    fprintf(stdout, "https_verify_cb (depth=%d)(preverify=%d)(error=%d)\n", depth, preverify, err);
+#endif
+    
+    /* We return the result of `preverify`, which is the result of customary  */
+    /* X509 verifcation. If all goes well, the value will be 1. If preverify  */
+    /* failed, then we return success if the certifcate is expired.           */
+    return preverify || (err == X509_V_ERR_CERT_HAS_EXPIRED);
+}
+
 SSL *getSSL(void)
 {
    if (!context) {
@@ -62,7 +86,12 @@
        if (!m) return NULL;
        context = SSL_CTX_new((void *)m);
        if (!context) return NULL;
-       SSL_CTX_set_options(context, SSL_OP_ALL);
+        
+       /* SSL_CTX_set_options(context, SSL_OP_ALL); */
+        const long flags = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
+        long old_opts = SSL_CTX_set_options(context, flags);
+        
+        SSL_CTX_set_verify(context, SSL_VERIFY_PEER, https_verify_cb);
        SSL_CTX_set_default_verify_paths(context);

    }

Note that OpenSSL prior to 1.1.0 does not perform hostname matching, so the library will succeed in building the path even if the names don't match. See the man page for X509_check_host(3).

Share:
6,078

Related videos on Youtube

jerz4lunch
Author by

jerz4lunch

Updated on September 18, 2022

Comments

  • jerz4lunch
    jerz4lunch over 1 year

    What version of links does the user called "bytepool" have that he's able to find this workaround? Refer to link below.

    How to tell `links` to ignore expired SSL certificate and proceed?

    He writes "I quickly peeked into the code, and it seems that the relevant function is verify_cert in https.c. .... So as a quick fix for my problem I just built myself a custom version in which verify_cert always returns true, i.e. the cert check is just completely bypassed."

    Further edit by barlop

    Going to http://links.twibright.com/download.php and downloading and extracting http://links.twibright.com/download/links-2.8.tar.gz I see this is the contents of https.c I see no verify_cert function

    Here is the contents of https.c
    /* https.c
     * HTTPS protocol client implementation
     * (c) 2002 Mikulas Patocka
     * This file is a part of the Links program, released under GPL.
    
     * In addition, as a special exception, the copyright holders give
     * permission to link the code of portions of this program with the
     * OpenSSL library under certain conditions as described in each
     * individual source file, and distribute linked combinations
     * including the two.
     * You must obey the GNU General Public License in all respects
     * for all of the code used other than OpenSSL.  If you modify
     * file(s) with this exception, you may extend this exception to your
     * version of the file(s), but you are not obligated to do so.  If you
     * do not wish to do so, delete this exception statement from your
     * version.  If you delete this exception statement from all source
     * files in the program, then also delete it here.
     */
    
    #include "links.h"
    
    #ifndef PATH_MAX
    #define PATH_MAX 255
    #endif
    
    #ifdef HAVE_SSL
    
    static SSL_CTX *context = NULL;
    
    SSL *getSSL(void)
    {
        if (!context) {
            const SSL_METHOD *m;
            unsigned char f_randfile[PATH_MAX];
            unsigned char *os_pool;
            unsigned os_pool_size;
    
            const unsigned char *f = (const unsigned char *)RAND_file_name(cast_char f_randfile, sizeof(f_randfile));
            if (f && RAND_egd(cast_const_char f) < 0) {
                /* Not an EGD, so read and write to it */
                if (RAND_load_file(cast_const_char f_randfile, -1))
                    RAND_write_file(cast_const_char f_randfile);
            }
    
            os_seed_random(&os_pool, &os_pool_size);
            if (os_pool_size) RAND_add(os_pool, os_pool_size, os_pool_size);
            mem_free(os_pool);
    
    /* needed for systems without /dev/random, but obviously kills security. */
            /*{
                static unsigned char pool[32768];
                int i;
                int rs;
                struct timeval tv;
                EINTRLOOP(rs, gettimeofday(&tv, NULL));
                for (i = 0; i < (int)sizeof pool; i++) pool[i] = random() ^ tv.tv_sec ^ tv.tv_usec;
                RAND_add(pool, sizeof pool, sizeof pool);
            }*/
    
            SSLeay_add_ssl_algorithms();
            m = SSLv23_client_method();
            if (!m) return NULL;
            context = SSL_CTX_new((void *)m);
            if (!context) return NULL;
            SSL_CTX_set_options(context, SSL_OP_ALL);
            SSL_CTX_set_default_verify_paths(context);
    
        }
        return (SSL_new(context));
    }
    void ssl_finish(void)
    {
        if (context) SSL_CTX_free(context);
    }
    
    void https_func(struct connection *c)
    {
        c->ssl = DUMMY;
        http_func(c);
    }
    
    #else
    
    void https_func(struct connection *c)
    {
        setcstate(c, S_NO_SSL);
        abort_connection(c);
    }
    
    #endif