Make certificate checks optional, enable per default
authorChristian Herdtweck <christian.herdtweck@intra2net.com>
Tue, 9 Apr 2019 08:20:55 +0000 (10:20 +0200)
committerChristian Herdtweck <christian.herdtweck@intra2net.com>
Tue, 9 Apr 2019 09:53:17 +0000 (11:53 +0200)
Also give an option to give an extra certificate to accept as .pem

src/web_interface.py

index 18316ab..a647a9c 100644 (file)
@@ -42,17 +42,19 @@ log = logging.getLogger('pyi2ncommon.web_interface')
 from .arnied_wrapper import accept_licence
 
 
-def find_in_form(regex, form="status", escape=False):
+def find_in_form(regex, form="status", escape=False, check_certs=True):
     """
     Find a regex in I2N web page's status frame.
 
     :param str regex: regular expression to find
     :param bool escape: whether to escape the regex
+    :param check_certs: forwarded to :py:func:`web_page_request`, see doc there
     :returns: whether the regex was found
     :rtype: bool
     """
     accept_licence()
-    data = web_page_request(method="GET", url="/arnie?form=" + form)
+    data = web_page_request(method="GET", url="/arnie?form=" + form,
+                            check_certs=check_certs)
     if escape:
         regex = re.escape(regex)
     if re.search(regex, data):
@@ -62,14 +64,24 @@ def find_in_form(regex, form="status", escape=False):
         return False
 
 
-def web_page_request(method="GET", url="/", body=None):
+def web_page_request(method="GET", url="/", body=None, check_certs=True):
     """
     Send an HTTPS request and return any response data.
 
+    SSL certificates are checked against a default set of certificates
+    installed on you system. This can be disabled (not recommended, security
+    implications!) by setting `check_certs` to `False`. To allow a secure
+    connection to host with e.g. a self-signed certificate, the caller can
+    load this certificate by specifying `check_certs=/path/to/cert.pem`.
+    (see also: :py:meth:`ssl.SSLContext.load_verify_locations`)
+
     :param str method: GET or POST method for the request
     :param str url: url location within the remote host
     :param body: dictionary to be parsed and added to the url
     :type body: {str, str} or None
+    :param check_certs: Whether or not to check ssl certificates for connection
+                        or file name to a certificate file
+    :type check_certs: bool or str
     :returns: data from the response if any
     :rtype: str
     """
@@ -77,8 +89,13 @@ def web_page_request(method="GET", url="/", body=None):
     headers = {"Content-Type": "application/x-www-form-urlencoded",
                "Accept": "text/plain"}
 
-    # Allow for an HTTPS connection with self-signed certificates
-    context = ssl._create_unverified_context()
+    if isinstance(check_certs, str):
+        context = ssl.create_default_context(cafile=check_certs)
+    elif check_certs:
+        context = ssl.create_default_context()
+    else:
+        # disable certificate checks
+        context = ssl._create_unverified_context()
     conn = client.HTTPSConnection("localhost", context=context)
     conn.request(method, url, body, headers)
     resp = conn.getresponse()