0

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

2 Answers 2

1

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).

0

It must be a very very old version since none of the downloadable versions contains such code. Apart from that you could simply disable verification completely using SSL_CTX_set_verify. While this is unsafe it is actually not much unsafer than the normal behavior of links, which is to check the certification path but not to check if the requested hostname matches the certificate. This make man-in-the-middle attack easy because you can just use any certificate signed by a trusted CA instead of the real one.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .