Andreas Weigl
Andreas Weigl

Reputation: 31

certificate verify failed with MechanicalSoup

I want to retrieve some data from my router using MechanicalSoup. However when I try I get "certificate verify failed". As I see it I have two options

  1. Find a way to disable SSL verification
  2. Tell MechanicalSoup where it can find the pem file (I created it using "openssl s_connect ....")

My code looks like this so far:

import argparse
import mechanicalsoup
from getpass import getpass

parser = argparse.ArgumentParser(description="Get data from router")
parser.add_argument("-u", "--username", help="User", type=str,
                    required=True)
parser.add_argument("-s", "--server", help="server", type=str,
                    required=True)
parser.add_argument("-p", "--port", help="Port", type=str,
                    required=False, default="8443")
parser.add_argument("-v", "--verbose", help="Verbose output. Add " +
                    "additional v to increase level.",
                    action="count", default=0)
args = parser.parse_args()

args.password = getpass("Password:")

browser = mechanicalsoup.StatefulBrowser(
    soup_config={'features': 'lxml'},
    raise_on_404=True,
    user_agent='getdata.py/0.1',
)

browser.set_verbose(args.verbose)

browser.open("https://" + args.server + ":" + args.port)

Full error message from end of stack:

Traceback (most recent call last):
  File "perfcreate.py", line 33, in <module>
    browser.open("https://" + args.server + ":" + args.port)
  File "/home/andyw/mypy_env/lib/python3.6/site-packages/mechanicalsoup/stateful_browser.py", line 133, in open
    resp = self.get(url, *args, **kwargs)
  File "/home/andyw/mypy_env/lib/python3.6/site-packages/mechanicalsoup/browser.py", line 124, in get
    response = self.session.get(*args, **kwargs)
  File "/home/andyw/mypy_env/lib/python3.6/site-packages/requests/sessions.py", line 546, in get
    return self.request('GET', url, **kwargs)
  File "/home/andyw/mypy_env/lib/python3.6/site-packages/requests/sessions.py", line 533, in request
    resp = self.send(prep, **send_kwargs)
  File "/home/andyw/mypy_env/lib/python3.6/site-packages/requests/sessions.py", line 646, in send
    r = adapter.send(request, **kwargs)
  File "/home/andyw/mypy_env/lib/python3.6/site-packages/requests/adapters.py", line 514, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='192.168.1.1', port=8443): Max retries exceeded with url: / (Caused by SSLError(SSLError("bad handshake: Error([('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')],)",),))

Upvotes: 2

Views: 1295

Answers (2)

Matthieu Moy
Matthieu Moy

Reputation: 16647

MechanicalSoup doesn't do anything specific with SSL certificates, but browser.open forwards its arguments to requests.Session.request's constructor, which exposes among others:

verify – (optional) Either a boolean, in which case it controls whether we verify the server’s TLS certificate, or a string, in which case it must be a path to a CA bundle to use. Defaults to True.

cert – (optional) if String, path to ssl client cert file (.pem). If Tuple, (‘cert’, ‘key’) pair.

So, you may use verify=False as the other answer suggests (unsafe), or download the certificate from the website and use cert="/path/to/certificate.pem.

Upvotes: 0

user3224454
user3224454

Reputation: 194

Maybe you could use: browser.open("https://" + args.server + ":" + args.port, verify=False)

Upvotes: 1

Related Questions