summaryrefslogtreecommitdiff
path: root/OpenSSL
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSSL')
-rw-r--r--OpenSSL/crypto/crl.c55
-rw-r--r--OpenSSL/crypto/crypto.c230
-rw-r--r--OpenSSL/crypto/netscape_spki.c26
-rw-r--r--OpenSSL/crypto/pkcs12.c48
-rw-r--r--OpenSSL/crypto/pkcs7.c10
-rw-r--r--OpenSSL/crypto/pkey.c44
-rw-r--r--OpenSSL/crypto/revoked.c26
-rw-r--r--OpenSSL/crypto/x509.c90
-rw-r--r--OpenSSL/crypto/x509ext.c26
-rw-r--r--OpenSSL/crypto/x509name.c10
-rw-r--r--OpenSSL/crypto/x509req.c32
-rw-r--r--OpenSSL/crypto/x509store.c4
-rw-r--r--OpenSSL/rand/rand.c36
-rwxr-xr-xOpenSSL/ssl/connection.c274
-rw-r--r--OpenSSL/ssl/context.c174
-rw-r--r--OpenSSL/ssl/session.c159
-rw-r--r--OpenSSL/ssl/session.h27
-rw-r--r--OpenSSL/ssl/ssl.c27
-rw-r--r--OpenSSL/ssl/ssl.h1
-rw-r--r--OpenSSL/test/__init__.py2
-rw-r--r--OpenSSL/test/test_crypto.py600
-rw-r--r--OpenSSL/test/test_rand.py44
-rw-r--r--OpenSSL/test/test_ssl.py648
-rw-r--r--OpenSSL/test/util.py49
24 files changed, 1769 insertions, 873 deletions
diff --git a/OpenSSL/crypto/crl.c b/OpenSSL/crypto/crl.c
index eec5bcb..3f56d83 100644
--- a/OpenSSL/crypto/crl.c
+++ b/OpenSSL/crypto/crl.c
@@ -2,7 +2,6 @@
#define crypto_MODULE
#include "crypto.h"
-
static X509_REVOKED * X509_REVOKED_dup(X509_REVOKED *orig) {
X509_REVOKED *dupe = NULL;
@@ -37,7 +36,7 @@ static char crypto_CRL_get_revoked_doc[] = "\n\
Return revoked portion of the CRL structure (by value\n\
not reference).\n\
\n\
-@return: A tuple of Revoked objects.\n\
+:return: A tuple of Revoked objects.\n\
";
static PyObject *
crypto_CRL_get_revoked(crypto_CRLObj *self, PyObject *args) {
@@ -84,9 +83,9 @@ crypto_CRL_get_revoked(crypto_CRLObj *self, PyObject *args) {
static char crypto_CRL_add_revoked_doc[] = "\n\
Add a revoked (by value not reference) to the CRL structure\n\
\n\
-@param cert: The new revoked.\n\
-@type cert: L{X509}\n\
-@return: None\n\
+:param cert: The new revoked.\n\
+:type cert: :class:`X509`\n\
+:return: None\n\
";
static PyObject *
crypto_CRL_add_revoked(crypto_CRLObj *self, PyObject *args, PyObject *keywds) {
@@ -112,14 +111,14 @@ crypto_CRL_add_revoked(crypto_CRLObj *self, PyObject *args, PyObject *keywds) {
static char crypto_CRL_export_doc[] = "\n\
export(cert, key[, type[, days]]) -> export a CRL as a string\n\
\n\
-@param cert: Used to sign CRL.\n\
-@type cert: L{X509}\n\
-@param key: Used to sign CRL.\n\
-@type key: L{PKey}\n\
-@param type: The export format, either L{FILETYPE_PEM}, L{FILETYPE_ASN1}, or L{FILETYPE_TEXT}.\n\
-@param days: The number of days until the next update of this CRL.\n\
-@type days: L{int}\n\
-@return: L{str}\n\
+:param cert: Used to sign CRL.\n\
+:type cert: :class:`X509`\n\
+:param key: Used to sign CRL.\n\
+:type key: :class:`PKey`\n\
+:param type: The export format, either :py:data:`FILETYPE_PEM`, :py:data:`FILETYPE_ASN1`, or :py:data:`FILETYPE_TEXT`.\n\
+:param days: The number of days until the next update of this CRL.\n\
+:type days: :py:data:`int`\n\
+:return: :py:data:`str`\n\
";
static PyObject *
crypto_CRL_export(crypto_CRLObj *self, PyObject *args, PyObject *keywds) {
@@ -131,13 +130,27 @@ crypto_CRL_export(crypto_CRLObj *self, PyObject *args, PyObject *keywds) {
ASN1_TIME *tmptm;
crypto_X509Obj *x509;
static char *kwlist[] = {"cert", "key", "type", "days", NULL};
-
+
if (!PyArg_ParseTupleAndKeywords(args, keywds, "O!O!|ii:dump_crl", kwlist,
- &crypto_X509_Type, &x509,
+ &crypto_X509_Type, &x509,
&crypto_PKey_Type, &key, &type, &days)) {
return NULL;
}
-
+
+
+#if OPENSSL_VERSION_NUMBER >= 0x01000000L
+ /* Older versions of OpenSSL had no problem with trying to export using an
+ * uninitialized key. Newer versions segfault, instead. We can only check
+ * on the new versions, though, because the old versions don't even have the
+ * field that the segfault is triggered by.
+ */
+ if (!key->pkey->ameth) {
+ PyErr_SetString(
+ crypto_Error, "Cannot export with an unitialized key");
+ return NULL;
+ }
+#endif
+
bio = BIO_new(BIO_s_mem());
tmptm = ASN1_TIME_new();
if (!tmptm) {
@@ -149,7 +162,13 @@ crypto_CRL_export(crypto_CRLObj *self, PyObject *args, PyObject *keywds) {
X509_CRL_set_nextUpdate(self->crl, tmptm);
ASN1_TIME_free(tmptm);
X509_CRL_set_issuer_name(self->crl, X509_get_subject_name(x509->x509));
- X509_CRL_sign(self->crl, key->pkey, EVP_md5());
+
+ if (!X509_CRL_sign(self->crl, key->pkey, EVP_md5())) {
+ exception_from_error_queue(crypto_Error);
+ BIO_free(bio);
+ return NULL;
+ }
+
switch (type) {
case X509_FILETYPE_PEM:
ret = PEM_write_bio_X509_CRL(bio, self->crl);
@@ -223,7 +242,7 @@ CRL() -> CRL instance\n\
\n\
Create a new empty CRL object.\n\
\n\
-@returns: The CRL object\n\
+:returns: The CRL object\n\
";
static PyObject* crypto_CRL_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs) {
diff --git a/OpenSSL/crypto/crypto.c b/OpenSSL/crypto/crypto.c
index 3573a12..ad35ce9 100644
--- a/OpenSSL/crypto/crypto.c
+++ b/OpenSSL/crypto/crypto.c
@@ -45,32 +45,82 @@ global_passphrase_callback(char *buf, int len, int rwflag, void *cb_arg)
func = (PyObject *)cb_arg;
argv = Py_BuildValue("(i)", rwflag);
+ if (argv == NULL) {
+ return 0;
+ }
ret = PyEval_CallObject(func, argv);
Py_DECREF(argv);
- if (ret == NULL)
+ if (ret == NULL) {
return 0;
- if (!PyBytes_Check(ret))
- {
+ }
+ if (!PyBytes_Check(ret)) {
+ Py_DECREF(ret);
PyErr_SetString(PyExc_ValueError, "String expected");
return 0;
}
nchars = PyBytes_Size(ret);
- if (nchars > len)
- nchars = len;
+ if (nchars > len) {
+ Py_DECREF(ret);
+ PyErr_SetString(PyExc_ValueError,
+ "passphrase returned by callback is too long");
+ return 0;
+ }
strncpy(buf, PyBytes_AsString(ret), nchars);
+ Py_DECREF(ret);
return nchars;
}
+static PyObject *
+raise_current_error(void)
+{
+ if (PyErr_Occurred()) {
+ /*
+ * The python exception from callback is more informative than
+ * OpenSSL's error.
+ */
+ flush_error_queue();
+ return NULL;
+ }
+ exception_from_error_queue(crypto_Error);
+ return NULL;
+}
+
+static int
+setup_callback(int type, PyObject *pw, pem_password_cb **cb, void **cb_arg) {
+ if (pw == NULL) {
+ *cb = NULL;
+ *cb_arg = NULL;
+ return 1;
+ }
+ if (type != X509_FILETYPE_PEM) {
+ PyErr_SetString(PyExc_ValueError,
+ "only FILETYPE_PEM key format supports encryption");
+ return 0;
+ }
+ if (PyBytes_Check(pw)) {
+ *cb = NULL;
+ *cb_arg = PyBytes_AsString(pw);
+ } else if (PyCallable_Check(pw)) {
+ *cb = global_passphrase_callback;
+ *cb_arg = pw;
+ } else {
+ PyErr_SetString(PyExc_TypeError,
+ "Last argument must be string or callable");
+ return 0;
+ }
+ return 1;
+}
+
static char crypto_load_privatekey_doc[] = "\n\
Load a private key from a buffer\n\
\n\
-@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
-@param buffer: The buffer the key is stored in\n\
-@param passphrase: (optional) if encrypted PEM format, this can be\n\
+:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
+:param buffer: The buffer the key is stored in\n\
+:param passphrase: (optional) if encrypted PEM format, this can be\n\
either the passphrase to use, or a callback for\n\
providing the passphrase.\n\
\n\
-@return: The PKey object\n\
+:return: The PKey object\n\
";
static PyObject *
@@ -85,31 +135,20 @@ crypto_load_privatekey(PyObject *spam, PyObject *args)
BIO *bio;
EVP_PKEY *pkey;
- if (!PyArg_ParseTuple(args, "is#|O:load_privatekey", &type, &buffer, &len, &pw))
+ if (!PyArg_ParseTuple(args, "is#|O:load_privatekey",
+ &type, &buffer, &len, &pw)) {
+ return NULL;
+ }
+ if (!setup_callback(type, pw, &cb, &cb_arg)) {
return NULL;
-
- if (pw != NULL)
- {
- if (PyBytes_Check(pw))
- {
- cb = NULL;
- cb_arg = PyBytes_AsString(pw);
- }
- else if (PyCallable_Check(pw))
- {
- cb = global_passphrase_callback;
- cb_arg = pw;
- }
- else
- {
- PyErr_SetString(PyExc_TypeError, "Last argument must be string or callable");
- return NULL;
- }
}
bio = BIO_new_mem_buf(buffer, len);
- switch (type)
- {
+ if (bio == NULL) {
+ exception_from_error_queue(crypto_Error);
+ return NULL;
+ }
+ switch (type) {
case X509_FILETYPE_PEM:
pkey = PEM_read_bio_PrivateKey(bio, NULL, cb, cb_arg);
break;
@@ -125,10 +164,8 @@ crypto_load_privatekey(PyObject *spam, PyObject *args)
}
BIO_free(bio);
- if (pkey == NULL)
- {
- exception_from_error_queue(crypto_Error);
- return NULL;
+ if (pkey == NULL) {
+ return raise_current_error();
}
return (PyObject *)crypto_PKey_New(pkey, 1);
@@ -137,15 +174,15 @@ crypto_load_privatekey(PyObject *spam, PyObject *args)
static char crypto_dump_privatekey_doc[] = "\n\
Dump a private key to a buffer\n\
\n\
-@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
-@param pkey: The PKey to dump\n\
-@param cipher: (optional) if encrypted PEM format, the cipher to\n\
+:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
+:param pkey: The PKey to dump\n\
+:param cipher: (optional) if encrypted PEM format, the cipher to\n\
use\n\
-@param passphrase - (optional) if encrypted PEM format, this can be either\n\
- the passphrase to use, or a callback for providing the\n\
- passphrase.\n\
-@return: The buffer with the dumped key in\n\
-@rtype: C{str}\n\
+:param passphrase: (optional) if encrypted PEM format, this can be either\n\
+ the passphrase to use, or a callback for providing the\n\
+ passphrase.\n\
+:return: The buffer with the dumped key in\n\
+:rtype: :py:data:`str`\n\
";
static PyObject *
@@ -164,49 +201,32 @@ crypto_dump_privatekey(PyObject *spam, PyObject *args)
crypto_PKeyObj *pkey;
if (!PyArg_ParseTuple(args, "iO!|sO:dump_privatekey", &type,
- &crypto_PKey_Type, &pkey, &cipher_name, &pw))
+ &crypto_PKey_Type, &pkey, &cipher_name, &pw)) {
return NULL;
-
- if (cipher_name != NULL && pw == NULL)
- {
+ }
+ if (cipher_name != NULL && pw == NULL) {
PyErr_SetString(PyExc_ValueError, "Illegal number of arguments");
return NULL;
}
- if (cipher_name != NULL)
- {
+ if (cipher_name != NULL) {
cipher = EVP_get_cipherbyname(cipher_name);
- if (cipher == NULL)
- {
+ if (cipher == NULL) {
PyErr_SetString(PyExc_ValueError, "Invalid cipher name");
return NULL;
}
- if (PyBytes_Check(pw))
- {
- cb = NULL;
- cb_arg = PyBytes_AsString(pw);
- }
- else if (PyCallable_Check(pw))
- {
- cb = global_passphrase_callback;
- cb_arg = pw;
- }
- else
- {
- PyErr_SetString(PyExc_TypeError, "Last argument must be string or callable");
+ if (!setup_callback(type, pw, &cb, &cb_arg)) {
return NULL;
}
}
bio = BIO_new(BIO_s_mem());
- switch (type)
- {
+ if (bio == NULL) {
+ exception_from_error_queue(crypto_Error);
+ return NULL;
+ }
+ switch (type) {
case X509_FILETYPE_PEM:
ret = PEM_write_bio_PrivateKey(bio, pkey->pkey, cipher, NULL, 0, cb, cb_arg);
- if (PyErr_Occurred())
- {
- BIO_free(bio);
- return NULL;
- }
break;
case X509_FILETYPE_ASN1:
@@ -215,8 +235,12 @@ crypto_dump_privatekey(PyObject *spam, PyObject *args)
case X509_FILETYPE_TEXT:
rsa = EVP_PKEY_get1_RSA(pkey->pkey);
+ if (rsa == NULL) {
+ ret = 0;
+ break;
+ }
ret = RSA_print(bio, rsa, 0);
- RSA_free(rsa);
+ RSA_free(rsa);
break;
default:
@@ -225,11 +249,9 @@ crypto_dump_privatekey(PyObject *spam, PyObject *args)
return NULL;
}
- if (ret == 0)
- {
+ if (ret == 0) {
BIO_free(bio);
- exception_from_error_queue(crypto_Error);
- return NULL;
+ return raise_current_error();
}
buf_len = BIO_get_mem_data(bio, &temp);
@@ -242,9 +264,9 @@ crypto_dump_privatekey(PyObject *spam, PyObject *args)
static char crypto_load_certificate_doc[] = "\n\
Load a certificate from a buffer\n\
\n\
-@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
+:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
buffer - The buffer the certificate is stored in\n\
-@return: The X509 object\n\
+:return: The X509 object\n\
";
static PyObject *
@@ -289,9 +311,9 @@ crypto_load_certificate(PyObject *spam, PyObject *args)
static char crypto_dump_certificate_doc[] = "\n\
Dump a certificate to a buffer\n\
\n\
-@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
-@param cert: The certificate to dump\n\
-@return: The buffer with the dumped certificate in\n\
+:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
+:param cert: The certificate to dump\n\
+:return: The buffer with the dumped certificate in\n\
";
static PyObject *
@@ -345,9 +367,9 @@ crypto_dump_certificate(PyObject *spam, PyObject *args)
static char crypto_load_certificate_request_doc[] = "\n\
Load a certificate request from a buffer\n\
\n\
-@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
+:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
buffer - The buffer the certificate request is stored in\n\
-@return: The X509Req object\n\
+:return: The X509Req object\n\
";
static PyObject *
@@ -392,9 +414,9 @@ crypto_load_certificate_request(PyObject *spam, PyObject *args)
static char crypto_dump_certificate_request_doc[] = "\n\
Dump a certificate request to a buffer\n\
\n\
-@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
+:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
req - The certificate request to dump\n\
-@return: The buffer with the dumped certificate request in\n\
+:return: The buffer with the dumped certificate request in\n\
";
static PyObject *
@@ -448,10 +470,10 @@ crypto_dump_certificate_request(PyObject *spam, PyObject *args)
static char crypto_load_crl_doc[] = "\n\
Load a certificate revocation list from a buffer\n\
\n\
-@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
-@param buffer: The buffer the CRL is stored in\n\
+:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
+:param buffer: The buffer the CRL is stored in\n\
\n\
-@return: The PKey object\n\
+:return: The PKey object\n\
";
static PyObject *
@@ -493,9 +515,9 @@ crypto_load_crl(PyObject *spam, PyObject *args) {
static char crypto_load_pkcs7_data_doc[] = "\n\
Load pkcs7 data from a buffer\n\
\n\
-@param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)\n\
+:param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)\n\
buffer - The buffer with the pkcs7 data.\n\
-@return: The PKCS7 object\n\
+:return: The PKCS7 object\n\
";
static PyObject *
@@ -509,8 +531,8 @@ crypto_load_pkcs7_data(PyObject *spam, PyObject *args)
if (!PyArg_ParseTuple(args, "is#:load_pkcs7_data", &type, &buffer, &len))
return NULL;
- /*
- * Try to read the pkcs7 data from the bio
+ /*
+ * Try to read the pkcs7 data from the bio
*/
bio = BIO_new_mem_buf(buffer, len);
switch (type)
@@ -545,9 +567,9 @@ crypto_load_pkcs7_data(PyObject *spam, PyObject *args)
static char crypto_load_pkcs12_doc[] = "\n\
Load a PKCS12 object from a buffer\n\
\n\
-@param buffer: The buffer the certificate is stored in\n\
+:param buffer: The buffer the certificate is stored in\n\
passphrase (Optional) - The password to decrypt the PKCS12 lump\n\
-@returns: The PKCS12 object\n\
+:returns: The PKCS12 object\n\
";
static PyObject *
@@ -577,8 +599,8 @@ crypto_load_pkcs12(PyObject *spam, PyObject *args)
static char crypto_X509_verify_cert_error_string_doc[] = "\n\
Get X509 verify certificate error string.\n\
\n\
-@param errnum: The error number.\n\
-@return: Error string as a Python string\n\
+:param errnum: The error number.\n\
+:return: Error string as a Python string\n\
";
static PyObject *
@@ -607,10 +629,10 @@ crypto_exception_from_error_queue(PyObject *spam, PyObject *eggs) {
static char crypto_sign_doc[] = "\n\
Sign data with a digest\n\
\n\
-@param pkey: Pkey to sign with\n\
-@param data: data to be signed\n\
-@param digest: message digest to use\n\
-@return: signature\n\
+:param pkey: Pkey to sign with\n\
+:param data: data to be signed\n\
+:param digest: message digest to use\n\
+:return: signature\n\
";
static PyObject *
@@ -654,11 +676,11 @@ crypto_sign(PyObject *spam, PyObject *args) {
static char crypto_verify_doc[] = "\n\
Verify a signature\n\
\n\
-@param cert: signing certificate (X509 object)\n\
-@param signature: signature returned by sign function\n\
-@param data: data to be verified\n\
-@param digest: message digest to use\n\
-@return: None if the signature is correct, raise exception otherwise\n\
+:param cert: signing certificate (X509 object)\n\
+:param signature: signature returned by sign function\n\
+:param data: data to be verified\n\
+:param digest: message digest to use\n\
+:return: None if the signature is correct, raise exception otherwise\n\
";
static PyObject *
diff --git a/OpenSSL/crypto/netscape_spki.c b/OpenSSL/crypto/netscape_spki.c
index 9369d50..8110a24 100644
--- a/OpenSSL/crypto/netscape_spki.c
+++ b/OpenSSL/crypto/netscape_spki.c
@@ -38,9 +38,9 @@ crypto_NetscapeSPKI_New(NETSCAPE_SPKI *name, int dealloc)
static char crypto_NetscapeSPKI_doc[] = "\n\
NetscapeSPKI([enc]) -> NetscapeSPKI instance\n\
\n\
-@param enc: Base64 encoded NetscapeSPKI object.\n\
-@type enc: C{str}\n\
-@return: The NetscapeSPKI object\n\
+:param enc: Base64 encoded NetscapeSPKI object.\n\
+:type enc: :py:data:`str`\n\
+:return: The NetscapeSPKI object\n\
";
static PyObject *
@@ -84,9 +84,9 @@ crypto_NetscapeSPKI_dealloc(crypto_NetscapeSPKIObj *self)
static char crypto_NetscapeSPKI_sign_doc[] = "\n\
Sign the certificate request using the supplied key and digest\n\
\n\
-@param pkey: The key to sign with\n\
-@param digest: The message digest to use\n\
-@return: None\n\
+:param pkey: The key to sign with\n\
+:param digest: The message digest to use\n\
+:return: None\n\
";
static PyObject *
@@ -129,9 +129,9 @@ crypto_NetscapeSPKI_sign(crypto_NetscapeSPKIObj *self, PyObject *args)
static char crypto_NetscapeSPKI_verify_doc[] = "\n\
Verifies a certificate request using the supplied public key\n\
\n\
-@param key: a public key\n\
-@return: True if the signature is correct.\n\
-@raise OpenSSL.crypto.Error: If the signature is invalid or there is a\n\
+:param key: a public key\n\
+:return: True if the signature is correct.\n\
+:raise OpenSSL.crypto.Error: If the signature is invalid or there is a\n\
problem verifying the signature.\n\
";
@@ -156,7 +156,7 @@ crypto_NetscapeSPKI_verify(crypto_NetscapeSPKIObj *self, PyObject *args)
static char crypto_NetscapeSPKI_b64_encode_doc[] = "\n\
Generate a base64 encoded string from an SPKI\n\
\n\
-@return: The base64 encoded string\n\
+:return: The base64 encoded string\n\
";
PyObject *
@@ -175,7 +175,7 @@ crypto_NetscapeSPKI_b64_encode(crypto_NetscapeSPKIObj *self, PyObject *args)
static char crypto_NetscapeSPKI_get_pubkey_doc[] = "\n\
Get the public key of the certificate\n\
\n\
-@return: The public key\n\
+:return: The public key\n\
";
static PyObject *
@@ -204,8 +204,8 @@ crypto_NetscapeSPKI_get_pubkey(crypto_NetscapeSPKIObj *self, PyObject *args)
static char crypto_NetscapeSPKI_set_pubkey_doc[] = "\n\
Set the public key of the certificate\n\
\n\
-@param pkey: The public key\n\
-@return: None\n\
+:param pkey: The public key\n\
+:return: None\n\
";
static PyObject *
diff --git a/OpenSSL/crypto/pkcs12.c b/OpenSSL/crypto/pkcs12.c
index a1a5a79..f8e66a8 100644
--- a/OpenSSL/crypto/pkcs12.c
+++ b/OpenSSL/crypto/pkcs12.c
@@ -26,7 +26,7 @@ static int crypto_PKCS12_clear(crypto_PKCS12Obj *self);
static char crypto_PKCS12_get_certificate_doc[] = "\n\
Return certificate portion of the PKCS12 structure\n\
\n\
-@return: X509 object containing the certificate\n\
+:return: X509 object containing the certificate\n\
";
static PyObject *
crypto_PKCS12_get_certificate(crypto_PKCS12Obj *self, PyObject *args)
@@ -41,9 +41,9 @@ crypto_PKCS12_get_certificate(crypto_PKCS12Obj *self, PyObject *args)
static char crypto_PKCS12_set_certificate_doc[] = "\n\
Replace the certificate portion of the PKCS12 structure\n\
\n\
-@param cert: The new certificate.\n\
-@type cert: L{X509} or L{NoneType}\n\
-@return: None\n\
+:param cert: The new certificate.\n\
+:type cert: :py:class:`X509` or :py:data:`None`\n\
+:return: None\n\
";
static PyObject *
crypto_PKCS12_set_certificate(crypto_PKCS12Obj *self, PyObject *args, PyObject *keywds) {
@@ -70,7 +70,7 @@ crypto_PKCS12_set_certificate(crypto_PKCS12Obj *self, PyObject *args, PyObject *
static char crypto_PKCS12_get_privatekey_doc[] = "\n\
Return private key portion of the PKCS12 structure\n\
\n\
-@returns: PKey object containing the private key\n\
+:returns: PKey object containing the private key\n\
";
static crypto_PKeyObj *
crypto_PKCS12_get_privatekey(crypto_PKCS12Obj *self, PyObject *args)
@@ -85,9 +85,9 @@ crypto_PKCS12_get_privatekey(crypto_PKCS12Obj *self, PyObject *args)
static char crypto_PKCS12_set_privatekey_doc[] = "\n\
Replace or set the certificate portion of the PKCS12 structure\n\
\n\
-@param pkey: The new private key.\n\
-@type pkey: L{PKey}\n\
-@return: None\n\
+:param pkey: The new private key.\n\
+:type pkey: :py:class:`PKey`\n\
+:return: None\n\
";
static PyObject *
crypto_PKCS12_set_privatekey(crypto_PKCS12Obj *self, PyObject *args, PyObject *keywds) {
@@ -114,7 +114,7 @@ crypto_PKCS12_set_privatekey(crypto_PKCS12Obj *self, PyObject *args, PyObject *k
static char crypto_PKCS12_get_ca_certificates_doc[] = "\n\
Return CA certificates within of the PKCS12 object\n\
\n\
-@return: A newly created tuple containing the CA certificates in the chain,\n\
+:return: A newly created tuple containing the CA certificates in the chain,\n\
if any are present, or None if no CA certificates are present.\n\
";
static PyObject *
@@ -130,9 +130,9 @@ crypto_PKCS12_get_ca_certificates(crypto_PKCS12Obj *self, PyObject *args)
static char crypto_PKCS12_set_ca_certificates_doc[] = "\n\
Replace or set the CA certificates withing the PKCS12 object.\n\
\n\
-@param cacerts: The new CA certificates.\n\
-@type cacerts: Iterable of L{X509} or L{NoneType}\n\
-@return: None\n\
+:param cacerts: The new CA certificates.\n\
+:type cacerts: Iterable of :py:class:`X509` or :py:data:`None`\n\
+:return: None\n\
";
static PyObject *
crypto_PKCS12_set_ca_certificates(crypto_PKCS12Obj *self, PyObject *args, PyObject *keywds)
@@ -176,7 +176,7 @@ crypto_PKCS12_set_ca_certificates(crypto_PKCS12Obj *self, PyObject *args, PyObje
static char crypto_PKCS12_get_friendlyname_doc[] = "\n\
Return friendly name portion of the PKCS12 structure\n\
\n\
-@returns: String containing the friendlyname\n\
+:returns: String containing the friendlyname\n\
";
static PyObject *
crypto_PKCS12_get_friendlyname(crypto_PKCS12Obj *self, PyObject *args) {
@@ -190,9 +190,9 @@ crypto_PKCS12_get_friendlyname(crypto_PKCS12Obj *self, PyObject *args) {
static char crypto_PKCS12_set_friendlyname_doc[] = "\n\
Replace or set the certificate portion of the PKCS12 structure\n\
\n\
-@param name: The new friendly name.\n\
-@type name: L{str}\n\
-@return: None\n\
+:param name: The new friendly name.\n\
+:type name: :py:data:`str`\n\
+:return: None\n\
";
static PyObject *
crypto_PKCS12_set_friendlyname(crypto_PKCS12Obj *self, PyObject *args, PyObject *keywds) {
@@ -220,13 +220,13 @@ static char crypto_PKCS12_export_doc[] = "\n\
export([passphrase=None][, friendly_name=None][, iter=2048][, maciter=1]\n\
Dump a PKCS12 object as a string. See also \"man PKCS12_create\".\n\
\n\
-@param passphrase: used to encrypt the PKCS12\n\
-@type passphrase: L{str}\n\
-@param iter: How many times to repeat the encryption\n\
-@type iter: L{int}\n\
-@param maciter: How many times to repeat the MAC\n\
-@type maciter: L{int}\n\
-@return: The string containing the PKCS12\n\
+:param passphrase: used to encrypt the PKCS12\n\
+:type passphrase: :py:data:`str`\n\
+:param iter: How many times to repeat the encryption\n\
+:type iter: :py:data:`int`\n\
+:param maciter: How many times to repeat the MAC\n\
+:type maciter: :py:data:`int`\n\
+:return: The string containing the PKCS12\n\
";
static PyObject *
crypto_PKCS12_export(crypto_PKCS12Obj *self, PyObject *args, PyObject *keywds) {
@@ -439,7 +439,7 @@ PKCS12() -> PKCS12 instance\n\
\n\
Create a new empty PKCS12 object.\n\
\n\
-@returns: The PKCS12 object\n\
+:returns: The PKCS12 object\n\
";
static PyObject *
crypto_PKCS12_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs) {
diff --git a/OpenSSL/crypto/pkcs7.c b/OpenSSL/crypto/pkcs7.c
index 1770f7f..24adde8 100644
--- a/OpenSSL/crypto/pkcs7.c
+++ b/OpenSSL/crypto/pkcs7.c
@@ -15,7 +15,7 @@
static char crypto_PKCS7_type_is_signed_doc[] = "\n\
Check if this NID_pkcs7_signed object\n\
\n\
-@return: True if the PKCS7 is of type signed\n\
+:return: True if the PKCS7 is of type signed\n\
";
static PyObject *
@@ -33,7 +33,7 @@ crypto_PKCS7_type_is_signed(crypto_PKCS7Obj *self, PyObject *args)
static char crypto_PKCS7_type_is_enveloped_doc[] = "\n\
Check if this NID_pkcs7_enveloped object\n\
\n\
-@returns: True if the PKCS7 is of type enveloped\n\
+:returns: True if the PKCS7 is of type enveloped\n\
";
static PyObject *
@@ -51,7 +51,7 @@ crypto_PKCS7_type_is_enveloped(crypto_PKCS7Obj *self, PyObject *args)
static char crypto_PKCS7_type_is_signedAndEnveloped_doc[] = "\n\
Check if this NID_pkcs7_signedAndEnveloped object\n\
\n\
-@returns: True if the PKCS7 is of type signedAndEnveloped\n\
+:returns: True if the PKCS7 is of type signedAndEnveloped\n\
";
static PyObject *
@@ -69,7 +69,7 @@ crypto_PKCS7_type_is_signedAndEnveloped(crypto_PKCS7Obj *self, PyObject *args)
static char crypto_PKCS7_type_is_data_doc[] = "\n\
Check if this NID_pkcs7_data object\n\
\n\
-@return: True if the PKCS7 is of type data\n\
+:return: True if the PKCS7 is of type data\n\
";
static PyObject *
@@ -87,7 +87,7 @@ crypto_PKCS7_type_is_data(crypto_PKCS7Obj *self, PyObject *args)
static char crypto_PKCS7_get_type_name_doc[] = "\n\
Returns the type name of the PKCS7 structure\n\
\n\
-@return: A string with the typename\n\
+:return: A string with the typename\n\
";
static PyObject *
diff --git a/OpenSSL/crypto/pkey.c b/OpenSSL/crypto/pkey.c
index 1f78682..f23ec70 100644
--- a/OpenSSL/crypto/pkey.c
+++ b/OpenSSL/crypto/pkey.c
@@ -30,9 +30,9 @@ do { \
static char crypto_PKey_generate_key_doc[] = "\n\
Generate a key of a given type, with a given number of a bits\n\
\n\
-@param type: The key type (TYPE_RSA or TYPE_DSA)\n\
-@param bits: The number of bits\n\
-@return: None\n\
+:param type: The key type (TYPE_RSA or TYPE_DSA)\n\
+:param bits: The number of bits\n\
+:return: None\n\
";
static PyObject *
@@ -52,19 +52,30 @@ crypto_PKey_generate_key(crypto_PKeyObj *self, PyObject *args)
PyErr_SetString(PyExc_ValueError, "Invalid number of bits");
return NULL;
}
- if ((rsa = RSA_generate_key(bits, 0x10001, NULL, NULL)) == NULL)
+ Py_BEGIN_ALLOW_THREADS;
+ rsa = RSA_generate_key(bits, 0x10001, NULL, NULL);
+ Py_END_ALLOW_THREADS;
+ if (rsa == NULL) {
FAIL();
- if (!EVP_PKEY_assign_RSA(self->pkey, rsa))
+ }
+ if (!EVP_PKEY_assign_RSA(self->pkey, rsa)) {
FAIL();
+ }
break;
case crypto_TYPE_DSA:
- if ((dsa = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL)) == NULL)
+ Py_BEGIN_ALLOW_THREADS;
+ dsa = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL);
+ Py_END_ALLOW_THREADS;
+ if (dsa == NULL) {
FAIL();
- if (!DSA_generate_key(dsa))
+ }
+ if (!DSA_generate_key(dsa)) {
FAIL();
- if (!EVP_PKEY_assign_DSA(self->pkey, dsa))
+ }
+ if (!EVP_PKEY_assign_DSA(self->pkey, dsa)) {
FAIL();
+ }
break;
default:
@@ -80,7 +91,7 @@ crypto_PKey_generate_key(crypto_PKeyObj *self, PyObject *args)
static char crypto_PKey_bits_doc[] = "\n\
Returns the number of bits of the key\n\
\n\
-@return: The number of bits of the key.\n\
+:return: The number of bits of the key.\n\
";
static PyObject *
@@ -95,7 +106,7 @@ crypto_PKey_bits(crypto_PKeyObj *self, PyObject *args)
static char crypto_PKey_type_doc[] = "\n\
Returns the type of the key\n\
\n\
-@return: The type of the key.\n\
+:return: The type of the key.\n\
";
static PyObject *
@@ -110,9 +121,9 @@ crypto_PKey_type(crypto_PKeyObj *self, PyObject *args)
static char crypto_PKey_check_doc[] = "\n\
Check the consistency of an RSA private key.\n\
\n\
-@return: True if key is consistent.\n\
-@raise Error: if the key is inconsistent.\n\
-@raise TypeError: if the key is of a type which cannot be checked.\n\
+:return: True if key is consistent.\n\
+:raise Error: if the key is inconsistent.\n\
+:raise TypeError: if the key is of a type which cannot be checked.\n\
Only RSA keys can currently be checked.\n\
";
@@ -124,6 +135,11 @@ crypto_PKey_check(crypto_PKeyObj *self, PyObject *args) {
return NULL;
}
+ if (self->only_public) {
+ PyErr_SetString(PyExc_TypeError, "public key only");
+ return NULL;
+ }
+
if (self->pkey->type == EVP_PKEY_RSA) {
RSA *rsa;
rsa = EVP_PKEY_get1_RSA(self->pkey);
@@ -194,7 +210,7 @@ PKey() -> PKey instance\n\
\n\
Create a new PKey object.\n\
\n\
-@return: The PKey object\n\
+:return: The PKey object\n\
";
static PyObject*
crypto_PKey_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs) {
diff --git a/OpenSSL/crypto/revoked.c b/OpenSSL/crypto/revoked.c
index 93f9946..ed183b7 100644
--- a/OpenSSL/crypto/revoked.c
+++ b/OpenSSL/crypto/revoked.c
@@ -26,7 +26,7 @@ static const char *crl_reasons[] = {
static char crypto_Revoked_all_reasons_doc[] = "\n\
Return a list of all the supported reason strings.\n\
\n\
-@return: A list of reason strings.\n\
+:return: A list of reason strings.\n\
";
static PyObject *
crypto_Revoked_all_reasons(crypto_RevokedObj *self, PyObject *args) {
@@ -126,9 +126,9 @@ reason_str_to_code(const char * reason_str) {
static char crypto_Revoked_set_reason_doc[] = "\n\
Set the reason of a Revoked object.\n\
\n\
-@param reason: The reason string.\n\
-@type reason: L{str}\n\
-@return: None\n\
+:param reason: The reason string.\n\
+:type reason: :py:data:`str`\n\
+:return: None\n\
";
static PyObject *
crypto_Revoked_set_reason(crypto_RevokedObj *self, PyObject *args, PyObject *keywds) {
@@ -176,7 +176,7 @@ crypto_Revoked_set_reason(crypto_RevokedObj *self, PyObject *args, PyObject *key
static char crypto_Revoked_get_reason_doc[] = "\n\
Return the reason of a Revoked object.\n\
\n\
-@return: The reason as a string\n\
+:return: The reason as a string\n\
";
static PyObject *
crypto_Revoked_get_reason(crypto_RevokedObj *self, PyObject *args) {
@@ -204,7 +204,7 @@ crypto_Revoked_get_reason(crypto_RevokedObj *self, PyObject *args) {
static char crypto_Revoked_get_rev_date_doc[] = "\n\
Retrieve the revocation date\n\
\n\
-@return: A string giving the timestamp, in the format:\n\
+:return: A string giving the timestamp, in the format:\n\
\n\
YYYYMMDDhhmmssZ\n\
YYYYMMDDhhmmss+hhmm\n\
@@ -221,13 +221,13 @@ crypto_Revoked_get_rev_date(crypto_RevokedObj *self, PyObject *args) {
static char crypto_Revoked_set_rev_date_doc[] = "\n\
Set the revocation timestamp\n\
\n\
-@param when: A string giving the timestamp, in the format:\n\
+:param when: A string giving the timestamp, in the format:\n\
\n\
YYYYMMDDhhmmssZ\n\
YYYYMMDDhhmmss+hhmm\n\
YYYYMMDDhhmmss-hhmm\n\
\n\
-@return: None\n\
+:return: None\n\
";
static PyObject*
@@ -278,7 +278,7 @@ ASN1_INTEGER_to_PyString(ASN1_INTEGER *asn1_int) {
static char crypto_Revoked_get_serial_doc[] = "\n\
Return the serial number of a Revoked structure\n\
\n\
-@return: The serial number as a string\n\
+:return: The serial number as a string\n\
";
static PyObject *
crypto_Revoked_get_serial(crypto_RevokedObj *self, PyObject *args) {
@@ -298,9 +298,9 @@ crypto_Revoked_get_serial(crypto_RevokedObj *self, PyObject *args) {
static char crypto_Revoked_set_serial_doc[] = "\n\
Set the serial number of a revoked Revoked structure\n\
\n\
-@param hex_str: The new serial number.\n\
-@type hex_str: L{str}\n\
-@return: None\n\
+:param hex_str: The new serial number.\n\
+:type hex_str: :py:data:`str`\n\
+:return: None\n\
";
static PyObject *
crypto_Revoked_set_serial(crypto_RevokedObj *self, PyObject *args, PyObject *keywds) {
@@ -377,7 +377,7 @@ Revoked() -> Revoked instance\n\
\n\
Create a new empty Revoked object.\n\
\n\
-@returns: The Revoked object\n\
+:returns: The Revoked object\n\
";
static PyObject* crypto_Revoked_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs) {
diff --git a/OpenSSL/crypto/x509.c b/OpenSSL/crypto/x509.c
index c086ce8..8ee4bff 100644
--- a/OpenSSL/crypto/x509.c
+++ b/OpenSSL/crypto/x509.c
@@ -23,7 +23,7 @@
static char crypto_X509_get_version_doc[] = "\n\
Return version number of the certificate\n\
\n\
-@return: Version number as a Python integer\n\
+:return: Version number as a Python integer\n\
";
static PyObject *
@@ -38,8 +38,8 @@ crypto_X509_get_version(crypto_X509Obj *self, PyObject *args)
static char crypto_X509_set_version_doc[] = "\n\
Set version number of the certificate\n\
\n\
-@param version: The version number\n\
-@return: None\n\
+:param version: The version number\n\
+:return: None\n\
";
static PyObject *
@@ -59,7 +59,7 @@ crypto_X509_set_version(crypto_X509Obj *self, PyObject *args)
static char crypto_X509_get_serial_number_doc[] = "\n\
Return serial number of the certificate\n\
\n\
-@return: Serial number as a Python integer\n\
+:return: Serial number as a Python integer\n\
";
static PyObject *
@@ -85,8 +85,8 @@ crypto_X509_get_serial_number(crypto_X509Obj *self, PyObject *args)
static char crypto_X509_set_serial_number_doc[] = "\n\
Set serial number of the certificate\n\
\n\
-@param serial: The serial number\n\
-@return: None\n\
+:param serial: The serial number\n\
+:return: None\n\
";
static PyObject *
@@ -176,7 +176,7 @@ crypto_X509_set_serial_number(crypto_X509Obj *self, PyObject *args)
static char crypto_X509_get_issuer_doc[] = "\n\
Create an X509Name object for the issuer of the certificate\n\
\n\
-@return: An X509Name object\n\
+:return: An X509Name object\n\
";
static PyObject *
@@ -201,9 +201,9 @@ crypto_X509_get_issuer(crypto_X509Obj *self, PyObject *args)
static char crypto_X509_set_issuer_doc[] = "\n\
Set the issuer of the certificate\n\
\n\
-@param issuer: The issuer name\n\
-@type issuer: L{X509Name}\n\
-@return: None\n\
+:param issuer: The issuer name\n\
+:type issuer: :py:class:`X509Name`\n\
+:return: None\n\
";
static PyObject *
@@ -228,7 +228,7 @@ crypto_X509_set_issuer(crypto_X509Obj *self, PyObject *args)
static char crypto_X509_get_subject_doc[] = "\n\
Create an X509Name object for the subject of the certificate\n\
\n\
-@return: An X509Name object\n\
+:return: An X509Name object\n\
";
static PyObject *
@@ -253,9 +253,9 @@ crypto_X509_get_subject(crypto_X509Obj *self, PyObject *args)
static char crypto_X509_set_subject_doc[] = "\n\
Set the subject of the certificate\n\
\n\
-@param subject: The subject name\n\
-@type subject: L{X509Name}\n\
-@return: None\n\
+:param subject: The subject name\n\
+:type subject: :py:class:`X509Name`\n\
+:return: None\n\
";
static PyObject *
@@ -280,7 +280,7 @@ crypto_X509_set_subject(crypto_X509Obj *self, PyObject *args)
static char crypto_X509_get_pubkey_doc[] = "\n\
Get the public key of the certificate\n\
\n\
-@return: The public key\n\
+:return: The public key\n\
";
static PyObject *
@@ -309,8 +309,8 @@ crypto_X509_get_pubkey(crypto_X509Obj *self, PyObject *args)
static char crypto_X509_set_pubkey_doc[] = "\n\
Set the public key of the certificate\n\
\n\
-@param pkey: The public key\n\
-@return: None\n\
+:param pkey: The public key\n\
+:return: None\n\
";
static PyObject *
@@ -358,13 +358,13 @@ _set_asn1_time(char *format, ASN1_TIME* timestamp, PyObject *args)
static char crypto_X509_set_notBefore_doc[] = "\n\
Set the time stamp for when the certificate starts being valid\n\
\n\
-@param when: A string giving the timestamp, in the format:\n\
+:param when: A string giving the timestamp, in the format:\n\
\n\
YYYYMMDDhhmmssZ\n\
YYYYMMDDhhmmss+hhmm\n\
YYYYMMDDhhmmss-hhmm\n\
\n\
-@return: None\n\
+:return: None\n\
";
static PyObject*
@@ -378,13 +378,13 @@ crypto_X509_set_notBefore(crypto_X509Obj *self, PyObject *args)
static char crypto_X509_set_notAfter_doc[] = "\n\
Set the time stamp for when the certificate stops being valid\n\
\n\
-@param when: A string giving the timestamp, in the format:\n\
+:param when: A string giving the timestamp, in the format:\n\
\n\
YYYYMMDDhhmmssZ\n\
YYYYMMDDhhmmss+hhmm\n\
YYYYMMDDhhmmss-hhmm\n\
\n\
-@return: None\n\
+:return: None\n\
";
static PyObject*
@@ -433,12 +433,13 @@ _get_asn1_time(char *format, ASN1_TIME* timestamp, PyObject *args)
static char crypto_X509_get_notBefore_doc[] = "\n\
Retrieve the time stamp for when the certificate starts being valid\n\
\n\
-@return: A string giving the timestamp, in the format:\n\
+:return: A string giving the timestamp, in the format::\n\
\n\
YYYYMMDDhhmmssZ\n\
YYYYMMDDhhmmss+hhmm\n\
YYYYMMDDhhmmss-hhmm\n\
- or None if there is no value set.\n\
+\n\
+ or None if there is no value set.\n\
";
static PyObject*
@@ -455,12 +456,13 @@ crypto_X509_get_notBefore(crypto_X509Obj *self, PyObject *args)
static char crypto_X509_get_notAfter_doc[] = "\n\
Retrieve the time stamp for when the certificate stops being valid\n\
\n\
-@return: A string giving the timestamp, in the format:\n\
+:return: A string giving the timestamp, in the format::\n\
\n\
YYYYMMDDhhmmssZ\n\
YYYYMMDDhhmmss+hhmm\n\
YYYYMMDDhhmmss-hhmm\n\
- or None if there is no value set.\n\
+\n\
+ or None if there is no value set.\n\
";
static PyObject*
@@ -478,9 +480,9 @@ static char crypto_X509_gmtime_adj_notBefore_doc[] = "\n\
Change the timestamp for when the certificate starts being valid to the current\n\
time plus an offset.\n \
\n\
-@param amount: The number of seconds by which to adjust the starting validity\n\
+:param amount: The number of seconds by which to adjust the starting validity\n\
time.\n\
-@return: None\n\
+:return: None\n\
";
static PyObject *
@@ -500,9 +502,9 @@ crypto_X509_gmtime_adj_notBefore(crypto_X509Obj *self, PyObject *args)
static char crypto_X509_gmtime_adj_notAfter_doc[] = "\n\
Adjust the time stamp for when the certificate stops being valid\n\
\n\
-@param amount: The number of seconds by which to adjust the ending validity\n\
+:param amount: The number of seconds by which to adjust the ending validity\n\
time.\n\
-@return: None\n\
+:return: None\n\
";
static PyObject *
@@ -523,9 +525,9 @@ crypto_X509_gmtime_adj_notAfter(crypto_X509Obj *self, PyObject *args)
static char crypto_X509_get_signature_algorithm_doc[] = "\n\
Retrieve the signature algorithm used in the certificate\n\
\n\
-@return: A byte string giving the name of the signature algorithm used in\n\
+:return: A byte string giving the name of the signature algorithm used in\n\
the certificate.\n\
-@raise ValueError: If the signature algorithm is undefined.\n\
+:raise ValueError: If the signature algorithm is undefined.\n\
";
static PyObject *
@@ -550,9 +552,9 @@ crypto_X509_get_signature_algorithm(crypto_X509Obj *self, PyObject *args) {
static char crypto_X509_sign_doc[] = "\n\
Sign the certificate using the supplied key and digest\n\
\n\
-@param pkey: The key to sign with\n\
-@param digest: The message digest to use\n\
-@return: None\n\
+:param pkey: The key to sign with\n\
+:param digest: The message digest to use\n\
+:return: None\n\
";
static PyObject *
@@ -595,7 +597,7 @@ crypto_X509_sign(crypto_X509Obj *self, PyObject *args)
static char crypto_X509_has_expired_doc[] = "\n\
Check whether the certificate has expired.\n\
\n\
-@return: True if the certificate has expired, false otherwise\n\
+:return: True if the certificate has expired, false otherwise\n\
";
static PyObject *
@@ -616,7 +618,7 @@ crypto_X509_has_expired(crypto_X509Obj *self, PyObject *args)
static char crypto_X509_subject_name_hash_doc[] = "\n\
Return the hash of the X509 subject.\n\
\n\
-@return: The hash of the subject\n\
+:return: The hash of the subject\n\
";
static PyObject *
@@ -631,7 +633,7 @@ crypto_X509_subject_name_hash(crypto_X509Obj *self, PyObject *args)
static char crypto_X509_digest_doc[] = "\n\
Return the digest of the X509 object.\n\
\n\
-@return: The digest of the object\n\
+:return: The digest of the object\n\
";
static PyObject *
@@ -672,8 +674,8 @@ crypto_X509_digest(crypto_X509Obj *self, PyObject *args)
static char crypto_X509_add_extensions_doc[] = "\n\
Add extensions to the certificate.\n\
\n\
-@param extensions: a sequence of X509Extension objects\n\
-@return: None\n\
+:param extensions: a sequence of X509Extension objects\n\
+:return: None\n\
";
static PyObject *
@@ -717,7 +719,7 @@ crypto_X509_add_extensions(crypto_X509Obj *self, PyObject *args)
static char crypto_X509_get_extension_count_doc[] = "\n\
Get the number of extensions on the certificate.\n\
\n\
-@return: Number of extensions as a Python integer\n\
+:return: Number of extensions as a Python integer\n\
";
static PyObject *
@@ -732,8 +734,8 @@ crypto_X509_get_extension_count(crypto_X509Obj *self, PyObject *args) {
static char crypto_X509_get_extension_doc[] = "\n\
Get a specific extension of the certificate by index.\n\
\n\
-@param index: The index of the extension to retrieve.\n\
-@return: The X509Extension object at the specified index.\n\
+:param index: The index of the extension to retrieve.\n\
+:return: The X509Extension object at the specified index.\n\
";
static PyObject *
@@ -825,11 +827,11 @@ crypto_X509_New(X509 *cert, int dealloc)
static char crypto_X509_doc[] = "\n\
-X509() -> X509 instance\n\
+A class representing X.509 certificates.\n\
\n\
Create a new X509 object.\n\
\n\
-@returns: The X509 object\n\
+:returns: The :class:`X509` object\n\
";
static PyObject *
diff --git a/OpenSSL/crypto/x509ext.c b/OpenSSL/crypto/x509ext.c
index 9e0b7d3..f8ecb4a 100644
--- a/OpenSSL/crypto/x509ext.c
+++ b/OpenSSL/crypto/x509ext.c
@@ -16,7 +16,7 @@
static char crypto_X509Extension_get_critical_doc[] = "\n\
Returns the critical field of the X509Extension\n\
\n\
-@return: The critical field.\n\
+:return: The critical field.\n\
";
static PyObject *
@@ -31,7 +31,7 @@ crypto_X509Extension_get_critical(crypto_X509ExtensionObj *self, PyObject *args)
static char crypto_X509Extension_get_short_name_doc[] = "\n\
Returns the short version of the type name of the X509Extension\n\
\n\
-@return: The short type name.\n\
+:return: The short type name.\n\
";
static PyObject *
@@ -54,7 +54,7 @@ crypto_X509Extension_get_short_name(crypto_X509ExtensionObj *self, PyObject *arg
static char crypto_X509Extension_get_data_doc[] = "\n\
Returns the data of the X509Extension\n\
\n\
-@return: A C{str} giving the X509Extension's ASN.1 encoded data.\n\
+:return: A :py:data:`str` giving the X509Extension's ASN.1 encoded data.\n\
";
static PyObject *
@@ -185,16 +185,16 @@ static char crypto_X509Extension_doc[] = "\n\
X509Extension(typename, critical, value[, subject][, issuer]) -> \n\
X509Extension instance\n\
\n\
-@param typename: The name of the extension to create.\n\
-@type typename: C{str}\n\
-@param critical: A flag indicating whether this is a critical extension.\n\
-@param value: The value of the extension.\n\
-@type value: C{str}\n\
-@param subject: Optional X509 cert to use as subject.\n\
-@type subject: C{X509}\n\
-@param issuer: Optional X509 cert to use as issuer.\n\
-@type issuer: C{X509}\n\
-@return: The X509Extension object\n\
+:param typename: The name of the extension to create.\n\
+:type typename: :py:data:`str`\n\
+:param critical: A flag indicating whether this is a critical extension.\n\
+:param value: The value of the extension.\n\
+:type value: :py:data:`str`\n\
+:param subject: Optional X509 cert to use as subject.\n\
+:type subject: :py:class:`X509`\n\
+:param issuer: Optional X509 cert to use as issuer.\n\
+:type issuer: :py:class:`X509`\n\
+:return: The X509Extension object\n\
";
static PyObject *
diff --git a/OpenSSL/crypto/x509name.c b/OpenSSL/crypto/x509name.c
index a62c957..705683e 100644
--- a/OpenSSL/crypto/x509name.c
+++ b/OpenSSL/crypto/x509name.c
@@ -48,8 +48,8 @@ X509Name(name) -> New X509Name object\n\
\n\
Create a new X509Name, copying the given X509Name instance.\n\
\n\
-@param name: An X509Name object to copy\n\
-@return: The X509Name object\n\
+:param name: An X509Name object to copy\n\
+:return: The X509Name object\n\
";
static PyObject *
@@ -320,7 +320,7 @@ crypto_X509Name_repr(crypto_X509NameObj *self)
static char crypto_X509Name_hash_doc[] = "\n\
Return the hash value of this name\n\
\n\
-@return: None\n\
+:return: None\n\
";
/*
@@ -344,7 +344,7 @@ crypto_X509Name_hash(crypto_X509NameObj *self, PyObject* args)
static char crypto_X509Name_der_doc[] = "\n\
Return the DER encoding of this name\n\
\n\
-@return: None\n\
+:return: None\n\
";
/*
@@ -367,7 +367,7 @@ crypto_X509Name_der(crypto_X509NameObj *self, PyObject *args)
static char crypto_X509Name_get_components_doc[] = "\n\
Returns the split-up components of this name.\n\
\n\
-@return: List of tuples (name, value).\n\
+:return: List of tuples (name, value).\n\
";
static PyObject *
diff --git a/OpenSSL/crypto/x509req.c b/OpenSSL/crypto/x509req.c
index a2d1f11..a331712 100644
--- a/OpenSSL/crypto/x509req.c
+++ b/OpenSSL/crypto/x509req.c
@@ -16,7 +16,7 @@
static char crypto_X509Req_get_subject_doc[] = "\n\
Create an X509Name object for the subject of the certificate request\n\
\n\
-@return: An X509Name object\n\
+:return: An X509Name object\n\
";
static PyObject *
@@ -44,7 +44,7 @@ crypto_X509Req_get_subject(crypto_X509ReqObj *self, PyObject *args)
static char crypto_X509Req_get_pubkey_doc[] = "\n\
Get the public key from the certificate request\n\
\n\
-@return: The public key\n\
+:return: The public key\n\
";
static PyObject *
@@ -73,8 +73,8 @@ crypto_X509Req_get_pubkey(crypto_X509ReqObj *self, PyObject *args)
static char crypto_X509Req_set_pubkey_doc[] = "\n\
Set the public key of the certificate request\n\
\n\
-@param pkey: The public key to use\n\
-@return: None\n\
+:param pkey: The public key to use\n\
+:return: None\n\
";
static PyObject *
@@ -98,9 +98,9 @@ crypto_X509Req_set_pubkey(crypto_X509ReqObj *self, PyObject *args)
static char crypto_X509Req_sign_doc[] = "\n\
Sign the certificate request using the supplied key and digest\n\
\n\
-@param pkey: The key to sign with\n\
-@param digest: The message digest to use\n\
-@return: None\n\
+:param pkey: The key to sign with\n\
+:param digest: The message digest to use\n\
+:return: None\n\
";
static PyObject *
@@ -143,9 +143,9 @@ crypto_X509Req_sign(crypto_X509ReqObj *self, PyObject *args)
static char crypto_X509Req_verify_doc[] = "\n\
Verifies a certificate request using the supplied public key\n\
\n\
-@param key: a public key\n\
-@return: True if the signature is correct.\n\
-@raise OpenSSL.crypto.Error: If the signature is invalid or there is a\n\
+:param key: a public key\n\
+:return: True if the signature is correct.\n\
+:raise OpenSSL.crypto.Error: If the signature is invalid or there is a\n\
problem verifying the signature.\n\
";
@@ -173,8 +173,8 @@ crypto_X509Req_verify(crypto_X509ReqObj *self, PyObject *args)
static char crypto_X509Req_add_extensions_doc[] = "\n\
Add extensions to the request.\n\
\n\
-@param extensions: a sequence of X509Extension objects\n\
-@return: None\n\
+:param extensions: a sequence of X509Extension objects\n\
+:return: None\n\
";
static PyObject *
@@ -234,8 +234,8 @@ static char crypto_X509Req_set_version_doc[] = "\n\
Set the version subfield (RFC 2459, section 4.1.2.1) of the certificate\n\
request.\n\
\n\
-@param version: The version number\n\
-@return: None\n\
+:param version: The version number\n\
+:return: None\n\
";
static PyObject *
@@ -259,7 +259,7 @@ static char crypto_X509Req_get_version_doc[] = "\n\
Get the version subfield (RFC 2459, section 4.1.2.1) of the certificate\n\
request.\n\
\n\
-@return: an integer giving the value of the version subfield\n\
+:return: an integer giving the value of the version subfield\n\
";
static PyObject *
@@ -328,7 +328,7 @@ X509Req() -> X509Req instance\n\
\n\
Create a new X509Req object.\n\
\n\
-@return: The X509Req object\n\
+:return: The X509Req object\n\
";
static PyObject *
diff --git a/OpenSSL/crypto/x509store.c b/OpenSSL/crypto/x509store.c
index bf22756..a9750ed 100644
--- a/OpenSSL/crypto/x509store.c
+++ b/OpenSSL/crypto/x509store.c
@@ -14,8 +14,8 @@
static char crypto_X509Store_add_cert_doc[] = "\n\
Add a certificate\n\
\n\
-@param cert: The certificate to add\n\
-@return: None\n\
+:param cert: The certificate to add\n\
+:return: None\n\
";
static PyObject *
diff --git a/OpenSSL/rand/rand.c b/OpenSSL/rand/rand.c
index 8307ac6..712ad56 100644
--- a/OpenSSL/rand/rand.c
+++ b/OpenSSL/rand/rand.c
@@ -33,9 +33,9 @@ See the file RATIONALE for a short explanation of why this module was written.\n
static char rand_add_doc[] = "\n\
Add data with a given entropy to the PRNG\n\
\n\
-@param buffer: Buffer with random data\n\
-@param entropy: The entropy (in bytes) measurement of the buffer\n\
-@return: None\n\
+:param buffer: Buffer with random data\n\
+:param entropy: The entropy (in bytes) measurement of the buffer\n\
+:return: None\n\
";
static PyObject *
@@ -57,8 +57,8 @@ rand_add(PyObject *spam, PyObject *args)
static char rand_seed_doc[] = "\n\
Alias for rand_add, with entropy equal to length\n\
\n\
-@param buffer: Buffer with random data\n\
-@return: None\n\
+:param buffer: Buffer with random data\n\
+:return: None\n\
";
static PyObject *
@@ -79,7 +79,7 @@ rand_seed(PyObject *spam, PyObject *args)
static char rand_status_doc[] = "\n\
Retrieve the status of the PRNG\n\
\n\
-@return: True if the PRNG is seeded enough, false otherwise\n\
+:return: True if the PRNG is seeded enough, false otherwise\n\
";
static PyObject *
@@ -96,7 +96,7 @@ static char rand_screen_doc[] = "\n\
Add the current contents of the screen to the PRNG state. Availability:\n\
Windows.\n\
\n\
-@return: None\n\
+:return: None\n\
";
static PyObject *
@@ -116,9 +116,9 @@ Query an entropy gathering daemon (EGD) for random data and add it to the\n\
PRNG. I haven't found any problems when the socket is missing, the function\n\
just returns 0.\n\
\n\
-@param path: The path to the EGD socket\n\
-@param bytes: (optional) The number of bytes to read, default is 255\n\
-@returns: The number of bytes read (NB: a value of 0 isn't necessarily an\n\
+:param path: The path to the EGD socket\n\
+:param bytes: (optional) The number of bytes to read, default is 255\n\
+:returns: The number of bytes read (NB: a value of 0 isn't necessarily an\n\
error, check rand.status())\n\
";
@@ -137,7 +137,7 @@ rand_egd(PyObject *spam, PyObject *args)
static char rand_cleanup_doc[] = "\n\
Erase the memory used by the PRNG.\n\
\n\
-@return: None\n\
+:return: None\n\
";
static PyObject *
@@ -155,10 +155,10 @@ rand_cleanup(PyObject *spam, PyObject *args)
static char rand_load_file_doc[] = "\n\
Seed the PRNG with data from a file\n\
\n\
-@param filename: The file to read data from\n\
-@param maxbytes: (optional) The number of bytes to read, default is\n\
+:param filename: The file to read data from\n\
+:param maxbytes: (optional) The number of bytes to read, default is\n\
to read the entire file\n\
-@return: The number of bytes read\n\
+:return: The number of bytes read\n\
";
static PyObject *
@@ -176,8 +176,8 @@ rand_load_file(PyObject *spam, PyObject *args)
static char rand_write_file_doc[] = "\n\
Save PRNG state to a file\n\
\n\
-@param filename: The file to write data to\n\
-@return: The number of bytes written\n\
+:param filename: The file to write data to\n\
+:return: The number of bytes written\n\
";
static PyObject *
@@ -194,8 +194,8 @@ rand_write_file(PyObject *spam, PyObject *args)
static char rand_bytes_doc[] = "\n\
Get some randomm bytes as a string.\n\
\n\
-@param num_bytes: The number of bytes to fetch\n\
-@return: A string of random bytes\n\
+:param num_bytes: The number of bytes to fetch\n\
+:return: A string of random bytes\n\
";
#if PY_VERSION_HEX < 0x02050000
diff --git a/OpenSSL/ssl/connection.c b/OpenSSL/ssl/connection.c
index 9e9794b..9428376 100755
--- a/OpenSSL/ssl/connection.c
+++ b/OpenSSL/ssl/connection.c
@@ -251,7 +251,7 @@ handle_ssl_errors(SSL *ssl, int err, int ret)
static char ssl_Connection_get_context_doc[] = "\n\
Get session context\n\
\n\
-@return: A Context object\n\
+:return: A Context object\n\
";
static PyObject *
ssl_Connection_get_context(ssl_ConnectionObj *self, PyObject *args) {
@@ -266,7 +266,7 @@ ssl_Connection_get_context(ssl_ConnectionObj *self, PyObject *args) {
static char ssl_Connection_set_context_doc[] = "\n\
Switch this connection to a new session context\n\
\n\
-@param context: A L{Context} instance giving the new session context to use.\n\
+:param context: A :py:class:`Context` instance giving the new session context to use.\n\
\n\
";
static PyObject *
@@ -305,7 +305,7 @@ static char ssl_Connection_get_servername_doc[] = "\n\
Retrieve the servername extension value if provided in the client hello\n\
message, or None if there wasn't one.\n\
\n\
-@return: A byte string giving the server name or C{None}.\n\
+:return: A byte string giving the server name or :py:data:`None`.\n\
\n\
";
static PyObject *
@@ -331,7 +331,7 @@ ssl_Connection_get_servername(ssl_ConnectionObj *self, PyObject *args) {
static char ssl_Connection_set_tlsext_host_name_doc[] = "\n\
Set the value of the servername extension to send in the client hello.\n\
\n\
-@param name: A byte string giving the name.\n\
+:param name: A byte string giving the name.\n\
\n\
";
static PyObject *
@@ -354,7 +354,7 @@ ssl_Connection_set_tlsext_host_name(ssl_ConnectionObj *self, PyObject *args) {
static char ssl_Connection_pending_doc[] = "\n\
Get the number of bytes that can be safely read from the connection\n\
\n\
-@return: The number of bytes available in the receive buffer.\n\
+:return: The number of bytes available in the receive buffer.\n\
";
static PyObject *
ssl_Connection_pending(ssl_ConnectionObj *self, PyObject *args) {
@@ -372,8 +372,8 @@ static char ssl_Connection_bio_write_doc[] = "\n\
When using non-socket connections this function sends\n\
\"dirty\" data that would have traveled in on the network.\n\
\n\
-@param buf: The string to put into the memory BIO.\n\
-@return: The number of bytes written\n\
+:param buf: The string to put into the memory BIO.\n\
+:return: The number of bytes written\n\
";
static PyObject *
ssl_Connection_bio_write(ssl_ConnectionObj *self, PyObject *args)
@@ -414,10 +414,10 @@ Send data on the connection. NOTE: If you get one of the WantRead,\n\
WantWrite or WantX509Lookup exceptions on this, you have to call the\n\
method again with the SAME buffer.\n\
\n\
-@param buf: The string to send\n\
-@param flags: (optional) Included for compatibility with the socket\n\
+:param buf: The string to send\n\
+:param flags: (optional) Included for compatibility with the socket\n\
API, the value is ignored\n\
-@return: The number of bytes written\n\
+:return: The number of bytes written\n\
";
static PyObject *
ssl_Connection_send(ssl_ConnectionObj *self, PyObject *args) {
@@ -425,17 +425,98 @@ ssl_Connection_send(ssl_ConnectionObj *self, PyObject *args) {
char *buf;
#if PY_VERSION_HEX >= 0x02060000
- Py_buffer pbuf;
- if (!PyArg_ParseTuple(args, "s*|i:send", &pbuf, &flags))
+ /*
+ * Sit back and I'll tell you a story of intrigue and corruption, deceit and
+ * murder.
+ *
+ * A Py_buffer is used to hold any kind of byte-like data - a string, a
+ * memoryview, a buffer, etc. PyArg_ParseTuple takes whatever kind of
+ * object was supplied, notices the "s*" format specifier, and tries to copy
+ * the metadata for that object into the Py_buffer also passed in.
+ *
+ * According to the Python documentation:
+ *
+ * ... the caller is responsible for calling PyBuffer_Release with the
+ * structure after it has processed the data.
+ *
+ * Correct use of PyBuffer_Release is necessary due to the fact that
+ * Py_buffer must hold a reference to the original Python object from which
+ * it was initialized. PyBuffer_Release will decrement the reference count
+ * of that original object, allowing it to eventually be deallocated - but
+ * only after the Py_buffer is no longer in use.
+ *
+ * To support failures partway through parsing a format string,
+ * PyArg_ParseTuple maintains an internal PyListObject of PyCObjects it has
+ * created so far. This allows it to easily clean up these objects when
+ * parsing fails, before returning an error to the caller (incidentally, it
+ * also makes sure to clean up the Py_buffer it initialized in this case, by
+ * calling PyBuffer_Release - which means the caller *must not* use
+ * PyBuffer_Release when PyArg_ParseTuple fails; not exactly what the
+ * documentation directs).
+ *
+ * The PyCObjects are given destructors which clean up some structure
+ * PyArg_ParseTuple has created (or initialized) - often another PyObject
+ * which needs to be decref'd.
+ *
+ * When parsing completes, the reference count of the PyListObject is merely
+ * decremented. The normal Python garbage collection logic (the reference
+ * counting logic, in this case) takes over and collects both the list and
+ * all of the objects in it. When each PyCObject in the list is collected,
+ * it triggers its destructor to clean up the structure it wraps. This all
+ * happens immediately, before the Py_XDECREF of the PyListObject returns.
+ *
+ * The PyListObject is similarly destroyed in the success case, but not
+ * until each PyCObject it contains has had its destructor set to NULL to
+ * prevent it from cleaning up its contents.
+ *
+ * When PyArg_ParseTuple returns in an error case, therefore,
+ * PyRelease_Buffer has already been used on the Py_buffer passed to
+ * PyArg_ParseTuple.
+ *
+ * This is fortuitous, as the Py_buffer is typically (always?) allocated on
+ * the stack of the caller of PyArg_ParseTuple. Once that caller returns,
+ * that stack memory is no longer valid, and the Py_buffer may no longer be
+ * used.
+ *
+ * On a Python runtime which does not use reference counting, the
+ * PyListObject may not actually be collected before Py_XDECREF returns. It
+ * may not even be collected before PyArg_ParseTuple returns. In fact, in
+ * particularly unfortunate cases, it may even not be collected before the
+ * caller of PyArg_ParseTuple returns. It may not be called until long,
+ * long after the stack memory the Py_buffer was allocated on has been
+ * re-used for some other function call, after the memory holding a pointer
+ * to the structure that owns the memory the Py_buffer wrapped has been
+ * overwritten. When PyBuffer_Release is used on the Py_buffer in this
+ * case, it will try to decrement a random integer - probably part of a
+ * local variable on some part of the stack.
+ *
+ * The PyPy runtime does not use reference counting.
+ *
+ * The solution adopted here is to allocate the Py_buffer on the heap,
+ * instead. As there is no mechanism for learning when the PyCObject used
+ * by PyArg_ParseTuple to do its internal cleanup has had its way with the
+ * Py_buffer, the Py_buffer is leaked in the error case, to ensure it is
+ * still valid whenever PyBuffer_Release is called on it.
+ *
+ * Real programs should rarely, if ever, trigger the error case of
+ * PyArg_ParseTuple, so this is probably okay. Plus, I'm tired of this
+ * stupid bug. -exarkun
+ */
+
+ Py_buffer *pbuf = PyMem_Malloc(sizeof *pbuf);
+
+ if (!PyArg_ParseTuple(args, "s*|i:send", pbuf, &flags)) {
return NULL;
+ }
- buf = pbuf.buf;
- len = pbuf.len;
+ buf = pbuf->buf;
+ len = pbuf->len;
#else
- if (!PyArg_ParseTuple(args, "s#|i:send", &buf, &len, &flags))
+ if (!PyArg_ParseTuple(args, "s#|i:send", &buf, &len, &flags)) {
return NULL;
+ }
#endif
MY_BEGIN_ALLOW_THREADS(self->tstate)
@@ -443,7 +524,8 @@ ssl_Connection_send(ssl_ConnectionObj *self, PyObject *args) {
MY_END_ALLOW_THREADS(self->tstate)
#if PY_VERSION_HEX >= 0x02060000
- PyBuffer_Release(&pbuf);
+ PyBuffer_Release(pbuf);
+ PyMem_Free(pbuf);
#endif
if (PyErr_Occurred())
@@ -469,10 +551,10 @@ Send \"all\" data on the connection. This calls send() repeatedly until\n\
all data is sent. If an error occurs, it's impossible to tell how much data\n\
has been sent.\n\
\n\
-@param buf: The string to send\n\
-@param flags: (optional) Included for compatibility with the socket\n\
+:param buf: The string to send\n\
+:param flags: (optional) Included for compatibility with the socket\n\
API, the value is ignored\n\
-@return: The number of bytes written\n\
+:return: The number of bytes written\n\
";
static PyObject *
ssl_Connection_sendall(ssl_ConnectionObj *self, PyObject *args)
@@ -482,16 +564,18 @@ ssl_Connection_sendall(ssl_ConnectionObj *self, PyObject *args)
PyObject *pyret = Py_None;
#if PY_VERSION_HEX >= 0x02060000
- Py_buffer pbuf;
+ Py_buffer *pbuf = PyMem_Malloc(sizeof *pbuf);
- if (!PyArg_ParseTuple(args, "s*|i:sendall", &pbuf, &flags))
+ if (!PyArg_ParseTuple(args, "s*|i:sendall", pbuf, &flags)) {
return NULL;
+ }
- buf = pbuf.buf;
- len = pbuf.len;
+ buf = pbuf->buf;
+ len = pbuf->len;
#else
- if (!PyArg_ParseTuple(args, "s#|i:sendall", &buf, &len, &flags))
+ if (!PyArg_ParseTuple(args, "s#|i:sendall", &buf, &len, &flags)) {
return NULL;
+ }
#endif
do {
@@ -520,7 +604,8 @@ ssl_Connection_sendall(ssl_ConnectionObj *self, PyObject *args)
} while (len > 0);
#if PY_VERSION_HEX >= 0x02060000
- PyBuffer_Release(&pbuf);
+ PyBuffer_Release(pbuf);
+ PyMem_Free(pbuf);
#endif
Py_XINCREF(pyret);
@@ -532,10 +617,10 @@ Receive data on the connection. NOTE: If you get one of the WantRead,\n\
WantWrite or WantX509Lookup exceptions on this, you have to call the\n\
method again with the SAME buffer.\n\
\n\
-@param bufsiz: The maximum number of bytes to read\n\
-@param flags: (optional) Included for compatibility with the socket\n\
+:param bufsiz: The maximum number of bytes to read\n\
+:param flags: (optional) Included for compatibility with the socket\n\
API, the value is ignored\n\
-@return: The string read from the Connection\n\
+:return: The string read from the Connection\n\
";
static PyObject *
ssl_Connection_recv(ssl_ConnectionObj *self, PyObject *args)
@@ -580,8 +665,8 @@ static char ssl_Connection_bio_read_doc[] = "\n\
When using non-socket connections this function reads\n\
the \"dirty\" data that would have traveled away on the network.\n\
\n\
-@param bufsiz: The maximum number of bytes to read\n\
-@return: The string read.\n\
+:param bufsiz: The maximum number of bytes to read\n\
+:return: The string read.\n\
";
static PyObject *
ssl_Connection_bio_read(ssl_ConnectionObj *self, PyObject *args)
@@ -634,7 +719,7 @@ ssl_Connection_bio_read(ssl_ConnectionObj *self, PyObject *args)
static char ssl_Connection_renegotiate_doc[] = "\n\
Renegotiate the session\n\
\n\
-@return: True if the renegotiation can be started, false otherwise\n\
+:return: True if the renegotiation can be started, false otherwise\n\
";
static PyObject *
ssl_Connection_renegotiate(ssl_ConnectionObj *self, PyObject *args) {
@@ -660,7 +745,7 @@ static char ssl_Connection_do_handshake_doc[] = "\n\
Perform an SSL handshake (usually called after renegotiate() or one of\n\
set_*_state()). This can raise the same exceptions as send and recv.\n\
\n\
-@return: None.\n\
+:return: None.\n\
";
static PyObject *
ssl_Connection_do_handshake(ssl_ConnectionObj *self, PyObject *args)
@@ -698,7 +783,7 @@ static char ssl_Connection_renegotiate_pending_doc[] = "\n\
Check if there's a renegotiation in progress, it will return false once\n\
a renegotiation is finished.\n\
\n\
-@return: Whether there's a renegotiation in progress\n\
+:return: Whether there's a renegotiation in progress\n\
";
static PyObject *
ssl_Connection_renegotiate_pending(ssl_ConnectionObj *self, PyObject *args)
@@ -713,7 +798,7 @@ ssl_Connection_renegotiate_pending(ssl_ConnectionObj *self, PyObject *args)
static char ssl_Connection_total_renegotiations_doc[] = "\n\
Find out the total number of renegotiations.\n\
\n\
-@return: The number of renegotiations.\n\
+:return: The number of renegotiations.\n\
";
static PyObject *
ssl_Connection_total_renegotiations(ssl_ConnectionObj *self, PyObject *args)
@@ -728,7 +813,7 @@ static char ssl_Connection_set_accept_state_doc[] = "\n\
Set the connection to work in server mode. The handshake will be handled\n\
automatically by read/write.\n\
\n\
-@return: None\n\
+:return: None\n\
";
static PyObject *
ssl_Connection_set_accept_state(ssl_ConnectionObj *self, PyObject *args)
@@ -746,7 +831,7 @@ static char ssl_Connection_set_connect_state_doc[] = "\n\
Set the connection to work in client mode. The handshake will be handled\n\
automatically by read/write.\n\
\n\
-@return: None\n\
+:return: None\n\
";
static PyObject *
ssl_Connection_set_connect_state(ssl_ConnectionObj *self, PyObject *args)
@@ -763,8 +848,8 @@ ssl_Connection_set_connect_state(ssl_ConnectionObj *self, PyObject *args)
static char ssl_Connection_connect_doc[] = "\n\
Connect to remote host and set up client-side SSL\n\
\n\
-@param addr: A remote address\n\
-@return: What the socket's connect method returns\n\
+:param addr: A remote address\n\
+:return: What the socket's connect method returns\n\
";
static PyObject *
ssl_Connection_connect(ssl_ConnectionObj *self, PyObject *args)
@@ -788,8 +873,8 @@ static char ssl_Connection_connect_ex_doc[] = "\n\
Connect to remote host and set up client-side SSL. Note that if the socket's\n\
connect_ex method doesn't return 0, SSL won't be initialized.\n\
\n\
-@param addr: A remove address\n\
-@return: What the socket's connect_ex method returns\n\
+:param addr: A remove address\n\
+:return: What the socket's connect_ex method returns\n\
";
static PyObject *
ssl_Connection_connect_ex(ssl_ConnectionObj *self, PyObject *args)
@@ -809,7 +894,7 @@ ssl_Connection_connect_ex(ssl_ConnectionObj *self, PyObject *args)
static char ssl_Connection_accept_doc[] = "\n\
Accept incoming connection and set up SSL on it\n\
\n\
-@return: A (conn,addr) pair where conn is a Connection and addr is an\n\
+:return: A (conn,addr) pair where conn is a Connection and addr is an\n\
address\n\
";
static PyObject *
@@ -853,7 +938,7 @@ static char ssl_Connection_bio_shutdown_doc[] = "\n\
When using non-socket connections this function signals end of\n\
data on the input for this connection.\n\
\n\
-@return: None\n\
+:return: None\n\
";
static PyObject *
@@ -875,7 +960,7 @@ ssl_Connection_bio_shutdown(ssl_ConnectionObj *self, PyObject *args)
static char ssl_Connection_shutdown_doc[] = "\n\
Send closure alert\n\
\n\
-@return: True if the shutdown completed successfully (i.e. both sides\n\
+:return: True if the shutdown completed successfully (i.e. both sides\n\
have sent closure alerts), false otherwise (i.e. you have to\n\
wait for a ZeroReturnError on a recv() method call\n\
";
@@ -917,7 +1002,7 @@ ssl_Connection_shutdown(ssl_ConnectionObj *self, PyObject *args)
static char ssl_Connection_get_cipher_list_doc[] = "\n\
Get the session cipher list\n\
\n\
-@return: A list of cipher strings\n\
+:return: A list of cipher strings\n\
";
static PyObject *
ssl_Connection_get_cipher_list(ssl_ConnectionObj *self, PyObject *args)
@@ -943,9 +1028,9 @@ ssl_Connection_get_cipher_list(ssl_ConnectionObj *self, PyObject *args)
static char ssl_Connection_get_client_ca_list_doc[] = "\n\
Get CAs whose certificates are suggested for client authentication.\n\
\n\
-@return: If this is a server connection, a list of X509Names representing\n\
- the acceptable CAs as set by L{OpenSSL.SSL.Context.set_client_ca_list} or\n\
- L{OpenSSL.SSL.Context.add_client_ca}. If this is a client connection,\n\
+:return: If this is a server connection, a list of X509Names representing\n\
+ the acceptable CAs as set by :py:meth:`OpenSSL.SSL.Context.set_client_ca_list` or\n\
+ :py:meth:`OpenSSL.SSL.Context.add_client_ca`. If this is a client connection,\n\
the list of such X509Names sent by the server, or an empty list if that\n\
has not yet happened.\n\
";
@@ -997,7 +1082,7 @@ static char ssl_Connection_makefile_doc[] = "\n\
The makefile() method is not implemented, since there is no dup semantics\n\
for SSL connections\n\
\n\
-@raise NotImplementedError\n\
+:raise NotImplementedError\n\
";
static PyObject *
ssl_Connection_makefile(ssl_ConnectionObj *self, PyObject *args)
@@ -1009,7 +1094,7 @@ ssl_Connection_makefile(ssl_ConnectionObj *self, PyObject *args)
static char ssl_Connection_get_app_data_doc[] = "\n\
Get application data\n\
\n\
-@return: The application data\n\
+:return: The application data\n\
";
static PyObject *
ssl_Connection_get_app_data(ssl_ConnectionObj *self, PyObject *args)
@@ -1024,8 +1109,8 @@ ssl_Connection_get_app_data(ssl_ConnectionObj *self, PyObject *args)
static char ssl_Connection_set_app_data_doc[] = "\n\
Set application data\n\
\n\
-@param data - The application data\n\
-@return: None\n\
+:param data - The application data\n\
+:return: None\n\
";
static PyObject *
ssl_Connection_set_app_data(ssl_ConnectionObj *self, PyObject *args)
@@ -1046,7 +1131,7 @@ ssl_Connection_set_app_data(ssl_ConnectionObj *self, PyObject *args)
static char ssl_Connection_get_shutdown_doc[] = "\n\
Get shutdown state\n\
\n\
-@return: The shutdown state, a bitvector of SENT_SHUTDOWN, RECEIVED_SHUTDOWN.\n\
+:return: The shutdown state, a bitvector of SENT_SHUTDOWN, RECEIVED_SHUTDOWN.\n\
";
static PyObject *
ssl_Connection_get_shutdown(ssl_ConnectionObj *self, PyObject *args)
@@ -1060,8 +1145,8 @@ ssl_Connection_get_shutdown(ssl_ConnectionObj *self, PyObject *args)
static char ssl_Connection_set_shutdown_doc[] = "\n\
Set shutdown state\n\
\n\
-@param state - bitvector of SENT_SHUTDOWN, RECEIVED_SHUTDOWN.\n\
-@return: None\n\
+:param state - bitvector of SENT_SHUTDOWN, RECEIVED_SHUTDOWN.\n\
+:return: None\n\
";
static PyObject *
ssl_Connection_set_shutdown(ssl_ConnectionObj *self, PyObject *args)
@@ -1079,7 +1164,7 @@ ssl_Connection_set_shutdown(ssl_ConnectionObj *self, PyObject *args)
static char ssl_Connection_state_string_doc[] = "\n\
Get a verbose state description\n\
\n\
-@return: A string representing the state\n\
+:return: A string representing the state\n\
";
static PyObject *
ssl_Connection_state_string(ssl_ConnectionObj *self, PyObject *args)
@@ -1093,7 +1178,7 @@ ssl_Connection_state_string(ssl_ConnectionObj *self, PyObject *args)
static char ssl_Connection_client_random_doc[] = "\n\
Get a copy of the client hello nonce.\n\
\n\
-@return: A string representing the state\n\
+:return: A string representing the state\n\
";
static PyObject *
ssl_Connection_client_random(ssl_ConnectionObj *self, PyObject *args)
@@ -1111,7 +1196,7 @@ ssl_Connection_client_random(ssl_ConnectionObj *self, PyObject *args)
static char ssl_Connection_server_random_doc[] = "\n\
Get a copy of the server hello nonce.\n\
\n\
-@return: A string representing the state\n\
+:return: A string representing the state\n\
";
static PyObject *
ssl_Connection_server_random(ssl_ConnectionObj *self, PyObject *args)
@@ -1129,7 +1214,7 @@ ssl_Connection_server_random(ssl_ConnectionObj *self, PyObject *args)
static char ssl_Connection_master_key_doc[] = "\n\
Get a copy of the master key.\n\
\n\
-@return: A string representing the state\n\
+:return: A string representing the state\n\
";
static PyObject *
ssl_Connection_master_key(ssl_ConnectionObj *self, PyObject *args)
@@ -1147,7 +1232,7 @@ ssl_Connection_master_key(ssl_ConnectionObj *self, PyObject *args)
static char ssl_Connection_sock_shutdown_doc[] = "\n\
See shutdown(2)\n\
\n\
-@return: What the socket's shutdown() method returns\n\
+:return: What the socket's shutdown() method returns\n\
";
static PyObject *
ssl_Connection_sock_shutdown(ssl_ConnectionObj *self, PyObject *args)
@@ -1164,7 +1249,7 @@ ssl_Connection_sock_shutdown(ssl_ConnectionObj *self, PyObject *args)
static char ssl_Connection_get_peer_certificate_doc[] = "\n\
Retrieve the other side's certificate (if any)\n\
\n\
-@return: The peer's certificate\n\
+:return: The peer's certificate\n\
";
static PyObject *
ssl_Connection_get_peer_certificate(ssl_ConnectionObj *self, PyObject *args)
@@ -1189,7 +1274,7 @@ ssl_Connection_get_peer_certificate(ssl_ConnectionObj *self, PyObject *args)
static char ssl_Connection_get_peer_cert_chain_doc[] = "\n\
Retrieve the other side's certificate (if any)\n\
\n\
-@return: A list of X509 instances giving the peer's certificate chain,\n\
+:return: A list of X509 instances giving the peer's certificate chain,\n\
or None if it does not have one.\n\
";
static PyObject *
@@ -1228,7 +1313,7 @@ static char ssl_Connection_want_read_doc[] = "\n\
Checks if more data has to be read from the transport layer to complete an\n\
operation.\n\
\n\
-@return: True iff more data has to be read\n\
+:return: True iff more data has to be read\n\
";
static PyObject *
ssl_Connection_want_read(ssl_ConnectionObj *self, PyObject *args)
@@ -1243,7 +1328,7 @@ static char ssl_Connection_want_write_doc[] = "\n\
Checks if there is data to write to the transport layer to complete an\n\
operation.\n\
\n\
-@return: True iff there is data to write\n\
+:return: True iff there is data to write\n\
";
static PyObject *
ssl_Connection_want_write(ssl_ConnectionObj *self, PyObject *args)
@@ -1254,6 +1339,63 @@ ssl_Connection_want_write(ssl_ConnectionObj *self, PyObject *args)
return PyLong_FromLong((long)SSL_want_write(self->ssl));
}
+static char ssl_Connection_get_session_doc[] = "\n\
+Returns the Session currently used.\n\
+\n\
+@return: An instance of :py:class:`OpenSSL.SSL.Session` or :py:obj:`None` if\n\
+ no session exists.\n\
+";
+static PyObject *
+ssl_Connection_get_session(ssl_ConnectionObj *self, PyObject *args) {
+ ssl_SessionObj *session;
+ SSL_SESSION *native_session;
+
+ if (!PyArg_ParseTuple(args, ":get_session")) {
+ return NULL;
+ }
+
+ native_session = SSL_get1_session(self->ssl);
+
+ if (native_session == NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ session = ssl_Session_from_SSL_SESSION(native_session);
+ if (!session) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ return (PyObject*)session;
+}
+
+static char ssl_Connection_set_session_doc[] = "\n\
+Set the session to be used when the TLS/SSL connection is established.\n\
+\n\
+:param session: A Session instance representing the session to use.\n\
+:returns: None\n\
+";
+static PyObject *
+ssl_Connection_set_session(ssl_ConnectionObj *self, PyObject *args) {
+ ssl_SessionObj *session;
+
+ if (!PyArg_ParseTuple(args, "O!:set_session", &ssl_Session_Type, &session)) {
+ return NULL;
+ }
+
+ if (SSL_set_session(self->ssl, session->session) == 0) {
+ /* The only case which leads to this seems to be a mismatch, between
+ * this connection and the session, of the SSL method.
+ */
+ exception_from_error_queue(ssl_Error);
+ return NULL;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
/*
* Member methods in the Connection object
* ADD_METHOD(name) expands to a correct PyMethodDef declaration
@@ -1309,6 +1451,8 @@ static PyMethodDef ssl_Connection_methods[] =
ADD_METHOD(want_write),
ADD_METHOD(set_accept_state),
ADD_METHOD(set_connect_state),
+ ADD_METHOD(get_session),
+ ADD_METHOD(set_session),
{ NULL, NULL }
};
#undef ADD_ALIAS
@@ -1320,8 +1464,8 @@ Connection(context, socket) -> Connection instance\n\
Create a new Connection object, using the given OpenSSL.SSL.Context instance\n\
and socket.\n\
\n\
-@param context: An SSL Context to use for this connection\n\
-@param socket: The socket to use for transport layer\n\
+:param context: An SSL Context to use for this connection\n\
+:param socket: The socket to use for transport layer\n\
";
/*
diff --git a/OpenSSL/ssl/context.c b/OpenSSL/ssl/context.c
index c2bdcab..e971c0a 100644
--- a/OpenSSL/ssl/context.c
+++ b/OpenSSL/ssl/context.c
@@ -292,7 +292,7 @@ Context(method) -> Context instance\n\
OpenSSL.SSL.Context instances define the parameters for setting up new SSL\n\
connections.\n\
\n\
-@param method: One of " SSLv2_METHOD_TEXT "SSLv3_METHOD, SSLv23_METHOD, or\n\
+:param method: One of " SSLv2_METHOD_TEXT "SSLv3_METHOD, SSLv23_METHOD, or\n\
TLSv1_METHOD.\n\
";
@@ -302,9 +302,9 @@ static char ssl_Context_load_verify_locations_doc[] = "\n\
Let SSL know where we can find trusted certificates for the certificate\n\
chain\n\
\n\
-@param cafile: In which file we can find the certificates\n\
-@param capath: In which directory we can find the certificates\n\
-@return: None\n\
+:param cafile: In which file we can find the certificates\n\
+:param capath: In which directory we can find the certificates\n\
+:return: None\n\
";
static PyObject *
ssl_Context_load_verify_locations(ssl_ContextObj *self, PyObject *args) {
@@ -330,7 +330,7 @@ ssl_Context_load_verify_locations(ssl_ContextObj *self, PyObject *args) {
static char ssl_Context_set_default_verify_paths_doc[] = "\n\
Use the platform-specific CA certificate locations\n\
\n\
-@return: None\n\
+:return: None\n\
";
static PyObject *
ssl_Context_set_default_verify_paths(ssl_ContextObj *self, PyObject *args) {
@@ -354,10 +354,10 @@ ssl_Context_set_default_verify_paths(ssl_ContextObj *self, PyObject *args) {
static char ssl_Context_set_passwd_cb_doc[] = "\n\
Set the passphrase callback\n\
\n\
-@param callback: The Python callback to use\n\
-@param userdata: (optional) A Python object which will be given as\n\
+:param callback: The Python callback to use\n\
+:param userdata: (optional) A Python object which will be given as\n\
argument to the callback\n\
-@return: None\n\
+:return: None\n\
";
static PyObject *
ssl_Context_set_passwd_cb(ssl_ContextObj *self, PyObject *args)
@@ -459,8 +459,8 @@ parse_certificate_argument(const char* format, PyObject* args) {
static char ssl_Context_add_extra_chain_cert_doc[] = "\n\
Add certificate to chain\n\
\n\
-@param certobj: The X509 certificate object to add to the chain\n\
-@return: None\n\
+:param certobj: The X509 certificate object to add to the chain\n\
+:return: None\n\
";
static PyObject *
@@ -496,8 +496,8 @@ ssl_Context_add_extra_chain_cert(ssl_ContextObj *self, PyObject *args)
static char ssl_Context_use_certificate_chain_file_doc[] = "\n\
Load a certificate chain from a file\n\
\n\
-@param certfile: The name of the certificate chain file\n\
-@return: None\n\
+:param certfile: The name of the certificate chain file\n\
+:return: None\n\
";
static PyObject *
ssl_Context_use_certificate_chain_file(ssl_ContextObj *self, PyObject *args)
@@ -523,9 +523,9 @@ ssl_Context_use_certificate_chain_file(ssl_ContextObj *self, PyObject *args)
static char ssl_Context_use_certificate_file_doc[] = "\n\
Load a certificate from a file\n\
\n\
-@param certfile: The name of the certificate file\n\
-@param filetype: (optional) The encoding of the file, default is PEM\n\
-@return: None\n\
+:param certfile: The name of the certificate file\n\
+:param filetype: (optional) The encoding of the file, default is PEM\n\
+:return: None\n\
";
static PyObject *
ssl_Context_use_certificate_file(ssl_ContextObj *self, PyObject *args)
@@ -551,8 +551,8 @@ ssl_Context_use_certificate_file(ssl_ContextObj *self, PyObject *args)
static char ssl_Context_use_certificate_doc[] = "\n\
Load a certificate from a X509 object\n\
\n\
-@param cert: The X509 object\n\
-@return: None\n\
+:param cert: The X509 object\n\
+:return: None\n\
";
static PyObject *
ssl_Context_use_certificate(ssl_ContextObj *self, PyObject *args)
@@ -578,9 +578,9 @@ ssl_Context_use_certificate(ssl_ContextObj *self, PyObject *args)
static char ssl_Context_use_privatekey_file_doc[] = "\n\
Load a private key from a file\n\
\n\
-@param keyfile: The name of the key file\n\
-@param filetype: (optional) The encoding of the file, default is PEM\n\
-@return: None\n\
+:param keyfile: The name of the key file\n\
+:param filetype: (optional) The encoding of the file, default is PEM\n\
+:return: None\n\
";
static PyObject *
ssl_Context_use_privatekey_file(ssl_ContextObj *self, PyObject *args)
@@ -616,8 +616,8 @@ ssl_Context_use_privatekey_file(ssl_ContextObj *self, PyObject *args)
static char ssl_Context_use_privatekey_doc[] = "\n\
Load a private key from a PKey object\n\
\n\
-@param pkey: The PKey object\n\
-@return: None\n\
+:param pkey: The PKey object\n\
+:return: None\n\
";
static PyObject *
ssl_Context_use_privatekey(ssl_ContextObj *self, PyObject *args) {
@@ -646,7 +646,7 @@ ssl_Context_use_privatekey(ssl_ContextObj *self, PyObject *args) {
static char ssl_Context_check_privatekey_doc[] = "\n\
Check that the private key and certificate match up\n\
\n\
-@return: None (raises an exception if something's wrong)\n\
+:return: None (raises an exception if something's wrong)\n\
";
static PyObject *
ssl_Context_check_privatekey(ssl_ContextObj *self, PyObject *args)
@@ -667,13 +667,13 @@ ssl_Context_check_privatekey(ssl_ContextObj *self, PyObject *args)
}
static char ssl_Context_load_client_ca_doc[] = "\n\
-Load the trusted certificates that will be sent to the client (basically\n \
+Load the trusted certificates that will be sent to the client (basically\n\
telling the client \"These are the guys I trust\"). Does not actually\n\
imply any of the certificates are trusted; that must be configured\n\
separately.\n\
\n\
-@param cafile: The name of the certificates file\n\
-@return: None\n\
+:param cafile: The name of the certificates file\n\
+:return: None\n\
";
static PyObject *
ssl_Context_load_client_ca(ssl_ContextObj *self, PyObject *args)
@@ -690,11 +690,11 @@ ssl_Context_load_client_ca(ssl_ContextObj *self, PyObject *args)
}
static char ssl_Context_set_session_id_doc[] = "\n\
-Set the session identifier, this is needed if you want to do session\n\
-resumption (which, ironically, isn't implemented yet)\n\
+Set the session identifier. This is needed if you want to do session\n\
+resumption.\n\
\n\
-@param buf: A Python object that can be safely converted to a string\n\
-@returns: None\n\
+:param buf: A Python object that can be safely converted to a string\n\
+:returns: None\n\
";
static PyObject *
ssl_Context_set_session_id(ssl_ContextObj *self, PyObject *args)
@@ -717,13 +717,46 @@ ssl_Context_set_session_id(ssl_ContextObj *self, PyObject *args)
}
}
+static char ssl_Context_set_session_cache_mode_doc[] = "\n\
+Enable/disable session caching and specify the mode used.\n\
+\n\
+:param mode: One or more of the SESS_CACHE_* flags (combine using bitwise or)\n\
+:returns: The previously set caching mode.\n\
+";
+static PyObject *
+ssl_Context_set_session_cache_mode(ssl_ContextObj *self, PyObject *args) {
+ long mode, result;
+
+ if (!PyArg_ParseTuple(args, "l:set_session_cache_mode", &mode)) {
+ return NULL;
+ }
+
+ result = SSL_CTX_set_session_cache_mode(self->ctx, mode);
+ return PyLong_FromLong(result);
+
+}
+
+static char ssl_Context_get_session_cache_mode_doc[] = "\n\
+:returns: The currently used cache mode.\n\
+";
+static PyObject *
+ssl_Context_get_session_cache_mode(ssl_ContextObj *self, PyObject *args) {
+ long result;
+
+ if (!PyArg_ParseTuple(args, ":get_session_cache_mode")) {
+ return NULL;
+ }
+ result = SSL_CTX_get_session_cache_mode(self->ctx);
+ return PyLong_FromLong(result);
+}
+
static char ssl_Context_set_verify_doc[] = "\n\
Set the verify mode and verify callback\n\
\n\
-@param mode: The verify mode, this is either VERIFY_NONE or\n\
+:param mode: The verify mode, this is either VERIFY_NONE or\n\
VERIFY_PEER combined with possible other flags\n\
-@param callback: The Python callback to use\n\
-@return: None\n\
+:param callback: The Python callback to use\n\
+:return: None\n\
\n\
See SSL_CTX_set_verify(3SSL) for further details.\n\
";
@@ -754,8 +787,8 @@ ssl_Context_set_verify(ssl_ContextObj *self, PyObject *args)
static char ssl_Context_set_verify_depth_doc[] = "\n\
Set the verify depth\n\
\n\
-@param depth: An integer specifying the verify depth\n\
-@return: None\n\
+:param depth: An integer specifying the verify depth\n\
+:return: None\n\
";
static PyObject *
ssl_Context_set_verify_depth(ssl_ContextObj *self, PyObject *args)
@@ -773,7 +806,7 @@ ssl_Context_set_verify_depth(ssl_ContextObj *self, PyObject *args)
static char ssl_Context_get_verify_mode_doc[] = "\n\
Get the verify mode\n\
\n\
-@return: The verify mode\n\
+:return: The verify mode\n\
";
static PyObject *
ssl_Context_get_verify_mode(ssl_ContextObj *self, PyObject *args)
@@ -790,7 +823,7 @@ ssl_Context_get_verify_mode(ssl_ContextObj *self, PyObject *args)
static char ssl_Context_get_verify_depth_doc[] = "\n\
Get the verify depth\n\
\n\
-@return: The verify depth\n\
+:return: The verify depth\n\
";
static PyObject *
ssl_Context_get_verify_depth(ssl_ContextObj *self, PyObject *args)
@@ -807,8 +840,8 @@ ssl_Context_get_verify_depth(ssl_ContextObj *self, PyObject *args)
static char ssl_Context_load_tmp_dh_doc[] = "\n\
Load parameters for Ephemeral Diffie-Hellman\n\
\n\
-@param dhfile: The file to load EDH parameters from\n\
-@return: None\n\
+:param dhfile: The file to load EDH parameters from\n\
+:return: None\n\
";
static PyObject *
ssl_Context_load_tmp_dh(ssl_ContextObj *self, PyObject *args)
@@ -838,8 +871,8 @@ ssl_Context_load_tmp_dh(ssl_ContextObj *self, PyObject *args)
static char ssl_Context_set_cipher_list_doc[] = "\n\
Change the cipher list\n\
\n\
-@param cipher_list: A cipher list, see ciphers(1)\n\
-@return: None\n\
+:param cipher_list: A cipher list, see ciphers(1)\n\
+:return: None\n\
";
static PyObject *
ssl_Context_set_cipher_list(ssl_ContextObj *self, PyObject *args)
@@ -867,8 +900,8 @@ Set the list of preferred client certificate signers for this server context.\n\
This list of certificate authorities will be sent to the client when the\n\
server requests a client certificate.\n\
\n\
-@param certificate_authorities: a sequence of X509Names.\n\
-@return: None\n\
+:param certificate_authorities: a sequence of X509Names.\n\
+:return: None\n\
";
static PyObject *
@@ -945,8 +978,8 @@ Add the CA certificate to the list of preferred signers for this context.\n\
The list of certificate authorities will be sent to the client when the\n\
server requests a client certificate.\n\
\n\
-@param certificate_authority: certificate authority's X509 certificate.\n\
-@return: None\n\
+:param certificate_authority: certificate authority's X509 certificate.\n\
+:return: None\n\
";
static PyObject *
@@ -969,8 +1002,8 @@ ssl_Context_add_client_ca(ssl_ContextObj *self, PyObject *args)
static char ssl_Context_set_timeout_doc[] = "\n\
Set session timeout\n\
\n\
-@param timeout: The timeout in seconds\n\
-@return: The previous session timeout\n\
+:param timeout: The timeout in seconds\n\
+:return: The previous session timeout\n\
";
static PyObject *
ssl_Context_set_timeout(ssl_ContextObj *self, PyObject *args)
@@ -987,7 +1020,7 @@ ssl_Context_set_timeout(ssl_ContextObj *self, PyObject *args)
static char ssl_Context_get_timeout_doc[] = "\n\
Get the session timeout\n\
\n\
-@return: The session timeout\n\
+:return: The session timeout\n\
";
static PyObject *
ssl_Context_get_timeout(ssl_ContextObj *self, PyObject *args)
@@ -1004,8 +1037,8 @@ ssl_Context_get_timeout(ssl_ContextObj *self, PyObject *args)
static char ssl_Context_set_info_callback_doc[] = "\n\
Set the info callback\n\
\n\
-@param callback: The Python callback to use\n\
-@return: None\n\
+:param callback: The Python callback to use\n\
+:return: None\n\
";
static PyObject *
ssl_Context_set_info_callback(ssl_ContextObj *self, PyObject *args)
@@ -1033,7 +1066,7 @@ ssl_Context_set_info_callback(ssl_ContextObj *self, PyObject *args)
static char ssl_Context_get_app_data_doc[] = "\n\
Get the application data (supplied via set_app_data())\n\
\n\
-@return: The application data\n\
+:return: The application data\n\
";
static PyObject *
ssl_Context_get_app_data(ssl_ContextObj *self, PyObject *args)
@@ -1048,8 +1081,8 @@ ssl_Context_get_app_data(ssl_ContextObj *self, PyObject *args)
static char ssl_Context_set_app_data_doc[] = "\n\
Set the application data (will be returned from get_app_data())\n\
\n\
-@param data: Any Python object\n\
-@return: None\n\
+:param data: Any Python object\n\
+:return: None\n\
";
static PyObject *
ssl_Context_set_app_data(ssl_ContextObj *self, PyObject *args)
@@ -1070,7 +1103,7 @@ ssl_Context_set_app_data(ssl_ContextObj *self, PyObject *args)
static char ssl_Context_get_cert_store_doc[] = "\n\
Get the certificate store for the context\n\
\n\
-@return: A X509Store object\n\
+:return: A X509Store object\n\
";
static PyObject *
ssl_Context_get_cert_store(ssl_ContextObj *self, PyObject *args)
@@ -1094,8 +1127,8 @@ ssl_Context_get_cert_store(ssl_ContextObj *self, PyObject *args)
static char ssl_Context_set_options_doc[] = "\n\
Add options. Options set before are not cleared!\n\
\n\
-@param options: The options to add.\n\
-@return: The new option bitmask.\n\
+:param options: The options to add.\n\
+:return: The new option bitmask.\n\
";
static PyObject *
ssl_Context_set_options(ssl_ContextObj *self, PyObject *args)
@@ -1108,10 +1141,27 @@ ssl_Context_set_options(ssl_ContextObj *self, PyObject *args)
return PyLong_FromLong(SSL_CTX_set_options(self->ctx, options));
}
+static char ssl_Context_set_mode_doc[] = "\n\
+Add modes via bitmask. Modes set before are not cleared!\n\
+\n\
+:param mode: The mode to add.\n\
+:return: The new mode bitmask.\n\
+";
+static PyObject *
+ssl_Context_set_mode(ssl_ContextObj *self, PyObject *args) {
+ long mode;
+
+ if (!PyArg_ParseTuple(args, "l:set_mode", &mode)) {
+ return NULL;
+ }
+
+ return PyLong_FromLong(SSL_CTX_set_mode(self->ctx, mode));
+}
+
static char ssl_Context_set_tlsext_servername_callback_doc[] = "\n\
Specify a callback function to be called when clients specify a server name.\n\
\n\
-@param callback: The callback function. It will be invoked with one\n\
+:param callback: The callback function. It will be invoked with one\n\
argument, the Connection instance.\n\
\n\
";
@@ -1159,6 +1209,8 @@ static PyMethodDef ssl_Context_methods[] = {
ADD_METHOD(check_privatekey),
ADD_METHOD(load_client_ca),
ADD_METHOD(set_session_id),
+ ADD_METHOD(set_session_cache_mode),
+ ADD_METHOD(get_session_cache_mode),
ADD_METHOD(set_verify),
ADD_METHOD(set_verify_depth),
ADD_METHOD(get_verify_mode),
@@ -1174,6 +1226,7 @@ static PyMethodDef ssl_Context_methods[] = {
ADD_METHOD(set_app_data),
ADD_METHOD(get_cert_store),
ADD_METHOD(set_options),
+ ADD_METHOD(set_mode),
ADD_METHOD(set_tlsext_servername_callback),
{ NULL, NULL }
};
@@ -1196,7 +1249,7 @@ ssl_Context_init(ssl_ContextObj *self, int i_method) {
#ifdef OPENSSL_NO_SSL2
PyErr_SetString(PyExc_ValueError, "SSLv2_METHOD not supported by this version of OpenSSL");
return NULL;
-#else
+#else
method = SSLv2_method();
#endif
break;
@@ -1215,6 +1268,11 @@ ssl_Context_init(ssl_ContextObj *self, int i_method) {
}
self->ctx = SSL_CTX_new(method);
+ if (self->ctx == NULL) {
+ exception_from_error_queue(ssl_Error);
+ return NULL;
+ }
+
Py_INCREF(Py_None);
self->passphrase_callback = Py_None;
Py_INCREF(Py_None);
diff --git a/OpenSSL/ssl/session.c b/OpenSSL/ssl/session.c
new file mode 100644
index 0000000..f9932a4
--- /dev/null
+++ b/OpenSSL/ssl/session.c
@@ -0,0 +1,159 @@
+/*
+ * session.c
+ *
+ * Copyright (C) Jean-Paul Calderone
+ * Copyright (C) Alejandro Alvarez Ayllon
+ * See LICENSE for details.
+ *
+ * SSL Session object data structures and functions.
+ *
+ */
+#include <Python.h>
+#define SSL_MODULE
+#include "ssl.h"
+
+static char ssl_Session_doc[] = "\n\
+Session() -> Session instance\n\
+\n\
+";
+
+/*
+ * Initialize an already-constructed Session instance with an OpenSSL session
+ * structure (or NULL). A reference to the OpenSSL session structure is stolen.
+ */
+static ssl_SessionObj*
+ssl_Session_init(ssl_SessionObj *self, SSL_SESSION *native_session) {
+ self->session = native_session;
+ return self;
+}
+
+/*
+ * Create a Session object
+ */
+static PyObject*
+ssl_Session_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs) {
+ ssl_SessionObj *self;
+
+ if (!PyArg_ParseTuple(args, ":Session")) {
+ return NULL;
+ }
+
+ self = PyObject_New(ssl_SessionObj, &ssl_Session_Type);
+ if (self == NULL) {
+ return NULL;
+ }
+
+ return (PyObject *)ssl_Session_init(self, NULL);
+}
+
+/*
+ * Create a Session object from an existing SSL_SESSION*. A reference to the
+ * SSL_SESSION* is stolen.
+ */
+ssl_SessionObj*
+ssl_Session_from_SSL_SESSION(SSL_SESSION *native_session) {
+ ssl_SessionObj *self;
+
+ self = PyObject_New(ssl_SessionObj, &ssl_Session_Type);
+ if (self == NULL) {
+ return NULL;
+ }
+
+ return ssl_Session_init(self, native_session);
+}
+
+/*
+ * Discard the reference to the OpenSSL session structure, if there is one, so
+ * that it can be freed if it is no longer in use. Also release the memory for
+ * the Python object.
+ */
+static void
+ssl_Session_dealloc(ssl_SessionObj *self) {
+ if (self->session != NULL) {
+ SSL_SESSION_free(self->session);
+ self->session = NULL;
+ }
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+/*
+ * Member methods in the Session object
+ * ADD_METHOD(name) expands to a correct PyMethodDef declaration
+ * { 'name', (PyCFunction)ssl_Session_name, METH_VARARGS }
+ * for convenience
+ * ADD_ALIAS(name,real) creates an "alias" of the ssl_Session_real
+ * function with the name 'name'
+ */
+#define ADD_METHOD(name) { #name, (PyCFunction)ssl_Session_##name, METH_VARARGS, ssl_Session_##name##_doc }
+static PyMethodDef ssl_Session_methods[] = {
+ { NULL, NULL }
+};
+#undef ADD_METHOD
+
+/*
+ * The Python Session type definition.
+ */
+PyTypeObject ssl_Session_Type = {
+ PyOpenSSL_HEAD_INIT(&PyType_Type, 0)
+ "OpenSSL.SSL.Session",
+ sizeof(ssl_SessionObj),
+ 0,
+ (destructor)ssl_Session_dealloc, /* tp_dealloc */
+ NULL, /* print */
+ NULL, /* tp_getattr */
+ NULL, /* setattr */
+ NULL, /* compare */
+ NULL, /* repr */
+ NULL, /* as_number */
+ NULL, /* as_sequence */
+ NULL, /* as_mapping */
+ NULL, /* hash */
+ NULL, /* call */
+ NULL, /* str */
+ NULL, /* getattro */
+ NULL, /* setattro */
+ NULL, /* as_buffer */
+ Py_TPFLAGS_DEFAULT, // Py_TPFLAGS_HAVE_GC, /* tp_flags */
+ ssl_Session_doc, /* tp_doc */
+ NULL, // (traverseproc)ssl_Session_traverse, /* tp_traverse */
+ NULL, // (inquiry)ssl_Session_clear, /* tp_clear */
+ NULL, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ NULL, /* tp_iter */
+ NULL, /* tp_iternext */
+ ssl_Session_methods, /* tp_methods */
+ NULL, /* tp_members */
+ NULL, /* tp_getset */
+ NULL, /* tp_base */
+ NULL, /* tp_dict */
+ NULL, /* tp_descr_get */
+ NULL, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ NULL, /* tp_init */
+ NULL, /* tp_alloc */
+ ssl_Session_new, /* tp_new */
+};
+
+/*
+ * Initialize the Session part of the SSL sub module
+ *
+ * Arguments: dict - The OpenSSL.SSL module
+ * Returns: 1 for success, 0 otherwise
+ */
+int
+init_ssl_session(PyObject *module) {
+
+ if (PyType_Ready(&ssl_Session_Type) < 0) {
+ return 0;
+ }
+
+ /* PyModule_AddObject steals a reference.
+ */
+ Py_INCREF((PyObject *)&ssl_Session_Type);
+ if (PyModule_AddObject(module, "Session", (PyObject *)&ssl_Session_Type) < 0) {
+ return 0;
+ }
+
+ return 1;
+}
+
diff --git a/OpenSSL/ssl/session.h b/OpenSSL/ssl/session.h
new file mode 100644
index 0000000..4e8de11
--- /dev/null
+++ b/OpenSSL/ssl/session.h
@@ -0,0 +1,27 @@
+/*
+ * session.h
+ * Copyright (C) Jean-Paul Calderone
+ * See LICENSE for details.
+ *
+ * Defined here is the Python type which represents an SSL session by wrapping
+ * an OpenSSL SSL_SESSION*.
+ *
+ */
+
+#ifndef PyOpenSSL_SSL_SESSION_H_
+#define PyOpenSSL_SSL_SESSION_H_
+
+#include <Python.h>
+#include <openssl/ssl.h>
+
+typedef struct {
+ PyObject_HEAD
+ SSL_SESSION *session;
+} ssl_SessionObj;
+
+extern PyTypeObject ssl_Session_Type;
+
+extern int init_ssl_session(PyObject *);
+extern ssl_SessionObj *ssl_Session_from_SSL_SESSION(SSL_SESSION *native_session);
+
+#endif
diff --git a/OpenSSL/ssl/ssl.c b/OpenSSL/ssl/ssl.c
index 0dd9871..5725d5d 100644
--- a/OpenSSL/ssl/ssl.c
+++ b/OpenSSL/ssl/ssl.c
@@ -53,7 +53,7 @@ PyObject *ssl_Error, /* Base class */
static char ssl_SSLeay_version_doc[] = "\n\
Return a string describing the version of OpenSSL in use.\n\
\n\
-@param type: One of the SSLEAY_ constants defined in this module.\n\
+:param type: One of the SSLEAY_ constants defined in this module.\n\
";
static PyObject *
@@ -224,6 +224,10 @@ do { \
PyModule_AddIntConstant(module, "OP_NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG);
PyModule_AddIntConstant(module, "OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG);
+#ifdef SSL_OP_NO_COMPRESSION
+ PyModule_AddIntConstant(module, "OP_NO_COMPRESSION", SSL_OP_NO_COMPRESSION);
+#endif
+
/* DTLS related options. The first two of these were introduced in
* 2005, the third in 2007. To accomodate systems which are still using
* older versions, make them optional. */
@@ -270,11 +274,32 @@ do { \
PyModule_AddIntConstant(module, "SSLEAY_PLATFORM", SSLEAY_PLATFORM);
PyModule_AddIntConstant(module, "SSLEAY_DIR", SSLEAY_DIR);
+ /* Cache modes */
+#define CACHE_MODE(mode) \
+ PyModule_AddIntConstant(module, "SESS_CACHE_" #mode, SSL_SESS_CACHE_##mode)
+
+ CACHE_MODE(OFF);
+ CACHE_MODE(CLIENT);
+ CACHE_MODE(SERVER);
+ CACHE_MODE(BOTH);
+ CACHE_MODE(NO_AUTO_CLEAR);
+ CACHE_MODE(NO_INTERNAL_LOOKUP);
+ CACHE_MODE(NO_INTERNAL_STORE);
+ CACHE_MODE(NO_INTERNAL);
+#undef CACHE_MODE
+
/* Straight up version number */
PyModule_AddIntConstant(module, "OPENSSL_VERSION_NUMBER", OPENSSL_VERSION_NUMBER);
+ /* SSL modes constants */
+#ifdef SSL_MODE_RELEASE_BUFFERS
+ PyModule_AddIntConstant(module, "MODE_RELEASE_BUFFERS", SSL_MODE_RELEASE_BUFFERS);
+#endif
+
if (!init_ssl_context(module))
goto error;
+ if (!init_ssl_session(module))
+ goto error;
if (!init_ssl_connection(module))
goto error;
diff --git a/OpenSSL/ssl/ssl.h b/OpenSSL/ssl/ssl.h
index 6a0a57e..3074ba5 100644
--- a/OpenSSL/ssl/ssl.h
+++ b/OpenSSL/ssl/ssl.h
@@ -16,6 +16,7 @@
#include <Python.h>
#include <pythread.h>
#include "context.h"
+#include "session.h"
#include "connection.h"
#include "../util.h"
#include "../crypto/crypto.h"
diff --git a/OpenSSL/test/__init__.py b/OpenSSL/test/__init__.py
index ccb4e9a..9b08060 100644
--- a/OpenSSL/test/__init__.py
+++ b/OpenSSL/test/__init__.py
@@ -2,5 +2,5 @@
# See LICENSE for details.
"""
-Package containing unit tests for L{OpenSSL}.
+Package containing unit tests for :py:mod:`OpenSSL`.
"""
diff --git a/OpenSSL/test/test_crypto.py b/OpenSSL/test/test_crypto.py
index 9b49213..b0940d8 100644
--- a/OpenSSL/test/test_crypto.py
+++ b/OpenSSL/test/test_crypto.py
@@ -2,7 +2,7 @@
# See LICENSE file for details.
"""
-Unit tests for L{OpenSSL.crypto}.
+Unit tests for :py:mod:`OpenSSL.crypto`.
"""
from unittest import main
@@ -299,7 +299,7 @@ RFEIPQsFZRLrtnCAiEhyT8bC2s/Njlu6ly9gtJZWSV46Q3ZjBL4q9sHKqZQ=
class X509ExtTests(TestCase):
"""
- Tests for L{OpenSSL.crypto.X509Extension}.
+ Tests for :py:class:`OpenSSL.crypto.X509Extension`.
"""
def setUp(self):
@@ -327,8 +327,8 @@ class X509ExtTests(TestCase):
def test_str(self):
"""
- The string representation of L{X509Extension} instances as returned by
- C{str} includes stuff.
+ The string representation of :py:class:`X509Extension` instances as returned by
+ :py:data:`str` includes stuff.
"""
# This isn't necessarily the best string representation. Perhaps it
# will be changed/improved in the future.
@@ -339,7 +339,7 @@ class X509ExtTests(TestCase):
def test_type(self):
"""
- L{X509Extension} and L{X509ExtensionType} refer to the same type object
+ :py:class:`X509Extension` and :py:class:`X509ExtensionType` refer to the same type object
and can be used to create instances of that type.
"""
self.assertIdentical(X509Extension, X509ExtensionType)
@@ -350,8 +350,8 @@ class X509ExtTests(TestCase):
def test_construction(self):
"""
- L{X509Extension} accepts an extension type name, a critical flag,
- and an extension value and returns an L{X509ExtensionType} instance.
+ :py:class:`X509Extension` accepts an extension type name, a critical flag,
+ and an extension value and returns an :py:class:`X509ExtensionType` instance.
"""
basic = X509Extension(b('basicConstraints'), True, b('CA:true'))
self.assertTrue(
@@ -369,7 +369,7 @@ class X509ExtTests(TestCase):
def test_invalid_extension(self):
"""
- L{X509Extension} raises something if it is passed a bad extension
+ :py:class:`X509Extension` raises something if it is passed a bad extension
name or value.
"""
self.assertRaises(
@@ -388,7 +388,7 @@ class X509ExtTests(TestCase):
def test_get_critical(self):
"""
- L{X509ExtensionType.get_critical} returns the value of the
+ :py:meth:`X509ExtensionType.get_critical` returns the value of the
extension's critical flag.
"""
ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
@@ -399,7 +399,7 @@ class X509ExtTests(TestCase):
def test_get_short_name(self):
"""
- L{X509ExtensionType.get_short_name} returns a string giving the short
+ :py:meth:`X509ExtensionType.get_short_name` returns a string giving the short
type name of the extension.
"""
ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
@@ -410,7 +410,7 @@ class X509ExtTests(TestCase):
def test_get_data(self):
"""
- L{X509Extension.get_data} returns a string giving the data of the
+ :py:meth:`X509Extension.get_data` returns a string giving the data of the
extension.
"""
ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
@@ -420,7 +420,7 @@ class X509ExtTests(TestCase):
def test_get_data_wrong_args(self):
"""
- L{X509Extension.get_data} raises L{TypeError} if passed any arguments.
+ :py:meth:`X509Extension.get_data` raises :py:exc:`TypeError` if passed any arguments.
"""
ext = X509Extension(b('basicConstraints'), True, b('CA:true'))
self.assertRaises(TypeError, ext.get_data, None)
@@ -430,7 +430,7 @@ class X509ExtTests(TestCase):
def test_unused_subject(self):
"""
- The C{subject} parameter to L{X509Extension} may be provided for an
+ The :py:data:`subject` parameter to :py:class:`X509Extension` may be provided for an
extension which does not use it and is ignored in this case.
"""
ext1 = X509Extension(
@@ -445,8 +445,8 @@ class X509ExtTests(TestCase):
def test_subject(self):
"""
- If an extension requires a subject, the C{subject} parameter to
- L{X509Extension} provides its value.
+ If an extension requires a subject, the :py:data:`subject` parameter to
+ :py:class:`X509Extension` provides its value.
"""
ext3 = X509Extension(
b('subjectKeyIdentifier'), False, b('hash'), subject=self.x509)
@@ -458,7 +458,7 @@ class X509ExtTests(TestCase):
def test_missing_subject(self):
"""
- If an extension requires a subject and the C{subject} parameter is
+ If an extension requires a subject and the :py:data:`subject` parameter is
given no value, something happens.
"""
self.assertRaises(
@@ -467,8 +467,8 @@ class X509ExtTests(TestCase):
def test_invalid_subject(self):
"""
- If the C{subject} parameter is given a value which is not an L{X509}
- instance, L{TypeError} is raised.
+ If the :py:data:`subject` parameter is given a value which is not an
+ :py:class:`X509` instance, :py:exc:`TypeError` is raised.
"""
for badObj in [True, object(), "hello", [], self]:
self.assertRaises(
@@ -479,7 +479,7 @@ class X509ExtTests(TestCase):
def test_unused_issuer(self):
"""
- The C{issuer} parameter to L{X509Extension} may be provided for an
+ The :py:data:`issuer` parameter to :py:class:`X509Extension` may be provided for an
extension which does not use it and is ignored in this case.
"""
ext1 = X509Extension(
@@ -493,8 +493,8 @@ class X509ExtTests(TestCase):
def test_issuer(self):
"""
- If an extension requires a issuer, the C{issuer} parameter to
- L{X509Extension} provides its value.
+ If an extension requires a issuer, the :py:data:`issuer` parameter to
+ :py:class:`X509Extension` provides its value.
"""
ext2 = X509Extension(
b('authorityKeyIdentifier'), False, b('issuer:always'),
@@ -508,7 +508,7 @@ class X509ExtTests(TestCase):
def test_missing_issuer(self):
"""
- If an extension requires an issue and the C{issuer} parameter is given
+ If an extension requires an issue and the :py:data:`issuer` parameter is given
no value, something happens.
"""
self.assertRaises(
@@ -520,8 +520,8 @@ class X509ExtTests(TestCase):
def test_invalid_issuer(self):
"""
- If the C{issuer} parameter is given a value which is not an L{X509}
- instance, L{TypeError} is raised.
+ If the :py:data:`issuer` parameter is given a value which is not an
+ :py:class:`X509` instance, :py:exc:`TypeError` is raised.
"""
for badObj in [True, object(), "hello", [], self]:
self.assertRaises(
@@ -534,12 +534,12 @@ class X509ExtTests(TestCase):
class PKeyTests(TestCase):
"""
- Unit tests for L{OpenSSL.crypto.PKey}.
+ Unit tests for :py:class:`OpenSSL.crypto.PKey`.
"""
def test_type(self):
"""
- L{PKey} and L{PKeyType} refer to the same type object and can be used
- to create instances of that type.
+ :py:class:`PKey` and :py:class:`PKeyType` refer to the same type object
+ and can be used to create instances of that type.
"""
self.assertIdentical(PKey, PKeyType)
self.assertConsistentType(PKey, 'PKey')
@@ -547,7 +547,7 @@ class PKeyTests(TestCase):
def test_construction(self):
"""
- L{PKey} takes no arguments and returns a new L{PKey} instance.
+ :py:class:`PKey` takes no arguments and returns a new :py:class:`PKey` instance.
"""
self.assertRaises(TypeError, PKey, None)
key = PKey()
@@ -558,8 +558,8 @@ class PKeyTests(TestCase):
def test_pregeneration(self):
"""
- L{PKeyType.bits} and L{PKeyType.type} return C{0} before the key is
- generated. L{PKeyType.check} raises L{TypeError} before the key is
+ :py:attr:`PKeyType.bits` and :py:attr:`PKeyType.type` return :py:data:`0` before the key is
+ generated. :py:attr:`PKeyType.check` raises :py:exc:`TypeError` before the key is
generated.
"""
key = PKey()
@@ -570,11 +570,11 @@ class PKeyTests(TestCase):
def test_failedGeneration(self):
"""
- L{PKeyType.generate_key} takes two arguments, the first giving the key
- type as one of L{TYPE_RSA} or L{TYPE_DSA} and the second giving the
+ :py:meth:`PKeyType.generate_key` takes two arguments, the first giving the key
+ type as one of :py:data:`TYPE_RSA` or :py:data:`TYPE_DSA` and the second giving the
number of bits to generate. If an invalid type is specified or
- generation fails, L{Error} is raised. If an invalid number of bits is
- specified, L{ValueError} or L{Error} is raised.
+ generation fails, :py:exc:`Error` is raised. If an invalid number of bits is
+ specified, :py:exc:`ValueError` or :py:exc:`Error` is raised.
"""
key = PKey()
self.assertRaises(TypeError, key.generate_key)
@@ -605,8 +605,8 @@ class PKeyTests(TestCase):
def test_rsaGeneration(self):
"""
- L{PKeyType.generate_key} generates an RSA key when passed
- L{TYPE_RSA} as a type and a reasonable number of bits.
+ :py:meth:`PKeyType.generate_key` generates an RSA key when passed
+ :py:data:`TYPE_RSA` as a type and a reasonable number of bits.
"""
bits = 128
key = PKey()
@@ -618,8 +618,8 @@ class PKeyTests(TestCase):
def test_dsaGeneration(self):
"""
- L{PKeyType.generate_key} generates a DSA key when passed
- L{TYPE_DSA} as a type and a reasonable number of bits.
+ :py:meth:`PKeyType.generate_key` generates a DSA key when passed
+ :py:data:`TYPE_DSA` as a type and a reasonable number of bits.
"""
# 512 is a magic number. The DSS (Digital Signature Standard)
# allows a minimum of 512 bits for DSA. DSA_generate_parameters
@@ -634,7 +634,7 @@ class PKeyTests(TestCase):
def test_regeneration(self):
"""
- L{PKeyType.generate_key} can be called multiple times on the same
+ :py:meth:`PKeyType.generate_key` can be called multiple times on the same
key to generate new keys.
"""
key = PKey()
@@ -646,7 +646,7 @@ class PKeyTests(TestCase):
def test_inconsistentKey(self):
"""
- L{PKeyType.check} returns C{False} if the key is not consistent.
+ :py:`PKeyType.check` returns :py:exc:`Error` if the key is not consistent.
"""
key = load_privatekey(FILETYPE_PEM, inconsistentPrivateKeyPEM)
self.assertRaises(Error, key.check)
@@ -654,17 +654,31 @@ class PKeyTests(TestCase):
def test_check_wrong_args(self):
"""
- L{PKeyType.check} raises L{TypeError} if called with any arguments.
+ :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if called with any arguments.
"""
self.assertRaises(TypeError, PKey().check, None)
self.assertRaises(TypeError, PKey().check, object())
self.assertRaises(TypeError, PKey().check, 1)
+ def test_check_public_key(self):
+ """
+ :py:meth:`PKeyType.check` raises :py:exc:`TypeError` if only the public
+ part of the key is available.
+ """
+ # A trick to get a public-only key
+ key = PKey()
+ key.generate_key(TYPE_RSA, 512)
+ cert = X509()
+ cert.set_pubkey(key)
+ pub = cert.get_pubkey()
+ self.assertRaises(TypeError, pub.check)
+
+
class X509NameTests(TestCase):
"""
- Unit tests for L{OpenSSL.crypto.X509Name}.
+ Unit tests for :py:class:`OpenSSL.crypto.X509Name`.
"""
def _x509name(self, **attrs):
# XXX There's no other way to get a new X509Name yet.
@@ -681,7 +695,7 @@ class X509NameTests(TestCase):
def test_type(self):
"""
- The type of X509Name objects is L{X509NameType}.
+ The type of X509Name objects is :py:class:`X509NameType`.
"""
self.assertIdentical(X509Name, X509NameType)
self.assertEqual(X509NameType.__name__, 'X509Name')
@@ -696,8 +710,8 @@ class X509NameTests(TestCase):
def test_onlyStringAttributes(self):
"""
- Attempting to set a non-L{str} attribute name on an L{X509NameType}
- instance causes L{TypeError} to be raised.
+ Attempting to set a non-:py:data:`str` attribute name on an :py:class:`X509NameType`
+ instance causes :py:exc:`TypeError` to be raised.
"""
name = self._x509name()
# Beyond these cases, you may also think that unicode should be
@@ -713,8 +727,8 @@ class X509NameTests(TestCase):
def test_setInvalidAttribute(self):
"""
- Attempting to set any attribute name on an L{X509NameType} instance for
- which no corresponding NID is defined causes L{AttributeError} to be
+ Attempting to set any attribute name on an :py:class:`X509NameType` instance for
+ which no corresponding NID is defined causes :py:exc:`AttributeError` to be
raised.
"""
name = self._x509name()
@@ -723,7 +737,7 @@ class X509NameTests(TestCase):
def test_attributes(self):
"""
- L{X509NameType} instances have attributes for each standard (?)
+ :py:class:`X509NameType` instances have attributes for each standard (?)
X509Name field.
"""
name = self._x509name()
@@ -743,8 +757,8 @@ class X509NameTests(TestCase):
def test_copy(self):
"""
- L{X509Name} creates a new L{X509NameType} instance with all the same
- attributes as an existing L{X509NameType} instance when called with
+ :py:class:`X509Name` creates a new :py:class:`X509NameType` instance with all the same
+ attributes as an existing :py:class:`X509NameType` instance when called with
one.
"""
name = self._x509name(commonName="foo", emailAddress="bar@example.com")
@@ -764,7 +778,7 @@ class X509NameTests(TestCase):
def test_repr(self):
"""
- L{repr} passed an L{X509NameType} instance should return a string
+ :py:func:`repr` passed an :py:class:`X509NameType` instance should return a string
containing a description of the type and the NIDs which have been set
on it.
"""
@@ -776,7 +790,7 @@ class X509NameTests(TestCase):
def test_comparison(self):
"""
- L{X509NameType} instances should compare based on their NIDs.
+ :py:class:`X509NameType` instances should compare based on their NIDs.
"""
def _equality(a, b, assertTrue, assertFalse):
assertTrue(a == b, "(%r == %r) --> False" % (a, b))
@@ -851,7 +865,7 @@ class X509NameTests(TestCase):
def test_hash(self):
"""
- L{X509Name.hash} returns an integer hash based on the value of the
+ :py:meth:`X509Name.hash` returns an integer hash based on the value of the
name.
"""
a = self._x509name(CN="foo")
@@ -863,7 +877,7 @@ class X509NameTests(TestCase):
def test_der(self):
"""
- L{X509Name.der} returns the DER encoded form of the name.
+ :py:meth:`X509Name.der` returns the DER encoded form of the name.
"""
a = self._x509name(CN="foo", C="US")
self.assertEqual(
@@ -874,7 +888,8 @@ class X509NameTests(TestCase):
def test_get_components(self):
"""
- L{X509Name.get_components} returns a C{list} of two-tuples of C{str}
+ :py:meth:`X509Name.get_components` returns a :py:data:`list` of
+ two-tuples of :py:data:`str`
giving the NIDs and associated values which make up the name.
"""
a = self._x509name()
@@ -889,7 +904,8 @@ class X509NameTests(TestCase):
def test_load_nul_byte_attribute(self):
"""
- An L{X509Name} from an L{X509} instance loaded from a file can have a
+ An :py:class:`OpenSSL.crypto.X509Name` from an
+ :py:class:`OpenSSL.crypto.X509` instance loaded from a file can have a
NUL byte in the value of one of its attributes.
"""
cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
@@ -905,14 +921,16 @@ class _PKeyInteractionTestsMixin:
"""
def signable(self):
"""
- Return something with a C{set_pubkey}, C{set_pubkey}, and C{sign} method.
+ Return something with a :py:meth:`set_pubkey`, :py:meth:`set_pubkey`,
+ and :py:meth:`sign` method.
"""
raise NotImplementedError()
def test_signWithUngenerated(self):
"""
- L{X509Req.sign} raises L{ValueError} when pass a L{PKey} with no parts.
+ :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
+ :py:class:`PKey` with no parts.
"""
request = self.signable()
key = PKey()
@@ -921,8 +939,8 @@ class _PKeyInteractionTestsMixin:
def test_signWithPublicKey(self):
"""
- L{X509Req.sign} raises L{ValueError} when pass a L{PKey} with no
- private part as the signing key.
+ :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when pass a
+ :py:class:`PKey` with no private part as the signing key.
"""
request = self.signable()
key = PKey()
@@ -934,7 +952,7 @@ class _PKeyInteractionTestsMixin:
def test_signWithUnknownDigest(self):
"""
- L{X509Req.sign} raises L{ValueError} when passed a digest name which is
+ :py:meth:`X509Req.sign` raises :py:exc:`ValueError` when passed a digest name which is
not known.
"""
request = self.signable()
@@ -945,8 +963,8 @@ class _PKeyInteractionTestsMixin:
def test_sign(self):
"""
- L{X509Req.sign} succeeds when passed a private key object and a valid
- digest function. C{X509Req.verify} can be used to check the signature.
+ :py:meth:`X509Req.sign` succeeds when passed a private key object and a valid
+ digest function. :py:meth:`X509Req.verify` can be used to check the signature.
"""
request = self.signable()
key = PKey()
@@ -967,18 +985,18 @@ class _PKeyInteractionTestsMixin:
class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
"""
- Tests for L{OpenSSL.crypto.X509Req}.
+ Tests for :py:class:`OpenSSL.crypto.X509Req`.
"""
def signable(self):
"""
- Create and return a new L{X509Req}.
+ Create and return a new :py:class:`X509Req`.
"""
return X509Req()
def test_type(self):
"""
- L{X509Req} and L{X509ReqType} refer to the same type object and can be
+ :py:obj:`X509Req` and :py:obj:`X509ReqType` refer to the same type object and can be
used to create instances of that type.
"""
self.assertIdentical(X509Req, X509ReqType)
@@ -987,7 +1005,7 @@ class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
def test_construction(self):
"""
- L{X509Req} takes no arguments and returns an L{X509ReqType} instance.
+ :py:obj:`X509Req` takes no arguments and returns an :py:obj:`X509ReqType` instance.
"""
request = X509Req()
self.assertTrue(
@@ -997,8 +1015,8 @@ class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
def test_version(self):
"""
- L{X509ReqType.set_version} sets the X.509 version of the certificate
- request. L{X509ReqType.get_version} returns the X.509 version of
+ :py:obj:`X509ReqType.set_version` sets the X.509 version of the certificate
+ request. :py:obj:`X509ReqType.get_version` returns the X.509 version of
the certificate request. The initial value of the version is 0.
"""
request = X509Req()
@@ -1011,9 +1029,9 @@ class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
def test_version_wrong_args(self):
"""
- L{X509ReqType.set_version} raises L{TypeError} if called with the wrong
- number of arguments or with a non-C{int} argument.
- L{X509ReqType.get_version} raises L{TypeError} if called with any
+ :py:obj:`X509ReqType.set_version` raises :py:obj:`TypeError` if called with the wrong
+ number of arguments or with a non-:py:obj:`int` argument.
+ :py:obj:`X509ReqType.get_version` raises :py:obj:`TypeError` if called with any
arguments.
"""
request = X509Req()
@@ -1025,7 +1043,7 @@ class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
def test_get_subject(self):
"""
- L{X509ReqType.get_subject} returns an L{X509Name} for the subject of
+ :py:obj:`X509ReqType.get_subject` returns an :py:obj:`X509Name` for the subject of
the request and which is valid even after the request object is
otherwise dead.
"""
@@ -1043,7 +1061,7 @@ class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
def test_get_subject_wrong_args(self):
"""
- L{X509ReqType.get_subject} raises L{TypeError} if called with any
+ :py:obj:`X509ReqType.get_subject` raises :py:obj:`TypeError` if called with any
arguments.
"""
request = X509Req()
@@ -1052,7 +1070,7 @@ class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
def test_add_extensions(self):
"""
- L{X509Req.add_extensions} accepts a C{list} of L{X509Extension}
+ :py:obj:`X509Req.add_extensions` accepts a :py:obj:`list` of :py:obj:`X509Extension`
instances and adds them to the X509 request.
"""
request = X509Req()
@@ -1063,9 +1081,9 @@ class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
def test_add_extensions_wrong_args(self):
"""
- L{X509Req.add_extensions} raises L{TypeError} if called with the wrong
- number of arguments or with a non-C{list}. Or it raises L{ValueError}
- if called with a C{list} containing objects other than L{X509Extension}
+ :py:obj:`X509Req.add_extensions` raises :py:obj:`TypeError` if called with the wrong
+ number of arguments or with a non-:py:obj:`list`. Or it raises :py:obj:`ValueError`
+ if called with a :py:obj:`list` containing objects other than :py:obj:`X509Extension`
instances.
"""
request = X509Req()
@@ -1078,7 +1096,7 @@ class X509ReqTests(TestCase, _PKeyInteractionTestsMixin):
class X509Tests(TestCase, _PKeyInteractionTestsMixin):
"""
- Tests for L{OpenSSL.crypto.X509}.
+ Tests for :py:obj:`OpenSSL.crypto.X509`.
"""
pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
@@ -1104,14 +1122,14 @@ WpOdIpB8KksUTCzV591Nr1wd
"""
def signable(self):
"""
- Create and return a new L{X509}.
+ Create and return a new :py:obj:`X509`.
"""
return X509()
def test_type(self):
"""
- L{X509} and L{X509Type} refer to the same type object and can be used
+ :py:obj:`X509` and :py:obj:`X509Type` refer to the same type object and can be used
to create instances of that type.
"""
self.assertIdentical(X509, X509Type)
@@ -1120,7 +1138,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_construction(self):
"""
- L{X509} takes no arguments and returns an instance of L{X509Type}.
+ :py:obj:`X509` takes no arguments and returns an instance of :py:obj:`X509Type`.
"""
certificate = X509()
self.assertTrue(
@@ -1136,7 +1154,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_get_version_wrong_args(self):
"""
- L{X509.get_version} raises L{TypeError} if invoked with any arguments.
+ :py:obj:`X509.get_version` raises :py:obj:`TypeError` if invoked with any arguments.
"""
cert = X509()
self.assertRaises(TypeError, cert.get_version, None)
@@ -1144,8 +1162,8 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_set_version_wrong_args(self):
"""
- L{X509.set_version} raises L{TypeError} if invoked with the wrong number
- of arguments or an argument not of type C{int}.
+ :py:obj:`X509.set_version` raises :py:obj:`TypeError` if invoked with the wrong number
+ of arguments or an argument not of type :py:obj:`int`.
"""
cert = X509()
self.assertRaises(TypeError, cert.set_version)
@@ -1155,8 +1173,8 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_version(self):
"""
- L{X509.set_version} sets the certificate version number.
- L{X509.get_version} retrieves it.
+ :py:obj:`X509.set_version` sets the certificate version number.
+ :py:obj:`X509.get_version` retrieves it.
"""
cert = X509()
cert.set_version(1234)
@@ -1165,7 +1183,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_get_serial_number_wrong_args(self):
"""
- L{X509.get_serial_number} raises L{TypeError} if invoked with any
+ :py:obj:`X509.get_serial_number` raises :py:obj:`TypeError` if invoked with any
arguments.
"""
cert = X509()
@@ -1174,8 +1192,8 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_serial_number(self):
"""
- The serial number of an L{X509Type} can be retrieved and modified with
- L{X509Type.get_serial_number} and L{X509Type.set_serial_number}.
+ The serial number of an :py:obj:`X509Type` can be retrieved and modified with
+ :py:obj:`X509Type.get_serial_number` and :py:obj:`X509Type.set_serial_number`.
"""
certificate = X509()
self.assertRaises(TypeError, certificate.set_serial_number)
@@ -1195,7 +1213,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def _setBoundTest(self, which):
"""
- L{X509Type.set_notBefore} takes a string in the format of an ASN1
+ :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
GENERALIZEDTIME and sets the beginning of the certificate's validity
period to it.
"""
@@ -1234,7 +1252,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_set_notBefore(self):
"""
- L{X509Type.set_notBefore} takes a string in the format of an ASN1
+ :py:obj:`X509Type.set_notBefore` takes a string in the format of an ASN1
GENERALIZEDTIME and sets the beginning of the certificate's validity
period to it.
"""
@@ -1243,7 +1261,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_set_notAfter(self):
"""
- L{X509Type.set_notAfter} takes a string in the format of an ASN1
+ :py:obj:`X509Type.set_notAfter` takes a string in the format of an ASN1
GENERALIZEDTIME and sets the end of the certificate's validity period
to it.
"""
@@ -1252,7 +1270,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_get_notBefore(self):
"""
- L{X509Type.get_notBefore} returns a string in the format of an ASN1
+ :py:obj:`X509Type.get_notBefore` returns a string in the format of an ASN1
GENERALIZEDTIME even for certificates which store it as UTCTIME
internally.
"""
@@ -1262,7 +1280,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_get_notAfter(self):
"""
- L{X509Type.get_notAfter} returns a string in the format of an ASN1
+ :py:obj:`X509Type.get_notAfter` returns a string in the format of an ASN1
GENERALIZEDTIME even for certificates which store it as UTCTIME
internally.
"""
@@ -1272,8 +1290,8 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_gmtime_adj_notBefore_wrong_args(self):
"""
- L{X509Type.gmtime_adj_notBefore} raises L{TypeError} if called with the
- wrong number of arguments or a non-C{int} argument.
+ :py:obj:`X509Type.gmtime_adj_notBefore` raises :py:obj:`TypeError` if called with the
+ wrong number of arguments or a non-:py:obj:`int` argument.
"""
cert = X509()
self.assertRaises(TypeError, cert.gmtime_adj_notBefore)
@@ -1283,7 +1301,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_gmtime_adj_notBefore(self):
"""
- L{X509Type.gmtime_adj_notBefore} changes the not-before timestamp to be
+ :py:obj:`X509Type.gmtime_adj_notBefore` changes the not-before timestamp to be
the current time plus the number of seconds passed in.
"""
cert = load_certificate(FILETYPE_PEM, self.pemData)
@@ -1294,8 +1312,8 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_gmtime_adj_notAfter_wrong_args(self):
"""
- L{X509Type.gmtime_adj_notAfter} raises L{TypeError} if called with the
- wrong number of arguments or a non-C{int} argument.
+ :py:obj:`X509Type.gmtime_adj_notAfter` raises :py:obj:`TypeError` if called with the
+ wrong number of arguments or a non-:py:obj:`int` argument.
"""
cert = X509()
self.assertRaises(TypeError, cert.gmtime_adj_notAfter)
@@ -1305,7 +1323,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_gmtime_adj_notAfter(self):
"""
- L{X509Type.gmtime_adj_notAfter} changes the not-after timestamp to be
+ :py:obj:`X509Type.gmtime_adj_notAfter` changes the not-after timestamp to be
the current time plus the number of seconds passed in.
"""
cert = load_certificate(FILETYPE_PEM, self.pemData)
@@ -1316,7 +1334,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_has_expired_wrong_args(self):
"""
- L{X509Type.has_expired} raises L{TypeError} if called with any
+ :py:obj:`X509Type.has_expired` raises :py:obj:`TypeError` if called with any
arguments.
"""
cert = X509()
@@ -1325,7 +1343,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_has_expired(self):
"""
- L{X509Type.has_expired} returns C{True} if the certificate's not-after
+ :py:obj:`X509Type.has_expired` returns :py:obj:`True` if the certificate's not-after
time is in the past.
"""
cert = X509()
@@ -1335,7 +1353,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_has_not_expired(self):
"""
- L{X509Type.has_expired} returns C{False} if the certificate's not-after
+ :py:obj:`X509Type.has_expired` returns :py:obj:`False` if the certificate's not-after
time is in the future.
"""
cert = X509()
@@ -1345,7 +1363,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_digest(self):
"""
- L{X509.digest} returns a string giving ":"-separated hex-encoded words
+ :py:obj:`X509.digest` returns a string giving ":"-separated hex-encoded words
of the digest of the certificate.
"""
cert = X509()
@@ -1370,7 +1388,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_extension_count(self):
"""
- L{X509.get_extension_count} returns the number of extensions that are
+ :py:obj:`X509.get_extension_count` returns the number of extensions that are
present in the certificate.
"""
pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
@@ -1394,7 +1412,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_get_extension(self):
"""
- L{X509.get_extension} takes an integer and returns an L{X509Extension}
+ :py:obj:`X509.get_extension` takes an integer and returns an :py:obj:`X509Extension`
corresponding to the extension at that index.
"""
pkey = load_privatekey(FILETYPE_PEM, client_key_pem)
@@ -1427,7 +1445,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_nullbyte_subjectAltName(self):
"""
- The fields of a I{subjectAltName} extension on an X509 may contain NUL
+ The fields of a `subjectAltName` extension on an X509 may contain NUL
bytes and this value is reflected in the string representation of the
extension object.
"""
@@ -1445,7 +1463,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_invalid_digest_algorithm(self):
"""
- L{X509.digest} raises L{ValueError} if called with an unrecognized hash
+ :py:obj:`X509.digest` raises :py:obj:`ValueError` if called with an unrecognized hash
algorithm.
"""
cert = X509()
@@ -1454,7 +1472,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_get_subject_wrong_args(self):
"""
- L{X509.get_subject} raises L{TypeError} if called with any arguments.
+ :py:obj:`X509.get_subject` raises :py:obj:`TypeError` if called with any arguments.
"""
cert = X509()
self.assertRaises(TypeError, cert.get_subject, None)
@@ -1462,7 +1480,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_get_subject(self):
"""
- L{X509.get_subject} returns an L{X509Name} instance.
+ :py:obj:`X509.get_subject` returns an :py:obj:`X509Name` instance.
"""
cert = load_certificate(FILETYPE_PEM, self.pemData)
subj = cert.get_subject()
@@ -1475,8 +1493,8 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_set_subject_wrong_args(self):
"""
- L{X509.set_subject} raises a L{TypeError} if called with the wrong
- number of arguments or an argument not of type L{X509Name}.
+ :py:obj:`X509.set_subject` raises a :py:obj:`TypeError` if called with the wrong
+ number of arguments or an argument not of type :py:obj:`X509Name`.
"""
cert = X509()
self.assertRaises(TypeError, cert.set_subject)
@@ -1486,7 +1504,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_set_subject(self):
"""
- L{X509.set_subject} changes the subject of the certificate to the one
+ :py:obj:`X509.set_subject` changes the subject of the certificate to the one
passed in.
"""
cert = X509()
@@ -1501,7 +1519,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_get_issuer_wrong_args(self):
"""
- L{X509.get_issuer} raises L{TypeError} if called with any arguments.
+ :py:obj:`X509.get_issuer` raises :py:obj:`TypeError` if called with any arguments.
"""
cert = X509()
self.assertRaises(TypeError, cert.get_issuer, None)
@@ -1509,7 +1527,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_get_issuer(self):
"""
- L{X509.get_issuer} returns an L{X509Name} instance.
+ :py:obj:`X509.get_issuer` returns an :py:obj:`X509Name` instance.
"""
cert = load_certificate(FILETYPE_PEM, self.pemData)
subj = cert.get_issuer()
@@ -1523,8 +1541,8 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_set_issuer_wrong_args(self):
"""
- L{X509.set_issuer} raises a L{TypeError} if called with the wrong
- number of arguments or an argument not of type L{X509Name}.
+ :py:obj:`X509.set_issuer` raises a :py:obj:`TypeError` if called with the wrong
+ number of arguments or an argument not of type :py:obj:`X509Name`.
"""
cert = X509()
self.assertRaises(TypeError, cert.set_issuer)
@@ -1534,7 +1552,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_set_issuer(self):
"""
- L{X509.set_issuer} changes the issuer of the certificate to the one
+ :py:obj:`X509.set_issuer` changes the issuer of the certificate to the one
passed in.
"""
cert = X509()
@@ -1549,8 +1567,8 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_get_pubkey_uninitialized(self):
"""
- When called on a certificate with no public key, L{X509.get_pubkey}
- raises L{OpenSSL.crypto.Error}.
+ When called on a certificate with no public key, :py:obj:`X509.get_pubkey`
+ raises :py:obj:`OpenSSL.crypto.Error`.
"""
cert = X509()
self.assertRaises(Error, cert.get_pubkey)
@@ -1558,7 +1576,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_subject_name_hash_wrong_args(self):
"""
- L{X509.subject_name_hash} raises L{TypeError} if called with any
+ :py:obj:`X509.subject_name_hash` raises :py:obj:`TypeError` if called with any
arguments.
"""
cert = X509()
@@ -1567,7 +1585,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_subject_name_hash(self):
"""
- L{X509.subject_name_hash} returns the hash of the certificate's subject
+ :py:obj:`X509.subject_name_hash` returns the hash of the certificate's subject
name.
"""
cert = load_certificate(FILETYPE_PEM, self.pemData)
@@ -1580,7 +1598,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_get_signature_algorithm(self):
"""
- L{X509Type.get_signature_algorithm} returns a string which means
+ :py:obj:`X509Type.get_signature_algorithm` returns a string which means
the algorithm used to sign the certificate.
"""
cert = load_certificate(FILETYPE_PEM, self.pemData)
@@ -1590,7 +1608,7 @@ WpOdIpB8KksUTCzV591Nr1wd
def test_get_undefined_signature_algorithm(self):
"""
- L{X509Type.get_signature_algorithm} raises L{ValueError} if the
+ :py:obj:`X509Type.get_signature_algorithm` raises :py:obj:`ValueError` if the
signature algorithm is undefined or unknown.
"""
# This certificate has been modified to indicate a bogus OID in the
@@ -1623,13 +1641,13 @@ tgI5
class PKCS12Tests(TestCase):
"""
- Test for L{OpenSSL.crypto.PKCS12} and L{OpenSSL.crypto.load_pkcs12}.
+ Test for :py:obj:`OpenSSL.crypto.PKCS12` and :py:obj:`OpenSSL.crypto.load_pkcs12`.
"""
pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
def test_type(self):
"""
- L{PKCS12Type} is a type object.
+ :py:obj:`PKCS12Type` is a type object.
"""
self.assertIdentical(PKCS12, PKCS12Type)
self.assertConsistentType(PKCS12, 'PKCS12')
@@ -1637,7 +1655,7 @@ class PKCS12Tests(TestCase):
def test_empty_construction(self):
"""
- L{PKCS12} returns a new instance of L{PKCS12} with no certificate,
+ :py:obj:`PKCS12` returns a new instance of :py:obj:`PKCS12` with no certificate,
private key, CA certificates, or friendly name.
"""
p12 = PKCS12()
@@ -1649,8 +1667,8 @@ class PKCS12Tests(TestCase):
def test_type_errors(self):
"""
- The L{PKCS12} setter functions (C{set_certificate}, C{set_privatekey},
- C{set_ca_certificates}, and C{set_friendlyname}) raise L{TypeError}
+ The :py:obj:`PKCS12` setter functions (:py:obj:`set_certificate`, :py:obj:`set_privatekey`,
+ :py:obj:`set_ca_certificates`, and :py:obj:`set_friendlyname`) raise :py:obj:`TypeError`
when passed objects of types other than those expected.
"""
p12 = PKCS12()
@@ -1670,8 +1688,8 @@ class PKCS12Tests(TestCase):
def test_key_only(self):
"""
- A L{PKCS12} with only a private key can be exported using
- L{PKCS12.export} and loaded again using L{load_pkcs12}.
+ A :py:obj:`PKCS12` with only a private key can be exported using
+ :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
"""
passwd = 'blah'
p12 = PKCS12()
@@ -1697,8 +1715,8 @@ class PKCS12Tests(TestCase):
def test_cert_only(self):
"""
- A L{PKCS12} with only a certificate can be exported using
- L{PKCS12.export} and loaded again using L{load_pkcs12}.
+ A :py:obj:`PKCS12` with only a certificate can be exported using
+ :py:obj:`PKCS12.export` and loaded again using :py:obj:`load_pkcs12`.
"""
passwd = 'blah'
p12 = PKCS12()
@@ -1777,7 +1795,7 @@ class PKCS12Tests(TestCase):
def test_load_pkcs12(self):
"""
A PKCS12 string generated using the openssl command line can be loaded
- with L{load_pkcs12} and its components extracted and examined.
+ with :py:obj:`load_pkcs12` and its components extracted and examined.
"""
passwd = 'whatever'
pem = client_key_pem + client_cert_pem
@@ -1795,7 +1813,7 @@ class PKCS12Tests(TestCase):
def test_load_pkcs12_garbage(self):
"""
- L{load_pkcs12} raises L{OpenSSL.crypto.Error} when passed a string
+ :py:obj:`load_pkcs12` raises :py:obj:`OpenSSL.crypto.Error` when passed a string
which is not a PKCS12 dump.
"""
passwd = 'whatever'
@@ -1806,9 +1824,9 @@ class PKCS12Tests(TestCase):
def test_replace(self):
"""
- L{PKCS12.set_certificate} replaces the certificate in a PKCS12 cluster.
- L{PKCS12.set_privatekey} replaces the private key.
- L{PKCS12.set_ca_certificates} replaces the CA certificates.
+ :py:obj:`PKCS12.set_certificate` replaces the certificate in a PKCS12 cluster.
+ :py:obj:`PKCS12.set_privatekey` replaces the private key.
+ :py:obj:`PKCS12.set_ca_certificates` replaces the CA certificates.
"""
p12 = self.gen_pkcs12(client_cert_pem, client_key_pem, root_cert_pem)
p12.set_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
@@ -1826,9 +1844,9 @@ class PKCS12Tests(TestCase):
def test_friendly_name(self):
"""
- The I{friendlyName} of a PKCS12 can be set and retrieved via
- L{PKCS12.get_friendlyname} and L{PKCS12_set_friendlyname}, and a
- L{PKCS12} with a friendly name set can be dumped with L{PKCS12.export}.
+ The *friendlyName* of a PKCS12 can be set and retrieved via
+ :py:obj:`PKCS12.get_friendlyname` and :py:obj:`PKCS12_set_friendlyname`, and a
+ :py:obj:`PKCS12` with a friendly name set can be dumped with :py:obj:`PKCS12.export`.
"""
passwd = 'Dogmeat[]{}!@#$%^&*()~`?/.,<>-_+=";:'
p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
@@ -1866,7 +1884,7 @@ class PKCS12Tests(TestCase):
def test_removing_ca_cert(self):
"""
- Passing C{None} to L{PKCS12.set_ca_certificates} removes all CA
+ Passing :py:obj:`None` to :py:obj:`PKCS12.set_ca_certificates` removes all CA
certificates.
"""
p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
@@ -1876,7 +1894,7 @@ class PKCS12Tests(TestCase):
def test_export_without_mac(self):
"""
- Exporting a PKCS12 with a C{maciter} of C{-1} excludes the MAC
+ Exporting a PKCS12 with a :py:obj:`maciter` of ``-1`` excludes the MAC
entirely.
"""
passwd = 'Lake Michigan'
@@ -1924,7 +1942,7 @@ class PKCS12Tests(TestCase):
def test_export_without_args(self):
"""
- All the arguments to L{PKCS12.export} are optional.
+ All the arguments to :py:obj:`PKCS12.export` are optional.
"""
p12 = self.gen_pkcs12(server_cert_pem, server_key_pem, root_cert_pem)
dumped_p12 = p12.export() # no args
@@ -1934,7 +1952,7 @@ class PKCS12Tests(TestCase):
def test_key_cert_mismatch(self):
"""
- L{PKCS12.export} raises an exception when a key and certificate
+ :py:obj:`PKCS12.export` raises an exception when a key and certificate
mismatch.
"""
p12 = self.gen_pkcs12(server_cert_pem, client_key_pem, root_cert_pem)
@@ -1949,14 +1967,14 @@ def cmdLineQuote(s):
"""
Internal method for quoting a single command-line argument.
- @type: C{str}
- @param s: A single unquoted string to quote for something that is expecting
- cmd.exe-style quoting
+ See http://www.perlmonks.org/?node_id=764004
- @rtype: C{str}
- @return: A cmd.exe-style quoted string
+ :type: :py:obj:`str`
+ :param s: A single unquoted string to quote for something that is expecting
+ cmd.exe-style quoting
- @see: U{http://www.perlmonks.org/?node_id=764004}
+ :rtype: :py:obj:`str`
+ :return: A cmd.exe-style quoted string
"""
s = _cmdLineQuoteRe2.sub(r"\1\1", _cmdLineQuoteRe.sub(r'\1\1\\"', s))
return '"%s"' % s
@@ -1966,14 +1984,14 @@ def cmdLineQuote(s):
def quoteArguments(arguments):
"""
Quote an iterable of command-line arguments for passing to CreateProcess or
- a similar API. This allows the list passed to C{reactor.spawnProcess} to
- match the child process's C{sys.argv} properly.
+ a similar API. This allows the list passed to :py:obj:`reactor.spawnProcess` to
+ match the child process's :py:obj:`sys.argv` properly.
- @type arguments: C{iterable} of C{str}
- @param arguments: An iterable of unquoted arguments to quote
+ :type arguments: :py:obj:`iterable` of :py:obj:`str`
+ :param arguments: An iterable of unquoted arguments to quote
- @rtype: C{str}
- @return: A space-delimited string containing quoted versions of L{arguments}
+ :rtype: :py:obj:`str`
+ :return: A space-delimited string containing quoted versions of :py:obj:`arguments`
"""
return ' '.join(map(cmdLineQuote, arguments))
@@ -1998,20 +2016,20 @@ def _runopenssl(pem, *args):
class FunctionTests(TestCase):
"""
- Tests for free-functions in the L{OpenSSL.crypto} module.
+ Tests for free-functions in the :py:obj:`OpenSSL.crypto` module.
"""
def test_load_privatekey_invalid_format(self):
"""
- L{load_privatekey} raises L{ValueError} if passed an unknown filetype.
+ :py:obj:`load_privatekey` raises :py:obj:`ValueError` if passed an unknown filetype.
"""
self.assertRaises(ValueError, load_privatekey, 100, root_key_pem)
def test_load_privatekey_invalid_passphrase_type(self):
"""
- L{load_privatekey} raises L{TypeError} if passed a passphrase that is
- neither a c{str} nor a callable.
+ :py:obj:`load_privatekey` raises :py:obj:`TypeError` if passed a passphrase that is
+ neither a :py:obj:`str` nor a callable.
"""
self.assertRaises(
TypeError,
@@ -2021,7 +2039,7 @@ class FunctionTests(TestCase):
def test_load_privatekey_wrong_args(self):
"""
- L{load_privatekey} raises L{TypeError} if called with the wrong number
+ :py:obj:`load_privatekey` raises :py:obj:`TypeError` if called with the wrong number
of arguments.
"""
self.assertRaises(TypeError, load_privatekey)
@@ -2029,7 +2047,7 @@ class FunctionTests(TestCase):
def test_load_privatekey_wrongPassphrase(self):
"""
- L{load_privatekey} raises L{OpenSSL.crypto.Error} when it is passed an
+ :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it is passed an
encrypted PEM and an incorrect passphrase.
"""
self.assertRaises(
@@ -2037,9 +2055,21 @@ class FunctionTests(TestCase):
load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, b("quack"))
+ def test_load_privatekey_passphraseWrongType(self):
+ """
+ :py:obj:`load_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
+ with a private key encoded in a format, that doesn't support
+ encryption.
+ """
+ key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
+ blob = dump_privatekey(FILETYPE_ASN1, key)
+ self.assertRaises(ValueError,
+ load_privatekey, FILETYPE_ASN1, blob, "secret")
+
+
def test_load_privatekey_passphrase(self):
"""
- L{load_privatekey} can create a L{PKey} object from an encrypted PEM
+ :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
string if given the passphrase.
"""
key = load_privatekey(
@@ -2048,16 +2078,28 @@ class FunctionTests(TestCase):
self.assertTrue(isinstance(key, PKeyType))
+ def test_load_privatekey_passphrase_exception(self):
+ """
+ If the passphrase callback raises an exception, that exception is raised
+ by :py:obj:`load_privatekey`.
+ """
+ def cb(ignored):
+ raise ArithmeticError
+
+ self.assertRaises(ArithmeticError,
+ load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
+
+
def test_load_privatekey_wrongPassphraseCallback(self):
"""
- L{load_privatekey} raises L{OpenSSL.crypto.Error} when it is passed an
- encrypted PEM and a passphrase callback which returns an incorrect
- passphrase.
+ :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it
+ is passed an encrypted PEM and a passphrase callback which returns an
+ incorrect passphrase.
"""
called = []
def cb(*a):
called.append(None)
- return "quack"
+ return b("quack")
self.assertRaises(
Error,
load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
@@ -2066,7 +2108,7 @@ class FunctionTests(TestCase):
def test_load_privatekey_passphraseCallback(self):
"""
- L{load_privatekey} can create a L{PKey} object from an encrypted PEM
+ :py:obj:`load_privatekey` can create a :py:obj:`PKey` object from an encrypted PEM
string if given a passphrase callback which returns the correct
password.
"""
@@ -2079,33 +2121,31 @@ class FunctionTests(TestCase):
self.assertEqual(called, [False])
- def test_load_privatekey_passphrase_exception(self):
+ def test_load_privatekey_passphrase_wrong_return_type(self):
"""
- An exception raised by the passphrase callback passed to
- L{load_privatekey} causes L{OpenSSL.crypto.Error} to be raised.
-
- This isn't as nice as just letting the exception pass through. The
- behavior might be changed to that eventually.
+ :py:obj:`load_privatekey` raises :py:obj:`ValueError` if the passphrase
+ callback returns something other than a byte string.
"""
- def broken(ignored):
- raise RuntimeError("This is not working.")
self.assertRaises(
- Error,
+ ValueError,
load_privatekey,
- FILETYPE_PEM, encryptedPrivateKeyPEM, broken)
+ FILETYPE_PEM, encryptedPrivateKeyPEM, lambda *args: 3)
def test_dump_privatekey_wrong_args(self):
"""
- L{dump_privatekey} raises L{TypeError} if called with the wrong number
+ :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with the wrong number
of arguments.
"""
self.assertRaises(TypeError, dump_privatekey)
+ # If cipher name is given, password is required.
+ self.assertRaises(
+ ValueError, dump_privatekey, FILETYPE_PEM, PKey(), "foo")
def test_dump_privatekey_unknown_cipher(self):
"""
- L{dump_privatekey} raises L{ValueError} if called with an unrecognized
+ :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
cipher name.
"""
key = PKey()
@@ -2117,8 +2157,8 @@ class FunctionTests(TestCase):
def test_dump_privatekey_invalid_passphrase_type(self):
"""
- L{dump_privatekey} raises L{TypeError} if called with a passphrase which
- is neither a C{str} nor a callable.
+ :py:obj:`dump_privatekey` raises :py:obj:`TypeError` if called with a passphrase which
+ is neither a :py:obj:`str` nor a callable.
"""
key = PKey()
key.generate_key(TYPE_RSA, 512)
@@ -2129,7 +2169,7 @@ class FunctionTests(TestCase):
def test_dump_privatekey_invalid_filetype(self):
"""
- L{dump_privatekey} raises L{ValueError} if called with an unrecognized
+ :py:obj:`dump_privatekey` raises :py:obj:`ValueError` if called with an unrecognized
filetype.
"""
key = PKey()
@@ -2137,9 +2177,21 @@ class FunctionTests(TestCase):
self.assertRaises(ValueError, dump_privatekey, 100, key)
+ def test_load_privatekey_passphraseCallbackLength(self):
+ """
+ :py:obj:`crypto.load_privatekey` should raise an error when the passphrase
+ provided by the callback is too long, not silently truncate it.
+ """
+ def cb(ignored):
+ return "a" * 1025
+
+ self.assertRaises(ValueError,
+ load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb)
+
+
def test_dump_privatekey_passphrase(self):
"""
- L{dump_privatekey} writes an encrypted PEM when given a passphrase.
+ :py:obj:`dump_privatekey` writes an encrypted PEM when given a passphrase.
"""
passphrase = b("foo")
key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
@@ -2151,9 +2203,20 @@ class FunctionTests(TestCase):
self.assertEqual(loadedKey.bits(), key.bits())
+ def test_dump_privatekey_passphraseWrongType(self):
+ """
+ :py:obj:`dump_privatekey` raises :py:obj:`ValueError` when it is passed a passphrase
+ with a private key encoded in a format, that doesn't support
+ encryption.
+ """
+ key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
+ self.assertRaises(ValueError,
+ dump_privatekey, FILETYPE_ASN1, key, "blowfish", "secret")
+
+
def test_dump_certificate(self):
"""
- L{dump_certificate} writes PEM, DER, and text.
+ :py:obj:`dump_certificate` writes PEM, DER, and text.
"""
pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
cert = load_certificate(FILETYPE_PEM, pemData)
@@ -2172,7 +2235,7 @@ class FunctionTests(TestCase):
def test_dump_privatekey(self):
"""
- L{dump_privatekey} writes a PEM, DER, and text.
+ :py:obj:`dump_privatekey` writes a PEM, DER, and text.
"""
key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
self.assertTrue(key.check())
@@ -2192,7 +2255,7 @@ class FunctionTests(TestCase):
def test_dump_certificate_request(self):
"""
- L{dump_certificate_request} writes a PEM, DER, and text.
+ :py:obj:`dump_certificate_request` writes a PEM, DER, and text.
"""
req = load_certificate_request(FILETYPE_PEM, cleartextCertificateRequestPEM)
dumped_pem = dump_certificate_request(FILETYPE_PEM, req)
@@ -2211,7 +2274,7 @@ class FunctionTests(TestCase):
def test_dump_privatekey_passphraseCallback(self):
"""
- L{dump_privatekey} writes an encrypted PEM when given a callback which
+ :py:obj:`dump_privatekey` writes an encrypted PEM when given a callback which
returns the correct passphrase.
"""
passphrase = b("foo")
@@ -2229,10 +2292,36 @@ class FunctionTests(TestCase):
self.assertEqual(loadedKey.bits(), key.bits())
+ def test_dump_privatekey_passphrase_exception(self):
+ """
+ :py:obj:`dump_privatekey` should not overwrite the exception raised
+ by the passphrase callback.
+ """
+ def cb(ignored):
+ raise ArithmeticError
+
+ key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
+ self.assertRaises(ArithmeticError,
+ dump_privatekey, FILETYPE_PEM, key, "blowfish", cb)
+
+
+ def test_dump_privatekey_passphraseCallbackLength(self):
+ """
+ :py:obj:`crypto.dump_privatekey` should raise an error when the passphrase
+ provided by the callback is too long, not silently truncate it.
+ """
+ def cb(ignored):
+ return "a" * 1025
+
+ key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
+ self.assertRaises(ValueError,
+ dump_privatekey, FILETYPE_PEM, key, "blowfish", cb)
+
+
def test_load_pkcs7_data(self):
"""
- L{load_pkcs7_data} accepts a PKCS#7 string and returns an instance of
- L{PKCS7Type}.
+ :py:obj:`load_pkcs7_data` accepts a PKCS#7 string and returns an instance of
+ :py:obj:`PKCS7Type`.
"""
pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
self.assertTrue(isinstance(pkcs7, PKCS7Type))
@@ -2241,11 +2330,11 @@ class FunctionTests(TestCase):
class PKCS7Tests(TestCase):
"""
- Tests for L{PKCS7Type}.
+ Tests for :py:obj:`PKCS7Type`.
"""
def test_type(self):
"""
- L{PKCS7Type} is a type object.
+ :py:obj:`PKCS7Type` is a type object.
"""
self.assertTrue(isinstance(PKCS7Type, type))
self.assertEqual(PKCS7Type.__name__, 'PKCS7')
@@ -2258,7 +2347,7 @@ class PKCS7Tests(TestCase):
def test_type_is_signed_wrong_args(self):
"""
- L{PKCS7Type.type_is_signed} raises L{TypeError} if called with any
+ :py:obj:`PKCS7Type.type_is_signed` raises :py:obj:`TypeError` if called with any
arguments.
"""
pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
@@ -2267,8 +2356,8 @@ class PKCS7Tests(TestCase):
def test_type_is_signed(self):
"""
- L{PKCS7Type.type_is_signed} returns C{True} if the PKCS7 object is of
- the type I{signed}.
+ :py:obj:`PKCS7Type.type_is_signed` returns :py:obj:`True` if the PKCS7 object is of
+ the type *signed*.
"""
pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
self.assertTrue(pkcs7.type_is_signed())
@@ -2276,7 +2365,7 @@ class PKCS7Tests(TestCase):
def test_type_is_enveloped_wrong_args(self):
"""
- L{PKCS7Type.type_is_enveloped} raises L{TypeError} if called with any
+ :py:obj:`PKCS7Type.type_is_enveloped` raises :py:obj:`TypeError` if called with any
arguments.
"""
pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
@@ -2285,8 +2374,8 @@ class PKCS7Tests(TestCase):
def test_type_is_enveloped(self):
"""
- L{PKCS7Type.type_is_enveloped} returns C{False} if the PKCS7 object is
- not of the type I{enveloped}.
+ :py:obj:`PKCS7Type.type_is_enveloped` returns :py:obj:`False` if the PKCS7 object is
+ not of the type *enveloped*.
"""
pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
self.assertFalse(pkcs7.type_is_enveloped())
@@ -2294,7 +2383,7 @@ class PKCS7Tests(TestCase):
def test_type_is_signedAndEnveloped_wrong_args(self):
"""
- L{PKCS7Type.type_is_signedAndEnveloped} raises L{TypeError} if called
+ :py:obj:`PKCS7Type.type_is_signedAndEnveloped` raises :py:obj:`TypeError` if called
with any arguments.
"""
pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
@@ -2303,8 +2392,8 @@ class PKCS7Tests(TestCase):
def test_type_is_signedAndEnveloped(self):
"""
- L{PKCS7Type.type_is_signedAndEnveloped} returns C{False} if the PKCS7
- object is not of the type I{signed and enveloped}.
+ :py:obj:`PKCS7Type.type_is_signedAndEnveloped` returns :py:obj:`False` if the PKCS7
+ object is not of the type *signed and enveloped*.
"""
pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
self.assertFalse(pkcs7.type_is_signedAndEnveloped())
@@ -2312,7 +2401,7 @@ class PKCS7Tests(TestCase):
def test_type_is_data(self):
"""
- L{PKCS7Type.type_is_data} returns C{False} if the PKCS7 object is not of
+ :py:obj:`PKCS7Type.type_is_data` returns :py:obj:`False` if the PKCS7 object is not of
the type data.
"""
pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
@@ -2321,7 +2410,7 @@ class PKCS7Tests(TestCase):
def test_type_is_data_wrong_args(self):
"""
- L{PKCS7Type.type_is_data} raises L{TypeError} if called with any
+ :py:obj:`PKCS7Type.type_is_data` raises :py:obj:`TypeError` if called with any
arguments.
"""
pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
@@ -2330,7 +2419,7 @@ class PKCS7Tests(TestCase):
def test_get_type_name_wrong_args(self):
"""
- L{PKCS7Type.get_type_name} raises L{TypeError} if called with any
+ :py:obj:`PKCS7Type.get_type_name` raises :py:obj:`TypeError` if called with any
arguments.
"""
pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
@@ -2339,7 +2428,7 @@ class PKCS7Tests(TestCase):
def test_get_type_name(self):
"""
- L{PKCS7Type.get_type_name} returns a C{str} giving the type name.
+ :py:obj:`PKCS7Type.get_type_name` returns a :py:obj:`str` giving the type name.
"""
pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
self.assertEquals(pkcs7.get_type_name(), b('pkcs7-signedData'))
@@ -2348,7 +2437,7 @@ class PKCS7Tests(TestCase):
def test_attribute(self):
"""
If an attribute other than one of the methods tested here is accessed on
- an instance of L{PKCS7Type}, L{AttributeError} is raised.
+ an instance of :py:obj:`PKCS7Type`, :py:obj:`AttributeError` is raised.
"""
pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
self.assertRaises(AttributeError, getattr, pkcs7, "foo")
@@ -2357,18 +2446,18 @@ class PKCS7Tests(TestCase):
class NetscapeSPKITests(TestCase, _PKeyInteractionTestsMixin):
"""
- Tests for L{OpenSSL.crypto.NetscapeSPKI}.
+ Tests for :py:obj:`OpenSSL.crypto.NetscapeSPKI`.
"""
def signable(self):
"""
- Return a new L{NetscapeSPKI} for use with signing tests.
+ Return a new :py:obj:`NetscapeSPKI` for use with signing tests.
"""
return NetscapeSPKI()
def test_type(self):
"""
- L{NetscapeSPKI} and L{NetscapeSPKIType} refer to the same type object
+ :py:obj:`NetscapeSPKI` and :py:obj:`NetscapeSPKIType` refer to the same type object
and can be used to create instances of that type.
"""
self.assertIdentical(NetscapeSPKI, NetscapeSPKIType)
@@ -2377,7 +2466,7 @@ class NetscapeSPKITests(TestCase, _PKeyInteractionTestsMixin):
def test_construction(self):
"""
- L{NetscapeSPKI} returns an instance of L{NetscapeSPKIType}.
+ :py:obj:`NetscapeSPKI` returns an instance of :py:obj:`NetscapeSPKIType`.
"""
nspki = NetscapeSPKI()
self.assertTrue(isinstance(nspki, NetscapeSPKIType))
@@ -2385,8 +2474,8 @@ class NetscapeSPKITests(TestCase, _PKeyInteractionTestsMixin):
def test_invalid_attribute(self):
"""
- Accessing a non-existent attribute of a L{NetscapeSPKI} instance causes
- an L{AttributeError} to be raised.
+ Accessing a non-existent attribute of a :py:obj:`NetscapeSPKI` instance causes
+ an :py:obj:`AttributeError` to be raised.
"""
nspki = NetscapeSPKI()
self.assertRaises(AttributeError, lambda: nspki.foo)
@@ -2394,7 +2483,7 @@ class NetscapeSPKITests(TestCase, _PKeyInteractionTestsMixin):
def test_b64_encode(self):
"""
- L{NetscapeSPKI.b64_encode} encodes the certificate to a base64 blob.
+ :py:obj:`NetscapeSPKI.b64_encode` encodes the certificate to a base64 blob.
"""
nspki = NetscapeSPKI()
blob = nspki.b64_encode()
@@ -2404,11 +2493,11 @@ class NetscapeSPKITests(TestCase, _PKeyInteractionTestsMixin):
class RevokedTests(TestCase):
"""
- Tests for L{OpenSSL.crypto.Revoked}
+ Tests for :py:obj:`OpenSSL.crypto.Revoked`
"""
def test_construction(self):
"""
- Confirm we can create L{OpenSSL.crypto.Revoked}. Check
+ Confirm we can create :py:obj:`OpenSSL.crypto.Revoked`. Check
that it is empty.
"""
revoked = Revoked()
@@ -2421,8 +2510,8 @@ class RevokedTests(TestCase):
def test_construction_wrong_args(self):
"""
- Calling L{OpenSSL.crypto.Revoked} with any arguments results
- in a L{TypeError} being raised.
+ Calling :py:obj:`OpenSSL.crypto.Revoked` with any arguments results
+ in a :py:obj:`TypeError` being raised.
"""
self.assertRaises(TypeError, Revoked, None)
self.assertRaises(TypeError, Revoked, 1)
@@ -2432,7 +2521,7 @@ class RevokedTests(TestCase):
def test_serial(self):
"""
Confirm we can set and get serial numbers from
- L{OpenSSL.crypto.Revoked}. Confirm errors are handled
+ :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
with grace.
"""
revoked = Revoked()
@@ -2455,7 +2544,7 @@ class RevokedTests(TestCase):
def test_date(self):
"""
Confirm we can set and get revocation dates from
- L{OpenSSL.crypto.Revoked}. Confirm errors are handled
+ :py:obj:`OpenSSL.crypto.Revoked`. Confirm errors are handled
with grace.
"""
revoked = Revoked()
@@ -2472,7 +2561,7 @@ class RevokedTests(TestCase):
def test_reason(self):
"""
Confirm we can set and get revocation reasons from
- L{OpenSSL.crypto.Revoked}. The "get" need to work
+ :py:obj:`OpenSSL.crypto.Revoked`. The "get" need to work
as "set". Likewise, each reason of all_reasons() must work.
"""
revoked = Revoked()
@@ -2492,9 +2581,9 @@ class RevokedTests(TestCase):
def test_set_reason_wrong_arguments(self):
"""
- Calling L{OpenSSL.crypto.Revoked.set_reason} with other than
+ Calling :py:obj:`OpenSSL.crypto.Revoked.set_reason` with other than
one argument, or an argument which isn't a valid reason,
- results in L{TypeError} or L{ValueError} being raised.
+ results in :py:obj:`TypeError` or :py:obj:`ValueError` being raised.
"""
revoked = Revoked()
self.assertRaises(TypeError, revoked.set_reason, 100)
@@ -2503,8 +2592,8 @@ class RevokedTests(TestCase):
def test_get_reason_wrong_arguments(self):
"""
- Calling L{OpenSSL.crypto.Revoked.get_reason} with any
- arguments results in L{TypeError} being raised.
+ Calling :py:obj:`OpenSSL.crypto.Revoked.get_reason` with any
+ arguments results in :py:obj:`TypeError` being raised.
"""
revoked = Revoked()
self.assertRaises(TypeError, revoked.get_reason, None)
@@ -2515,14 +2604,14 @@ class RevokedTests(TestCase):
class CRLTests(TestCase):
"""
- Tests for L{OpenSSL.crypto.CRL}
+ Tests for :py:obj:`OpenSSL.crypto.CRL`
"""
cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
def test_construction(self):
"""
- Confirm we can create L{OpenSSL.crypto.CRL}. Check
+ Confirm we can create :py:obj:`OpenSSL.crypto.CRL`. Check
that it is empty
"""
crl = CRL()
@@ -2532,8 +2621,8 @@ class CRLTests(TestCase):
def test_construction_wrong_args(self):
"""
- Calling L{OpenSSL.crypto.CRL} with any number of arguments
- results in a L{TypeError} being raised.
+ Calling :py:obj:`OpenSSL.crypto.CRL` with any number of arguments
+ results in a :py:obj:`TypeError` being raised.
"""
self.assertRaises(TypeError, CRL, 1)
self.assertRaises(TypeError, CRL, "")
@@ -2573,10 +2662,19 @@ class CRLTests(TestCase):
self.assertEqual(text, dumped_text)
+ def test_export_invalid(self):
+ """
+ If :py:obj:`CRL.export` is used with an uninitialized :py:obj:`X509`
+ instance, :py:obj:`OpenSSL.crypto.Error` is raised.
+ """
+ crl = CRL()
+ self.assertRaises(Error, crl.export, X509(), PKey())
+
+
def test_add_revoked_keyword(self):
"""
- L{OpenSSL.CRL.add_revoked} accepts its single argument as the
- I{revoked} keyword argument.
+ :py:obj:`OpenSSL.CRL.add_revoked` accepts its single argument as the
+ ``revoked`` keyword argument.
"""
crl = CRL()
revoked = Revoked()
@@ -2586,10 +2684,10 @@ class CRLTests(TestCase):
def test_export_wrong_args(self):
"""
- Calling L{OpenSSL.CRL.export} with fewer than two or more than
+ Calling :py:obj:`OpenSSL.CRL.export` with fewer than two or more than
four arguments, or with arguments other than the certificate,
private key, integer file type, and integer number of days it
- expects, results in a L{TypeError} being raised.
+ expects, results in a :py:obj:`TypeError` being raised.
"""
crl = CRL()
self.assertRaises(TypeError, crl.export)
@@ -2604,9 +2702,9 @@ class CRLTests(TestCase):
def test_export_unknown_filetype(self):
"""
- Calling L{OpenSSL.CRL.export} with a file type other than
- L{FILETYPE_PEM}, L{FILETYPE_ASN1}, or L{FILETYPE_TEXT} results
- in a L{ValueError} being raised.
+ Calling :py:obj:`OpenSSL.CRL.export` with a file type other than
+ :py:obj:`FILETYPE_PEM`, :py:obj:`FILETYPE_ASN1`, or :py:obj:`FILETYPE_TEXT` results
+ in a :py:obj:`ValueError` being raised.
"""
crl = CRL()
self.assertRaises(ValueError, crl.export, self.cert, self.pkey, 100, 10)
@@ -2615,7 +2713,7 @@ class CRLTests(TestCase):
def test_get_revoked(self):
"""
Use python to create a simple CRL with two revocations.
- Get back the L{Revoked} using L{OpenSSL.CRL.get_revoked} and
+ Get back the :py:obj:`Revoked` using :py:obj:`OpenSSL.CRL.get_revoked` and
verify them.
"""
crl = CRL()
@@ -2641,8 +2739,8 @@ class CRLTests(TestCase):
def test_get_revoked_wrong_args(self):
"""
- Calling L{OpenSSL.CRL.get_revoked} with any arguments results
- in a L{TypeError} being raised.
+ Calling :py:obj:`OpenSSL.CRL.get_revoked` with any arguments results
+ in a :py:obj:`TypeError` being raised.
"""
crl = CRL()
self.assertRaises(TypeError, crl.get_revoked, None)
@@ -2653,8 +2751,8 @@ class CRLTests(TestCase):
def test_add_revoked_wrong_args(self):
"""
- Calling L{OpenSSL.CRL.add_revoked} with other than one
- argument results in a L{TypeError} being raised.
+ Calling :py:obj:`OpenSSL.CRL.add_revoked` with other than one
+ argument results in a :py:obj:`TypeError` being raised.
"""
crl = CRL()
self.assertRaises(TypeError, crl.add_revoked)
@@ -2687,8 +2785,8 @@ class CRLTests(TestCase):
def test_load_crl_wrong_args(self):
"""
- Calling L{OpenSSL.crypto.load_crl} with other than two
- arguments results in a L{TypeError} being raised.
+ Calling :py:obj:`OpenSSL.crypto.load_crl` with other than two
+ arguments results in a :py:obj:`TypeError` being raised.
"""
self.assertRaises(TypeError, load_crl)
self.assertRaises(TypeError, load_crl, FILETYPE_PEM)
@@ -2697,27 +2795,27 @@ class CRLTests(TestCase):
def test_load_crl_bad_filetype(self):
"""
- Calling L{OpenSSL.crypto.load_crl} with an unknown file type
- raises a L{ValueError}.
+ Calling :py:obj:`OpenSSL.crypto.load_crl` with an unknown file type
+ raises a :py:obj:`ValueError`.
"""
self.assertRaises(ValueError, load_crl, 100, crlData)
def test_load_crl_bad_data(self):
"""
- Calling L{OpenSSL.crypto.load_crl} with file data which can't
- be loaded raises a L{OpenSSL.crypto.Error}.
+ Calling :py:obj:`OpenSSL.crypto.load_crl` with file data which can't
+ be loaded raises a :py:obj:`OpenSSL.crypto.Error`.
"""
self.assertRaises(Error, load_crl, FILETYPE_PEM, "hello, world")
class SignVerifyTests(TestCase):
"""
- Tests for L{OpenSSL.crypto.sign} and L{OpenSSL.crypto.verify}.
+ Tests for :py:obj:`OpenSSL.crypto.sign` and :py:obj:`OpenSSL.crypto.verify`.
"""
def test_sign_verify(self):
"""
- L{sign} generates a cryptographic signature which L{verify} can check.
+ :py:obj:`sign` generates a cryptographic signature which :py:obj:`verify` can check.
"""
content = b(
"It was a bright cold day in April, and the clocks were striking "
@@ -2758,7 +2856,7 @@ class SignVerifyTests(TestCase):
def test_sign_nulls(self):
"""
- L{sign} produces a signature for a string with embedded nulls.
+ :py:obj:`sign` produces a signature for a string with embedded nulls.
"""
content = b("Watch out! \0 Did you see it?")
priv_key = load_privatekey(FILETYPE_PEM, root_key_pem)
diff --git a/OpenSSL/test/test_rand.py b/OpenSSL/test/test_rand.py
index 00fc6d1..8a3c5fe 100644
--- a/OpenSSL/test/test_rand.py
+++ b/OpenSSL/test/test_rand.py
@@ -2,7 +2,7 @@
# See LICENSE for details.
"""
-Unit tests for L{OpenSSL.rand}.
+Unit tests for :py:obj:`OpenSSL.rand`.
"""
from unittest import main
@@ -16,8 +16,8 @@ from OpenSSL import rand
class RandTests(TestCase):
def test_bytes_wrong_args(self):
"""
- L{OpenSSL.rand.bytes} raises L{TypeError} if called with the wrong
- number of arguments or with a non-C{int} argument.
+ :py:obj:`OpenSSL.rand.bytes` raises :py:obj:`TypeError` if called with the wrong
+ number of arguments or with a non-:py:obj:`int` argument.
"""
self.assertRaises(TypeError, rand.bytes)
self.assertRaises(TypeError, rand.bytes, None)
@@ -44,7 +44,7 @@ class RandTests(TestCase):
def test_add_wrong_args(self):
"""
When called with the wrong number of arguments, or with arguments not of
- type C{str} and C{int}, L{OpenSSL.rand.add} raises L{TypeError}.
+ type :py:obj:`str` and :py:obj:`int`, :py:obj:`OpenSSL.rand.add` raises :py:obj:`TypeError`.
"""
self.assertRaises(TypeError, rand.add)
self.assertRaises(TypeError, rand.add, b("foo"), None)
@@ -54,15 +54,15 @@ class RandTests(TestCase):
def test_add(self):
"""
- L{OpenSSL.rand.add} adds entropy to the PRNG.
+ :py:obj:`OpenSSL.rand.add` adds entropy to the PRNG.
"""
rand.add(b('hamburger'), 3)
def test_seed_wrong_args(self):
"""
- When called with the wrong number of arguments, or with a non-C{str}
- argument, L{OpenSSL.rand.seed} raises L{TypeError}.
+ When called with the wrong number of arguments, or with a non-:py:obj:`str`
+ argument, :py:obj:`OpenSSL.rand.seed` raises :py:obj:`TypeError`.
"""
self.assertRaises(TypeError, rand.seed)
self.assertRaises(TypeError, rand.seed, None)
@@ -71,14 +71,14 @@ class RandTests(TestCase):
def test_seed(self):
"""
- L{OpenSSL.rand.seed} adds entropy to the PRNG.
+ :py:obj:`OpenSSL.rand.seed` adds entropy to the PRNG.
"""
rand.seed(b('milk shake'))
def test_status_wrong_args(self):
"""
- L{OpenSSL.rand.status} raises L{TypeError} when called with any
+ :py:obj:`OpenSSL.rand.status` raises :py:obj:`TypeError` when called with any
arguments.
"""
self.assertRaises(TypeError, rand.status, None)
@@ -86,8 +86,8 @@ class RandTests(TestCase):
def test_status(self):
"""
- L{OpenSSL.rand.status} returns C{True} if the PRNG has sufficient
- entropy, C{False} otherwise.
+ :py:obj:`OpenSSL.rand.status` returns :py:obj:`True` if the PRNG has sufficient
+ entropy, :py:obj:`False` otherwise.
"""
# It's hard to know what it is actually going to return. Different
# OpenSSL random engines decide differently whether they have enough
@@ -97,8 +97,8 @@ class RandTests(TestCase):
def test_egd_wrong_args(self):
"""
- L{OpenSSL.rand.egd} raises L{TypeError} when called with the wrong
- number of arguments or with arguments not of type C{str} and C{int}.
+ :py:obj:`OpenSSL.rand.egd` raises :py:obj:`TypeError` when called with the wrong
+ number of arguments or with arguments not of type :py:obj:`str` and :py:obj:`int`.
"""
self.assertRaises(TypeError, rand.egd)
self.assertRaises(TypeError, rand.egd, None)
@@ -109,8 +109,8 @@ class RandTests(TestCase):
def test_egd_missing(self):
"""
- L{OpenSSL.rand.egd} returns C{0} or C{-1} if the EGD socket passed
- to it does not exist.
+ :py:obj:`OpenSSL.rand.egd` returns :py:obj:`0` or :py:obj:`-1` if the
+ EGD socket passed to it does not exist.
"""
result = rand.egd(self.mktemp())
expected = (-1, 0)
@@ -121,7 +121,7 @@ class RandTests(TestCase):
def test_cleanup_wrong_args(self):
"""
- L{OpenSSL.rand.cleanup} raises L{TypeError} when called with any
+ :py:obj:`OpenSSL.rand.cleanup` raises :py:obj:`TypeError` when called with any
arguments.
"""
self.assertRaises(TypeError, rand.cleanup, None)
@@ -129,16 +129,16 @@ class RandTests(TestCase):
def test_cleanup(self):
"""
- L{OpenSSL.rand.cleanup} releases the memory used by the PRNG and returns
- C{None}.
+ :py:obj:`OpenSSL.rand.cleanup` releases the memory used by the PRNG and returns
+ :py:obj:`None`.
"""
self.assertIdentical(rand.cleanup(), None)
def test_load_file_wrong_args(self):
"""
- L{OpenSSL.rand.load_file} raises L{TypeError} when called the wrong
- number of arguments or arguments not of type C{str} and C{int}.
+ :py:obj:`OpenSSL.rand.load_file` raises :py:obj:`TypeError` when called the wrong
+ number of arguments or arguments not of type :py:obj:`str` and :py:obj:`int`.
"""
self.assertRaises(TypeError, rand.load_file)
self.assertRaises(TypeError, rand.load_file, "foo", None)
@@ -148,8 +148,8 @@ class RandTests(TestCase):
def test_write_file_wrong_args(self):
"""
- L{OpenSSL.rand.write_file} raises L{TypeError} when called with the
- wrong number of arguments or a non-C{str} argument.
+ :py:obj:`OpenSSL.rand.write_file` raises :py:obj:`TypeError` when called with the
+ wrong number of arguments or a non-:py:obj:`str` argument.
"""
self.assertRaises(TypeError, rand.write_file)
self.assertRaises(TypeError, rand.write_file, None)
diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py
index 2ab67fd..3e4e3da 100644
--- a/OpenSSL/test/test_ssl.py
+++ b/OpenSSL/test/test_ssl.py
@@ -2,7 +2,7 @@
# See LICENSE for details.
"""
-Unit tests for L{OpenSSL.SSL}.
+Unit tests for :py:obj:`OpenSSL.SSL`.
"""
from gc import collect
@@ -10,7 +10,7 @@ from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK
from sys import platform, version_info
from socket import error, socket
from os import makedirs
-from os.path import join
+from os.path import join, dirname
from unittest import main
from weakref import ref
@@ -26,9 +26,16 @@ from OpenSSL.SSL import SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD
from OpenSSL.SSL import OP_NO_SSLv2, OP_NO_SSLv3, OP_SINGLE_DH_USE
from OpenSSL.SSL import (
VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
+
+from OpenSSL.SSL import (
+ SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
+ SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
+ SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
+
from OpenSSL.SSL import (
Error, SysCallError, WantReadError, ZeroReturnError, SSLeay_version)
-from OpenSSL.SSL import Context, ContextType, Connection, ConnectionType
+from OpenSSL.SSL import (
+ Context, ContextType, Session, Connection, ConnectionType)
from OpenSSL.test.util import TestCase, bytes, b
from OpenSSL.test.test_crypto import (
@@ -50,6 +57,16 @@ try:
except ImportError:
OP_NO_TICKET = None
+try:
+ from OpenSSL.SSL import OP_NO_COMPRESSION
+except ImportError:
+ OP_NO_COMPRESSION = None
+
+try:
+ from OpenSSL.SSL import MODE_RELEASE_BUFFERS
+except ImportError:
+ MODE_RELEASE_BUFFERS = None
+
from OpenSSL.SSL import (
SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
SSL_ST_OK, SSL_ST_RENEGOTIATE,
@@ -172,16 +189,30 @@ class _LoopbackMixin:
Helper mixin which defines methods for creating a connected socket pair and
for forcing two connected SSL sockets to talk to each other via memory BIOs.
"""
- def _loopback(self):
- (server, client) = socket_pair()
+ def _loopbackClientFactory(self, socket):
+ client = Connection(Context(TLSv1_METHOD), socket)
+ client.set_connect_state()
+ return client
+
+ def _loopbackServerFactory(self, socket):
ctx = Context(TLSv1_METHOD)
ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
- server = Connection(ctx, server)
+ server = Connection(ctx, socket)
server.set_accept_state()
- client = Connection(Context(TLSv1_METHOD), client)
- client.set_connect_state()
+ return server
+
+
+ def _loopback(self, serverFactory=None, clientFactory=None):
+ if serverFactory is None:
+ serverFactory = self._loopbackServerFactory
+ if clientFactory is None:
+ clientFactory = self._loopbackClientFactory
+
+ (server, client) = socket_pair()
+ server = serverFactory(server)
+ client = clientFactory(client)
handshake(client, server)
@@ -192,10 +223,10 @@ class _LoopbackMixin:
def _interactInMemory(self, client_conn, server_conn):
"""
- Try to read application bytes from each of the two L{Connection}
+ Try to read application bytes from each of the two :py:obj:`Connection`
objects. Copy bytes back and forth between their send/receive buffers
for as long as there is anything to copy. When there is nothing more
- to copy, return C{None}. If one of them actually manages to deliver
+ to copy, return :py:obj:`None`. If one of them actually manages to deliver
some application bytes, return a two-tuple of the connection from which
the bytes were read and the bytes themselves.
"""
@@ -241,12 +272,12 @@ class _LoopbackMixin:
class VersionTests(TestCase):
"""
Tests for version information exposed by
- L{OpenSSL.SSL.SSLeay_version} and
- L{OpenSSL.SSL.OPENSSL_VERSION_NUMBER}.
+ :py:obj:`OpenSSL.SSL.SSLeay_version` and
+ :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
"""
def test_OPENSSL_VERSION_NUMBER(self):
"""
- L{OPENSSL_VERSION_NUMBER} is an integer with status in the low
+ :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
byte and the patch, fix, minor, and major versions in the
nibbles above that.
"""
@@ -255,7 +286,7 @@ class VersionTests(TestCase):
def test_SSLeay_version(self):
"""
- L{SSLeay_version} takes a version type indicator and returns
+ :py:obj:`SSLeay_version` takes a version type indicator and returns
one of a number of version strings based on that indicator.
"""
versions = {}
@@ -270,19 +301,19 @@ class VersionTests(TestCase):
class ContextTests(TestCase, _LoopbackMixin):
"""
- Unit tests for L{OpenSSL.SSL.Context}.
+ Unit tests for :py:obj:`OpenSSL.SSL.Context`.
"""
def test_method(self):
"""
- L{Context} can be instantiated with one of L{SSLv2_METHOD},
- L{SSLv3_METHOD}, L{SSLv23_METHOD}, or L{TLSv1_METHOD}.
+ :py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
+ :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, or :py:obj:`TLSv1_METHOD`.
"""
for meth in [SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]:
Context(meth)
try:
Context(SSLv2_METHOD)
- except ValueError:
+ except (Error, ValueError):
# Some versions of OpenSSL have SSLv2, some don't.
# Difficult to say in advance.
pass
@@ -293,7 +324,7 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_type(self):
"""
- L{Context} and L{ContextType} refer to the same type object and can be
+ :py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
used to create instances of that type.
"""
self.assertIdentical(Context, ContextType)
@@ -302,7 +333,7 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_use_privatekey(self):
"""
- L{Context.use_privatekey} takes an L{OpenSSL.crypto.PKey} instance.
+ :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey` instance.
"""
key = PKey()
key.generate_key(TYPE_RSA, 128)
@@ -313,7 +344,7 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_set_app_data_wrong_args(self):
"""
- L{Context.set_app_data} raises L{TypeError} if called with other than
+ :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
one argument.
"""
context = Context(TLSv1_METHOD)
@@ -323,7 +354,7 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_get_app_data_wrong_args(self):
"""
- L{Context.get_app_data} raises L{TypeError} if called with any
+ :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called with any
arguments.
"""
context = Context(TLSv1_METHOD)
@@ -332,8 +363,8 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_app_data(self):
"""
- L{Context.set_app_data} stores an object for later retrieval using
- L{Context.get_app_data}.
+ :py:obj:`Context.set_app_data` stores an object for later retrieval using
+ :py:obj:`Context.get_app_data`.
"""
app_data = object()
context = Context(TLSv1_METHOD)
@@ -343,8 +374,8 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_set_options_wrong_args(self):
"""
- L{Context.set_options} raises L{TypeError} if called with the wrong
- number of arguments or a non-C{int} argument.
+ :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with the wrong
+ number of arguments or a non-:py:obj:`int` argument.
"""
context = Context(TLSv1_METHOD)
self.assertRaises(TypeError, context.set_options)
@@ -352,10 +383,34 @@ class ContextTests(TestCase, _LoopbackMixin):
self.assertRaises(TypeError, context.set_options, 1, None)
+ def test_set_mode_wrong_args(self):
+ """
+ :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
+ number of arguments or a non-:py:obj:`int` argument.
+ """
+ context = Context(TLSv1_METHOD)
+ self.assertRaises(TypeError, context.set_mode)
+ self.assertRaises(TypeError, context.set_mode, None)
+ self.assertRaises(TypeError, context.set_mode, 1, None)
+
+
+ if MODE_RELEASE_BUFFERS is not None:
+ def test_set_mode(self):
+ """
+ :py:obj:`Context.set_mode` accepts a mode bitvector and returns the newly
+ set mode.
+ """
+ context = Context(TLSv1_METHOD)
+ self.assertTrue(
+ MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
+ else:
+ "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
+
+
def test_set_timeout_wrong_args(self):
"""
- L{Context.set_timeout} raises L{TypeError} if called with the wrong
- number of arguments or a non-C{int} argument.
+ :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with the wrong
+ number of arguments or a non-:py:obj:`int` argument.
"""
context = Context(TLSv1_METHOD)
self.assertRaises(TypeError, context.set_timeout)
@@ -365,7 +420,7 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_get_timeout_wrong_args(self):
"""
- L{Context.get_timeout} raises L{TypeError} if called with any arguments.
+ :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with any arguments.
"""
context = Context(TLSv1_METHOD)
self.assertRaises(TypeError, context.get_timeout, None)
@@ -373,8 +428,8 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_timeout(self):
"""
- L{Context.set_timeout} sets the session timeout for all connections
- created using the context object. L{Context.get_timeout} retrieves this
+ :py:obj:`Context.set_timeout` sets the session timeout for all connections
+ created using the context object. :py:obj:`Context.get_timeout` retrieves this
value.
"""
context = Context(TLSv1_METHOD)
@@ -384,8 +439,8 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_set_verify_depth_wrong_args(self):
"""
- L{Context.set_verify_depth} raises L{TypeError} if called with the wrong
- number of arguments or a non-C{int} argument.
+ :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
+ number of arguments or a non-:py:obj:`int` argument.
"""
context = Context(TLSv1_METHOD)
self.assertRaises(TypeError, context.set_verify_depth)
@@ -395,7 +450,7 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_get_verify_depth_wrong_args(self):
"""
- L{Context.get_verify_depth} raises L{TypeError} if called with any arguments.
+ :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called with any arguments.
"""
context = Context(TLSv1_METHOD)
self.assertRaises(TypeError, context.get_verify_depth, None)
@@ -403,9 +458,9 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_verify_depth(self):
"""
- L{Context.set_verify_depth} sets the number of certificates in a chain
+ :py:obj:`Context.set_verify_depth` sets the number of certificates in a chain
to follow before giving up. The value can be retrieved with
- L{Context.get_verify_depth}.
+ :py:obj:`Context.get_verify_depth`.
"""
context = Context(TLSv1_METHOD)
context.set_verify_depth(11)
@@ -429,7 +484,7 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_set_passwd_cb_wrong_args(self):
"""
- L{Context.set_passwd_cb} raises L{TypeError} if called with the
+ :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called with the
wrong arguments or with a non-callable first argument.
"""
context = Context(TLSv1_METHOD)
@@ -440,7 +495,7 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_set_passwd_cb(self):
"""
- L{Context.set_passwd_cb} accepts a callable which will be invoked when
+ :py:obj:`Context.set_passwd_cb` accepts a callable which will be invoked when
a private key is loaded from an encrypted PEM.
"""
passphrase = b("foobar")
@@ -460,7 +515,7 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_passwd_callback_exception(self):
"""
- L{Context.use_privatekey_file} propagates any exception raised by the
+ :py:obj:`Context.use_privatekey_file` propagates any exception raised by the
passphrase callback.
"""
pemFile = self._write_encrypted_pem(b("monkeys are nice"))
@@ -474,7 +529,7 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_passwd_callback_false(self):
"""
- L{Context.use_privatekey_file} raises L{OpenSSL.SSL.Error} if the
+ :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
passphrase callback returns a false value.
"""
pemFile = self._write_encrypted_pem(b("monkeys are nice"))
@@ -488,7 +543,7 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_passwd_callback_non_string(self):
"""
- L{Context.use_privatekey_file} raises L{OpenSSL.SSL.Error} if the
+ :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
passphrase callback returns a true non-string value.
"""
pemFile = self._write_encrypted_pem(b("monkeys are nice"))
@@ -521,7 +576,7 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_set_info_callback(self):
"""
- L{Context.set_info_callback} accepts a callable which will be invoked
+ :py:obj:`Context.set_info_callback` accepts a callable which will be invoked
when certain information about an SSL connection is available.
"""
(server, client) = socket_pair()
@@ -556,8 +611,8 @@ class ContextTests(TestCase, _LoopbackMixin):
def _load_verify_locations_test(self, *args):
"""
Create a client context which will verify the peer certificate and call
- its C{load_verify_locations} method with C{*args}. Then connect it to a
- server and ensure that the handshake succeeds.
+ its :py:obj:`load_verify_locations` method with the given arguments.
+ Then connect it to a server and ensure that the handshake succeeds.
"""
(server, client) = socket_pair()
@@ -593,7 +648,7 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_load_verify_file(self):
"""
- L{Context.load_verify_locations} accepts a file name and uses the
+ :py:obj:`Context.load_verify_locations` accepts a file name and uses the
certificates within for verification purposes.
"""
cafile = self.mktemp()
@@ -606,7 +661,7 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_load_verify_invalid_file(self):
"""
- L{Context.load_verify_locations} raises L{Error} when passed a
+ :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
non-existent cafile.
"""
clientContext = Context(TLSv1_METHOD)
@@ -616,7 +671,7 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_load_verify_directory(self):
"""
- L{Context.load_verify_locations} accepts a directory name and uses
+ :py:obj:`Context.load_verify_locations` accepts a directory name and uses
the certificates within for verification purposes.
"""
capath = self.mktemp()
@@ -635,8 +690,8 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_load_verify_locations_wrong_args(self):
"""
- L{Context.load_verify_locations} raises L{TypeError} if called with
- the wrong number of arguments or with non-C{str} arguments.
+ :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
+ the wrong number of arguments or with non-:py:obj:`str` arguments.
"""
context = Context(TLSv1_METHOD)
self.assertRaises(TypeError, context.load_verify_locations)
@@ -651,7 +706,7 @@ class ContextTests(TestCase, _LoopbackMixin):
else:
def test_set_default_verify_paths(self):
"""
- L{Context.set_default_verify_paths} causes the platform-specific CA
+ :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
certificate locations to be used for verification purposes.
"""
# Testing this requires a server with a certificate signed by one of
@@ -680,8 +735,8 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_set_default_verify_paths_signature(self):
"""
- L{Context.set_default_verify_paths} takes no arguments and raises
- L{TypeError} if given any.
+ :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
+ :py:obj:`TypeError` if given any.
"""
context = Context(TLSv1_METHOD)
self.assertRaises(TypeError, context.set_default_verify_paths, None)
@@ -691,9 +746,9 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_add_extra_chain_cert_invalid_cert(self):
"""
- L{Context.add_extra_chain_cert} raises L{TypeError} if called with
+ :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
other than one argument or if called with an object which is not an
- instance of L{X509}.
+ instance of :py:obj:`X509`.
"""
context = Context(TLSv1_METHOD)
self.assertRaises(TypeError, context.add_extra_chain_cert)
@@ -726,10 +781,10 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_add_extra_chain_cert(self):
"""
- L{Context.add_extra_chain_cert} accepts an L{X509} instance to add to
+ :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509` instance to add to
the certificate chain.
- See L{_create_certificate_chain} for the details of the certificate
+ See :py:obj:`_create_certificate_chain` for the details of the certificate
chain tested.
The chain is tested by starting a server with scert and connecting
@@ -770,7 +825,7 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_use_certificate_chain_file(self):
"""
- L{Context.use_certificate_chain_file} reads a certificate chain from
+ :py:obj:`Context.use_certificate_chain_file` reads a certificate chain from
the specified file.
The chain is tested by starting a server with scert and connecting
@@ -809,7 +864,7 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_get_verify_mode_wrong_args(self):
"""
- L{Context.get_verify_mode} raises L{TypeError} if called with any
+ :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
arguments.
"""
context = Context(TLSv1_METHOD)
@@ -818,8 +873,8 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_get_verify_mode(self):
"""
- L{Context.get_verify_mode} returns the verify mode flags previously
- passed to L{Context.set_verify}.
+ :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
+ passed to :py:obj:`Context.set_verify`.
"""
context = Context(TLSv1_METHOD)
self.assertEquals(context.get_verify_mode(), 0)
@@ -831,8 +886,8 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_load_tmp_dh_wrong_args(self):
"""
- L{Context.load_tmp_dh} raises L{TypeError} if called with the wrong
- number of arguments or with a non-C{str} argument.
+ :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
+ number of arguments or with a non-:py:obj:`str` argument.
"""
context = Context(TLSv1_METHOD)
self.assertRaises(TypeError, context.load_tmp_dh)
@@ -842,7 +897,7 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_load_tmp_dh_missing_file(self):
"""
- L{Context.load_tmp_dh} raises L{OpenSSL.SSL.Error} if the specified file
+ :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
does not exist.
"""
context = Context(TLSv1_METHOD)
@@ -851,7 +906,7 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_load_tmp_dh(self):
"""
- L{Context.load_tmp_dh} loads Diffie-Hellman parameters from the
+ :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
specified file.
"""
context = Context(TLSv1_METHOD)
@@ -865,7 +920,7 @@ class ContextTests(TestCase, _LoopbackMixin):
def test_set_cipher_list(self):
"""
- L{Context.set_cipher_list} accepts a C{str} naming the ciphers which
+ :py:obj:`Context.set_cipher_list` accepts a :py:obj:`str` naming the ciphers which
connections created with the context object will be able to choose from.
"""
context = Context(TLSv1_METHOD)
@@ -874,15 +929,46 @@ class ContextTests(TestCase, _LoopbackMixin):
self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
+ def test_set_session_cache_mode_wrong_args(self):
+ """
+ L{Context.set_session_cache_mode} raises L{TypeError} if called with
+ other than one integer argument.
+ """
+ context = Context(TLSv1_METHOD)
+ self.assertRaises(TypeError, context.set_session_cache_mode)
+ self.assertRaises(TypeError, context.set_session_cache_mode, object())
+
+
+ def test_get_session_cache_mode_wrong_args(self):
+ """
+ L{Context.get_session_cache_mode} raises L{TypeError} if called with any
+ arguments.
+ """
+ context = Context(TLSv1_METHOD)
+ self.assertRaises(TypeError, context.get_session_cache_mode, 1)
+
+
+ def test_session_cache_mode(self):
+ """
+ L{Context.set_session_cache_mode} specifies how sessions are cached.
+ The setting can be retrieved via L{Context.get_session_cache_mode}.
+ """
+ context = Context(TLSv1_METHOD)
+ old = context.set_session_cache_mode(SESS_CACHE_OFF)
+ off = context.set_session_cache_mode(SESS_CACHE_BOTH)
+ self.assertEqual(SESS_CACHE_OFF, off)
+ self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
+
+
class ServerNameCallbackTests(TestCase, _LoopbackMixin):
"""
- Tests for L{Context.set_tlsext_servername_callback} and its interaction with
- L{Connection}.
+ Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
+ :py:obj:`Connection`.
"""
def test_wrong_args(self):
"""
- L{Context.set_tlsext_servername_callback} raises L{TypeError} if called
+ :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
with other than one argument.
"""
context = Context(TLSv1_METHOD)
@@ -892,7 +978,7 @@ class ServerNameCallbackTests(TestCase, _LoopbackMixin):
def test_old_callback_forgotten(self):
"""
- If L{Context.set_tlsext_servername_callback} is used to specify a new
+ If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
callback, the one it replaces is dereferenced.
"""
def callback(connection):
@@ -915,8 +1001,8 @@ class ServerNameCallbackTests(TestCase, _LoopbackMixin):
def test_no_servername(self):
"""
When a client specifies no server name, the callback passed to
- L{Context.set_tlsext_servername_callback} is invoked and the result of
- L{Connection.get_servername} is C{None}.
+ :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
+ :py:obj:`Connection.get_servername` is :py:obj:`None`.
"""
args = []
def servername(conn):
@@ -948,8 +1034,8 @@ class ServerNameCallbackTests(TestCase, _LoopbackMixin):
def test_servername(self):
"""
When a client specifies a server name in its hello message, the callback
- passed to L{Contexts.set_tlsext_servername_callback} is invoked and the
- result of L{Connection.get_servername} is that server name.
+ passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
+ result of :py:obj:`Connection.get_servername` is that server name.
"""
args = []
def servername(conn):
@@ -975,9 +1061,33 @@ class ServerNameCallbackTests(TestCase, _LoopbackMixin):
+class SessionTests(TestCase):
+ """
+ Unit tests for :py:obj:`OpenSSL.SSL.Session`.
+ """
+ def test_construction(self):
+ """
+ :py:class:`Session` can be constructed with no arguments, creating a new
+ instance of that type.
+ """
+ new_session = Session()
+ self.assertTrue(isinstance(new_session, Session))
+
+
+ def test_construction_wrong_args(self):
+ """
+ If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
+ is raised.
+ """
+ self.assertRaises(TypeError, Session, 123)
+ self.assertRaises(TypeError, Session, "hello")
+ self.assertRaises(TypeError, Session, object())
+
+
+
class ConnectionTests(TestCase, _LoopbackMixin):
"""
- Unit tests for L{OpenSSL.SSL.Connection}.
+ Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
"""
# XXX want_write
# XXX want_read
@@ -999,7 +1109,7 @@ class ConnectionTests(TestCase, _LoopbackMixin):
def test_type(self):
"""
- L{Connection} and L{ConnectionType} refer to the same type object and
+ :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
can be used to create instances of that type.
"""
self.assertIdentical(Connection, ConnectionType)
@@ -1009,8 +1119,8 @@ class ConnectionTests(TestCase, _LoopbackMixin):
def test_get_context(self):
"""
- L{Connection.get_context} returns the L{Context} instance used to
- construct the L{Connection} instance.
+ :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
+ construct the :py:obj:`Connection` instance.
"""
context = Context(TLSv1_METHOD)
connection = Connection(context, None)
@@ -1019,7 +1129,7 @@ class ConnectionTests(TestCase, _LoopbackMixin):
def test_get_context_wrong_args(self):
"""
- L{Connection.get_context} raises L{TypeError} if called with any
+ :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
arguments.
"""
connection = Connection(Context(TLSv1_METHOD), None)
@@ -1028,8 +1138,8 @@ class ConnectionTests(TestCase, _LoopbackMixin):
def test_set_context_wrong_args(self):
"""
- L{Connection.set_context} raises L{TypeError} if called with a
- non-L{Context} instance argument or with any number of arguments other
+ :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
+ non-:py:obj:`Context` instance argument or with any number of arguments other
than 1.
"""
ctx = Context(TLSv1_METHOD)
@@ -1046,7 +1156,7 @@ class ConnectionTests(TestCase, _LoopbackMixin):
def test_set_context(self):
"""
- L{Connection.set_context} specifies a new L{Context} instance to be used
+ :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
for the connection.
"""
original = Context(SSLv23_METHOD)
@@ -1062,9 +1172,9 @@ class ConnectionTests(TestCase, _LoopbackMixin):
def test_set_tlsext_host_name_wrong_args(self):
"""
- If L{Connection.set_tlsext_host_name} is called with a non-byte string
+ If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
argument or a byte string with an embedded NUL or other than one
- argument, L{TypeError} is raised.
+ argument, :py:obj:`TypeError` is raised.
"""
conn = Connection(Context(TLSv1_METHOD), None)
self.assertRaises(TypeError, conn.set_tlsext_host_name)
@@ -1082,7 +1192,7 @@ class ConnectionTests(TestCase, _LoopbackMixin):
def test_get_servername_wrong_args(self):
"""
- L{Connection.get_servername} raises L{TypeError} if called with any
+ :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
arguments.
"""
connection = Connection(Context(TLSv1_METHOD), None)
@@ -1093,7 +1203,7 @@ class ConnectionTests(TestCase, _LoopbackMixin):
def test_pending(self):
"""
- L{Connection.pending} returns the number of bytes available for
+ :py:obj:`Connection.pending` returns the number of bytes available for
immediate read.
"""
connection = Connection(Context(TLSv1_METHOD), None)
@@ -1102,7 +1212,7 @@ class ConnectionTests(TestCase, _LoopbackMixin):
def test_pending_wrong_args(self):
"""
- L{Connection.pending} raises L{TypeError} if called with any arguments.
+ :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
"""
connection = Connection(Context(TLSv1_METHOD), None)
self.assertRaises(TypeError, connection.pending, None)
@@ -1110,7 +1220,7 @@ class ConnectionTests(TestCase, _LoopbackMixin):
def test_connect_wrong_args(self):
"""
- L{Connection.connect} raises L{TypeError} if called with a non-address
+ :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
argument or with the wrong number of arguments.
"""
connection = Connection(Context(TLSv1_METHOD), socket())
@@ -1121,7 +1231,7 @@ class ConnectionTests(TestCase, _LoopbackMixin):
def test_connect_refused(self):
"""
- L{Connection.connect} raises L{socket.error} if the underlying socket
+ :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
connect method raises it.
"""
client = socket()
@@ -1133,7 +1243,7 @@ class ConnectionTests(TestCase, _LoopbackMixin):
def test_connect(self):
"""
- L{Connection.connect} establishes a connection to the specified address.
+ :py:obj:`Connection.connect` establishes a connection to the specified address.
"""
port = socket()
port.bind(('', 0))
@@ -1149,7 +1259,7 @@ class ConnectionTests(TestCase, _LoopbackMixin):
else:
def test_connect_ex(self):
"""
- If there is a connection error, L{Connection.connect_ex} returns the
+ If there is a connection error, :py:obj:`Connection.connect_ex` returns the
errno instead of raising an exception.
"""
port = socket()
@@ -1166,7 +1276,7 @@ class ConnectionTests(TestCase, _LoopbackMixin):
def test_accept_wrong_args(self):
"""
- L{Connection.accept} raises L{TypeError} if called with any arguments.
+ :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
"""
connection = Connection(Context(TLSv1_METHOD), socket())
self.assertRaises(TypeError, connection.accept, None)
@@ -1174,8 +1284,8 @@ class ConnectionTests(TestCase, _LoopbackMixin):
def test_accept(self):
"""
- L{Connection.accept} accepts a pending connection attempt and returns a
- tuple of a new L{Connection} (the accepted client) and the address the
+ :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
+ tuple of a new :py:obj:`Connection` (the accepted client) and the address the
connection originated from.
"""
ctx = Context(TLSv1_METHOD)
@@ -1201,7 +1311,7 @@ class ConnectionTests(TestCase, _LoopbackMixin):
def test_shutdown_wrong_args(self):
"""
- L{Connection.shutdown} raises L{TypeError} if called with the wrong
+ :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
number of arguments or with arguments other than integers.
"""
connection = Connection(Context(TLSv1_METHOD), None)
@@ -1214,7 +1324,7 @@ class ConnectionTests(TestCase, _LoopbackMixin):
def test_shutdown(self):
"""
- L{Connection.shutdown} performs an SSL-level connection shutdown.
+ :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
"""
server, client = self._loopback()
self.assertFalse(server.shutdown())
@@ -1229,7 +1339,7 @@ class ConnectionTests(TestCase, _LoopbackMixin):
def test_set_shutdown(self):
"""
- L{Connection.set_shutdown} sets the state of the SSL connection shutdown
+ :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
process.
"""
connection = Connection(Context(TLSv1_METHOD), socket())
@@ -1239,8 +1349,8 @@ class ConnectionTests(TestCase, _LoopbackMixin):
def test_app_data_wrong_args(self):
"""
- L{Connection.set_app_data} raises L{TypeError} if called with other than
- one argument. L{Connection.get_app_data} raises L{TypeError} if called
+ :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
+ one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
with any arguments.
"""
conn = Connection(Context(TLSv1_METHOD), None)
@@ -1252,8 +1362,8 @@ class ConnectionTests(TestCase, _LoopbackMixin):
def test_app_data(self):
"""
Any object can be set as app data by passing it to
- L{Connection.set_app_data} and later retrieved with
- L{Connection.get_app_data}.
+ :py:obj:`Connection.set_app_data` and later retrieved with
+ :py:obj:`Connection.get_app_data`.
"""
conn = Connection(Context(TLSv1_METHOD), None)
app_data = object()
@@ -1263,8 +1373,8 @@ class ConnectionTests(TestCase, _LoopbackMixin):
def test_makefile(self):
"""
- L{Connection.makefile} is not implemented and calling that method raises
- L{NotImplementedError}.
+ :py:obj:`Connection.makefile` is not implemented and calling that method raises
+ :py:obj:`NotImplementedError`.
"""
conn = Connection(Context(TLSv1_METHOD), None)
self.assertRaises(NotImplementedError, conn.makefile)
@@ -1272,7 +1382,7 @@ class ConnectionTests(TestCase, _LoopbackMixin):
def test_get_peer_cert_chain_wrong_args(self):
"""
- L{Connection.get_peer_cert_chain} raises L{TypeError} if called with any
+ :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
arguments.
"""
conn = Connection(Context(TLSv1_METHOD), None)
@@ -1284,7 +1394,7 @@ class ConnectionTests(TestCase, _LoopbackMixin):
def test_get_peer_cert_chain(self):
"""
- L{Connection.get_peer_cert_chain} returns a list of certificates which
+ :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
the connected server returned for the certification verification.
"""
chain = _create_certificate_chain()
@@ -1318,7 +1428,7 @@ class ConnectionTests(TestCase, _LoopbackMixin):
def test_get_peer_cert_chain_none(self):
"""
- L{Connection.get_peer_cert_chain} returns C{None} if the peer sends no
+ :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
certificate chain.
"""
ctx = Context(TLSv1_METHOD)
@@ -1332,14 +1442,151 @@ class ConnectionTests(TestCase, _LoopbackMixin):
self.assertIdentical(None, server.get_peer_cert_chain())
+ def test_get_session_wrong_args(self):
+ """
+ :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
+ with any arguments.
+ """
+ ctx = Context(TLSv1_METHOD)
+ server = Connection(ctx, None)
+ self.assertRaises(TypeError, server.get_session, 123)
+ self.assertRaises(TypeError, server.get_session, "hello")
+ self.assertRaises(TypeError, server.get_session, object())
+
+
+ def test_get_session_unconnected(self):
+ """
+ :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
+ an object which has not been connected.
+ """
+ ctx = Context(TLSv1_METHOD)
+ server = Connection(ctx, None)
+ session = server.get_session()
+ self.assertIdentical(None, session)
+
+
+ def test_server_get_session(self):
+ """
+ On the server side of a connection, :py:obj:`Connection.get_session`
+ returns a :py:class:`Session` instance representing the SSL session for
+ that connection.
+ """
+ server, client = self._loopback()
+ session = server.get_session()
+ self.assertTrue(session, Session)
+
+
+ def test_client_get_session(self):
+ """
+ On the client side of a connection, :py:obj:`Connection.get_session`
+ returns a :py:class:`Session` instance representing the SSL session for
+ that connection.
+ """
+ server, client = self._loopback()
+ session = client.get_session()
+ self.assertTrue(session, Session)
+
+
+ def test_set_session_wrong_args(self):
+ """
+ If called with an object that is not an instance of :py:class:`Session`,
+ or with other than one argument, :py:obj:`Connection.set_session` raises
+ :py:obj:`TypeError`.
+ """
+ ctx = Context(TLSv1_METHOD)
+ connection = Connection(ctx, None)
+ self.assertRaises(TypeError, connection.set_session)
+ self.assertRaises(TypeError, connection.set_session, 123)
+ self.assertRaises(TypeError, connection.set_session, "hello")
+ self.assertRaises(TypeError, connection.set_session, object())
+ self.assertRaises(
+ TypeError, connection.set_session, Session(), Session())
+
+
+ def test_client_set_session(self):
+ """
+ :py:obj:`Connection.set_session`, when used prior to a connection being
+ established, accepts a :py:class:`Session` instance and causes an
+ attempt to re-use the session it represents when the SSL handshake is
+ performed.
+ """
+ key = load_privatekey(FILETYPE_PEM, server_key_pem)
+ cert = load_certificate(FILETYPE_PEM, server_cert_pem)
+ ctx = Context(TLSv1_METHOD)
+ ctx.use_privatekey(key)
+ ctx.use_certificate(cert)
+ ctx.set_session_id("unity-test")
+
+ def makeServer(socket):
+ server = Connection(ctx, socket)
+ server.set_accept_state()
+ return server
+
+ originalServer, originalClient = self._loopback(
+ serverFactory=makeServer)
+ originalSession = originalClient.get_session()
+
+ def makeClient(socket):
+ client = self._loopbackClientFactory(socket)
+ client.set_session(originalSession)
+ return client
+ resumedServer, resumedClient = self._loopback(
+ serverFactory=makeServer,
+ clientFactory=makeClient)
+
+ # This is a proxy: in general, we have no access to any unique
+ # identifier for the session (new enough versions of OpenSSL expose a
+ # hash which could be usable, but "new enough" is very, very new).
+ # Instead, exploit the fact that the master key is re-used if the
+ # session is re-used. As long as the master key for the two connections
+ # is the same, the session was re-used!
+ self.assertEqual(
+ originalServer.master_key(), resumedServer.master_key())
+
+
+ def test_set_session_wrong_method(self):
+ """
+ If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
+ instance associated with a context using a different SSL method than the
+ :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
+ raised.
+ """
+ key = load_privatekey(FILETYPE_PEM, server_key_pem)
+ cert = load_certificate(FILETYPE_PEM, server_cert_pem)
+ ctx = Context(TLSv1_METHOD)
+ ctx.use_privatekey(key)
+ ctx.use_certificate(cert)
+ ctx.set_session_id("unity-test")
+
+ def makeServer(socket):
+ server = Connection(ctx, socket)
+ server.set_accept_state()
+ return server
+
+ originalServer, originalClient = self._loopback(
+ serverFactory=makeServer)
+ originalSession = originalClient.get_session()
+
+ def makeClient(socket):
+ # Intentionally use a different, incompatible method here.
+ client = Connection(Context(SSLv3_METHOD), socket)
+ client.set_connect_state()
+ client.set_session(originalSession)
+ return client
+
+ self.assertRaises(
+ Error,
+ self._loopback, clientFactory=makeClient, serverFactory=makeServer)
+
+
class ConnectionGetCipherListTests(TestCase):
"""
- Tests for L{Connection.get_cipher_list}.
+ Tests for :py:obj:`Connection.get_cipher_list`.
"""
def test_wrong_args(self):
"""
- L{Connection.get_cipher_list} raises L{TypeError} if called with any
+ :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
arguments.
"""
connection = Connection(Context(TLSv1_METHOD), None)
@@ -1348,7 +1595,7 @@ class ConnectionGetCipherListTests(TestCase):
def test_result(self):
"""
- L{Connection.get_cipher_list} returns a C{list} of C{str} giving the
+ :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of :py:obj:`str` giving the
names of the ciphers which might be used.
"""
connection = Connection(Context(TLSv1_METHOD), None)
@@ -1361,12 +1608,12 @@ class ConnectionGetCipherListTests(TestCase):
class ConnectionSendTests(TestCase, _LoopbackMixin):
"""
- Tests for L{Connection.send}
+ Tests for :py:obj:`Connection.send`
"""
def test_wrong_args(self):
"""
When called with arguments other than a single string,
- L{Connection.send} raises L{TypeError}.
+ :py:obj:`Connection.send` raises :py:obj:`TypeError`.
"""
connection = Connection(Context(TLSv1_METHOD), None)
self.assertRaises(TypeError, connection.send)
@@ -1376,7 +1623,7 @@ class ConnectionSendTests(TestCase, _LoopbackMixin):
def test_short_bytes(self):
"""
- When passed a short byte string, L{Connection.send} transmits all of it
+ When passed a short byte string, :py:obj:`Connection.send` transmits all of it
and returns the number of bytes sent.
"""
server, client = self._loopback()
@@ -1392,7 +1639,7 @@ class ConnectionSendTests(TestCase, _LoopbackMixin):
def test_short_memoryview(self):
"""
When passed a memoryview onto a small number of bytes,
- L{Connection.send} transmits all of them and returns the number of
+ :py:obj:`Connection.send` transmits all of them and returns the number of
bytes sent.
"""
server, client = self._loopback()
@@ -1404,12 +1651,12 @@ class ConnectionSendTests(TestCase, _LoopbackMixin):
class ConnectionSendallTests(TestCase, _LoopbackMixin):
"""
- Tests for L{Connection.sendall}.
+ Tests for :py:obj:`Connection.sendall`.
"""
def test_wrong_args(self):
"""
When called with arguments other than a single string,
- L{Connection.sendall} raises L{TypeError}.
+ :py:obj:`Connection.sendall` raises :py:obj:`TypeError`.
"""
connection = Connection(Context(TLSv1_METHOD), None)
self.assertRaises(TypeError, connection.sendall)
@@ -1419,7 +1666,7 @@ class ConnectionSendallTests(TestCase, _LoopbackMixin):
def test_short(self):
"""
- L{Connection.sendall} transmits all of the bytes in the string passed to
+ :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
it.
"""
server, client = self._loopback()
@@ -1435,7 +1682,7 @@ class ConnectionSendallTests(TestCase, _LoopbackMixin):
def test_short_memoryview(self):
"""
When passed a memoryview onto a small number of bytes,
- L{Connection.sendall} transmits all of them.
+ :py:obj:`Connection.sendall` transmits all of them.
"""
server, client = self._loopback()
server.sendall(memoryview(b('x')))
@@ -1444,7 +1691,7 @@ class ConnectionSendallTests(TestCase, _LoopbackMixin):
def test_long(self):
"""
- L{Connection.sendall} transmits all of the bytes in the string passed to
+ :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
it even if this requires multiple calls of an underlying write function.
"""
server, client = self._loopback()
@@ -1464,7 +1711,7 @@ class ConnectionSendallTests(TestCase, _LoopbackMixin):
def test_closed(self):
"""
- If the underlying socket is closed, L{Connection.sendall} propagates the
+ If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
write error from the low level write call.
"""
server, client = self._loopback()
@@ -1479,7 +1726,7 @@ class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
"""
def test_renegotiate_wrong_args(self):
"""
- L{Connection.renegotiate} raises L{TypeError} if called with any
+ :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
arguments.
"""
connection = Connection(Context(TLSv1_METHOD), None)
@@ -1488,7 +1735,7 @@ class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
def test_total_renegotiations_wrong_args(self):
"""
- L{Connection.total_renegotiations} raises L{TypeError} if called with
+ :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
any arguments.
"""
connection = Connection(Context(TLSv1_METHOD), None)
@@ -1497,7 +1744,7 @@ class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
def test_total_renegotiations(self):
"""
- L{Connection.total_renegotiations} returns C{0} before any
+ :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
renegotiations have happened.
"""
connection = Connection(Context(TLSv1_METHOD), None)
@@ -1528,11 +1775,11 @@ class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
class ErrorTests(TestCase):
"""
- Unit tests for L{OpenSSL.SSL.Error}.
+ Unit tests for :py:obj:`OpenSSL.SSL.Error`.
"""
def test_type(self):
"""
- L{Error} is an exception type.
+ :py:obj:`Error` is an exception type.
"""
self.assertTrue(issubclass(Error, Exception))
self.assertEqual(Error.__name__, 'Error')
@@ -1541,7 +1788,7 @@ class ErrorTests(TestCase):
class ConstantsTests(TestCase):
"""
- Tests for the values of constants exposed in L{OpenSSL.SSL}.
+ Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
These are values defined by OpenSSL intended only to be used as flags to
OpenSSL APIs. The only assertions it seems can be made about them is
@@ -1551,8 +1798,8 @@ class ConstantsTests(TestCase):
if OP_NO_QUERY_MTU is not None:
def test_op_no_query_mtu(self):
"""
- The value of L{OpenSSL.SSL.OP_NO_QUERY_MTU} is 0x1000, the value of
- I{SSL_OP_NO_QUERY_MTU} defined by I{openssl/ssl.h}.
+ The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
+ :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
"""
self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
else:
@@ -1562,8 +1809,8 @@ class ConstantsTests(TestCase):
if OP_COOKIE_EXCHANGE is not None:
def test_op_cookie_exchange(self):
"""
- The value of L{OpenSSL.SSL.OP_COOKIE_EXCHANGE} is 0x2000, the value
- of I{SSL_OP_COOKIE_EXCHANGE} defined by I{openssl/ssl.h}.
+ The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
+ of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
"""
self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
else:
@@ -1573,23 +1820,100 @@ class ConstantsTests(TestCase):
if OP_NO_TICKET is not None:
def test_op_no_ticket(self):
"""
- The value of L{OpenSSL.SSL.OP_NO_TICKET} is 0x4000, the value of
- I{SSL_OP_NO_TICKET} defined by I{openssl/ssl.h}.
+ The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
+ :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
"""
self.assertEqual(OP_NO_TICKET, 0x4000)
else:
"OP_NO_TICKET unavailable - OpenSSL version may be too old"
+ if OP_NO_COMPRESSION is not None:
+ def test_op_no_compression(self):
+ """
+ The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
+ of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
+ """
+ self.assertEqual(OP_NO_COMPRESSION, 0x20000)
+ else:
+ "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
+
+
+ def test_sess_cache_off(self):
+ """
+ The value of L{OpenSSL.SSL.SESS_CACHE_OFF} 0x0, the value of
+ L{SSL_SESS_CACHE_OFF} defined by I{openssl/ssl.h}.
+ """
+ self.assertEqual(0x0, SESS_CACHE_OFF)
+
+
+ def test_sess_cache_client(self):
+ """
+ The value of L{OpenSSL.SSL.SESS_CACHE_CLIENT} 0x1, the value of
+ L{SSL_SESS_CACHE_CLIENT} defined by I{openssl/ssl.h}.
+ """
+ self.assertEqual(0x1, SESS_CACHE_CLIENT)
+
+
+ def test_sess_cache_server(self):
+ """
+ The value of L{OpenSSL.SSL.SESS_CACHE_SERVER} 0x2, the value of
+ L{SSL_SESS_CACHE_SERVER} defined by I{openssl/ssl.h}.
+ """
+ self.assertEqual(0x2, SESS_CACHE_SERVER)
+
+
+ def test_sess_cache_both(self):
+ """
+ The value of L{OpenSSL.SSL.SESS_CACHE_BOTH} 0x3, the value of
+ L{SSL_SESS_CACHE_BOTH} defined by I{openssl/ssl.h}.
+ """
+ self.assertEqual(0x3, SESS_CACHE_BOTH)
+
+
+ def test_sess_cache_no_auto_clear(self):
+ """
+ The value of L{OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR} 0x80, the value of
+ L{SSL_SESS_CACHE_NO_AUTO_CLEAR} defined by I{openssl/ssl.h}.
+ """
+ self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
+
+
+ def test_sess_cache_no_internal_lookup(self):
+ """
+ The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP} 0x100, the
+ value of L{SSL_SESS_CACHE_NO_INTERNAL_LOOKUP} defined by
+ I{openssl/ssl.h}.
+ """
+ self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
+
+
+ def test_sess_cache_no_internal_store(self):
+ """
+ The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE} 0x200, the
+ value of L{SSL_SESS_CACHE_NO_INTERNAL_STORE} defined by
+ I{openssl/ssl.h}.
+ """
+ self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
+
+
+ def test_sess_cache_no_internal(self):
+ """
+ The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL} 0x300, the value of
+ L{SSL_SESS_CACHE_NO_INTERNAL} defined by I{openssl/ssl.h}.
+ """
+ self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
+
+
class MemoryBIOTests(TestCase, _LoopbackMixin):
"""
- Tests for L{OpenSSL.SSL.Connection} using a memory BIO.
+ Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
"""
def _server(self, sock):
"""
- Create a new server-side SSL L{Connection} object wrapped around
- C{sock}.
+ Create a new server-side SSL :py:obj:`Connection` object wrapped around
+ :py:obj:`sock`.
"""
# Create the server side Connection. This is mostly setup boilerplate
# - use TLSv1, use a particular certificate, etc.
@@ -1610,8 +1934,8 @@ class MemoryBIOTests(TestCase, _LoopbackMixin):
def _client(self, sock):
"""
- Create a new client-side SSL L{Connection} object wrapped around
- C{sock}.
+ Create a new client-side SSL :py:obj:`Connection` object wrapped around
+ :py:obj:`sock`.
"""
# Now create the client side Connection. Similar boilerplate to the
# above.
@@ -1630,7 +1954,7 @@ class MemoryBIOTests(TestCase, _LoopbackMixin):
def test_memoryConnect(self):
"""
- Two L{Connection}s which use memory BIOs can be manually connected by
+ Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
reading from the output of each and writing those bytes to the input of
the other and in this way establish a connection and exchange
application-level bytes with each other.
@@ -1674,10 +1998,10 @@ class MemoryBIOTests(TestCase, _LoopbackMixin):
def test_socketConnect(self):
"""
- Just like L{test_memoryConnect} but with an actual socket.
+ Just like :py:obj:`test_memoryConnect` but with an actual socket.
This is primarily to rule out the memory BIO code as the source of
- any problems encountered while passing data over a L{Connection} (if
+ any problems encountered while passing data over a :py:obj:`Connection` (if
this test fails, there must be a problem outside the memory BIO
code, as no memory BIO is involved here). Even though this isn't a
memory BIO test, it's convenient to have it here.
@@ -1698,8 +2022,8 @@ class MemoryBIOTests(TestCase, _LoopbackMixin):
def test_socketOverridesMemory(self):
"""
- Test that L{OpenSSL.SSL.bio_read} and L{OpenSSL.SSL.bio_write} don't
- work on L{OpenSSL.SSL.Connection}() that use sockets.
+ Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
+ work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
"""
context = Context(SSLv3_METHOD)
client = socket()
@@ -1712,7 +2036,7 @@ class MemoryBIOTests(TestCase, _LoopbackMixin):
def test_outgoingOverflow(self):
"""
If more bytes than can be written to the memory BIO are passed to
- L{Connection.send} at once, the number of bytes which were written is
+ :py:obj:`Connection.send` at once, the number of bytes which were written is
returned and that many bytes from the beginning of the input can be
read from the other end of the connection.
"""
@@ -1738,8 +2062,8 @@ class MemoryBIOTests(TestCase, _LoopbackMixin):
def test_shutdown(self):
"""
- L{Connection.bio_shutdown} signals the end of the data stream from
- which the L{Connection} reads.
+ :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
+ which the :py:obj:`Connection` reads.
"""
server = self._server(None)
server.bio_shutdown()
@@ -1751,13 +2075,13 @@ class MemoryBIOTests(TestCase, _LoopbackMixin):
def _check_client_ca_list(self, func):
"""
- Verify the return value of the C{get_client_ca_list} method for server and client connections.
+ Verify the return value of the :py:obj:`get_client_ca_list` method for server and client connections.
- @param func: A function which will be called with the server context
+ :param func: A function which will be called with the server context
before the client and server are connected to each other. This
function should specify a list of CAs for the server to send to the
client and return that same list. The list will be used to verify
- that C{get_client_ca_list} returns the proper value at various
+ that :py:obj:`get_client_ca_list` returns the proper value at various
times.
"""
server = self._server(None)
@@ -1775,7 +2099,7 @@ class MemoryBIOTests(TestCase, _LoopbackMixin):
def test_set_client_ca_list_errors(self):
"""
- L{Context.set_client_ca_list} raises a L{TypeError} if called with a
+ :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
non-list or a list that contains objects other than X509Names.
"""
ctx = Context(TLSv1_METHOD)
@@ -1786,9 +2110,9 @@ class MemoryBIOTests(TestCase, _LoopbackMixin):
def test_set_empty_ca_list(self):
"""
- If passed an empty list, L{Context.set_client_ca_list} configures the
+ If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
context to send no CA names to the client and, on both the server and
- client sides, L{Connection.get_client_ca_list} returns an empty list
+ client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
after the connection is set up.
"""
def no_ca(ctx):
@@ -1800,9 +2124,9 @@ class MemoryBIOTests(TestCase, _LoopbackMixin):
def test_set_one_ca_list(self):
"""
If passed a list containing a single X509Name,
- L{Context.set_client_ca_list} configures the context to send that CA
+ :py:obj:`Context.set_client_ca_list` configures the context to send that CA
name to the client and, on both the server and client sides,
- L{Connection.get_client_ca_list} returns a list containing that
+ :py:obj:`Connection.get_client_ca_list` returns a list containing that
X509Name after the connection is set up.
"""
cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
@@ -1816,9 +2140,9 @@ class MemoryBIOTests(TestCase, _LoopbackMixin):
def test_set_multiple_ca_list(self):
"""
If passed a list containing multiple X509Name objects,
- L{Context.set_client_ca_list} configures the context to send those CA
+ :py:obj:`Context.set_client_ca_list` configures the context to send those CA
names to the client and, on both the server and client sides,
- L{Connection.get_client_ca_list} returns a list containing those
+ :py:obj:`Connection.get_client_ca_list` returns a list containing those
X509Names after the connection is set up.
"""
secert = load_certificate(FILETYPE_PEM, server_cert_pem)
@@ -1837,7 +2161,7 @@ class MemoryBIOTests(TestCase, _LoopbackMixin):
def test_reset_ca_list(self):
"""
If called multiple times, only the X509Names passed to the final call
- of L{Context.set_client_ca_list} are used to configure the CA names
+ of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
sent to the client.
"""
cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
@@ -1857,7 +2181,7 @@ class MemoryBIOTests(TestCase, _LoopbackMixin):
def test_mutated_ca_list(self):
"""
- If the list passed to L{Context.set_client_ca_list} is mutated
+ If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
afterwards, this does not affect the list of CA names sent to the
client.
"""
@@ -1877,7 +2201,7 @@ class MemoryBIOTests(TestCase, _LoopbackMixin):
def test_add_client_ca_errors(self):
"""
- L{Context.add_client_ca} raises L{TypeError} if called with a non-X509
+ :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
object or with a number of arguments other than one.
"""
ctx = Context(TLSv1_METHOD)
@@ -1890,7 +2214,7 @@ class MemoryBIOTests(TestCase, _LoopbackMixin):
def test_one_add_client_ca(self):
"""
A certificate's subject can be added as a CA to be sent to the client
- with L{Context.add_client_ca}.
+ with :py:obj:`Context.add_client_ca`.
"""
cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
cadesc = cacert.get_subject()
@@ -1903,7 +2227,7 @@ class MemoryBIOTests(TestCase, _LoopbackMixin):
def test_multiple_add_client_ca(self):
"""
Multiple CA names can be sent to the client by calling
- L{Context.add_client_ca} with multiple X509 objects.
+ :py:obj:`Context.add_client_ca` with multiple X509 objects.
"""
cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
secert = load_certificate(FILETYPE_PEM, server_cert_pem)
@@ -1920,8 +2244,8 @@ class MemoryBIOTests(TestCase, _LoopbackMixin):
def test_set_and_add_client_ca(self):
"""
- A call to L{Context.set_client_ca_list} followed by a call to
- L{Context.add_client_ca} results in using the CA names from the first
+ A call to :py:obj:`Context.set_client_ca_list` followed by a call to
+ :py:obj:`Context.add_client_ca` results in using the CA names from the first
call and the CA name from the second call.
"""
cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
@@ -1941,8 +2265,8 @@ class MemoryBIOTests(TestCase, _LoopbackMixin):
def test_set_after_add_client_ca(self):
"""
- A call to L{Context.set_client_ca_list} after a call to
- L{Context.add_client_ca} replaces the CA name specified by the former
+ A call to :py:obj:`Context.set_client_ca_list` after a call to
+ :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
call with the names specified by the latter cal.
"""
cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
diff --git a/OpenSSL/test/util.py b/OpenSSL/test/util.py
index 643fb91..79da76b 100644
--- a/OpenSSL/test/util.py
+++ b/OpenSSL/test/util.py
@@ -27,12 +27,12 @@ else:
class TestCase(TestCase):
"""
- L{TestCase} adds useful testing functionality beyond what is available
- from the standard library L{unittest.TestCase}.
+ :py:class:`TestCase` adds useful testing functionality beyond what is available
+ from the standard library :py:class:`unittest.TestCase`.
"""
def tearDown(self):
"""
- Clean up any files or directories created using L{TestCase.mktemp}.
+ Clean up any files or directories created using :py:meth:`TestCase.mktemp`.
Subclasses must invoke this method if they override it or the
cleanup will not occur.
"""
@@ -52,12 +52,12 @@ class TestCase(TestCase):
def failUnlessIn(self, containee, container, msg=None):
"""
- Fail the test if C{containee} is not found in C{container}.
+ Fail the test if :py:data:`containee` is not found in :py:data:`container`.
- @param containee: the value that should be in C{container}
- @param container: a sequence type, or in the case of a mapping type,
+ :param containee: the value that should be in :py:class:`container`
+ :param container: a sequence type, or in the case of a mapping type,
will follow semantics of 'if key in dict.keys()'
- @param msg: if msg is None, then the failure message will be
+ :param msg: if msg is None, then the failure message will be
'%r not in %r' % (first, second)
"""
if containee not in container:
@@ -68,11 +68,11 @@ class TestCase(TestCase):
def failUnlessIdentical(self, first, second, msg=None):
"""
- Fail the test if C{first} is not C{second}. This is an
+ Fail the test if :py:data:`first` is not :py:data:`second`. This is an
obect-identity-equality test, not an object equality
- (i.e. C{__eq__}) test.
+ (i.e. :py:func:`__eq__`) test.
- @param msg: if msg is None, then the failure message will be
+ :param msg: if msg is None, then the failure message will be
'%r is not %r' % (first, second)
"""
if first is not second:
@@ -83,11 +83,11 @@ class TestCase(TestCase):
def failIfIdentical(self, first, second, msg=None):
"""
- Fail the test if C{first} is C{second}. This is an
+ Fail the test if :py:data:`first` is :py:data:`second`. This is an
obect-identity-equality test, not an object equality
- (i.e. C{__eq__}) test.
+ (i.e. :py:func:`__eq__`) test.
- @param msg: if msg is None, then the failure message will be
+ :param msg: if msg is None, then the failure message will be
'%r is %r' % (first, second)
"""
if first is second:
@@ -98,15 +98,16 @@ class TestCase(TestCase):
def failUnlessRaises(self, exception, f, *args, **kwargs):
"""
- Fail the test unless calling the function C{f} with the given
- C{args} and C{kwargs} raises C{exception}. The failure will report
- the traceback and call stack of the unexpected exception.
+ Fail the test unless calling the function :py:data:`f` with the given
+ :py:data:`args` and :py:data:`kwargs` raises :py:data:`exception`. The
+ failure will report the traceback and call stack of the unexpected
+ exception.
- @param exception: exception type that is to be expected
- @param f: the function to call
+ :param exception: exception type that is to be expected
+ :param f: the function to call
- @return: The raised exception instance, if it is of the given type.
- @raise self.failureException: Raised if the function call does
+ :return: The raised exception instance, if it is of the given type.
+ :raise self.failureException: Raised if the function call does
not raise an exception or if it raises an exception of a
different type.
"""
@@ -150,14 +151,14 @@ class TestCase(TestCase):
# Other stuff
def assertConsistentType(self, theType, name, *constructionArgs):
"""
- Perform various assertions about C{theType} to ensure that it is a
+ Perform various assertions about :py:data:`theType` to ensure that it is a
well-defined type. This is useful for extension types, where it's
pretty easy to do something wacky. If something about the type is
unusual, an exception will be raised.
- @param theType: The type object about which to make assertions.
- @param name: A string giving the name of the type.
- @param constructionArgs: Positional arguments to use with C{theType} to
+ :param theType: The type object about which to make assertions.
+ :param name: A string giving the name of the type.
+ :param constructionArgs: Positional arguments to use with :py:data:`theType` to
create an instance of it.
"""
self.assertEqual(theType.__name__, name)