[Inteproxy-commits] r282 - in trunk: . inteproxy

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Mon Oct 11 10:29:19 CEST 2010


Author: iweinzierl
Date: 2010-10-11 10:29:18 +0200 (Mon, 11 Oct 2010)
New Revision: 282

Modified:
   trunk/ChangeLog
   trunk/inteproxy/proxycore.py
Log:
Validate remote certificates when creating HTTPS connections.

Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2010-10-11 08:22:07 UTC (rev 281)
+++ trunk/ChangeLog	2010-10-11 08:29:18 UTC (rev 282)
@@ -1,5 +1,14 @@
 2010-10-11  Ingo Weinzierl <ingo.weinzierl at intevation.de>
 
+	* inteproxy/proxycore.py: Validate remote certificates when an ssl
+	connection is created (requires python >= 2.6, otherwise no validation
+	takes place) using pythons ssl module. If the validation failes, a popup
+	dialog is opened with the error/warning. If the user accepts the
+	certificate, the ssl connection is created, otherwise a HTML error code
+	502 is returned.
+
+2010-10-11  Ingo Weinzierl <ingo.weinzierl at intevation.de>
+
 	* inteproxy/certificatedialog.py: New module to handle errors/warnings
 	that occured while certificate validation.
 

Modified: trunk/inteproxy/proxycore.py
===================================================================
--- trunk/inteproxy/proxycore.py	2010-10-11 08:22:07 UTC (rev 281)
+++ trunk/inteproxy/proxycore.py	2010-10-11 08:29:18 UTC (rev 282)
@@ -16,8 +16,16 @@
 import socket
 import base64
 
+# the ssl modules was introduced in Python 2.6.  If available, we use
+# that, otherwise the older ssl support from the socket module
+try:
+    import ssl
+except ImportError:
+    ssl = None
+
 from inteproxy.threadpool import ThreadPool
 from inteproxy.feesdialog import handle_fees_and_access_constraints
+from inteproxy.certificatedialog import handle_certificate_validation_error
 from inteproxy.httpserver import HTTPServer
 from inteproxy.httpmessage import HTTPRequestMessage, HTTPResponseMessage
 from inteproxy.httpconnection import connect_tcp, connect_http_connect, \
@@ -118,11 +126,39 @@
         return headers
 
 
-    def open_https_connection(self, remote_address):
+    def https_connection_wrapper(self, remote_address):
+        """Open a HTTPS connection to remote_address and validate the server
+        certificate
+
+        The server certificate is validated if python >= 2.6. If the validation
+        failed, a popup dialog with technical details of the failure is shown.
+        The user has the choice to trust or reject the connection. Rejecting the
+        connection will result in a HTTP-502. If python < 2.6 is installed, the
+        certificate is not validated but an ssl connection is used as well to
+        encrypt the data."""
+        if ssl is not None:
+            try:
+                return self.open_https_connection(remote_address)
+            except ssl.SSLError:
+                self.log_debug("SSL certificate validation failed.")
+                if handle_certificate_validation_error(remote_address[0]):
+                    return self.open_https_connection(remote_address,
+                                                      validate=False)
+                return None
+        else:
+            return self.open_https_connection(remote_address, validate=False)
+
+
+    def open_https_connection(self, remote_address, validate=True):
         """Open a HTTPS connection to remote_address
 
         This method handles proxies as well. Its return value is a socket like
-        object using SSL to encrypt the data."""
+        object using SSL to encrypt the data. If python >= 2.6 is installed, the
+        server certificate is validated. If this validation failed None is
+        returned, otherwise a ssl like object.  The parameter validate may be
+        used to skip the certificate validation.If python < 2.6 is installed,
+        the certificate is not validated, but a ssl connection is used to
+        encrypt the data."""
         self.log_debug("Open HTTPS connection to %r" % remote_address[0])
         sock = None
 
@@ -137,9 +173,21 @@
         else:
             sock = connect_tcp(remote_address[0], remote_address[1],
                                log_debug=self.log_debug)
-        return connect_ssl(sock, log_debug=self.log_debug)
 
+        if ssl is not None and validate:
+            self.log_debug("Start HTTPS connection and validate certificates.")
+            cert_file = self.server.get_cacert_path()
+            return connect_ssl(sock, log_debug=self.log_debug,
+                               ca_certs=cert_file, remote_url=remote_address[0])
+        elif ssl is not None and not validate:
+            self.log_debug("Start HTTPS connection but do not validate certificates.")
+            return connect_ssl(sock, log_debug=self.log_debug,
+                               cert_required=False)
+        else:
+            self.log_debug("Certificate validation is not supported.")
+            return connect_ssl(sock, log_debug=self.log_debug)
 
+
     def open_http_connection(self, remote_url, remote_address, request_uri,
                              extra_headers):
         """Open a HTTP connection to remote_address
@@ -182,7 +230,10 @@
                                                           request_uri,
                                                           extra_headers)
         elif scheme == "https":
-            sock = self.open_https_connection(remote_address)
+            sock = self.https_connection_wrapper(remote_address)
+            if not sock:
+                self.send_error(502)
+                return
 
         connection = SocketHTTPConnection(sock, *remote_address)
         if self.debug_level > 1:



More information about the Inteproxy-commits mailing list