diff options
author | Jean-Paul Calderone <exarkun@twistedmatrix.com> | 2013-03-06 10:29:21 -0800 |
---|---|---|
committer | Jean-Paul Calderone <exarkun@twistedmatrix.com> | 2013-03-06 10:29:21 -0800 |
commit | 173cff9ff499246703d3e1cf78ed75f5be9f51f0 (patch) | |
tree | 408aec912154fbb787120ca882d4d85f5b7253b8 | |
parent | e6f32b8404e539a7dd5746b1effe9765b9d3237e (diff) | |
download | pyopenssl-173cff9ff499246703d3e1cf78ed75f5be9f51f0.tar.gz |
Fixes and more tests for Context.use_certificate_file and Context.use_certificate
-rw-r--r-- | OpenSSL/SSL.py | 33 | ||||
-rw-r--r-- | OpenSSL/test/test_ssl.py | 88 |
2 files changed, 112 insertions, 9 deletions
diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py index 1ef3006..866fb8a 100644 --- a/OpenSSL/SSL.py +++ b/OpenSSL/SSL.py @@ -186,11 +186,12 @@ class Context(object): context = _api.ffi.gc(context, _api.SSL_CTX_free) self._context = context + self._passphrase_helper = None self._passphrase_callback = None + self._passphrase_userdata = None self._verify_callback = None self._info_callback = None self._tlsext_servername_callback = None - self._passphrase_userdata = None self._app_data = None # SSL_CTX_set_app_data(self->ctx, self); @@ -278,7 +279,7 @@ class Context(object): _raise_current_error(Error) - def use_certificate_file(self, certfile, filetype=_unspecified): + def use_certificate_file(self, certfile, filetype=FILETYPE_PEM): """ Load a certificate from a file @@ -286,6 +287,15 @@ class Context(object): :param filetype: (optional) The encoding of the file, default is PEM :return: None """ + if not isinstance(certfile, bytes): + raise TypeError("certfile must be a byte string") + if not isinstance(filetype, int): + raise TypeError("filetype must be an integer") + + use_result = _api.SSL_CTX_use_certificate_file(self._context, certfile, filetype) + if not use_result: + _raise_current_error(Error) + def use_certificate(self, cert): """ @@ -299,7 +309,7 @@ class Context(object): use_result = _api.SSL_CTX_use_certificate(self._context, cert._x509) if not use_result: - 1/0 + _raise_current_error(Error) def add_extra_chain_cert(self, certobj): @@ -319,6 +329,15 @@ class Context(object): # _raise_current_error(Error) 1/0 + + def _raise_passphrase_exception(self): + if self._passphrase_helper is None: + _raise_current_error(Error) + exception = self._passphrase_helper.raise_if_problem(Error) + if exception is not None: + raise exception + + def use_privatekey_file(self, keyfile, filetype=_unspecified): """ Load a private key from a file @@ -338,9 +357,7 @@ class Context(object): use_result = _api.SSL_CTX_use_PrivateKey_file( self._context, keyfile, filetype) if not use_result: - exception = self._passphrase_helper.raise_if_problem(Error) - if exception is not None: - raise exception + self._raise_passphrase_exception() def use_privatekey(self, pkey): @@ -355,9 +372,7 @@ class Context(object): use_result = _api.SSL_CTX_use_PrivateKey(self._context, pkey._pkey) if not use_result: - exception = self._passphrase_helper.raise_if_problem(Error) - if exception is not None: - raise exception + self._raise_passphrase_exception() def check_privatekey(self): diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py index bdb497e..884801a 100644 --- a/OpenSSL/test/test_ssl.py +++ b/OpenSSL/test/test_ssl.py @@ -342,6 +342,94 @@ class ContextTests(TestCase, _LoopbackMixin): self.assertRaises(TypeError, ctx.use_privatekey, "") + def test_use_privatekey_file_missing(self): + """ + :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` + when passed the name of a file which does not exist. + """ + ctx = Context(TLSv1_METHOD) + self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp()) + + + def test_use_certificate_wrong_args(self): + """ + :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError` + when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as an + argument. + """ + ctx = Context(TLSv1_METHOD) + self.assertRaises(TypeError, ctx.use_certificate) + self.assertRaises(TypeError, ctx.use_certificate, "hello, world") + self.assertRaises(TypeError, ctx.use_certificate, X509(), "hello, world") + + + def test_use_certificate_uninitialized(self): + """ + :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error` + when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been + initialized (ie, which does not actually have any certificate data). + """ + ctx = Context(TLSv1_METHOD) + self.assertRaises(Error, ctx.use_certificate, X509()) + + + def test_use_certificate(self): + """ + :py:obj:`Context.use_certificate` sets the certificate which will be + used to identify connections created using the context. + """ + # TODO + # Hard to assert anything. But we could set a privatekey then ask + # OpenSSL if the cert and key agree using check_privatekey. Then as + # long as check_privatekey works right we're good... + ctx = Context(TLSv1_METHOD) + ctx.use_certificate(load_certificate(FILETYPE_PEM, cleartextCertificatePEM)) + + + def test_use_certificate_file_wrong_args(self): + """ + :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if + called with zero arguments or more than two arguments, or if the first + argument is not a byte string or the second argumnent is not an integer. + """ + ctx = Context(TLSv1_METHOD) + self.assertRaises(TypeError, ctx.use_certificate_file) + self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile", object()) + self.assertRaises( + TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM, object()) + self.assertRaises( + TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM) + self.assertRaises( + TypeError, ctx.use_certificate_file, b"somefile", object()) + + + def test_use_certificate_file_missing(self): + """ + :py:obj:`Context.use_certificate_file` raises + `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does not + exist. + """ + ctx = Context(TLSv1_METHOD) + self.assertRaises(Error, ctx.use_certificate_file, self.mktemp()) + + + def test_use_certificate_file(self): + """ + :py:obj:`Context.use_certificate` sets the certificate which will be + used to identify connections created using the context. + """ + # TODO + # Hard to assert anything. But we could set a privatekey then ask + # OpenSSL if the cert and key agree using check_privatekey. Then as + # long as check_privatekey works right we're good... + pem_filename = self.mktemp() + with open(pem_filename, "w") as pem_file: + pem_file.write(cleartextCertificatePEM) + + ctx = Context(TLSv1_METHOD) + ctx.use_certificate_file(pem_filename) + + def test_set_app_data_wrong_args(self): """ :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than |