Support OpenSSL 1.0
diff --git a/ChangeLog b/ChangeLog
index 680a6d0..d16f254 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+2011-05-10 Jean-Paul Calderone <exarkun@twistedmatrix.com>
+
+ * OpenSSL/crypto/crypto.h: Work around a Windows/OpenSSL 1.0 issue
+ explicitly including a Windows header before any OpenSSL headers.
+
+ * OpenSSL/crypto/pkcs12.c: Work around an OpenSSL 1.0 issue by
+ explicitly flushing errors known to be uninteresting after calling
+ PKCS12_parse.
+
+ * OpenSSL/ssl/context.c: Remove SSLv2 support if the underlying
+ OpenSSL library does not provide it.
+
+ * OpenSSL/test/test_crypto.py: Support an OpenSSL 1.0 change from
+ MD5 to SHA1 by allowing either hash algorithm's result as the
+ return value of X509.subject_name_hash.
+
+ * OpenSSL/test/test_ssl.py: Support an OpenSSL 1.0 change from MD5
+ to SHA1 by constructing certificate files named using both hash
+ algorithms' results when testing Context.load_verify_locations.
+
+ * Support OpenSSL 1.0.0a.
+
+2011-04-15 Jean-Paul Calderone <exarkun@twistedmatrix.com>
+
+ * OpenSSL/ssl/ssl.c: Add OPENSSL_VERSION_NUMBER, SSLeay_version
+ and related constants for retrieving version information about the
+ underlying OpenSSL library.
+
2011-04-07 Jean-Paul Calderone <exarkun@twistedmatrix.com>
* Release 0.12
diff --git a/MANIFEST.in b/MANIFEST.in
index a26f83f..0c2be95 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,5 +1,5 @@
recursive-include OpenSSL *.h
-include COPYING ChangeLog INSTALL README TODO MANIFEST.in OpenSSL/RATIONALE
+include LICENSE ChangeLog INSTALL README TODO MANIFEST.in OpenSSL/RATIONALE
include doc/pyOpenSSL.tex doc/Makefile
recursive-include doc/tools *
recursive-include examples *
diff --git a/OpenSSL/crypto/crl.c b/OpenSSL/crypto/crl.c
index bc76f22..eec5bcb 100644
--- a/OpenSSL/crypto/crl.c
+++ b/OpenSSL/crypto/crl.c
@@ -276,12 +276,15 @@
};
int init_crypto_crl(PyObject *module) {
- if (PyType_Ready(&crypto_CRL_Type) < 0) {
- return 0;
- }
+ if (PyType_Ready(&crypto_CRL_Type) < 0) {
+ return 0;
+ }
- if (PyModule_AddObject(module, "CRL", (PyObject *)&crypto_CRL_Type) != 0) {
- return 0;
- }
- return 1;
+ /* PyModule_AddObject steals a reference.
+ */
+ Py_INCREF((PyObject *)&crypto_CRL_Type);
+ if (PyModule_AddObject(module, "CRL", (PyObject *)&crypto_CRL_Type) != 0) {
+ return 0;
+ }
+ return 1;
}
diff --git a/OpenSSL/crypto/crypto.c b/OpenSSL/crypto/crypto.c
index 1e2abc2..8bea656 100644
--- a/OpenSSL/crypto/crypto.c
+++ b/OpenSSL/crypto/crypto.c
@@ -836,13 +836,21 @@
crypto_API[crypto_PKCS7_New_NUM] = (void *)crypto_PKCS7_New;
crypto_API[crypto_NetscapeSPKI_New_NUM] = (void *)crypto_NetscapeSPKI_New;
c_api_object = PyCObject_FromVoidPtr((void *)crypto_API, NULL);
- if (c_api_object != NULL)
+ if (c_api_object != NULL) {
+ /* PyModule_AddObject steals a reference.
+ */
+ Py_INCREF(c_api_object);
PyModule_AddObject(module, "_C_API", c_api_object);
+ }
#endif
crypto_Error = PyErr_NewException("OpenSSL.crypto.Error", NULL, NULL);
if (crypto_Error == NULL)
goto error;
+
+ /* PyModule_AddObject steals a reference.
+ */
+ Py_INCREF(crypto_Error);
if (PyModule_AddObject(module, "Error", crypto_Error) != 0)
goto error;
diff --git a/OpenSSL/crypto/crypto.h b/OpenSSL/crypto/crypto.h
index adb6509..4006e71 100644
--- a/OpenSSL/crypto/crypto.h
+++ b/OpenSSL/crypto/crypto.h
@@ -123,7 +123,7 @@
PyObject *crypto_dict, *crypto_api_object; \
crypto_dict = PyModule_GetDict(crypto_module); \
crypto_api_object = PyDict_GetItemString(crypto_dict, "_C_API"); \
- if (PyCObject_Check(crypto_api_object)) { \
+ if (crypto_api_object && PyCObject_Check(crypto_api_object)) { \
crypto_API = (void **)PyCObject_AsVoidPtr(crypto_api_object); \
} \
} \
diff --git a/OpenSSL/crypto/netscape_spki.c b/OpenSSL/crypto/netscape_spki.c
index 1792178..9369d50 100644
--- a/OpenSSL/crypto/netscape_spki.c
+++ b/OpenSSL/crypto/netscape_spki.c
@@ -298,10 +298,16 @@
return 0;
}
+ /* PyModule_AddObject steals a reference
+ */
+ Py_INCREF((PyObject *)&crypto_NetscapeSPKI_Type);
if (PyModule_AddObject(module, "NetscapeSPKI", (PyObject *)&crypto_NetscapeSPKI_Type) != 0) {
return 0;
}
+ /* PyModule_AddObject steals a reference
+ */
+ Py_INCREF((PyObject *)&crypto_NetscapeSPKI_Type);
if (PyModule_AddObject(module, "NetscapeSPKIType", (PyObject *)&crypto_NetscapeSPKI_Type) != 0) {
return 0;
}
diff --git a/OpenSSL/crypto/pkcs12.c b/OpenSSL/crypto/pkcs12.c
index a3319c0..a1a5a79 100644
--- a/OpenSSL/crypto/pkcs12.c
+++ b/OpenSSL/crypto/pkcs12.c
@@ -562,10 +562,16 @@
return 0;
}
+ /* PyModule_AddObject steals a reference.
+ */
+ Py_INCREF((PyObject *)&crypto_PKCS12_Type);
if (PyModule_AddObject(module, "PKCS12", (PyObject *)&crypto_PKCS12_Type) != 0) {
return 0;
}
+ /* PyModule_AddObject steals a reference.
+ */
+ Py_INCREF((PyObject *)&crypto_PKCS12_Type);
if (PyModule_AddObject(module, "PKCS12Type", (PyObject *)&crypto_PKCS12_Type) != 0) {
return 0;
}
diff --git a/OpenSSL/crypto/pkcs7.c b/OpenSSL/crypto/pkcs7.c
index a074800..1770f7f 100644
--- a/OpenSSL/crypto/pkcs7.c
+++ b/OpenSSL/crypto/pkcs7.c
@@ -204,6 +204,9 @@
return 0;
}
+ /* PyModule_AddObject steals a reference.
+ */
+ Py_INCREF((PyObject *)&crypto_PKCS7_Type);
if (PyModule_AddObject(module, "PKCS7Type", (PyObject *)&crypto_PKCS7_Type) != 0) {
return 0;
}
diff --git a/OpenSSL/crypto/pkey.c b/OpenSSL/crypto/pkey.c
index 938a222..0a13aa3 100644
--- a/OpenSSL/crypto/pkey.c
+++ b/OpenSSL/crypto/pkey.c
@@ -252,10 +252,16 @@
return 0;
}
+ /* PyModule_AddObject steals a reference.
+ */
+ Py_INCREF((PyObject *)&crypto_PKey_Type);
if (PyModule_AddObject(module, "PKey", (PyObject *)&crypto_PKey_Type) != 0) {
return 0;
}
+ /* PyModule_AddObject steals a reference.
+ */
+ Py_INCREF((PyObject *)&crypto_PKey_Type);
if (PyModule_AddObject(module, "PKeyType", (PyObject *)&crypto_PKey_Type) != 0) {
return 0;
}
diff --git a/OpenSSL/crypto/revoked.c b/OpenSSL/crypto/revoked.c
index e9b1297..93f9946 100644
--- a/OpenSSL/crypto/revoked.c
+++ b/OpenSSL/crypto/revoked.c
@@ -434,6 +434,9 @@
return 0;
}
+ /* PyModule_AddObject steals a reference.
+ */
+ Py_INCREF((PyObject *)&crypto_Revoked_Type);
if (PyModule_AddObject(module, "Revoked", (PyObject *)&crypto_Revoked_Type) != 0) {
return 0;
}
diff --git a/OpenSSL/crypto/x509.c b/OpenSSL/crypto/x509.c
index 5d03d2e..a12220b 100644
--- a/OpenSSL/crypto/x509.c
+++ b/OpenSSL/crypto/x509.c
@@ -883,10 +883,14 @@
return 0;
}
+ /* PyModule_AddObject steals a reference.
+ */
+ Py_INCREF((PyObject *)&crypto_X509_Type);
if (PyModule_AddObject(module, "X509", (PyObject *)&crypto_X509_Type) != 0) {
return 0;
}
+ Py_INCREF((PyObject *)&crypto_X509_Type);
if (PyModule_AddObject(module, "X509Type", (PyObject *)&crypto_X509_Type) != 0) {
return 0;
}
diff --git a/OpenSSL/crypto/x509ext.c b/OpenSSL/crypto/x509ext.c
index bdaac7d..adbe084 100644
--- a/OpenSSL/crypto/x509ext.c
+++ b/OpenSSL/crypto/x509ext.c
@@ -316,11 +316,17 @@
return 0;
}
+ /* PyModule_AddObject steals a reference.
+ */
+ Py_INCREF((PyObject *)&crypto_X509Extension_Type);
if (PyModule_AddObject(module, "X509Extension",
(PyObject *)&crypto_X509Extension_Type) != 0) {
return 0;
}
+ /* PyModule_AddObject steals a reference.
+ */
+ Py_INCREF((PyObject *)&crypto_X509Extension_Type);
if (PyModule_AddObject(module, "X509ExtensionType",
(PyObject *)&crypto_X509Extension_Type) != 0) {
return 0;
diff --git a/OpenSSL/crypto/x509name.c b/OpenSSL/crypto/x509name.c
index 91f617a..a62c957 100644
--- a/OpenSSL/crypto/x509name.c
+++ b/OpenSSL/crypto/x509name.c
@@ -195,14 +195,30 @@
* value - The value to set
*/
static int
-crypto_X509Name_setattr(crypto_X509NameObj *self, char *name, PyObject *value)
+crypto_X509Name_setattro(crypto_X509NameObj *self, PyObject *nameobj, PyObject *value)
{
int nid;
int result;
char *buffer;
+ char *name;
+
+ if (!PyBytes_CheckExact(nameobj) && !PyUnicode_CheckExact(nameobj)) {
+ PyErr_Format(PyExc_TypeError,
+ "attribute name must be string, not '%.200s'",
+ Py_TYPE(nameobj)->tp_name);
+ return -1;
+ }
+
+#ifdef PY3
+ name = PyBytes_AsString(PyUnicode_AsASCIIString(nameobj));
+#else
+ name = PyBytes_AsString(nameobj);
+#endif
if ((nid = OBJ_txt2nid(name)) == NID_undef)
{
+ /* Just like the case in the getattr function */
+ flush_error_queue();
PyErr_SetString(PyExc_AttributeError, "No such attribute");
return -1;
}
@@ -475,7 +491,7 @@
(destructor)crypto_X509Name_dealloc,
NULL, /* print */
NULL, /* getattr */
- (setattrfunc)crypto_X509Name_setattr,
+ NULL, /* setattr */
NULL, /* reserved */
(reprfunc)crypto_X509Name_repr,
NULL, /* as_number */
@@ -485,7 +501,7 @@
NULL, /* call */
NULL, /* str */
(getattrofunc)crypto_X509Name_getattro, /* getattro */
- NULL, /* setattro */
+ (setattrofunc)crypto_X509Name_setattro, /* setattro */
NULL, /* as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
crypto_X509Name_doc, /* tp_doc */
@@ -521,10 +537,16 @@
return 0;
}
+ /* PyModule_AddObject steals a reference.
+ */
+ Py_INCREF((PyObject *)&crypto_X509Name_Type);
if (PyModule_AddObject(module, "X509Name", (PyObject *)&crypto_X509Name_Type) != 0) {
return 0;
}
+ /* PyModule_AddObject steals a reference.
+ */
+ Py_INCREF((PyObject *)&crypto_X509Name_Type);
if (PyModule_AddObject(module, "X509NameType", (PyObject *)&crypto_X509Name_Type) != 0) {
return 0;
}
diff --git a/OpenSSL/crypto/x509req.c b/OpenSSL/crypto/x509req.c
index 4d7467d..a2d1f11 100644
--- a/OpenSSL/crypto/x509req.c
+++ b/OpenSSL/crypto/x509req.c
@@ -413,10 +413,16 @@
return 0;
}
+ /* PyModule_AddObject steals a reference.
+ */
+ Py_INCREF((PyObject *)&crypto_X509Req_Type);
if (PyModule_AddObject(module, "X509Req", (PyObject *)&crypto_X509Req_Type) != 0) {
return 0;
}
+ /* PyModule_AddObject steals a reference.
+ */
+ Py_INCREF((PyObject *)&crypto_X509Req_Type);
if (PyModule_AddObject(module, "X509ReqType", (PyObject *)&crypto_X509Req_Type) != 0) {
return 0;
}
diff --git a/OpenSSL/crypto/x509store.c b/OpenSSL/crypto/x509store.c
index c6fa10c..bf22756 100644
--- a/OpenSSL/crypto/x509store.c
+++ b/OpenSSL/crypto/x509store.c
@@ -138,6 +138,9 @@
return 0;
}
+ /* PyModule_AddObject steals a reference.
+ */
+ Py_INCREF((PyObject *)&crypto_X509Store_Type);
if (PyModule_AddObject(module, "X509StoreType", (PyObject *)&crypto_X509Store_Type) != 0) {
return 0;
}
diff --git a/OpenSSL/rand/rand.c b/OpenSSL/rand/rand.c
index bce5e89..8307ac6 100644
--- a/OpenSSL/rand/rand.c
+++ b/OpenSSL/rand/rand.c
@@ -288,6 +288,9 @@
goto error;
}
+ /* PyModule_AddObject steals a reference.
+ */
+ Py_INCREF(rand_Error);
if (PyModule_AddObject(module, "Error", rand_Error) != 0) {
goto error;
}
diff --git a/OpenSSL/ssl/connection.c b/OpenSSL/ssl/connection.c
index bef8c2f..5b304b1 100755
--- a/OpenSSL/ssl/connection.c
+++ b/OpenSSL/ssl/connection.c
@@ -1432,10 +1432,16 @@
return 0;
}
+ /* PyModule_AddObject steals a reference.
+ */
+ Py_INCREF((PyObject *)&ssl_Connection_Type);
if (PyModule_AddObject(module, "Connection", (PyObject *)&ssl_Connection_Type) != 0) {
return 0;
}
+ /* PyModule_AddObject steals a reference.
+ */
+ Py_INCREF((PyObject *)&ssl_Connection_Type);
if (PyModule_AddObject(module, "ConnectionType", (PyObject *)&ssl_Connection_Type) != 0) {
return 0;
}
diff --git a/OpenSSL/ssl/context.c b/OpenSSL/ssl/context.c
index f13b447..f178eec 100644
--- a/OpenSSL/ssl/context.c
+++ b/OpenSSL/ssl/context.c
@@ -1329,10 +1329,16 @@
return 0;
}
+ /* PyModule_AddObject steals a reference.
+ */
+ Py_INCREF((PyObject *)&ssl_Context_Type);
if (PyModule_AddObject(module, "Context", (PyObject *)&ssl_Context_Type) < 0) {
return 0;
}
+ /* PyModule_AddObject steals a reference.
+ */
+ Py_INCREF((PyObject *)&ssl_Context_Type);
if (PyModule_AddObject(module, "ContextType", (PyObject *)&ssl_Context_Type) < 0) {
return 0;
}
diff --git a/OpenSSL/ssl/ssl.c b/OpenSSL/ssl/ssl.c
index 7a827a0..0dd9871 100644
--- a/OpenSSL/ssl/ssl.c
+++ b/OpenSSL/ssl/ssl.c
@@ -139,8 +139,12 @@
ssl_API[ssl_Context_New_NUM] = (void *)ssl_Context_New;
ssl_API[ssl_Connection_New_NUM] = (void *)ssl_Connection_New;
ssl_api_object = PyCObject_FromVoidPtr((void *)ssl_API, NULL);
- if (ssl_api_object != NULL)
+ if (ssl_api_object != NULL) {
+ /* PyModule_AddObject steals a reference.
+ */
+ Py_INCREF(ssl_api_object);
PyModule_AddObject(module, "_C_API", ssl_api_object);
+ }
#endif
/* Exceptions */
@@ -148,18 +152,24 @@
* ADD_EXCEPTION(dict,name,base) expands to a correct Exception declaration,
* inserting OpenSSL.SSL.name into dict, derviving the exception from base.
*/
-#define ADD_EXCEPTION(_name, _base) \
-do { \
+#define ADD_EXCEPTION(_name, _base) \
+do { \
ssl_##_name = PyErr_NewException("OpenSSL.SSL."#_name, _base, NULL);\
if (ssl_##_name == NULL) \
- goto error; \
+ goto error; \
+ /* PyModule_AddObject steals a reference. */ \
+ Py_INCREF(ssl_##_name); \
if (PyModule_AddObject(module, #_name, ssl_##_name) != 0) \
- goto error; \
+ goto error; \
} while (0)
ssl_Error = PyErr_NewException("OpenSSL.SSL.Error", NULL, NULL);
- if (ssl_Error == NULL)
+ if (ssl_Error == NULL) {
goto error;
+ }
+
+ /* PyModule_AddObject steals a reference. */
+ Py_INCREF(ssl_Error);
if (PyModule_AddObject(module, "Error", ssl_Error) != 0)
goto error;
diff --git a/OpenSSL/test/test_crypto.py b/OpenSSL/test/test_crypto.py
index 305c78d..496dc59 100644
--- a/OpenSSL/test/test_crypto.py
+++ b/OpenSSL/test/test_crypto.py
@@ -626,6 +626,33 @@
name, type(name), X509NameType))
+ def test_onlyStringAttributes(self):
+ """
+ Attempting to set a non-L{str} attribute name on an L{X509NameType}
+ instance causes L{TypeError} to be raised.
+ """
+ name = self._x509name()
+ # Beyond these cases, you may also think that unicode should be
+ # rejected. Sorry, you're wrong. unicode is automatically converted to
+ # str outside of the control of X509Name, so there's no way to reject
+ # it.
+ self.assertRaises(TypeError, setattr, name, None, "hello")
+ self.assertRaises(TypeError, setattr, name, 30, "hello")
+ class evil(str):
+ pass
+ self.assertRaises(TypeError, setattr, name, evil(), "hello")
+
+
+ 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
+ raised.
+ """
+ name = self._x509name()
+ self.assertRaises(AttributeError, setattr, name, "no such thing", None)
+
+
def test_attributes(self):
"""
L{X509NameType} instances have attributes for each standard (?)
diff --git a/OpenSSL/util.h b/OpenSSL/util.h
index 4cef481..e634b01 100644
--- a/OpenSSL/util.h
+++ b/OpenSSL/util.h
@@ -137,4 +137,8 @@
#define PyOpenSSL_LongToHex(o) PyNumber_ToBase(o, 16)
#endif
+#ifndef Py_TYPE
+#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
+#endif
+
#endif
diff --git a/doc/pyOpenSSL.tex b/doc/pyOpenSSL.tex
index cef0a27..239133f 100644
--- a/doc/pyOpenSSL.tex
+++ b/doc/pyOpenSSL.tex
@@ -305,24 +305,6 @@
\versionadded{0.11}
\end{funcdesc}
-\subsubsection{X509Extension objects \label{openssl-x509ext}}
-
-X509Extension objects have the following methods:
-
-\begin{methoddesc}[X509Extension]{get_short_name}{}
-Retrieve the short descriptive name for this extension.
-
-The result is a byte string like \code{``basicConstraints''}.
-\versionadded{0.12}
-\end{methoddesc}
-
-\begin{methoddesc}[X509Extension]{get_data}{}
-Retrieve the data for this extension.
-
-The result is the ASN.1 encoded form of the extension data as a byte string.
-\versionadded{0.12}
-\end{methoddesc}
-
\subsubsection{X509 objects \label{openssl-x509}}
X509 objects have the following methods:
@@ -648,7 +630,17 @@
\end{methoddesc}
\begin{methoddesc}[X509Extension]{get_short_name}{}
-Return the short type name of the extension object.
+Retrieve the short descriptive name for this extension.
+
+The result is a byte string like \code{``basicConstraints''}.
+\versionadded{0.12}
+\end{methoddesc}
+
+\begin{methoddesc}[X509Extension]{get_data}{}
+Retrieve the data for this extension.
+
+The result is the ASN.1 encoded form of the extension data as a byte string.
+\versionadded{0.12}
\end{methoddesc}
\subsubsection{NetscapeSPKI objects \label{openssl-netscape-spki}}
@@ -849,6 +841,28 @@
handshake, but don't want to use SSLv2.
\end{datadesc}
+\begin{datadesc}{SSLEAY_VERSION}
+\dataline{SSLEAY_CFLAGS}
+\dataline{SSLEAY_BUILT_ON}
+\dataline{SSLEAY_PLATFORM}
+\dataline{SSLEAY_DIR}
+Constants used with \method{SSLeay_version} to specify what OpenSSL version
+information to retrieve. See the man page for the \function{SSLeay_version} C
+API for details.
+\end{datadesc}
+
+\begin{datadesc}{OPENSSL_VERSION_NUMBER}
+An integer giving the version number of the OpenSSL library used to build this
+version of pyOpenSSL. See the man page for the \function{SSLeay_version} C API
+for details.
+\end{datadesc}
+
+\begin{funcdesc}{SSLeay_version}{type}
+Retrieve a string describing some aspect of the underlying OpenSSL version. The
+type passed in should be one of the \constant{SSLEAY_*} constants defined in
+this module.
+\end{funcdesc}
+
\begin{datadesc}{ContextType}
See \class{Context}.
\end{datadesc}