mayk93
mayk93

Reputation: 1537

Disable SSL certificate check Twisted Agents

I am using Twisted (16.3) and Treq (15.1) to make async requests in Python (2.7).

I am having issues with some requests over HTTPS.

Some sites have an invalid certificate and thus when making a request to them, I get this:

twisted.python.failure.Failure OpenSSL.SSL.Error

I want my client to trust any server, including those without certificates or with self signed certificates.

How can I disable certificate checks on my client?

This is a question essentially identical to mine: https://stackoverflow.com/questions/34357439/ssl-options-for-twisted-agents

Thanks!

Upvotes: 4

Views: 4099

Answers (2)

VladiC4T
VladiC4T

Reputation: 236

If you want to completely ignore the check for SSL here is a workaround:

from twisted.internet import ssl, _sslverify
from twisted.web.iweb import IPolicyForHTTPS

@implementer(IPolicyForHTTPS)
class IgnoreHTTPS:
    def creatorForNetloc(self, hostname, port):
        options = ssl.CertificateOptions(verify=False)
        return _sslverify.ClientTLSOptions(hostname.decode('ascii'), options.getContext())

Upvotes: 1

notorious.no
notorious.no

Reputation: 5107

Update Feb 7, 2019

Here's a simple way to make a domain whitelist for treq

from treq.client import HTTPClient
from twisted.web.iweb import IPolicyForHTTPS
from twisted.web.client import BrowserLikePolicyForHTTPS, Agent
from twisted.internet.ssl import CertificateOptions
from twisted.internet import task, defer, ssl
from zope.interface import implementer

@implementer(IPolicyForHTTPS)
class WhitelistContextFactory(object):
    def __init__(self, good_domains=None):
        """
        :param good_domains: List of domains. The URLs must be in bytes
        """
        if not good_domains:
            self.good_domains = []
        else:
            self.good_domains = good_domains

        # by default, handle requests like a browser would
        self.default_policy = BrowserLikePolicyForHTTPS()

    def creatorForNetloc(self, hostname, port):
        # check if the hostname is in the the whitelist, otherwise return the default policy
        if hostname in self.good_domains:
            return ssl.CertificateOptions(verify=False)
        return self.default_policy.creatorForNetloc(hostname, port)

@task.react
@defer.inlineCallbacks
def main(reactor):
    # make a custom client, agent, and context factory
    # NOTE: WhitelistContextFactory() takes a list of BYTES
    treq = HTTPClient(Agent(reactor, contextFactory=WhitelistContextFactory([b'example.net'])))
    response = yield treq.get('https://example.net/version')
    content = yield response.content()
    print(content)

WhitelistContextFactory takes a list of URLs (in bytes) and checks if the hostname is in the list to disregard TLS verification. You can get fancy and use regex too. Kudos to https://github.com/twisted/treq/issues/213

DO NOT DO THIS!

I've been trying to do this too over the past few days as well. With all the effort I put into circumventing certificate verification, I could've easily just created a pair of keys and been on my merry way :D. I found this comment on the treq issues board that monkeypatches the issue:

from twisted.internet import _sslverify
_sslverify.platformTrust = lambda : None

I'm sure there's a convoluted way of doing it "correctly" but it wouldn't be worth the effort in my opinion. I did a patch such that it wouldn't override platformTrust() and I'll try to get it merged but I wouldn't hold my breath. From the tone of some of the bug comments I've seen pertaining to trust roots, ssl, and certificates, I don't think it will get merged. Hope this helps though.

Upvotes: 6

Related Questions