]> granicus.if.org Git - python/commitdiff
Fix issue issue9706: provides a better error handling for various SSL operations
authorGiampaolo Rodolà <g.rodola@gmail.com>
Sun, 29 Aug 2010 19:25:49 +0000 (19:25 +0000)
committerGiampaolo Rodolà <g.rodola@gmail.com>
Sun, 29 Aug 2010 19:25:49 +0000 (19:25 +0000)
Lib/ssl.py
Lib/test/test_ssl.py
Modules/_ssl.c

index af1cc840a437f78e99da069049ad5523bec26e82..a634442e13c82ec7dff40185237dba446ba192bb 100644 (file)
@@ -122,6 +122,9 @@ class SSLSocket(socket):
         if _context:
             self.context = _context
         else:
+            if server_side and not certfile:
+                raise ValueError("certfile must be specified for server-side "
+                                 "operations")
             if certfile and not keyfile:
                 keyfile = certfile
             self.context = SSLContext(ssl_version)
@@ -138,7 +141,7 @@ class SSLSocket(socket):
             self.ssl_version = ssl_version
             self.ca_certs = ca_certs
             self.ciphers = ciphers
-
+        self.server_side = server_side
         self.do_handshake_on_connect = do_handshake_on_connect
         self.suppress_ragged_eofs = suppress_ragged_eofs
         connected = False
@@ -358,7 +361,8 @@ class SSLSocket(socket):
     def connect(self, addr):
         """Connects to remote ADDR, and then wraps the connection in
         an SSL channel."""
-
+        if self.server_side:
+            raise ValueError("can't connect in server-side mode")
         # Here we assume that the socket is client-side, and not
         # connected at the time of the call.  We connect it, then wrap it.
         if self._sslobj:
index 71ba9e1bcbd0eac386e32f49fc262231a2bbc7bf..b485605d420a0abcefbd8e4e49d7fbd137c5778f 100644 (file)
@@ -172,6 +172,19 @@ class BasicSocketTests(unittest.TestCase):
             ss = ssl.wrap_socket(s)
             self.assertEqual(timeout, ss.gettimeout())
 
+    def test_errors(self):
+        sock = socket.socket()
+        with self.assertRaisesRegexp(ValueError, "certfile must be specified"):
+            ssl.wrap_socket(sock, server_side=True)
+            ssl.wrap_socket(sock, server_side=True, certfile="")
+        s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
+        self.assertRaisesRegexp(ValueError, "can't connect in server-side mode",
+                                s.connect, (HOST, 8080))
+        with self.assertRaisesRegexp(IOError, "No such file"):
+            ssl.wrap_socket(sock, certfile=WRONGCERT)
+            ssl.wrap_socket(sock, keyfile=WRONGCERT)
+            ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
+
 
 class ContextTests(unittest.TestCase):
 
@@ -240,7 +253,7 @@ class ContextTests(unittest.TestCase):
         ctx.load_cert_chain(CERTFILE)
         ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
         self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
-        with self.assertRaisesRegexp(ssl.SSLError, "system lib"):
+        with self.assertRaisesRegexp(IOError, "No such file"):
             ctx.load_cert_chain(WRONGCERT)
         with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
             ctx.load_cert_chain(BADCERT)
@@ -270,7 +283,7 @@ class ContextTests(unittest.TestCase):
         ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None)
         self.assertRaises(TypeError, ctx.load_verify_locations)
         self.assertRaises(TypeError, ctx.load_verify_locations, None, None)
-        with self.assertRaisesRegexp(ssl.SSLError, "system lib"):
+        with self.assertRaisesRegexp(IOError, "No such file"):
             ctx.load_verify_locations(WRONGCERT)
         with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"):
             ctx.load_verify_locations(BADCERT)
@@ -863,6 +876,9 @@ else:
             except socket.error as x:
                 if support.verbose:
                     sys.stdout.write("\nsocket.error is %s\n" % x[1])
+            except IOError as x:
+                if support.verbose:
+                    sys.stdout.write("\nsocket.error is %s\n" % str(x))
             else:
                 raise AssertionError("Use of invalid cert should have failed!")
         finally:
index f8428c4d5b52ca5abeb65a1e90ea6b02a537cd97..0008691181cea4acbb3c0a2f330bf69abda9e71f 100644 (file)
@@ -1580,6 +1580,7 @@ load_cert_chain(PySSLContext *self, PyObject *args, PyObject *kwds)
     PyObject *certfile_bytes = NULL, *keyfile_bytes = NULL;
     int r;
 
+    errno = 0;
     if (!PyArg_ParseTupleAndKeywords(args, kwds,
         "O|O:load_cert_chain", kwlist,
         &certfile, &keyfile))
@@ -1601,7 +1602,12 @@ load_cert_chain(PySSLContext *self, PyObject *args, PyObject *kwds)
         PyBytes_AS_STRING(certfile_bytes));
     PySSL_END_ALLOW_THREADS
     if (r != 1) {
-        _setSSLError(NULL, 0, __FILE__, __LINE__);
+        if (errno != 0) {
+            PyErr_SetFromErrno(PyExc_IOError);
+        }
+        else {
+            _setSSLError(NULL, 0, __FILE__, __LINE__);
+        }
         goto error;
     }
     PySSL_BEGIN_ALLOW_THREADS
@@ -1612,7 +1618,12 @@ load_cert_chain(PySSLContext *self, PyObject *args, PyObject *kwds)
     Py_XDECREF(keyfile_bytes);
     Py_XDECREF(certfile_bytes);
     if (r != 1) {
-        _setSSLError(NULL, 0, __FILE__, __LINE__);
+        if (errno != 0) {
+            PyErr_SetFromErrno(PyExc_IOError);
+        }
+        else {
+            _setSSLError(NULL, 0, __FILE__, __LINE__);
+        }
         return NULL;
     }
     PySSL_BEGIN_ALLOW_THREADS
@@ -1639,6 +1650,7 @@ load_verify_locations(PySSLContext *self, PyObject *args, PyObject *kwds)
     const char *cafile_buf = NULL, *capath_buf = NULL;
     int r;
 
+    errno = 0;
     if (!PyArg_ParseTupleAndKeywords(args, kwds,
         "|OO:load_verify_locations", kwlist,
         &cafile, &capath))
@@ -1673,7 +1685,12 @@ load_verify_locations(PySSLContext *self, PyObject *args, PyObject *kwds)
     Py_XDECREF(cafile_bytes);
     Py_XDECREF(capath_bytes);
     if (r != 1) {
-        _setSSLError(NULL, 0, __FILE__, __LINE__);
+        if (errno != 0) {
+            PyErr_SetFromErrno(PyExc_IOError);
+        }
+        else {
+            _setSSLError(NULL, 0, __FILE__, __LINE__);
+        }
         return NULL;
     }
     Py_RETURN_NONE;