aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xconfigure4
-rw-r--r--configure.ac4
-rw-r--r--rpkid/ext/POW.c3355
3 files changed, 932 insertions, 2431 deletions
diff --git a/configure b/configure
index af9775c6..68082f43 100755
--- a/configure
+++ b/configure
@@ -4490,9 +4490,9 @@ $as_echo "$OPENSSL_SO_GLOB" >&6; }
# search list to preempt conflicts with system copies.
CFLAGS="-I\${abs_top_srcdir}/openssl/openssl/include $CFLAGS"
- LIBS="\${abs_top_builddir}/openssl/openssl/libssl.a \${abs_top_builddir}/openssl/openssl/libcrypto.a $LIBS"
+ LIBS="\${abs_top_builddir}/openssl/openssl/libcrypto.a $LIBS"
else
- LIBS="$LIBS -lssl -lcrypto"
+ LIBS="$LIBS -lcrypto"
fi
if test $build_ca_tools = yes
diff --git a/configure.ac b/configure.ac
index dafa1154..c3f927de 100644
--- a/configure.ac
+++ b/configure.ac
@@ -440,9 +440,9 @@ then
# search list to preempt conflicts with system copies.
CFLAGS="-I\${abs_top_srcdir}/openssl/openssl/include $CFLAGS"
- LIBS="\${abs_top_builddir}/openssl/openssl/libssl.a \${abs_top_builddir}/openssl/openssl/libcrypto.a $LIBS"
+ LIBS="\${abs_top_builddir}/openssl/openssl/libcrypto.a $LIBS"
else
- LIBS="$LIBS -lssl -lcrypto"
+ LIBS="$LIBS -lcrypto"
fi
if test $build_ca_tools = yes
diff --git a/rpkid/ext/POW.c b/rpkid/ext/POW.c
index fdb863d0..f91d8129 100644
--- a/rpkid/ext/POW.c
+++ b/rpkid/ext/POW.c
@@ -1,38 +1,95 @@
-/*****************************************************************************/
-/* */
-/* Copyright (c) 2001, 2002, Peter Shannon */
-/* All rights reserved. */
-/* */
-/* Redistribution and use in source and binary forms, with or without */
-/* modification, are permitted provided that the following conditions */
-/* are met: */
-/* */
-/* * Redistributions of source code must retain the above */
-/* copyright notice, this list of conditions and the following */
-/* disclaimer. */
-/* */
-/* * Redistributions in binary form must reproduce the above */
-/* copyright notice, this list of conditions and the following */
-/* disclaimer in the documentation and/or other materials */
-/* provided with the distribution. */
-/* */
-/* * The name of the contributors may be used to endorse or promote */
-/* products derived from this software without specific prior */
-/* written permission. */
-/* */
-/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
-/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
-/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
-/* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS */
-/* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
-/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
-/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */
-/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */
-/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
-/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */
-/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-/* */
-/*****************************************************************************/
+/*
+ * This module started out as the core of Peter Shannon's "Python
+ * OpenSSL Wrappers" package, an excellent but somewhat dated package
+ * which I encountered while looking for some halfway sane way to cram
+ * RFC 3779 certificate support code into Python.
+ *
+ * At this point enough of the code has been added or rewritten that
+ * it's unclear (either way) whether this code properly qualifies as a
+ * derivative work. Given that both Peter's original code and all of
+ * subsequent changes to it were done under something equivalent to a
+ * BSD license, this may not matter very much, but the following
+ * attempts to give proper credit to all concerned.
+ *
+ ****
+ *
+ * Copyright (C) 2009--2012 Internet Systems Consortium ("ISC")
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ ****
+ *
+ * Portions copyright (C) 2006--2008 American Registry for Internet
+ * Numbers ("ARIN")
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ARIN DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ARIN BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ ****
+ *
+ * Portions Copyright (c) 2001, 2002, Peter Shannon
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * * The name of the contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* $Id: rcynic.c 4613 2012-07-30 23:24:15Z sra $ */
+
+/*
+ * Disable compilation of X509 certificate signature and verification
+ * API. We don't currently need this for RPKI but I'm not quite ready
+ * to rip it out yet. The current API has issues which I'd rather
+ * defer until I decide whether we need to fix it, so just omit the
+ * code for now.
+ */
+
+#define ENABLE_X509_CERTIFICATE_SIGNATURE_AND_VERIFICATION 0
#include <Python.h>
@@ -52,7 +109,7 @@
#include <time.h>
#include <string.h>
-// PEM encoded data types
+/* PEM encoded data types */
#define RSA_PUBLIC_KEY 1
#define RSA_PRIVATE_KEY 2
#define DSA_PUBLIC_KEY 3
@@ -60,15 +117,15 @@
#define DH_PUBLIC_KEY 5
#define DH_PRIVATE_KEY 6
#define X509_CERTIFICATE 7
-#define X_X509_CRL 8 // X509_CRL already used by OpenSSL library
+#define X_X509_CRL 8 /* X509_CRL already used by OpenSSL library */
#define CMS_MESSAGE 9
-// Asymmetric ciphers
+/* Asymmetric ciphers */
#define RSA_CIPHER 1
#define DSA_CIPHER 2
#define DH_CIPHER 3
-// Digests
+/* Digests */
#define MD5_DIGEST 2
#define SHA_DIGEST 3
#define SHA1_DIGEST 4
@@ -76,68 +133,39 @@
#define SHA384_DIGEST 7
#define SHA512_DIGEST 8
-// Object format
+/* Object format */
#define SHORTNAME_FORMAT 1
#define LONGNAME_FORMAT 2
-#define OIDNAME_FORMAT 3
+#define OIDNAME_FORMAT 3
-// Output format
+/* Output format */
#define PEM_FORMAT 1
#define DER_FORMAT 2
-// Object check functions
+/* Object check functions */
#define X_X509_Check(op) ((op)->ob_type == &x509type)
#define X_X509_store_Check(op) ((op)->ob_type == &x509_storetype)
#define X_X509_crl_Check(op) ((op)->ob_type == &x509_crltype)
-#define X_X509_revoked_Check(op) ((op)->ob_type == &x509_revokedtype)
#define X_asymmetric_Check(op) ((op)->ob_type == &asymmetrictype)
#define X_digest_Check(op) ((op)->ob_type == &digesttype)
#define X_cms_Check(op) ((op)->ob_type == &cmstype)
static char pow_module__doc__ [] =
-"<moduleDescription>\n"
-" <header>\n"
-" <name>POW</name>\n"
-" <author>Peter Shannon</author>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This third major release of POW addresses the most critical missing\n"
-" parts of functionality, X509v3 support. Initially I thought adding\n"
-" support via the OpenSSL code would be the easiest option but this\n"
-" proved to be incorrect mainly due to the way I have chosen to handle\n"
-" the complex data such as <classname>directoryNames</classname> and\n"
-" <classname>generalNames</classname>. It is easier in python to\n"
-" construct complex sets of data using lists and dictionaries than\n"
-" coordinate large numbers of objects and method calls. This is no\n"
-" criticism, it is just extremely easy. Coding complex data such as the\n"
-" <classname>certificatePolicies</classname> coding coding routines in C\n"
-" to handle the data proved laborous and ultimately error prone.\n"
-" </para>\n"
-" <para>\n"
-" PKIX structures are supported by a few operations on the relevant POW\n"
-" objects and through a Python library which is modelled on the DER\n"
-" encoding rules. Modeling DER does expose some of the complexities of\n"
-" the ASN1 specifications but avoids coding many assumptions into the\n"
-" data structures and the interface for the objects. For an example of\n"
-" overly complex definitions take a look at the\n"
-" <classname>Name</classname> object in RFC3280. It is equally\n"
-" important that modeling DER in the way leads to a library which is\n"
-" trivial to extend to support new objects - simple objects are one\n"
-" liners and complex objects only require the definition of a new\n"
-" constructor.\n"
-" </para>\n"
-" <para>\n"
-" functionality have been plugged. The <classname>Ssl</classname> class has received\n"
-" several new features relating to security. Other areas have been\n"
-" improved: PRNG support, certificate and CRL signing, certificate chain\n"
-" and client verification. Many bugs have been fixed, and certain\n"
-" parts of code re-written where necessary. I hope you enjoy using POW\n"
-" and please feel free to send me feature requests and bug reports.\n"
-" </para>\n"
-" </body>\n"
-"</moduleDescription>\n"
-;
+ "Python interface to RFC-3779-enabled OpenSSL. This code is intended\n"
+ "to support the rpki.net toolset.\n"
+ "\n"
+ "This code started out life as Peter Shannon's excellent \"Python OpenSSL\n"
+ "Wrappers\" package. It has been extensively modified since then, to add\n"
+ "support for things needed for the RPKI protocols, to upgrade the code\n"
+ "to use modern (circa Python 2.7) classes, and to remove code not\n"
+ "needed for RPKI.\n"
+ ;
+
+#define LAME_DISCLAIMER_IN_ALL_CLASS_DOCUMENTATION \
+ "The documentation for this class used to provide a nice example of how\n" \
+ "to use the class. Sadly, most of what was in that example is now\n" \
+ "obsolete due to recent or impending API changes. Once the new API is\n" \
+ "stable, this documentation should be rewritten to provide such examples.\n"
/*========== Pre-definitions ==========*/
static PyObject
@@ -150,7 +178,6 @@ static PyTypeObject
x509type,
x509_storetype,
x509_crltype,
- x509_revokedtype,
asymmetrictype,
digesttype,
cmstype;
@@ -174,11 +201,6 @@ typedef struct {
typedef struct {
PyObject_HEAD
- X509_REVOKED *revoked;
-} x509_revoked_object;
-
-typedef struct {
- PyObject_HEAD
void *cipher;
int key_type;
int cipher_type;
@@ -197,11 +219,6 @@ typedef struct {
/*========== C structs ==========*/
-/* Declarations */
-
-static PyObject *
-x509_revoked_object_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
/*========== helper functions ==========*/
/*
@@ -234,7 +251,7 @@ x509_revoked_object_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
goto error; \
} while (0)
-#define lose_no_memory() \
+#define lose_no_memory() \
do { \
PyErr_NoMemory(); \
goto error; \
@@ -248,7 +265,7 @@ x509_revoked_object_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
#define lose_openssl_error(_msg_) \
do { \
- set_openssl_exception(OpenSSLErrorObject, (_msg_)); \
+ set_openssl_exception(OpenSSLErrorObject, (_msg_)); \
goto error; \
} while (0)
@@ -282,11 +299,11 @@ evp_digest_factory(int digest_type)
{
switch (digest_type) {
case MD5_DIGEST: return EVP_md5();
- case SHA_DIGEST: return EVP_sha();
- case SHA1_DIGEST: return EVP_sha1();
- case SHA256_DIGEST: return EVP_sha256();
- case SHA384_DIGEST: return EVP_sha384();
- case SHA512_DIGEST: return EVP_sha512();
+ case SHA_DIGEST: return EVP_sha();
+ case SHA1_DIGEST: return EVP_sha1();
+ case SHA256_DIGEST: return EVP_sha256();
+ case SHA384_DIGEST: return EVP_sha384();
+ case SHA512_DIGEST: return EVP_sha512();
default: return NULL;
}
}
@@ -295,13 +312,13 @@ static int
evp_digest_nid(int digest_type)
{
switch (digest_type) {
- case MD5_DIGEST: return NID_md5;
- case SHA_DIGEST: return NID_sha;
- case SHA1_DIGEST: return NID_sha1;
- case SHA256_DIGEST: return NID_sha256;
- case SHA384_DIGEST: return NID_sha384;
- case SHA512_DIGEST: return NID_sha512;
- default: return NID_undef;
+ case MD5_DIGEST: return NID_md5;
+ case SHA_DIGEST: return NID_sha;
+ case SHA1_DIGEST: return NID_sha1;
+ case SHA256_DIGEST: return NID_sha256;
+ case SHA384_DIGEST: return NID_sha384;
+ case SHA512_DIGEST: return NID_sha512;
+ default: return NID_undef;
}
}
@@ -600,16 +617,26 @@ ASN1_TIME_to_Python(ASN1_TIME *t)
return result;
}
-static int
-python_ASN1_TIME_set_string(ASN1_TIME *t, const char *s)
+static ASN1_TIME *
+Python_to_ASN1_TIME(const char *s)
{
- if (t == NULL || s == NULL || strlen(s) < 10)
- return 0;
+ ASN1_TIME *t = NULL;
+ int ok;
+
+ if (s == NULL || strlen(s) < 10 || (t = ASN1_TIME_new()) == NULL)
+ return NULL;
+
if ((s[0] == '1' && s[1] == '9' && s[2] > '4') ||
(s[0] == '2' && s[1] == '0' && s[2] < '5'))
- return ASN1_UTCTIME_set_string(t, s + 2);
+ ok = ASN1_UTCTIME_set_string(t, s + 2);
else
- return ASN1_GENERALIZEDTIME_set_string(t, s);
+ ok = ASN1_GENERALIZEDTIME_set_string(t, s);
+
+ if (ok)
+ return t;
+
+ ASN1_TIME_free(t);
+ return NULL;
}
/*
@@ -727,19 +754,8 @@ x509_object_write_helper(x509_object *self, int format)
}
static char x509_object_pem_write__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509</memberof>\n"
-" <name>pemWrite</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns a PEM encoded certificate as a\n"
-" string.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns a PEM- encoded certificate as a string.\n"
+ ;
static PyObject *
x509_object_pem_write(x509_object *self)
@@ -748,19 +764,8 @@ x509_object_pem_write(x509_object *self)
}
static char x509_object_der_write__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509</memberof>\n"
-" <name>derWrite</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns a DER encoded certificate as a\n"
-" string.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns a DER encoded certificate as a string.\n"
+ ;
static PyObject *
x509_object_der_write(x509_object *self)
@@ -771,22 +776,12 @@ x509_object_der_write(x509_object *self)
/*
* Currently this function only supports RSA keys.
*/
+
static char x509_object_set_public_key__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509</memberof>\n"
-" <name>setPublicKey</name>\n"
-" <parameter>key</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method sets the public key for this certificate object. The\n"
-" parameter <parameter>key</parameter> should be an instance of\n"
-" <classname>Asymmetric</classname> containing a public key.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method sets the public key for this certificate object.\n"
+ "The \"key\" parameter should be an instance of the Asymmetric class,\n"
+ "containing a public key.\n"
+ ;
static PyObject *
x509_object_set_public_key(x509_object *self, PyObject *args)
@@ -812,34 +807,23 @@ x509_object_set_public_key(x509_object *self, PyObject *args)
}
static char x509_object_sign__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509</memberof>\n"
-" <name>sign</name>\n"
-" <parameter>key</parameter>\n"
-" <optional><parameter>digest = SHA256_DIGEST</parameter></optional>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method signs a certificate with a private key. See the\n"
-" example for the methods which should be invoked before signing a\n"
-" certificate. <parameter>key</parameter> should be an instance of\n"
-" <classname>Asymmetric</classname> containing a private key.\n"
-" The optional parameter <parameter>digest</parameter> indicates\n"
-" which digest function should be used to compute the hash to be\n"
-" signed, it should be one of the following:\n"
-" </para>\n"
-" <simplelist>\n"
-" <member><constant>MD5_DIGEST</constant></member>\n"
-" <member><constant>SHA_DIGEST</constant></member>\n"
-" <member><constant>SHA1_DIGEST</constant></member>\n"
-" <member><constant>SHA256_DIGEST</constant></member>\n"
-" <member><constant>SHA384_DIGEST</constant></member>\n"
-" <member><constant>SHA512_DIGEST</constant></member>\n"
-" </simplelist>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method signs a certificate with a private key.\n"
+ "\n"
+ "The \"key\" parameter should be an instance of the Asymmetric class,\n"
+ "containing a private key.\n"
+ "\n"
+ "The optional \"digest\" parameter indicates which digest to compute and\n"
+ "sign, and should be one of the following:\n"
+ "\n"
+ "* MD5_DIGEST\n"
+ "* SHA_DIGEST\n"
+ "* SHA1_DIGEST\n"
+ "* SHA256_DIGEST\n"
+ "* SHA384_DIGEST\n"
+ "* SHA512_DIGEST\n"
+ "\n"
+ "The default digest algorithm is SHA-256.\n"
+ ;
static PyObject *
x509_object_sign(x509_object *self, PyObject *args)
@@ -875,20 +859,8 @@ x509_object_sign(x509_object *self, PyObject *args)
}
static char x509_object_get_version__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509</memberof>\n"
-" <name>getVersion</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns the version number from the version field of\n"
-" this certificate.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
-
+ "This method returns the version number from the version field of this certificate.\n"
+ ;
static PyObject *
x509_object_get_version(x509_object *self)
@@ -897,20 +869,8 @@ x509_object_get_version(x509_object *self)
}
static char x509_object_set_version__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509</memberof>\n"
-" <name>setVersion</name>\n"
-" <parameter>version</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method sets the version number in the version field of\n"
-" this certificate. <parameter>version</parameter> should be an\n"
-" integer.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
+ "This method sets the version number in the version field of this certificate.\n"
+ "The \"version\" parameter should be an integer.\n"
;
static PyObject *
@@ -932,19 +892,8 @@ x509_object_set_version(x509_object *self, PyObject *args)
}
static char x509_object_get_serial__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509</memberof>\n"
-" <name>getSerial</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method get the serial number in the serial field of\n"
-" this certificate.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method get the serial number in the serial field of this certificate.\n"
+ ;
static PyObject *
x509_object_get_serial(x509_object *self)
@@ -953,76 +902,56 @@ x509_object_get_serial(x509_object *self)
}
static char x509_object_set_serial__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509</memberof>\n"
-" <name>setSerial</name>\n"
-" <parameter>serial</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method sets the serial number in the serial field of\n"
-" this certificate. <parameter>serial</parameter> should ba an\n"
-" integer.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method sets the serial number in the serial field of this certificate.\n"
+ "The \"serial\" parameter should ba an integer.\n"
+ ;
static PyObject *
x509_object_set_serial(x509_object *self, PyObject *args)
{
long c_serial = 0;
- ASN1_INTEGER *asn1_serial = NULL;
+ ASN1_INTEGER *a_serial = NULL;
if (!PyArg_ParseTuple(args, "l", &c_serial))
goto error;
- if ((asn1_serial = ASN1_INTEGER_new()) == NULL ||
- !ASN1_INTEGER_set(asn1_serial, c_serial) ||
- !X509_set_serialNumber(self->x509, asn1_serial))
+ if ((a_serial = ASN1_INTEGER_new()) == NULL ||
+ !ASN1_INTEGER_set(a_serial, c_serial) ||
+ !X509_set_serialNumber(self->x509, a_serial))
lose_no_memory();
- ASN1_INTEGER_free(asn1_serial);
+ ASN1_INTEGER_free(a_serial);
Py_RETURN_NONE;
error:
- ASN1_INTEGER_free(asn1_serial);
+ ASN1_INTEGER_free(a_serial);
return NULL;
}
static char x509_object_get_issuer__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509</memberof>\n"
-" <name>getIssuer</name>\n"
-" <parameter>format = OIDNAME_FORMAT</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns a tuple containing the issuers name. Each\n"
-" element of the tuple is a tuple with 2 elements. The first tuple\n"
-" is an object name and the second is it's value. Both issuer and\n"
-" subject are names distinguished normally composed of a small\n"
-" number of objects:\n"
-" </para>\n"
-" <simplelist>\n"
-" <member><constant>c</constant> or <constant>countryName</constant></member>\n"
-" <member><constant>st</constant> or <constant>stateOrProvinceName</constant></member>\n"
-" <member><constant>o</constant> or <constant>organizationName</constant></member>\n"
-" <member><constant>l</constant> or <constant>localityName</constant></member>\n"
-" <member><constant>ou</constant> or <constant>organizationalUnitName</constant></member>\n"
-" <member><constant>cn</constant> or <constant>commonName</constant></member>\n"
-" </simplelist>\n"
-" <para>\n"
-" The data type varies from one object to another, however, all the\n"
-" common objects are strings. It would be possible to specify any\n"
-" kind of object but that would certainly adversely effect\n"
-" portability and is not recommended.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns a tuple representing the issuers name.\n"
+ "Each element of this tuple is another tuple representing one\n"
+ "\"Relative Distinguished Name\" (RDN), each element of which in turn\n"
+ "is yet another tuple representing one AttributeTypeAndValue pair.\n"
+ "In practice, RDNs containing multiple attributes are rare, thus the RDN\n"
+ "tuples will usually be exactly one element long, but using this\n"
+ "structure allows us to represent the general case.\n"
+ "\n"
+ "The AttributeTypeANdValue pairs are two-element tuples, the first\n"
+ "element of which is a string representing an Object Identifier (OID),\n"
+ "the second of which contains the attribute value.\n"
+ "\n"
+ "This method takes an optional \"format\" parameter which controls\n"
+ "the format in which OIDs are returned. Allowed values are:\n"
+ "\n"
+ " * SHORTNAME_FORMAT (the OpenSSL \"short name\" for this OID)\n"
+ " * LONGNAME_FORMAT (the OpenSSL \"long name\" for this OID)\n"
+ " * OIDNAME_FORMAT (the OID in dotted decimal numeric format)\n"
+ "\n"
+ "The default is OIDNAME_FORMAT.\n"
+ "\n"
+ "See RFC 5280 section 4.1.2.4 for details of the ASN.1 structure.\n"
+ ;
static PyObject *
x509_object_get_issuer(x509_object *self, PyObject *args)
@@ -1041,21 +970,10 @@ x509_object_get_issuer(x509_object *self, PyObject *args)
}
static char x509_object_get_subject__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509</memberof>\n"
-" <name>getSubject</name>\n"
-" <parameter>format = OIDNAME_FORMAT</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns a tuple containing the subjects name. See\n"
-" <function>getIssuer</function> for a description of the returned\n"
-" object's format.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns a tuple containing the subjects name. See\n"
+ "the \"getIssuer\" method for details of the return value\n"
+ "and use of the optional \"format\" parameter.\n"
+ ;
static PyObject *
x509_object_get_subject(x509_object *self, PyObject *args)
@@ -1074,21 +992,10 @@ x509_object_get_subject(x509_object *self, PyObject *args)
}
static char x509_object_set_subject__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509</memberof>\n"
-" <name>setSubject</name>\n"
-" <parameter>name</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method is used to set the subjects name.\n"
-" <parameter>name</parameter> can be comprised of lists or tuples in\n"
-" the format described in the <function>getIssuer</function> method.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method is used to set the certificate's subject name.\n"
+ "The \"name\" parameter should be in the same format as the return\n"
+ "value from the \"getIssuer\" method.\n"
+ ;
static PyObject *
x509_object_set_subject(x509_object *self, PyObject *args)
@@ -1118,21 +1025,10 @@ x509_object_set_subject(x509_object *self, PyObject *args)
}
static char x509_object_set_issuer__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509</memberof>\n"
-" <name>setIssuer</name>\n"
-" <parameter>name</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method is used to set the issuers name.\n"
-" <parameter>name</parameter> can be comprised of lists or tuples in\n"
-" the format described in the <function>getissuer</function> method.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method is used to set the certificate's issuer name.\n"
+ "The \"name\" parameter should be in the same format as the return\n"
+ "value from the \"getIssuer\" method.\n"
+ ;
static PyObject *
x509_object_set_issuer(x509_object *self, PyObject *args)
@@ -1162,256 +1058,186 @@ x509_object_set_issuer(x509_object *self, PyObject *args)
}
static char x509_object_get_not_before__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509</memberof>\n"
-" <name>getNotBefore</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" In a change from previous releases, for reasons of portability\n"
-" and to avoid hard to fix issues with problems in unreliable time\n"
-" functions, this function returns a UTCTime string. You\n"
-" can use the function <function>time2utc</function> to convert to a\n"
-" string if you like and <function>utc2time</function> to back.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns the certificate's \"notBefore\" value\n"
+ "in the form of a GeneralizedTime string as restricted by RFC 5280.\n"
+ "The code automatically converts RFC-5280-compliant UTCTime strings\n"
+ "into the GeneralizedTime format, so that Python code need not worry\n"
+ "about the conversion rules.\n"
+ ;
static PyObject *
x509_object_get_not_before (x509_object *self)
{
- return ASN1_TIME_to_Python(self->x509->cert_info->validity->notBefore);
+ return ASN1_TIME_to_Python(X509_get_notBefore(self->x509));
}
static char x509_object_get_not_after__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509</memberof>\n"
-" <name>getNotAfter</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" In a change from previous releases, for reasons of portability\n"
-" and to avoid hard to fix issues with problems in unreliable time\n"
-" functions, this function returns a UTCTime string. You\n"
-" can use the function <function>time2utc</function> to convert to a\n"
-" string if you like and <function>utc2time</function> to back.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns the certificate's \"notAfter\" value\n"
+ "in the form of a GeneralizedTime string as restricted by RFC 5280.\n"
+ "The code automatically converts RFC-5280-compliant UTCTime strings\n"
+ "into the GeneralizedTime format, so that Python code need not worry\n"
+ "about the conversion rules.\n"
+ ;
static PyObject *
x509_object_get_not_after (x509_object *self)
{
- return ASN1_TIME_to_Python(self->x509->cert_info->validity->notAfter);
+ return ASN1_TIME_to_Python(X509_get_notAfter(self->x509));
}
static char x509_object_set_not_after__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509</memberof>\n"
-" <name>setNotAfter</name>\n"
-" <parameter>time</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" In a change from previous releases, for reasons of portability\n"
-" and to avoid hard to fix issues with problems in unreliable time\n"
-" functions, this accepts one parameter, a UTCTime string. You\n"
-" can use the function <function>time2utc</function> to convert to a\n"
-" string if you like and <function>utc2time</function> to back.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method sets the certificate's \"notAfter\" value.\n"
+ "\n"
+ "The \"time\" parameter should be in the form of a GeneralizedTime string\n"
+ "as restricted by RFC 5280. The code automatically converts to UTCTime\n"
+ "when the RFC 5280 rules require UTCTime instead of GeneralizedTime,\n"
+ "so that Python code need not worry about the conversion rules.\n"
+ ;
static PyObject *
x509_object_set_not_after (x509_object *self, PyObject *args)
{
- char *new_time = NULL;
+ char *s = NULL;
+ ASN1_TIME *t = NULL;
- if (!PyArg_ParseTuple(args, "s", &new_time))
+ if (!PyArg_ParseTuple(args, "s", &s))
goto error;
- if (!python_ASN1_TIME_set_string(self->x509->cert_info->validity->notAfter, new_time))
+ if ((t = Python_to_ASN1_TIME(s)) == NULL)
+ lose("Couldn't convert notAfter string");
+
+ if (!X509_set_notAfter(self->x509, t))
lose("Couldn't set notAfter");
+ ASN1_TIME_free(t);
Py_RETURN_NONE;
error:
-
+ ASN1_TIME_free(t);
return NULL;
}
static char x509_object_set_not_before__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509</memberof>\n"
-" <name>setNotBefore</name>\n"
-" <parameter>time</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" In a change from previous releases, for reasons of portability\n"
-" and to avoid hard to fix issues with problems in unreliable time\n"
-" functions, this accepts one parameter, a UTCTime string. You\n"
-" can use the function <function>time2utc</function> to convert to a\n"
-" string if you like and <function>utc2time</function> to back.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method sets the certificate's \"notBefore\" value.\n"
+ "\n"
+ "The \"time\" parameter should be in the form of a GeneralizedTime string\n"
+ "as restricted by RFC 5280. The code automatically converts to UTCTime\n"
+ "when the RFC 5280 rules require UTCTime instead of GeneralizedTime,\n"
+ "so that Python code need not worry about the conversion rules.\n"
+ ;
static PyObject *
x509_object_set_not_before (x509_object *self, PyObject *args)
{
- char *new_time = NULL;
+ char *s = NULL;
+ ASN1_TIME *t = NULL;
- if (!PyArg_ParseTuple(args, "s", &new_time))
+ if (!PyArg_ParseTuple(args, "s", &s))
goto error;
- if (!python_ASN1_TIME_set_string(self->x509->cert_info->validity->notBefore, new_time))
+ if ((t = Python_to_ASN1_TIME(s)) == NULL)
+ lose("Couldn't convert notBefore string");
+
+ if (!X509_set_notBefore(self->x509, t))
lose("Couldn't set notBefore");
+ ASN1_TIME_free(t);
Py_RETURN_NONE;
error:
-
+ ASN1_TIME_free(t);
return NULL;
}
static char x509_object_add_extension__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509</memberof>\n"
-" <name>addExtension</name>\n"
-" <parameter>extensionName</parameter>\n"
-" <parameter>critical</parameter>\n"
-" <parameter>extensionValue</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method adds an extension to this certificate.\n"
-" <parameter>extensionName</parameter> should be the of the\n"
-" extension. <parameter>critical</parameter> should an integer, 1\n"
-" for true and 0 for false. <parameter>extensionValue</parameter>\n"
-" should be a string, DER encoded value of the extension. The name\n"
-" of the extension must be correct according to OpenSSL and can be\n"
-" checked in the <constant>objects.h</constant> header file, part of\n"
-" the OpenSSL source distribution. In the majority of cases they\n"
-" are the same as those defined in <constant>POW._oids</constant>\n"
-" but if you do encounter problems is may be worth checking.\n"
-" </para>\n"
-" <example>\n"
-" <title><function>addExtension</function> method usage</title>\n"
-" <programlisting>\n"
-" basic = POW.pkix.BasicConstraints()\n"
-" basic.set([1,5])\n"
-" serverCert.addExtension('basicConstraints', 0, basic.toString())\n"
-" </programlisting>\n"
-" </example>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method provides a generalized mechanism for adding an X509v3\n"
+ "extension to a certificate. Sadly, this is less useful than it might\n"
+ "at first appear, because the extension to be added must be encoded using\n"
+ "ASN.1 DER for encapsulation in the extension as an OCTET STRING.\n"
+ "It might be possible to make this method more useful by combining it\n"
+ "with code using the OpenSSL ASN1_generate_v3(), ASN1_generate_nconf(),\n"
+ "X509V3_EXT_conf_nid(), or X509V3_EXT_nconf() functions, but for RPKI\n"
+ "work we probably want extension-specific methods anyway. For now, we\n"
+ "retain this API function, but it may go away in the near future.\n"
+ "\n"
+ "This method takes three parameters:\n"
+ "\n"
+ " * \"name\", an OpenSSL \"short name\"\n"
+ " * \"critical\", a boolean\n"
+ " * \"value\", the DER-encoded extension value as a Python string\n"
+ ;
static PyObject *
x509_object_add_extension(x509_object *self, PyObject *args)
{
- int critical = 0, nid = 0, len = 0;
+ int critical = 0, len = 0, ok = 0;
char *name = NULL;
unsigned char *buf = NULL;
+ ASN1_OBJECT *oid = NULL;
ASN1_OCTET_STRING *octetString = NULL;
- X509_EXTENSION *extn = NULL;
+ X509_EXTENSION *ext = NULL;
if (!PyArg_ParseTuple(args, "sis#", &name, &critical, &buf, &len))
goto error;
- if ((octetString = M_ASN1_OCTET_STRING_new()) == NULL)
- lose_no_memory();
-
- if (!ASN1_OCTET_STRING_set(octetString, buf, len))
- lose_openssl_error("Couldn't set ASN.1 OCTET STRING");
-
- if ((nid = OBJ_txt2nid(name)) == NID_undef)
+ if ((oid = OBJ_txt2obj(name, 0)) == NULL)
lose("Extension has unknown object identifier");
- if ((extn = X509_EXTENSION_create_by_NID(NULL, nid, critical, octetString)) == NULL)
+ if ((octetString = ASN1_OCTET_STRING_new()) == NULL ||
+ !ASN1_OCTET_STRING_set(octetString, buf, len))
+ lose_no_memory();
+
+ if ((ext = X509_EXTENSION_create_by_OBJ(NULL, oid, critical, octetString)) == NULL)
lose_openssl_error("Unable to create ASN.1 X.509 Extension object");
- if ((!self->x509->cert_info->extensions &&
- (self->x509->cert_info->extensions = sk_X509_EXTENSION_new_null()) == NULL) ||
- !sk_X509_EXTENSION_push(self->x509->cert_info->extensions, extn))
+ if (!X509_add_ext(self->x509, ext, -1))
lose_no_memory();
- Py_RETURN_NONE;
+ ok = 1;
- error:
- X509_EXTENSION_free(extn);
- return NULL;
+ error: /* Fall through */
+ ASN1_OBJECT_free(oid);
+ ASN1_OCTET_STRING_free(octetString);
+ X509_EXTENSION_free(ext);
+
+ if (ok)
+ Py_RETURN_NONE;
+ else
+ return NULL;
}
static char x509_object_clear_extensions__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509</memberof>\n"
-" <name>clearExtensions</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method clears the structure which holds the extension for\n"
-" this certificate.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method clears all extensions attached to this certificate.\n"
+ ;
static PyObject *
x509_object_clear_extensions(x509_object *self)
{
- sk_X509_EXTENSION_free(self->x509->cert_info->extensions);
- self->x509->cert_info->extensions = NULL;
+ X509_EXTENSION *ext;
+
+ while ((ext = X509_delete_ext(self->x509, 0)) != NULL)
+ X509_EXTENSION_free(ext);
+
Py_RETURN_NONE;
}
static char x509_object_count_extensions__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509</memberof>\n"
-" <name>countExtensions</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns the size of the structure which holds the\n"
-" extension for this certificate.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns the number of extensions attached to this certificate.\n"
+ ;
static PyObject *
x509_object_count_extensions(x509_object *self)
{
- return Py_BuildValue("i", sk_X509_EXTENSION_num(self->x509->cert_info->extensions));
+ return Py_BuildValue("i", X509_get_ext_count(self->x509));
}
static char x509_object_get_extension__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509</memberof>\n"
-" <name>getExtension</name>\n"
-" <parameter>index</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns a tuple equivalent the parameters of\n"
-" <function>addExtension</function>.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns a tuple equivalent the parameters of the\n"
+ "\"addExtension\" method, and suffers from similar limitations.\n"
+ "\n"
+ "The \"index\" parameter is the position in the extension list of\n"
+ "the extension to be returned.\n"
+ ;
static PyObject *
x509_object_get_extension(x509_object *self, PyObject *args)
@@ -1424,9 +1250,11 @@ x509_object_get_extension(x509_object *self, PyObject *args)
if (!PyArg_ParseTuple(args, "i", &ext_num))
goto error;
- if ((ext = sk_X509_EXTENSION_value(self->x509->cert_info->extensions, ext_num)) == NULL)
+ if ((ext = X509_get_ext(self->x509, ext_num)) == NULL)
lose_openssl_error("Couldn't get extension");
+#warning OpenSSL NIDs and longNames again, should take format or just return decimal OID
+
if ((ext_nid = OBJ_obj2nid(ext->object)) == NID_undef)
lose("Extension has unknown object identifier");
@@ -1440,15 +1268,15 @@ x509_object_get_extension(x509_object *self, PyObject *args)
return NULL;
}
-static char x509_object_get_ski__doc__[] = "Not written yet.";
+static char x509_object_get_ski__doc__[] =
+ "This method returns the Subject Key Identifier (SKI) value for this\n"
+ "certificate, or None if the certificate has no SKI extension"
+ ;
static PyObject *
x509_object_get_ski(x509_object *self, PyObject *args)
{
- /*
- * Called for side-effect (calls x509v3_cache_extensions() for us).
- */
- (void) X509_check_ca(self->x509);
+ (void) X509_check_ca(self->x509); /* Called for side-effect */
if (self->x509->skid == NULL)
Py_RETURN_NONE;
@@ -1457,19 +1285,8 @@ x509_object_get_ski(x509_object *self, PyObject *args)
}
static char x509_object_pprint__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509</memberof>\n"
-" <name>pprint</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns a formatted string showing the information\n"
-" held in the certificate.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns a pretty-printed rendition of the certificate.\n"
+ ;
static PyObject *
x509_object_pprint(x509_object *self)
@@ -1524,52 +1341,10 @@ x509_object_dealloc(x509_object *self)
}
static char x509type__doc__[] =
-"<class>\n"
-" <header>\n"
-" <name>X509</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This class provides access to a significant proportion of X509\n"
-" functionality of OpenSSL.\n"
-" </para>\n"
-"\n"
-" <example>\n"
-" <title><classname>x509</classname> class usage</title>\n"
-" <programlisting>\n"
-" privateFile = open('test/private.key', 'r')\n"
-" publicFile = open('test/public.key', 'r')\n"
-" certFile = open('test/cacert.pem', 'w')\n"
-"\n"
-" publicKey = POW.pemRead(POW.RSA_PUBLIC_KEY, publicFile.read())\n"
-" privateKey = POW.pemRead(POW.RSA_PRIVATE_KEY, privateFile.read(), 'pass')\n"
-"\n"
-" c = POW.X509()\n"
-"\n"
-" name = [ ['C', 'GB'], ['ST', 'Hertfordshire'],\n"
-" ['O','The House'], ['CN', 'Peter Shannon'] ]\n"
-"\n"
-" c.setIssuer(name)\n"
-" c.setSubject(name)\n"
-" c.setSerial(0)\n"
-" t1 = POW.pkix.time2utc(time.time())\n"
-" t2 = POW.pkix.time2utc(time.time() + 60*60*24*365)\n"
-" c.setNotBefore(t1)\n"
-" c.setNotAfter(t2)\n"
-" c.setPublicKey(publicKey)\n"
-" c.sign(privateKey)\n"
-"\n"
-" certFile.write(c.pemWrite())\n"
-"\n"
-" privateFile.close()\n"
-" publicFile.close()\n"
-" certFile.close()\n"
-" </programlisting>\n"
-" </example>\n"
-"\n"
-" </body>\n"
-"</class>\n"
-;
+ "This class represents an X.509 certificate.\n"
+ "\n"
+ LAME_DISCLAIMER_IN_ALL_CLASS_DOCUMENTATION
+ ;
static PyTypeObject x509type = {
PyObject_HEAD_INIT(0)
@@ -1630,42 +1405,43 @@ x509_store_object_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return NULL;
}
+#if ENABLE_X509_CERTIFICATE_SIGNATURE_AND_VERIFICATION
+
static char x509_store_object_verify__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Store</memberof>\n"
-" <name>verify</name>\n"
-" <parameter>certificate</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" The <classname>X509Store</classname> method\n"
-" <function>verify</function> is based on the\n"
-" <function>X509_verify_cert</function>. It handles certain aspects\n"
-" of verification but not others. The certificate will be verified\n"
-" against <constant>notBefore</constant>,\n"
-" <constant>notAfter</constant> and trusted certificates.\n"
-" It crucially will not handle checking the certificate against\n"
-" CRLs. This functionality will probably make it into OpenSSL\n"
-" 0.9.7.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method performs X.509 certificate verification using\n"
+ "the OpenSSL X509_verify_cert() function.\n"
+ "\n"
+ "The \"certificate\" parameter is the certificate to verify, and\n"
+ "should be an X509 object.\n"
+ ;
+
+#warning Check X509_verify_cert options
+/*
+ * I once knew all the grotty details of how X509_verify_cert() gets
+ * its control flags and data, but don't remember off the top of my head,
+ * and would prefer not to stop the current documentation cleanup pass
+ * to relearn all of that. So come back to this.
+ *
+ * Mostly what I'm worried about here is the ten zillion flags that
+ * tell X509_verify_cert() whether to check CRLs, whether to verify
+ * the whole chain, whether to enforce policy constraints, etc etc.
+ * This may all be covered already, I just don't remember. Might not
+ * even matter, not sure whether anything is calling this method.
+ */
static PyObject *
x509_store_object_verify(x509_store_object *self, PyObject *args)
{
- X509_STORE_CTX csc;
+ X509_STORE_CTX ctx;
x509_object *x509 = NULL;
int ok;
if (!PyArg_ParseTuple(args, "O!", &x509type, &x509))
goto error;
- X509_STORE_CTX_init(&csc, self->store, x509->x509, NULL);
- ok = X509_verify_cert(&csc) == 1;
- X509_STORE_CTX_cleanup(&csc);
+ X509_STORE_CTX_init(&ctx, self->store, x509->x509, NULL);
+ ok = X509_verify_cert(&ctx) == 1;
+ X509_STORE_CTX_cleanup(&ctx);
return PyBool_FromLong(ok);
@@ -1675,41 +1451,21 @@ x509_store_object_verify(x509_store_object *self, PyObject *args)
}
static char x509_store_object_verify_chain__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Store</memberof>\n"
-" <name>verifyChain</name>\n"
-" <parameter>certificate</parameter>\n"
-" <parameter>chain</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" The <classname>X509Store</classname> method <function>verifyChain</function>\n"
-" is based on the <function>X509_verify_cert</function> but is initialised\n"
-" with a <classname>X509</classname> object to verify and list of\n"
-" <classname>X509</classname> objects which form a chain to a trusted\n"
-" certificate. Certain aspects of the verification are handled but not others.\n"
-" The certificates will be verified against <constant>notBefore</constant>,\n"
-" <constant>notAfter</constant> and trusted certificates. It crucially will\n"
-" not handle checking the certificate against CRLs. This functionality will\n"
-" probably make it into OpenSSL 0.9.7.\n"
-" </para>\n"
-" <para>\n"
-" This may all sound quite straight forward but determining the\n"
-" certificate associated with the signature on another certificate\n"
-" can be very time consuming. The management aspects of\n"
-" certificates are addressed by various V3 extensions which are not\n"
-" currently supported.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method performs X.509 certificate verification using\n"
+ "the OpenSSL X509_verify_cert() function.\n"
+ "\n"
+ "The \"certificate\" parameter is the certificate to verify, and\n"
+ "should be an X509 object.\n"
+ "\n"
+ "the \"chain\" paramater should be a sequence of X509 objects which\n"
+ "form a chain to a trusted certificate.\n"
+ ;
static PyObject *
x509_store_object_verify_chain(x509_store_object *self, PyObject *args)
{
PyObject *x509_sequence = NULL;
- X509_STORE_CTX csc;
+ X509_STORE_CTX ctx;
x509_object *x509 = NULL;
STACK_OF(X509) *x509_stack = NULL;
int ok;
@@ -1720,11 +1476,11 @@ x509_store_object_verify_chain(x509_store_object *self, PyObject *args)
if ((x509_stack = x509_helper_sequence_to_stack(x509_sequence)) == NULL)
goto error;
- X509_STORE_CTX_init(&csc, self->store, x509->x509, x509_stack);
+ X509_STORE_CTX_init(&ctx, self->store, x509->x509, x509_stack);
- ok = X509_verify_cert(&csc) == 1;
+ ok = X509_verify_cert(&ctx) == 1;
- X509_STORE_CTX_cleanup(&csc);
+ X509_STORE_CTX_cleanup(&ctx);
sk_X509_free(x509_stack);
return PyBool_FromLong(ok);
@@ -1735,50 +1491,31 @@ x509_store_object_verify_chain(x509_store_object *self, PyObject *args)
}
static char x509_store_object_verify_detailed__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Store</memberof>\n"
-" <name>verifyDetailed</name>\n"
-" <parameter>certificate</parameter>\n"
-" <optional>\n"
-" <parameter>chain</parameter>\n"
-" </optional>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" The <classname>X509Store</classname> method <function>verifyDetailed</function>\n"
-" is based on the <function>X509_verify_cert</function> but is initialised\n"
-" with a <classname>X509</classname> object to verify and list of\n"
-" <classname>X509</classname> objects which form a chain to a trusted\n"
-" certificate. Certain aspects of the verification are handled but not others.\n"
-" The certificates will be verified against <constant>notBefore</constant>,\n"
-" <constant>notAfter</constant> and trusted certificates. It crucially will\n"
-" not handle checking the certificate against CRLs. This functionality will\n"
-" probably make it into OpenSSL 0.9.7.\n"
-" </para>\n"
-" <para>\n"
-" This may all sound quite straight forward but determining the\n"
-" certificate associated with the signature on another certificate\n"
-" can be very time consuming. The management aspects of\n"
-" certificates are addressed by various V3 extensions which are not\n"
-" currently supported.\n"
-" </para>\n"
-" <para>\n"
-" Unlike the <function>verify</function> and <function>verifyChain</function>\n"
-" methods, <function>verifyDetailed</function> returns some information about\n"
-" what went wrong when verification fails. The return value is currently a 3-tuple:\n"
-" the first value is the return value from X509_verify_cert(), the second and third\n"
-" are the error and error_depth values from the X509_STORE_CTX.\n"
-" Other values may added to this tuple later.\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method performs X.509 certificate verification using\n"
+ "the OpenSSL X509_verify_cert() function.\n"
+ "\n"
+ "The \"certificate\" parameter is the certificate to verify, and\n"
+ "should be an X509 object.\n"
+ "\n"
+ "the \"chain\" paramater should be a sequence of X509 objects which\n"
+ "form a chain to a trusted certificate.\n"
+ "\n"
+ "Unlike the \"verify\" and \"verifyChain\" methods, this method returns\n"
+ "some information about what went wrong when verification fails.\n"
+ "The return value is currently a 3-element tuple consisting of:\n"
+ "\n"
+ " * The numeric return value from X509_verify_cert()\n"
+ " * The numeric error code value from the X509_STORE_CTX\n"
+ " * The numeric error_depth value from the X509_STORE_CTX\n"
+ "\n"
+ "Other values may added to this tuple later, if needed.\n"
+ ;
static PyObject *
x509_store_object_verify_detailed(x509_store_object *self, PyObject *args)
{
PyObject *x509_sequence = Py_None;
- X509_STORE_CTX csc;
+ X509_STORE_CTX ctx;
x509_object *x509 = NULL;
STACK_OF(X509) *x509_stack = NULL;
PyObject *result = NULL;
@@ -1790,38 +1527,30 @@ x509_store_object_verify_detailed(x509_store_object *self, PyObject *args)
if (x509_sequence && !(x509_stack = x509_helper_sequence_to_stack(x509_sequence)))
goto error;
- X509_STORE_CTX_init(&csc, self->store, x509->x509, x509_stack);
+ X509_STORE_CTX_init(&ctx, self->store, x509->x509, x509_stack);
- ok = X509_verify_cert(&csc) == 1;
+ ok = X509_verify_cert(&ctx) == 1;
- result = Py_BuildValue("(iii)", ok, csc.error, csc.error_depth);
+ result = Py_BuildValue("(iii)", ok, ctx.error, ctx.error_depth);
- X509_STORE_CTX_cleanup(&csc);
+ X509_STORE_CTX_cleanup(&ctx);
error: /* fall through */
sk_X509_free(x509_stack);
return result;
}
+#endif /* ENABLE_X509_CERTIFICATE_SIGNATURE_AND_VERIFICATION */
+
static char x509_store_object_add_trust__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Store</memberof>\n"
-" <name>addTrust</name>\n"
-" <parameter>cert</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method adds a new certificate to the store to be used in the\n"
-" verification process. <parameter>cert</parameter> should be an\n"
-" instance of <classname>X509</classname>. Using trusted certificates to manage\n"
-" verification is relatively primitive, more sophisticated systems\n"
-" can be constructed at an application level by by constructing\n"
-" certificate chains to verify.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method adds a new trusted certificate to the store object.\n"
+ "\n"
+ "The \"certificate\" parameter should be an instance of the X509 class.\n"
+ "\n"
+ "Using trusted certificates to manage verification is relatively primitive,\n"
+ "more sophisticated systems can be constructed at application level by\n"
+ "constructing certificate chains to verify.\n"
+ ;
static PyObject *
x509_store_object_add_trust(x509_store_object *self, PyObject *args)
@@ -1841,26 +1570,12 @@ x509_store_object_add_trust(x509_store_object *self, PyObject *args)
}
static char x509_store_object_add_crl__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Store</memberof>\n"
-" <name>addCrl</name>\n"
-" <parameter>crl</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method adds a CRL to a store to be used for verification.\n"
-" <parameter>crl</parameter> should be an instance of\n"
-" <classname>X509Crl</classname>.\n"
-" Unfortunately, the current stable release of OpenSSL does not\n"
-" support CRL checking for certificate verification.\n"
-" This functionality will probably make it into OpenSSL 0.9.7, until\n"
-" it does this function is useless and CRL verification must be\n"
-" implemented by the application.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method adds a CRL to the store object.\n"
+ "\n"
+ "The \"crl\" parameter should be an instance of X509Crl.\n"
+ ;
+
+#warning These badly capitalized class names are starting to bug me, clean them up
static PyObject *
x509_store_object_add_crl(x509_store_object *self, PyObject *args)
@@ -1880,9 +1595,11 @@ x509_store_object_add_crl(x509_store_object *self, PyObject *args)
}
static struct PyMethodDef x509_store_object_methods[] = {
+#if ENABLE_X509_CERTIFICATE_SIGNATURE_AND_VERIFICATION
Define_Method(verify, x509_store_object_verify, METH_VARARGS),
Define_Method(verifyChain, x509_store_object_verify_chain, METH_VARARGS),
Define_Method(verifyDetailed, x509_store_object_verify_detailed, METH_VARARGS),
+#endif
Define_Method(addTrust, x509_store_object_add_trust, METH_VARARGS),
Define_Method(addCrl, x509_store_object_add_crl, METH_VARARGS),
{NULL}
@@ -1896,42 +1613,11 @@ x509_store_object_dealloc(x509_store_object *self)
}
static char x509_storetype__doc__[] =
-"<class>\n"
-" <header>\n"
-" <name>X509Store</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This class provides preliminary access to OpenSSL X509 verification\n"
-" facilities.\n"
-" </para>\n"
-"\n"
-" <example>\n"
-" <title><classname>x509_store</classname> class usage</title>\n"
-" <programlisting>\n"
-" store = POW.X509Store()\n"
-"\n"
-" caFile = open('test/cacert.pem', 'r')\n"
-" ca = POW.pemRead(POW.X509_CERTIFICATE, caFile.read())\n"
-" caFile.close()\n"
-"\n"
-" store.addTrust(ca)\n"
-"\n"
-" certFile = open('test/foocom.cert', 'r')\n"
-" x509 = POW.pemRead(POW.X509_CERTIFICATE, certFile.read())\n"
-" certFile.close()\n"
-"\n"
-" print x509.pprint()\n"
-"\n"
-" if store.verify(x509):\n"
-" print 'Verified certificate!.'\n"
-" else:\n"
-" print 'Failed to verify certificate!.'\n"
-" </programlisting>\n"
-" </example>\n"
-" </body>\n"
-"</class>\n"
-;
+ "This class provides basic access to the OpenSSL certificate store\n"
+ "mechanism used in X.509 and CMS verification.\n"
+ "\n"
+ LAME_DISCLAIMER_IN_ALL_CLASS_DOCUMENTATION
+ ;
static PyTypeObject x509_storetype = {
PyObject_HEAD_INIT(0)
@@ -2033,42 +1719,20 @@ x509_crl_object_der_read(unsigned char *src, int len)
}
static char x509_crl_object_get_version__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Crl</memberof>\n"
-" <name>getVersion</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns the version number from the version field of\n"
-" this CRL.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns the version number of this CRL.\n"
+ ;
static PyObject *
x509_crl_object_get_version(x509_crl_object *self)
{
- return Py_BuildValue("l", ASN1_INTEGER_get(self->crl->crl->version));
+ return Py_BuildValue("l", X509_CRL_get_version(self->crl));
}
static char x509_crl_object_set_version__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Crl</memberof>\n"
-" <name>setVersion</name>\n"
-" <parameter>version</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method sets the version number in the version field of\n"
-" this CRL. <parameter>version</parameter> should be an\n"
-" integer.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method sets the version number of this CRL.\n"
+ "\n"
+ "The \"version\" parameter should be a positive integer.\n"
+ ;
static PyObject *
x509_crl_object_set_version(x509_crl_object *self, PyObject *args)
@@ -2088,21 +1752,9 @@ x509_crl_object_set_version(x509_crl_object *self, PyObject *args)
}
static char x509_crl_object_get_issuer__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Crl</memberof>\n"
-" <name>getIssuer</name>\n"
-" <parameter>format = OIDNAME_FORMAT</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns a tuple containing the issuers name. See the\n"
-" <function>getIssuer</function> method of\n"
-" <classname>X509</classname> for more details.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns issuer name from this CRL.\n"
+ "See the \"getIssuer\" method of the X509 class for more details.\n"
+ ;
static PyObject *
x509_crl_object_get_issuer(x509_crl_object *self, PyObject *args)
@@ -2113,29 +1765,16 @@ x509_crl_object_get_issuer(x509_crl_object *self, PyObject *args)
if (!PyArg_ParseTuple(args, "|i", &format))
goto error;
- result = x509_object_helper_get_name(self->crl->crl->issuer, format);
+ result = x509_object_helper_get_name(X509_CRL_get_issuer(self->crl), format);
error: /* Fall through */
return result;
}
static char x509_crl_object_set_issuer__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Crl</memberof>\n"
-" <name>setIssuer</name>\n"
-" <parameter>name</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method is used to set the issuers name.\n"
-" <parameter>name</parameter> can be comprised of lists or tuples in\n"
-" the format described in the <function>getIssuer</function> method\n"
-" of <classname>X509</classname>.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method sets the CRL's issuer name.\n"
+ "See the \"setIssuer\" method of the X509 class for details.\n"
+ ;
static PyObject *
x509_crl_object_set_issuer(x509_crl_object *self, PyObject *args)
@@ -2164,464 +1803,290 @@ x509_crl_object_set_issuer(x509_crl_object *self, PyObject *args)
return NULL;
}
+/*
+ * NB: OpenSSL is confused about the name of this field, probably for
+ * backwards compatability with some ancient mistake. What RFC 5280
+ * calls "thisUpdate", OpenSSL calls "lastUpdate".
+ */
+
static char x509_crl_object_set_this_update__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Crl</memberof>\n"
-" <name>setThisUpdate</name>\n"
-" <parameter>time</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" In a change from previous releases, for reasons of portability\n"
-" and to avoid hard to fix issues with problems in unreliable time\n"
-" functions, this accepts one parameter, a UTCTime string. You\n"
-" can use the function <function>time2utc</function> to convert to a\n"
-" string if you like and <function>utc2time</function> to back.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method sets the CRL's \"thisUpdate\" value.\n"
+ "\n"
+ "The \"time\" parameter should be in the form of a GeneralizedTime string\n"
+ "as restricted by RFC 5280. The code automatically converts to UTCTime\n"
+ "when the RFC 5280 rules require UTCTime instead of GeneralizedTime,\n"
+ "so that Python code need not worry about the conversion rules.\n"
+ ;
static PyObject *
x509_crl_object_set_this_update (x509_crl_object *self, PyObject *args)
{
- char *new_time = NULL;
+ char *s = NULL;
+ ASN1_TIME *t = NULL;
- if (!PyArg_ParseTuple(args, "s", &new_time))
+ if (!PyArg_ParseTuple(args, "s", &s))
goto error;
- if (!python_ASN1_TIME_set_string(self->crl->crl->lastUpdate, new_time))
- lose("Couldn't set lastUpdate");
+ if ((t = Python_to_ASN1_TIME(s)) == NULL)
+ lose("Couldn't convert thisUpdate string");
+ if (!X509_CRL_set_lastUpdate(self->crl, t)) /* sic */
+ lose("Couldn't set thisUpdate");
+
+ ASN1_TIME_free(t);
Py_RETURN_NONE;
error:
-
+ ASN1_TIME_free(t);
return NULL;
}
static char x509_crl_object_get_this_update__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Crl</memberof>\n"
-" <name>getThisUpdate</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" In a change from previous releases, for reasons of portability\n"
-" and to avoid hard to fix issues with problems in unreliable time\n"
-" functions, this function returns a UTCTime string. You\n"
-" can use the function <function>time2utc</function> to convert to a\n"
-" string if you like and <function>utc2time</function> to back.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns the CRL's \"thisUpdate\" value\n"
+ "in the form of a GeneralizedTime string as restricted by RFC 5280.\n"
+ "The code automatically converts RFC-5280-compliant UTCTime strings\n"
+ "into the GeneralizedTime format, so that Python code need not worry\n"
+ "about the conversion rules.\n"
+ ;
static PyObject *
x509_crl_object_get_this_update (x509_crl_object *self)
{
- return ASN1_TIME_to_Python(self->crl->crl->lastUpdate);
+ return ASN1_TIME_to_Python(X509_CRL_get_lastUpdate(self->crl)); /* sic */
}
static char x509_crl_object_set_next_update__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Crl</memberof>\n"
-" <name>setNextUpdate</name>\n"
-" <parameter>time</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" In a change from previous releases, for reasons of portability\n"
-" and to avoid hard to fix issues with problems in unreliable time\n"
-" functions, this accepts one parameter, a UTCTime string. You\n"
-" can use the function <function>time2utc</function> to convert to a\n"
-" string if you like and <function>utc2time</function> to back.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method sets the CRL's \"nextUpdate\" value.\n"
+ "\n"
+ "The \"time\" parameter should be in the form of a GeneralizedTime string\n"
+ "as restricted by RFC 5280. The code automatically converts to UTCTime\n"
+ "when the RFC 5280 rules require UTCTime instead of GeneralizedTime,\n"
+ "so that Python code need not worry about the conversion rules.\n"
+ ;
static PyObject *
x509_crl_object_set_next_update (x509_crl_object *self, PyObject *args)
{
- char *new_time = NULL;
- ASN1_UTCTIME *time = NULL;
+ char *s = NULL;
+ ASN1_TIME *t = NULL;
- if (!PyArg_ParseTuple(args, "s", &new_time))
+ if (!PyArg_ParseTuple(args, "s", &s))
goto error;
- if (self->crl->crl->nextUpdate == NULL && (time = ASN1_UTCTIME_new()) == NULL)
- lose_no_memory();
-
- self->crl->crl->nextUpdate = time;
+ if ((t = Python_to_ASN1_TIME(s)) == NULL)
+ lose("Couldn't parse nextUpdate string");
- if (!python_ASN1_TIME_set_string(time, new_time))
+ if (!X509_CRL_set_nextUpdate(self->crl, t))
lose("Couldn't set nextUpdate");
+ ASN1_TIME_free(t);
Py_RETURN_NONE;
error:
-
+ ASN1_TIME_free(t);
return NULL;
}
static char x509_crl_object_get_next_update__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Crl</memberof>\n"
-" <name>getNextUpdate</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" In a change from previous releases, for reasons of portability\n"
-" and to avoid hard to fix issues with problems in unreliable time\n"
-" functions, this function returns a UTCTime string. You\n"
-" can use the function <function>time2utc</function> to convert to a\n"
-" string if you like and <function>utc2time</function> to back.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns the CRL's \"nextUpdate\" value\n"
+ "in the form of a GeneralizedTime string as restricted by RFC 5280.\n"
+ "The code automatically converts RFC-5280-compliant UTCTime strings\n"
+ "into the GeneralizedTime format, so that Python code need not worry\n"
+ "about the conversion rules.\n"
+ ;
static PyObject *
x509_crl_object_get_next_update (x509_crl_object *self)
{
- return ASN1_TIME_to_Python(self->crl->crl->nextUpdate);
+ return ASN1_TIME_to_Python(X509_CRL_get_nextUpdate(self->crl));
}
-static char x509_crl_object_set_revoked__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Crl</memberof>\n"
-" <name>setRevoked</name>\n"
-" <parameter>revoked</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method sets the sequence of revoked certificates in this CRL.\n"
-" <parameter>revoked</parameter> should be a list or tuple of\n"
-" <classname>X509Revoked</classname>.\n"
-" </para>\n"
-" <example>\n"
-" <title><function>setRevoked</function> function usage</title>\n"
-" <programlisting>\n"
-" privateFile = open('test/private.key', 'r')\n"
-" publicFile = open('test/public.key', 'r')\n"
-" crlFile = open('test/crl.pem', 'w')\n"
-"\n"
-" publicKey = POW.pemRead(POW.RSA_PUBLIC_KEY, publicFile.read())\n"
-" privateKey = POW.pemRead(POW.RSA_PRIVATE_KEY, privateFile.read(), 'pass')\n"
-"\n"
-" crl = POW.X509Crl()\n"
-"\n"
-" name = [ ['C', 'GB'], ['ST', 'Hertfordshire'],\n"
-" ['O','The House'], ['CN', 'Peter Shannon'] ]\n"
-"\n"
-" t1 = POW.pkix.time2utc(time.time())\n"
-" t2 = POW.pkix.time2utc(time.time() + 60*60*24*365)\n"
-" crl.setIssuer(name)\n"
-" rev = [ POW.X509Revoked(3, t1),\n"
-" POW.X509Revoked(4, t1),\n"
-" POW.X509Revoked(5, t1) ]\n"
-"\n"
-" crl.setRevoked(rev)\n"
-" crl.setThisUpdate(t1)\n"
-" crl.setNextUpdate(t2)\n"
-" crl.sign(privateKey)\n"
-"\n"
-" crlFile.write(crl.pemWrite())\n"
-"\n"
-" privateFile.close()\n"
-" publicFile.close()\n"
-" crlFile.close()\n"
-" </programlisting>\n"
-" </example>\n"
-"\n"
-" </body>\n"
-"</method>\n"
-;
-
-// added because we don't already have one!
-static X509_REVOKED *
-X509_REVOKED_dup(X509_REVOKED *rev)
-{
- return((X509_REVOKED *)ASN1_dup((i2d_of_void *) i2d_X509_REVOKED,
- (d2i_of_void *) d2i_X509_REVOKED,
- (char *) rev));
-}
+static char x509_crl_object_add_revocations__doc__[] =
+ "This method adds a collection of revocations to this CRL.\n"
+ "\n"
+ "The \"iterable\" parameter should be an iterable object, each element\n"
+ "of which is a two-element sequence; the first element of this sequence\n"
+ "should be the revoked serial number (an integer), the second element\n"
+ "should be the revocation date (a timestamp in GeneralizedTime format).\n"
+ ;
static PyObject *
-x509_crl_object_set_revoked(x509_crl_object *self, PyObject *args)
+x509_crl_object_add_revocations(x509_crl_object *self, PyObject *args)
{
- PyObject *revoked_sequence = NULL;
- x509_revoked_object *revoked = NULL;
- X509_REVOKED *tmp_revoked = NULL;
- int i = 0,size = 0;
+ PyObject *iterator = NULL;
+ PyObject *item = NULL;
+ X509_REVOKED *revoked = NULL;
+ ASN1_INTEGER *a_serial = NULL;
+ ASN1_TIME *a_date = NULL;
+ int ok = 0;
+ long c_serial;
+ char *c_date;
- if (!PyArg_ParseTuple(args, "O", &revoked_sequence))
+ if (!PyArg_ParseTuple(args, "O", &iterator))
goto error;
- if (!PySequence_Check(revoked_sequence))
- lose_type_error("inapropriate type");
+ while ((item = PyIter_Next(iterator)) != NULL) {
- size = PySequence_Size(revoked_sequence);
- for (i = 0; i < size; i++) {
- if ((revoked = (x509_revoked_object *) PySequence_GetItem(revoked_sequence, i)) == NULL)
+ if (!PyArg_ParseTuple(item, "ls", &c_serial, &c_date))
goto error;
- if (!X_X509_revoked_Check(revoked))
- lose_type_error("inapropriate type");
+ if ((revoked = X509_REVOKED_new()) == NULL)
+ lose_no_memory();
- if ((tmp_revoked = X509_REVOKED_dup(revoked->revoked)) == NULL ||
- !X509_CRL_add0_revoked(self->crl, tmp_revoked))
+ if ((a_serial = ASN1_INTEGER_new()) == NULL ||
+ !ASN1_INTEGER_set(a_serial, c_serial) ||
+ !X509_REVOKED_set_serialNumber(revoked, a_serial))
lose_no_memory();
+ ASN1_INTEGER_free(a_serial);
+ a_serial = NULL;
- tmp_revoked = NULL;
+ if ((a_date = Python_to_ASN1_TIME(c_date)) == NULL)
+ lose("Couldn't convert revocationDate string");
+ if (!X509_REVOKED_set_revocationDate(revoked, a_date))
+ lose("Couldn't set revocationDate");
+ ASN1_TIME_free(a_date);
+ a_date = NULL;
- Py_XDECREF(revoked);
+ if (!X509_CRL_add0_revoked(self->crl, revoked))
+ lose_no_memory();
revoked = NULL;
}
- Py_RETURN_NONE;
+ if (!X509_CRL_sort(self->crl))
+ lose_openssl_error("Couldn't sort CRL");
+
+ ok = 1;
error:
- X509_REVOKED_free(tmp_revoked);
- Py_XDECREF(revoked);
- return NULL;
+ Py_XDECREF(iterator);
+ Py_XDECREF(item);
+ X509_REVOKED_free(revoked);
+ ASN1_INTEGER_free(a_serial);
+ ASN1_TIME_free(a_date);
+
+ if (ok)
+ Py_RETURN_NONE;
+ else
+ return NULL;
}
+static char x509_crl_object_get_revoked__doc__[] =
+ "This method returns a tuple of X509Revoked objects representing the sequence\n"
+ "of revoked certificates listed in the CRL.\n"
+ ;
+
static PyObject *
-x509_crl_object_helper_get_revoked(STACK_OF(X509_REVOKED) *revoked)
+x509_crl_object_get_revoked(x509_crl_object *self)
{
- int no_entries = 0, i = 0;
- x509_revoked_object *revoke_obj = NULL;
- PyObject *result_list = NULL, *result_tuple = NULL;
-
- no_entries = sk_X509_REVOKED_num(revoked);
-
- if ((result_list = PyList_New(0)) == NULL)
- lose_no_memory();
+ STACK_OF(X509_REVOKED) *revoked = NULL;
+ X509_REVOKED *r = NULL;
+ PyObject *result = NULL;
+ PyObject *item = NULL;
+ int i;
- for (i = 0; i < no_entries; i++) {
- if ((revoke_obj = (x509_revoked_object *) x509_revoked_object_new(&x509_revokedtype, NULL, NULL)) == NULL)
- lose_no_memory();
+ if ((revoked = X509_CRL_get_REVOKED(self->crl)) == NULL)
+ lose("Inexplicable NULL revocation list pointer");
- X509_REVOKED_free(revoke_obj->revoked);
+ if ((result = PyTuple_New(sk_X509_REVOKED_num(revoked))) == NULL)
+ goto error;
- if ((revoke_obj->revoked = X509_REVOKED_dup(sk_X509_REVOKED_value(revoked, i))) == NULL)
- goto error;
+ for (i = 0; i < sk_X509_REVOKED_num(revoked); i++) {
+ r = sk_X509_REVOKED_value(revoked, i);
- if (PyList_Append(result_list, (PyObject*) revoke_obj) != 0)
+ if ((item = Py_BuildValue("(lN)",
+ ASN1_INTEGER_get(r->serialNumber),
+ ASN1_TIME_to_Python(r->revocationDate))) == NULL)
goto error;
- Py_XDECREF(revoke_obj);
- revoke_obj = NULL;
+ PyTuple_SET_ITEM(result, i, item);
+ item = NULL;
}
- result_tuple = PyList_AsTuple(result_list);
- Py_XDECREF(result_list);
-
- return result_tuple;
+ return result;
error:
-
- Py_XDECREF(revoke_obj);
- Py_XDECREF(result_list);
+ Py_XDECREF(result);
+ Py_XDECREF(item);
return NULL;
}
-static char x509_crl_object_get_revoked__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Crl</memberof>\n"
-" <name>getRevoked</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns a tuple of <classname>X509Revoked</classname>\n"
-" objects described in the CRL.\n"
-" </para>\n"
-" <example>\n"
-" <title><function>getRevoked</function> function usage</title>\n"
-" <programlisting>\n"
-" publicFile = open('test/public.key', 'r')\n"
-" crlFile = open('test/crl.pem', 'r')\n"
-"\n"
-" publicKey = POW.pemRead(POW.RSA_PUBLIC_KEY, publicFile.read())\n"
-"\n"
-" crl = POW.pemRead(POW.X509_CRL, crlFile.read())\n"
-"\n"
-" print crl.pprint()\n"
-" if crl.verify(publicKey):\n"
-" print 'signature ok!'\n"
-" else:\n"
-" print 'signature not ok!'\n"
-"\n"
-" revocations = crl.getRevoked()\n"
-" for revoked in revocations:\n"
-" print 'serial number:', revoked.getSerial()\n"
-" print 'date:', time.ctime(revoked.getDate()[0])\n"
-"\n"
-" publicFile.close()\n"
-" crlFile.close()\n"
-" </programlisting>\n"
-" </example>\n"
-"\n"
-" </body>\n"
-"</method>\n"
-;
-
-static PyObject *
-x509_crl_object_get_revoked(x509_crl_object *self)
-{
- return x509_crl_object_helper_get_revoked(X509_CRL_get_REVOKED(self->crl));
-}
-
static char x509_crl_object_add_extension__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Crl</memberof>\n"
-" <name>addExtension</name>\n"
-" <parameter>extensionName</parameter>\n"
-" <parameter>critical</parameter>\n"
-" <parameter>extensionValue</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method adds an extension to this CRL.\n"
-" <parameter>extensionName</parameter> should be the of the\n"
-" extension. <parameter>critical</parameter> should an integer, 1\n"
-" for true and 0 for clase. <parameter>extensionValue</parameter>\n"
-" should be a string, DER encoded value of the extension. The name\n"
-" of the extension must be correct according to OpenSSL and can be\n"
-" checkd in the <constant>objects.h</constant> header file, part of\n"
-" the OpenSSL source distrobution. In the majority of cases they\n"
-" are the same as those defined in <constant>POW._oids</constant>\n"
-" but if you do encounter problems is may be worth checking.\n"
-" </para>\n"
-" <example>\n"
-" <title><function>addExtension</function> method usage</title>\n"
-" <programlisting>\n"
-" oids = POW.pkix.OidData()\n"
-" o2i = oids.obj2oid\n"
-"\n"
-" n1 = ('directoryName', (((o2i('countryName'), ('printableString', 'UK')),),\n"
-" ((o2i('stateOrProvinceName'), ('printableString', 'Herts')),),\n"
-" ((o2i('organizationName'), ('printableString', 'The House')),),\n"
-" ((o2i('commonName'), ('printableString', 'Shannon Works')),)))\n"
-"\n"
-" n2 = ('rfc822Name', 'peter_shannon@yahoo.com')\n"
-" n3 = ('uri', 'http://www.p-s.org.uk')\n"
-" n4 = ('iPAddress', (192,168,100,51))\n"
-"\n"
-" issuer = POW.pkix.IssuerAltName()\n"
-" issuer.set([n1,n2,n3,n4])\n"
-" crl.addExtension('issuerAltName', 0, issuer.toString())\n"
-" </programlisting>\n"
-" </example>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method adds an extension to this CRL.\n"
+ "It takes the same arguments and has the same limitations as the\n"
+ "X509.addExtension() method (q.v.).\n"
+ ;
static PyObject *
x509_crl_object_add_extension(x509_crl_object *self, PyObject *args)
{
- int critical = 0, nid = 0, len = 0;
+ int critical = 0, len = 0, ok = 0;
char *name = NULL;
unsigned char *buf = NULL;
+ ASN1_OBJECT *oid = NULL;
ASN1_OCTET_STRING *octetString = NULL;
- X509_EXTENSION *extn = NULL;
+ X509_EXTENSION *ext = NULL;
if (!PyArg_ParseTuple(args, "sis#", &name, &critical, &buf, &len))
goto error;
+ if ((oid = OBJ_txt2obj(name, 0)) == NULL)
+ lose("Extension has unknown object identifier");
+
if ((octetString = ASN1_OCTET_STRING_new()) == NULL ||
!ASN1_OCTET_STRING_set(octetString, buf, len))
lose_no_memory();
- if ((nid = OBJ_txt2nid(name)) == NID_undef)
- lose("Extension has unknown object identifier");
-
- if ((extn = X509_EXTENSION_create_by_NID(NULL, nid, critical, octetString)) == NULL)
+ if ((ext = X509_EXTENSION_create_by_OBJ(NULL, oid, critical, octetString)) == NULL)
lose_openssl_error("Unable to create ASN.1 X.509 Extension object");
- octetString = NULL;
-
- if ((!self->crl->crl->extensions &&
- (self->crl->crl->extensions = sk_X509_EXTENSION_new_null()) == NULL) ||
- !sk_X509_EXTENSION_push(self->crl->crl->extensions, extn))
+ if (!X509_CRL_add_ext(self->crl, ext, -1))
lose_no_memory();
- Py_RETURN_NONE;
+ ok = 1;
- error:
+ error: /* Fall through */
+ ASN1_OBJECT_free(oid);
ASN1_OCTET_STRING_free(octetString);
- X509_EXTENSION_free(extn);
- return NULL;
+ X509_EXTENSION_free(ext);
+
+ if (ok)
+ Py_RETURN_NONE;
+ else
+ return NULL;
}
static char x509_crl_object_clear_extensions__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Crl</memberof>\n"
-" <name>clearExtensions</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method clears the structure which holds the extension for\n"
-" this CRL.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method clears all extensions attached to this CRL.\n"
+ ;
static PyObject *
x509_crl_object_clear_extensions(x509_crl_object *self)
{
- sk_X509_EXTENSION_free(self->crl->crl->extensions);
- self->crl->crl->extensions = NULL;
+ X509_EXTENSION *ext;
+
+ while ((ext = X509_CRL_delete_ext(self->crl, 0)) != NULL)
+ X509_EXTENSION_free(ext);
+
Py_RETURN_NONE;
}
static char x509_crl_object_count_extensions__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Crl</memberof>\n"
-" <name>countExtensions</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns the size of the structure which holds the\n"
-" extension for this CRL.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns the number of extensions attached to this CRL.\n"
+ ;
static PyObject *
x509_crl_object_count_extensions(x509_crl_object *self)
{
- return Py_BuildValue("i", sk_X509_EXTENSION_num(self->crl->crl->extensions));
+ return Py_BuildValue("i", X509_CRL_get_ext_count(self->crl));
}
static char x509_crl_object_get_extension__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Crl</memberof>\n"
-" <name>getExtension</name>\n"
-" <parameter>index</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns a tuple equivalent the parameters of\n"
-" <function>addExtension</function>.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns a tuple equivalent the parameters of the\n"
+ "\"addExtension\" method, and suffers from similar limitations.\n"
+ "\n"
+ "The \"index\" parameter is the position in the extension list of\n"
+ "the extension to be returned.\n"
+ ;
static PyObject *
x509_crl_object_get_extension(x509_crl_object *self, PyObject *args)
@@ -2634,7 +2099,7 @@ x509_crl_object_get_extension(x509_crl_object *self, PyObject *args)
if (!PyArg_ParseTuple(args, "i", &index))
goto error;
- if ((ext = sk_X509_EXTENSION_value(self->crl->crl->extensions, ext_num)) == NULL)
+ if ((ext = X509_CRL_get_ext(self->crl, ext_num)) == NULL)
lose_openssl_error("Couldn't get extension");
if ((ext_nid = OBJ_obj2nid(ext->object)) == NID_undef)
@@ -2651,32 +2116,23 @@ x509_crl_object_get_extension(x509_crl_object *self, PyObject *args)
}
static char x509_crl_object_sign__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Crl</memberof>\n"
-" <name>sign</name>\n"
-" <parameter>key</parameter>\n"
-" <parameter>digest = SHA256_DIGEST</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" <parameter>key</parameter> should be an instance of\n"
-" <classname>Asymmetric</classname> and contain a private key.\n"
-" <parameter>digest</parameter> indicates\n"
-" which digest function should be used to compute the hash to be\n"
-" signed, it should be one of the following:\n"
-" </para>\n"
-" <simplelist>\n"
-" <member><constant>MD5_DIGEST</constant></member>\n"
-" <member><constant>SHA_DIGEST</constant></member>\n"
-" <member><constant>SHA1_DIGEST</constant></member>\n"
-" <member><constant>SHA256_DIGEST</constant></member>\n"
-" <member><constant>SHA384_DIGEST</constant></member>\n"
-" <member><constant>SHA512_DIGEST</constant></member>\n"
-" </simplelist>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method signs a CRL with a private key.\n"
+ "\n"
+ "The \"key\" parameter should be an instance of the Asymmetric class,\n"
+ "containing a private key.\n"
+ "\n"
+ "The optional \"digest\" parameter indicates which digest to compute and\n"
+ "sign, and should be one of the following:\n"
+ "\n"
+ "* MD5_DIGEST\n"
+ "* SHA_DIGEST\n"
+ "* SHA1_DIGEST\n"
+ "* SHA256_DIGEST\n"
+ "* SHA384_DIGEST\n"
+ "* SHA512_DIGEST\n"
+ "\n"
+ "The default digest algorithm is SHA-256.\n"
+ ;
static PyObject *
x509_crl_object_sign(x509_crl_object *self, PyObject *args)
@@ -2710,26 +2166,12 @@ x509_crl_object_sign(x509_crl_object *self, PyObject *args)
}
static char x509_crl_object_verify__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Crl</memberof>\n"
-" <name>verify</name>\n"
-" <parameter>key</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" The <classname>X509Crl</classname> method\n"
-" <function>verify</function> is based on the\n"
-" <function>X509_CRL_verify</function> function. Unlike the\n"
-" <classname>X509</classname> function of the same name, this\n"
-" function simply checks the CRL was signed with the private key\n"
-" which corresponds the parameter <parameter>key</parameter>.\n"
-" <parameter>key</parameter> should be an instance of\n"
-" <classname>Asymmetric</classname> and contain a public key.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method verifies the CRL's signature.\n"
+ "The check is performed using OpenSSL's X509_CRL_verify() function.\n"
+ "\n"
+ "The \"key\" parameter should be an instance of the Asymmetric class\n"
+ "containing the public key of the purported signer.\n"
+ ;
static PyObject *
x509_crl_object_verify(x509_crl_object *self, PyObject *args)
@@ -2785,19 +2227,8 @@ x509_crl_object_write_helper(x509_crl_object *self, int format)
}
static char x509_crl_object_pem_write__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Crl</memberof>\n"
-" <name>pemWrite</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns a PEM encoded CRL as a\n"
-" string.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns a PEM encoded CRL as a string.\n"
+ ;
static PyObject *
x509_crl_object_pem_write(x509_crl_object *self)
@@ -2806,18 +2237,8 @@ x509_crl_object_pem_write(x509_crl_object *self)
}
static char x509_crl_object_der_write__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Crl</memberof>\n"
-" <name>derWrite</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns a DER encoded CRL as a string.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns a DER encoded CRL as a string.\n"
+ ;
static PyObject *
x509_crl_object_der_write(x509_crl_object *self)
@@ -2826,19 +2247,8 @@ x509_crl_object_der_write(x509_crl_object *self)
}
static char x509_crl_object_pprint__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Crl</memberof>\n"
-" <name>pprint</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns a formatted string showing the information\n"
-" held in the CRL.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns a pretty-printed rendition of the CRL.\n"
+ ;
static PyObject *
x509_crl_object_pprint(x509_crl_object *self)
@@ -2870,8 +2280,8 @@ static struct PyMethodDef x509_crl_object_methods[] = {
Define_Method(setThisUpdate, x509_crl_object_set_this_update, METH_VARARGS),
Define_Method(getNextUpdate, x509_crl_object_get_next_update, METH_NOARGS),
Define_Method(setNextUpdate, x509_crl_object_set_next_update, METH_VARARGS),
- Define_Method(setRevoked, x509_crl_object_set_revoked, METH_VARARGS),
Define_Method(getRevoked, x509_crl_object_get_revoked, METH_NOARGS),
+ Define_Method(addRevocations, x509_crl_object_add_revocations, METH_VARARGS),
Define_Method(addExtension, x509_crl_object_add_extension, METH_VARARGS),
Define_Method(clearExtensions, x509_crl_object_clear_extensions, METH_NOARGS),
Define_Method(countExtensions, x509_crl_object_count_extensions, METH_NOARGS),
@@ -2890,18 +2300,8 @@ x509_crl_object_dealloc(x509_crl_object *self)
}
static char x509_crltype__doc__[] =
-"<class>\n"
-" <header>\n"
-" <name>X509Crl</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This class provides access to OpenSSL X509 CRL management\n"
-" facilities.\n"
-" </para>\n"
-" </body>\n"
-"</class>\n"
-;
+ "This class provides access to OpenSSL X509 CRL management facilities.\n"
+ ;
static PyTypeObject x509_crltype = {
PyObject_HEAD_INIT(0)
@@ -2947,407 +2347,6 @@ static PyTypeObject x509_crltype = {
/*========== x509 crl Code ==========*/
-/*========== revoked Code ==========*/
-
-static PyObject *
-x509_revoked_object_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- x509_revoked_object *self = NULL;
-
- if ((self = (x509_revoked_object *) type->tp_alloc(type, 0)) == NULL)
- goto error;
-
- if ((self->revoked = X509_REVOKED_new()) == NULL)
- goto error;
-
- return (PyObject *) self;
-
- error:
-
- Py_XDECREF(self);
- return NULL;
-}
-
-static int
-x509_revoked_object_init(x509_revoked_object *self, PyObject *args, PyObject *kwds)
-{
- static char *kwlist[] = {"serial", "date", NULL};
- int serial = -1;
- char *date = NULL;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|is", kwlist, &serial, &date))
- goto error;
-
- if (serial != -1 && !ASN1_INTEGER_set(self->revoked->serialNumber, serial))
- lose_no_memory();
-
- if (date != NULL && !python_ASN1_TIME_set_string(self->revoked->revocationDate, date))
- lose_no_memory();
-
- return 0;
-
- error:
- return -1;
-}
-
-static char x509_revoked_object_set_serial__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Revoked</memberof>\n"
-" <name>setSerial</name>\n"
-" <parameter>serial</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method sets the serial number in the serial field of\n"
-" this object. <parameter>serial</parameter> should be an\n"
-" integer.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
-
-static PyObject *
-x509_revoked_object_set_serial(x509_revoked_object *self, PyObject *args)
-{
- int serial = 0;
-
- if (!PyArg_ParseTuple(args, "i", &serial))
- goto error;
-
- if (!ASN1_INTEGER_set(self->revoked->serialNumber, serial))
- lose_no_memory();
-
- Py_RETURN_NONE;
-
- error:
-
- return NULL;
-}
-
-static char x509_revoked_object_get_serial__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Revoked</memberof>\n"
-" <name>getSerial</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method gets the serial number in the serial field of\n"
-" this object.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
-
-static PyObject *
-x509_revoked_object_get_serial(x509_revoked_object *self)
-{
- return Py_BuildValue("i", ASN1_INTEGER_get(self->revoked->serialNumber));
-}
-
-static char x509_revoked_object_get_date__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Revoked</memberof>\n"
-" <name>getDate</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" In a change from previous releases, for reasons of portability\n"
-" and to avoid hard to fix issues with problems in unreliable time\n"
-" functions, this function returns a UTCTime string. You\n"
-" can use the function <function>time2utc</function> to convert to a\n"
-" string if you like and <function>utc2time</function> to back.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
-
-static PyObject *
-x509_revoked_object_get_date(x509_revoked_object *self)
-{
- return ASN1_TIME_to_Python(self->revoked->revocationDate);
-}
-
-static char x509_revoked_object_set_date__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Revoked</memberof>\n"
-" <name>setDate</name>\n"
-" <parameter>time</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" In a change from previous releases, for reasons of portability\n"
-" and to avoid hard to fix issues with problems in unreliable time\n"
-" functions, this accepts one parameter, a UTCTime string. You\n"
-" can use the function <function>time2utc</function> to convert to a\n"
-" string if you like and <function>utc2time</function> to back.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
-
-static PyObject *
-x509_revoked_object_set_date(x509_revoked_object *self, PyObject *args)
-{
- char *time = NULL;
-
- if (!PyArg_ParseTuple(args, "s", &time))
- goto error;
-
- if (!python_ASN1_TIME_set_string(self->revoked->revocationDate, time))
- lose_type_error("Couldn't set revocationDate");
-
- Py_RETURN_NONE;
-
- error:
-
- return NULL;
-}
-
-static char X509_revoked_object_add_extension__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Revoked</memberof>\n"
-" <name>addExtension</name>\n"
-" <parameter>extensionName</parameter>\n"
-" <parameter>critical</parameter>\n"
-" <parameter>extensionValue</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method adds an extension to this revocation.\n"
-" <parameter>extensionName</parameter> should be the of the\n"
-" extension. <parameter>critical</parameter> should an integer, 1\n"
-" for true and 0 for clase. <parameter>extensionValue</parameter>\n"
-" should be a string, DER encoded value of the extension. The name\n"
-" of the extension must be correct according to OpenSSL and can be\n"
-" checkd in the <constant>objects.h</constant> header file, part of\n"
-" the OpenSSL source distrobution. In the majority of cases they\n"
-" are the same as those defined in <constant>POW._oids</constant>\n"
-" but if you do encounter problems is may be worth checking.\n"
-" </para>\n"
-" <example>\n"
-" <title><function>addExtension</function> method usage</title>\n"
-" <programlisting>\n"
-" reason = POW.pkix.CrlReason()\n"
-" reason.set(1)\n"
-" revocation.addExtension('CRLReason', 0, reason.toString())\n"
-" </programlisting>\n"
-" </example>\n"
-" </body>\n"
-"</method>\n"
-;
-
-static PyObject *
-X509_revoked_object_add_extension(x509_revoked_object *self, PyObject *args)
-{
- int critical = 0, nid = 0, len = 0;
- char *name = NULL;
- unsigned char *buf = NULL;
- ASN1_OCTET_STRING *octetString = NULL;
- X509_EXTENSION *extn = NULL;
-
- if (!PyArg_ParseTuple(args, "sis#", &name, &critical, &buf, &len))
- goto error;
-
- if ((octetString = ASN1_OCTET_STRING_new()) == NULL ||
- !ASN1_OCTET_STRING_set(octetString, buf, strlen((char *) buf)))
- lose_no_memory();
-
- if ((nid = OBJ_txt2nid(name)) == NID_undef)
- lose("Extension has unknown object identifier");
-
- if ((extn = X509_EXTENSION_create_by_NID(NULL, nid, critical, octetString)) == NULL)
- lose_openssl_error("Unable to create ASN.1 X.509 Extension object");
-
- octetString = NULL;
-
- if ((!self->revoked->extensions &&
- (self->revoked->extensions = sk_X509_EXTENSION_new_null()) == NULL) ||
- !sk_X509_EXTENSION_push(self->revoked->extensions, extn))
- lose_no_memory();
-
- Py_RETURN_NONE;
-
- error:
- ASN1_OCTET_STRING_free(octetString);
- X509_EXTENSION_free(extn);
- return NULL;
-}
-
-static char X509_revoked_object_clear_extensions__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Revoked</memberof>\n"
-" <name>clearExtensions</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method clears the structure which holds the extension for\n"
-" this revocation.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
-
-static PyObject *
-X509_revoked_object_clear_extensions(x509_revoked_object *self)
-{
- sk_X509_EXTENSION_free(self->revoked->extensions);
- self->revoked->extensions = NULL;
- Py_RETURN_NONE;
-}
-
-static char X509_revoked_object_count_extensions__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Revoked</memberof>\n"
-" <name>countExtensions</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns the size of the structure which holds the\n"
-" extension for this revocation.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
-
-static PyObject *
-X509_revoked_object_count_extensions(x509_revoked_object *self)
-{
- return Py_BuildValue("i", sk_X509_EXTENSION_num(self->revoked->extensions));
-}
-
-static char X509_revoked_object_get_extension__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>X509Revoked</memberof>\n"
-" <name>getExtension</name>\n"
-" <parameter>index</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns a tuple equivalent the parameters of\n"
-" <function>addExtension</function>.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
-
-static PyObject *
-X509_revoked_object_get_extension(x509_revoked_object *self, PyObject *args)
-{
- int ext_num = 0, ext_nid = 0;
- char const *ext_ln = NULL;
- char unknown_ext [] = "unknown";
- X509_EXTENSION *ext;
-
- if (!PyArg_ParseTuple(args, "i", &ext_num))
- goto error;
-
- if ((ext = sk_X509_EXTENSION_value(self->revoked->extensions, ext_num)) == NULL)
- lose_openssl_error("Couldn't get extension");
-
- if ((ext_nid = OBJ_obj2nid(ext->object)) == NID_undef)
- lose("Extension has unknown object identifier");
-
- if ((ext_ln = OBJ_nid2sn(ext_nid)) == NULL)
- ext_ln = unknown_ext;
-
- return Py_BuildValue("sis#", ext_ln, ext->critical, ext->value->data, ext->value->length);
-
- error:
-
- return NULL;
-}
-
-static struct PyMethodDef x509_revoked_object_methods[] = {
- Define_Method(getSerial, x509_revoked_object_get_serial, METH_NOARGS),
- Define_Method(setSerial, x509_revoked_object_set_serial, METH_VARARGS),
- Define_Method(getDate, x509_revoked_object_get_date, METH_NOARGS),
- Define_Method(setDate, x509_revoked_object_set_date, METH_VARARGS),
- Define_Method(addExtension, X509_revoked_object_add_extension, METH_VARARGS),
- Define_Method(clearExtensions, X509_revoked_object_clear_extensions, METH_NOARGS),
- Define_Method(countExtensions, X509_revoked_object_count_extensions, METH_NOARGS),
- Define_Method(getExtension, X509_revoked_object_get_extension, METH_VARARGS),
- {NULL}
-};
-
-static void
-x509_revoked_object_dealloc(x509_revoked_object *self)
-{
- X509_REVOKED_free(self->revoked);
- self->ob_type->tp_free((PyObject*) self);
-}
-
-static char x509_revokedtype__doc__[] =
-"<class>\n"
-" <header>\n"
-" <name>X509Revoked</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This class provides a container for details of a revoked\n"
-" certificate. It normally would only be used in association with\n"
-" a CRL, its not much use by itself. Indeed the only reason this\n"
-" class exists is because in the future POW is likely to be extended\n"
-" to support extensions for certificates, CRLs and revocations.\n"
-" <classname>X509Revoked</classname> existing as an object in its\n"
-" own right will make adding this support easier, while avoiding\n"
-" backwards compatibility issues.\n"
-" </para>\n"
-" </body>\n"
-"</class>\n"
-;
-
-static PyTypeObject x509_revokedtype = {
- PyObject_HEAD_INIT(0)
- 0, /* ob_size */
- "_POW.X509Revoked", /* tp_name */
- sizeof(x509_revoked_object), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor)x509_revoked_object_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
- x509_revokedtype__doc__, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- x509_revoked_object_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc) x509_revoked_object_init, /* tp_init */
- 0, /* tp_alloc */
- x509_revoked_object_new, /* tp_new */
-};
-
-/*========== x509 revoked Code ==========*/
-
/*========== asymmetric Object ==========*/
static PyObject *
@@ -3474,29 +2473,21 @@ asymmetric_object_der_read(int key_type, unsigned char *src, int len)
}
static char asymmetric_object_pem_write__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>Asymmetric</memberof>\n"
-" <name>pemWrite</name>\n"
-" <parameter>keytype</parameter>\n"
-" <parameter>passphrase = None</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method is used to write <classname>Asymmetric</classname>\n"
-" objects out as strings. The first argument should be either\n"
-" <constant>RSA_PUBLIC_KEY</constant> or\n"
-" <constant>RSA_PRIVATE_KEY</constant>. Private keys are often\n"
-" saved in encrypted files to offer extra security above access\n"
-" control mechanisms. If the <parameter>keytype</parameter> is\n"
-" <constant>RSA_PRIVATE_KEY</constant> a\n"
-" <parameter>passphrase</parameter> can also be specified, in which\n"
-" case the private key will be encrypted with AES-256-CBC using the\n"
-" given passphrase.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method is used to write \"Asymmetric objects out as strings.\n"
+ "\n"
+ "The \"keytype\" argument should be one of:\n"
+ "\n"
+ " * RSA_PUBLIC_KEY\n"
+ " * RSA_PRIVATE_KEY\n"
+ "\n"
+ "Private keys are often saved in encrypted files to offer extra\n"
+ "security above access control mechanisms. If the keytype parameter is\n"
+ "RSA_PRIVATE_KEY, a \"passphrase\" parameter can also be specified, in\n"
+ "which case the private key will be encrypted with AES-256-CBC using\n"
+ "the given passphrase.\n"
+ ;
+
+#warning This probably ought to be separate methods for private and public keys.
static PyObject *
asymmetric_object_pem_write(asymmetric_object *self, PyObject *args)
@@ -3550,22 +2541,13 @@ asymmetric_object_pem_write(asymmetric_object *self, PyObject *args)
}
static char asymmetric_object_der_write__doc__[] =
-"<method>"
-" <header>"
-" <memberof>Asymmetric</memberof>"
-" <name>derWrite</name>"
-" <parameter>keytype</parameter>"
-" </header>"
-" <body>"
-" <para>"
-" This method is used to write <classname>Asymmetric</classname>"
-" objects out as strings. The first argument should be either"
-" <constant>RSA_PUBLIC_KEY</constant> or "
-" <constant>RSA_PRIVATE_KEY</constant>."
-" </para>"
-" </body>"
-"</method>"
-;
+ "This method is used to write Asymmetric objects out as strings.\n"
+ "\n"
+ "The \"keytype\" parameter should be one of:\n"
+ "\n"
+ " * RSA_PUBLIC_KEY\n"
+ " * RSA_PRIVATE_KEY\n"
+ ;
static PyObject *
asymmetric_object_der_write(asymmetric_object *self, PyObject *args)
@@ -3606,257 +2588,28 @@ asymmetric_object_der_write(asymmetric_object *self, PyObject *args)
return result;
}
-static char asymmetric_object_public_encrypt__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>Asymmetric</memberof>\n"
-" <name>publicEncrypt</name>\n"
-" <parameter>plaintext</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method is used to encrypt the <parameter>plaintext</parameter>\n"
-" using a public key. It should be noted; in practice this\n"
-" function would be used almost exclusively to encrypt symmetric cipher\n"
-" keys and not data since asymmetric cipher operations are very slow.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
-
-static PyObject *
-asymmetric_object_public_encrypt(asymmetric_object *self, PyObject *args)
-{
- unsigned char *plain_text = NULL, *cipher_text = NULL;
- int len = 0, size = 0;
- PyObject *obj = NULL;
-
- if (self->cipher_type != RSA_CIPHER)
- lose("Unsupported cipher type");
-
- if (!PyArg_ParseTuple(args, "s#", &plain_text, &len))
- goto error;
-
- size = RSA_size(self->cipher);
- if (len > size)
- lose("Plain text is too long");
-
- if ((cipher_text = malloc(size + 16)) == NULL)
- lose_no_memory();
-
- if ((len = RSA_public_encrypt(len, plain_text, cipher_text, self->cipher, RSA_PKCS1_PADDING)) < 0)
- lose_openssl_error("Couldn't encrypt plain text");
-
- obj = Py_BuildValue("s#", cipher_text, len);
- free(cipher_text);
- return obj;
-
- error:
-
- if (cipher_text)
- free(cipher_text);
-
- return NULL;
-}
-
-static char asymmetric_object_private_encrypt__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>Asymmetric</memberof>\n"
-" <name>privateEncrypt</name>\n"
-" <parameter>plaintext</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method is used to encrypt the <parameter>plaintext</parameter>\n"
-" using a private key. It should be noted; in practice this\n"
-" function would be used almost exclusively to encrypt symmetric cipher\n"
-" keys and not data since asymmetric cipher operations are very slow.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
-
-static PyObject *
-asymmetric_object_private_encrypt(asymmetric_object *self, PyObject *args)
-{
- unsigned char *plain_text = NULL, *cipher_text = NULL;
- int len = 0, size = 0;
- PyObject *obj = NULL;
-
- if (self->key_type != RSA_PRIVATE_KEY)
- lose("Don't know how to perform private encryption with this key");
-
- if (!PyArg_ParseTuple(args, "s#", &plain_text, &len))
- goto error;
-
- size = RSA_size(self->cipher);
- if (len > size)
- lose("Plain text is too long");
-
- if ((cipher_text = malloc(size + 16)) == NULL)
- lose_no_memory();
-
- if ((len = RSA_private_encrypt(len, plain_text, cipher_text, self->cipher, RSA_PKCS1_PADDING)) < 0)
- lose_openssl_error("Couldn't encrypt plain text");
-
- obj = Py_BuildValue("s#", cipher_text, len);
- free(cipher_text);
- return obj;
-
- error:
-
- if (cipher_text)
- free(cipher_text);
-
- return NULL;
-}
-
-static char asymmetric_object_public_decrypt__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>Asymmetric</memberof>\n"
-" <name>publicDecrypt</name>\n"
-" <parameter>ciphertext</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method is used to decrypt the\n"
-" <parameter>ciphertext</parameter> which has been encrypted\n"
-" using the corresponding private key and the\n"
-" <function>privateEncrypt</function> function.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
-
-static PyObject *
-asymmetric_object_public_decrypt(asymmetric_object *self, PyObject *args)
-{
- unsigned char *plain_text = NULL, *cipher_text = NULL;
- int len = 0, size = 0;
- PyObject *obj = NULL;
-
- if (self->cipher_type != RSA_CIPHER)
- lose("Unsupported cipher type");
-
- if (!PyArg_ParseTuple(args, "s#", &cipher_text, &len))
- goto error;
-
- size = RSA_size(self->cipher);
- if (len > size)
- lose("Cipher text is too long");
-
- if ((plain_text = malloc(size + 16)) == NULL)
- lose_no_memory();
-
- if ((len = RSA_public_decrypt(len, cipher_text, plain_text, self->cipher, RSA_PKCS1_PADDING)) < 0)
- lose_openssl_error("Couldn't decrypt cipher text");
-
- obj = Py_BuildValue("s#", plain_text, len);
- free(plain_text);
- return obj;
-
- error:
-
- if (plain_text)
- free(plain_text);
-
- return NULL;
-}
-
-static char asymmetric_object_private_decrypt__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>Asymmetric</memberof>\n"
-" <name>privateDecrypt</name>\n"
-" <parameter>ciphertext</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method is used to decrypt ciphertext which has been encrypted\n"
-" using the corresponding public key and the\n"
-" <function>publicEncrypt</function> function.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
-
-static PyObject *
-asymmetric_object_private_decrypt(asymmetric_object *self, PyObject *args)
-{
- unsigned char *plain_text = NULL, *cipher_text = NULL;
- int len = 0, size = 0;
- PyObject *obj = NULL;
-
- if (self->key_type != RSA_PRIVATE_KEY)
- lose("Don't know how to perform private decryption with this key");
-
- if (!PyArg_ParseTuple(args, "s#", &cipher_text, &len))
- goto error;
-
- size = RSA_size(self->cipher);
- if (len > size)
- lose("Cipher text is too long");
-
- if ((plain_text = malloc(size + 16)) == NULL)
- lose_no_memory();
-
- if ((len = RSA_private_decrypt(len, cipher_text, plain_text, self->cipher, RSA_PKCS1_PADDING)) < 0)
- lose_openssl_error("Couldn't decrypt cipher text");
-
- obj = Py_BuildValue("s#", plain_text, len);
- free(plain_text);
- return obj;
-
- error:
-
- if (plain_text)
- free(plain_text);
- return NULL;
-}
-
static char asymmetric_object_sign__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>Asymmetric</memberof>\n"
-" <name>sign</name>\n"
-" <parameter>digesttext</parameter>\n"
-" <parameter>digesttype</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method is used to produce a signed digest text.\n"
-" This instance of\n"
-" <classname>Asymmetric</classname> should be a private key used for\n"
-" signing. The parameter\n"
-" <parameter>digesttext</parameter> should be a digest of the\n"
-" data to protect against alteration and\n"
-" finally <parameter>digesttype</parameter> should be one of the\n"
-" following:\n"
-" </para>\n"
-" <simplelist>\n"
-" <member><constant>MD5_DIGEST</constant></member>\n"
-" <member><constant>SHA_DIGEST</constant></member>\n"
-" <member><constant>SHA1_DIGEST</constant></member>\n"
-" <member><constant>SHA256_DIGEST</constant></member>\n"
-" <member><constant>SHA384_DIGEST</constant></member>\n"
-" <member><constant>SHA512_DIGEST</constant></member>\n"
-" </simplelist>\n"
-" <para>\n"
-" If the procedure was successful, a string containing the signed\n"
-" digest is returned.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method signs a digest of text to be protected.\n"
+ "The Asymmetric object should be the private key to be used for signing.\n"
+ "\n"
+ "The \"digesttext\" parameter should be a digest of the protected data.\n"
+ "\n"
+ "The \"digesttype\" parameter should be one of the following:\n"
+ "\n"
+ " * MD5_DIGEST\n"
+ " * SHA_DIGEST\n"
+ " * SHA1_DIGEST\n"
+ " * SHA256_DIGEST\n"
+ " * SHA384_DIGEST\n"
+ " * SHA512_DIGEST\n"
+ ;
static PyObject *
asymmetric_object_sign(asymmetric_object *self, PyObject *args)
{
unsigned char *digest_text = NULL, *signed_text = NULL;
unsigned int digest_type = 0, signed_len = 0, digest_len = 0;
- PyObject *obj = NULL;
+ PyObject *result = NULL;
if (!PyArg_ParseTuple(args, "s#i", &digest_text, &digest_len, &digest_type))
goto error;
@@ -3872,82 +2625,35 @@ asymmetric_object_sign(asymmetric_object *self, PyObject *args)
signed_text, &signed_len, self->cipher))
lose_openssl_error("Couldn't sign digest");
- obj = Py_BuildValue("s#", signed_text, signed_len);
- free(signed_text);
- return obj;
-
- error:
+ result = Py_BuildValue("s#", signed_text, signed_len);
+ error: /* Fall through */
if (signed_text)
free(signed_text);
-
- return NULL;
+ return result;
}
static char asymmetric_object_verify__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>Asymmetric</memberof>\n"
-" <name>verify</name>\n"
-" <parameter>signedtext</parameter>\n"
-" <parameter>digesttext</parameter>\n"
-" <parameter>digesttype</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method is used to verify a signed digest text.\n"
-" </para>\n"
-" <example>\n"
-" <title><function>verify</function> method usage</title>\n"
-" <programlisting>\n"
-" plain_text = 'Hello World!'\n"
-" print '\tPlain text:', plain_text\n"
-" digest = POW.Digest(POW.RIPEMD160_DIGEST)\n"
-" digest.update(plain_text)\n"
-" print '\tDigest text:', digest.digest()\n"
-"\n"
-" privateFile = open('test/private.key', 'r')\n"
-" privateKey = POW.pemRead(POW.RSA_PRIVATE_KEY, privateFile.read(), 'pass')\n"
-" privateFile.close()\n"
-" signed_text = privateKey.sign(digest.digest(), POW.RIPEMD160_DIGEST)\n"
-" print '\tSigned text:', signed_text\n"
-"\n"
-" digest2 = POW.Digest(POW.RIPEMD160_DIGEST)\n"
-" digest2.update(plain_text)\n"
-" publicFile = open('test/public.key', 'r')\n"
-" publicKey = POW.pemRead(POW.RSA_PUBLIC_KEY, publicFile.read())\n"
-" publicFile.close()\n"
-" if publicKey.verify(signed_text, digest2.digest(), POW.RIPEMD160_DIGEST):\n"
-" print 'Signing verified!'\n"
-" else:\n"
-" print 'Signing gone wrong!'\n"
-" </programlisting>\n"
-" </example>\n"
-" <para>\n"
-" The parameter <parameter>signedtext</parameter> should be a\n"
-" signed digest text. This instance of\n"
-" <classname>Asymmetric</classname> should correspond to the private\n"
-" key used to sign the digest. The parameter\n"
-" <parameter>digesttext</parameter> should be a digest of the same\n"
-" data used to produce the <parameter>signedtext</parameter> and\n"
-" finally <parameter>digesttype</parameter> should be one of the\n"
-" following:\n"
-" </para>\n"
-" <simplelist>\n"
-" <member><constant>MD5_DIGEST</constant></member>\n"
-" <member><constant>SHA_DIGEST</constant></member>\n"
-" <member><constant>SHA1_DIGEST</constant></member>\n"
-" <member><constant>SHA256_DIGEST</constant></member>\n"
-" <member><constant>SHA384_DIGEST</constant></member>\n"
-" <member><constant>SHA512_DIGEST</constant></member>\n"
-" </simplelist>\n"
-" <para>\n"
-" If the procedure was successful, 1 is returned, otherwise 0 is\n"
-" returned.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method verifies a signed digest. The Assymetric object should be\n"
+ "the public key against which to verify the signature.\n"
+ "\n"
+ "The \"signedtext\" parameter should be the signed digest to verify.\n"
+ "\n"
+ "The \"digesttext\" parameter should be a digest of the same data used\n"
+ "to produce signedtext.\n"
+ "\n"
+ "The \"digesttype\" parameter should be one of the following:\n"
+ "\n"
+ " * MD5_DIGEST\n"
+ " * SHA_DIGEST\n"
+ " * SHA1_DIGEST\n"
+ " * SHA256_DIGEST\n"
+ " * SHA384_DIGEST\n"
+ " * SHA512_DIGEST\n"
+ "\n"
+ "This method returns a boolean value indicating whether the signature\n"
+ "could be verified.\n"
+ ;
static PyObject *
asymmetric_object_verify(asymmetric_object *self, PyObject *args)
@@ -3973,10 +2679,6 @@ asymmetric_object_verify(asymmetric_object *self, PyObject *args)
static struct PyMethodDef asymmetric_object_methods[] = {
Define_Method(pemWrite, asymmetric_object_pem_write, METH_VARARGS),
Define_Method(derWrite, asymmetric_object_der_write, METH_VARARGS),
- Define_Method(publicEncrypt, asymmetric_object_public_encrypt, METH_VARARGS),
- Define_Method(privateEncrypt, asymmetric_object_private_encrypt, METH_VARARGS),
- Define_Method(privateDecrypt, asymmetric_object_private_decrypt, METH_VARARGS),
- Define_Method(publicDecrypt, asymmetric_object_public_decrypt, METH_VARARGS),
Define_Method(sign, asymmetric_object_sign, METH_VARARGS),
Define_Method(verify, asymmetric_object_verify, METH_VARARGS),
{NULL}
@@ -3994,20 +2696,10 @@ asymmetric_object_dealloc(asymmetric_object *self)
}
static char asymmetrictype__doc__[] =
-"<class>\n"
-" <header>\n"
-" <name>Asymmetric</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This class provides access to RSA asymmetric ciphers in OpenSSL.\n"
-" Other ciphers will probably be supported in the future but this is\n"
-" not a priority.\n"
-" </para>\n"
-" </body>\n"
-"</class>\n"
-;
-
+ "This class provides basic access to RSA signature and verification.\n"
+ "\n"
+ LAME_DISCLAIMER_IN_ALL_CLASS_DOCUMENTATION
+ ;
static PyTypeObject asymmetrictype = {
PyObject_HEAD_INIT(0)
@@ -4095,21 +2787,10 @@ digest_object_init(digest_object *self, PyObject *args, PyObject *kwds)
}
static char digest_object_update__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>Digest</memberof>\n"
-" <name>update</name>\n"
-" <parameter>data</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method updates the internal structures of the\n"
-" <classname>Digest</classname> object with <parameter>data</parameter>.\n"
-" <parameter>data</parameter> should be a string.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method adds data to a digest.\n"
+ "\n"
+ "the \"data\" parameter should be a string containing the data to be added.\n"
+ ;
static PyObject *
digest_object_update(digest_object *self, PyObject *args)
@@ -4130,19 +2811,8 @@ digest_object_update(digest_object *self, PyObject *args)
}
static char digest_object_copy__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>Digest</memberof>\n"
-" <name>copy</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns a copy of the <classname>Digest</classname>\n"
-" object.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns a copy of the Digest object.\n"
+ ;
static PyObject *
digest_object_copy(digest_object *self, PyObject *args)
@@ -4165,21 +2835,15 @@ digest_object_copy(digest_object *self, PyObject *args)
}
static char digest_object_digest__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>Digest</memberof>\n"
-" <name>digest</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns the digest of all the data which has been\n"
-" processed. This function can be called at any time and will not\n"
-" effect the internal structure of the <classname>digest</classname>\n"
-" object.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns the digest of all the data which has been processed.\n"
+ "This function can be called at any time and will not effect the internal\n"
+ "structure of the Digest object.\n"
+ ;
+
+/*
+ * Do we really need to do this copy? Nice general operation, but does
+ * anything we're doing for RPKI care?
+ */
static PyObject *
digest_object_digest(digest_object *self)
@@ -4216,30 +2880,20 @@ digest_object_dealloc(digest_object *self)
}
static char digesttype__doc__[] =
-"<class>\n"
-" <header>\n"
-" <name>Digest</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This class provides access to the digest functionality of OpenSSL.\n"
-" It emulates the digest modules in the Python Standard Library but\n"
-" does not currently support the <function>hexdigest</function>\n"
-" function.\n"
-" </para>\n"
-" <example>\n"
-" <title><classname>digest</classname> class usage</title>\n"
-" <programlisting>\n"
-" plain_text = 'Hello World!'\n"
-" sha1 = POW.Digest(POW.SHA1_DIGEST)\n"
-" sha1.update(plain_text)\n"
-" print '\tPlain text: Hello World! =>', sha1.digest()\n"
-" </programlisting>\n"
-" </example>\n"
-" </body>\n"
-"</class>\n"
-;
-
+ "This class provides access to the digest functionality of OpenSSL.\n"
+ "It emulates the digest modules in the Python Standard Library, but\n"
+ "does not currently support the \"hexdigest\" method.\n"
+ "\n"
+ "The constructor takes one parameter, the kind of Digest object to create.\n"
+ "This should be one of the following:\n"
+ "\n"
+ " * MD5_DIGEST\n"
+ " * SHA_DIGEST\n"
+ " * SHA1_DIGEST\n"
+ " * SHA256_DIGEST\n"
+ " * SHA384_DIGEST\n"
+ " * SHA512_DIGEST\n"
+ ;
static PyTypeObject digesttype = {
PyObject_HEAD_INIT(0)
@@ -4376,19 +3030,8 @@ cms_object_write_helper(cms_object *self, int format)
}
static char cms_object_pem_write__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>CMS</memberof>\n"
-" <name>pemWrite</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns a PEM encoded CMS message as a\n"
-" string.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns a PEM encoded CMS message as a string.\n"
+ ;
static PyObject *
cms_object_pem_write(cms_object *self)
@@ -4397,19 +3040,8 @@ cms_object_pem_write(cms_object *self)
}
static char cms_object_der_write__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>CMS</memberof>\n"
-" <name>derWrite</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns a DER encoded CMS message as a\n"
-" string.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns a DER encoded CMS message as a string.\n"
+ ;
static PyObject *
cms_object_der_write(cms_object *self)
@@ -4418,28 +3050,31 @@ cms_object_der_write(cms_object *self)
}
static char cms_object_sign__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>CMS</memberof>\n"
-" <name>sign</name>\n"
-" <parameter>signcert</parameter>\n"
-" <parameter>key</parameter>\n"
-" <parameter>data</parameter>\n"
-" <optional>\n"
-" <parameter>certs</parameter>\n"
-" <parameter>crls</parameter>\n"
-" <parameter>eContentType</parameter>\n"
-" <parameter>flags</parameter>\n"
-" </optional>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method signs a message with a private key.\n"
-" Supported flags: CMS_NOCERTS, CMS_NOATTR.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method signs a message with a private key.\n"
+ "\n"
+ "the \"signcert\" parameter should be the certificate against which the\n"
+ "message will eventually be verified, an X509 object.\n"
+ "\n"
+ "The \"key\" parameter should be the private key with which to sign the\n"
+ "message, an Asymmetric object.\n"
+ "\n"
+ "The \"data\" parameter should be the message to be signed, a string.\n"
+ "\n"
+ "The optional \"certs\" parameter should be a sequence of X509 objects\n"
+ "to be included in the signed message.\n"
+ "\n"
+ "The optional \"crls\" parameter should be a sequence of CRL objects\n"
+ "to be included in the signed message.\n"
+ "\n"
+ "The optional \"eContentType\" parameter should be an Object Identifier\n"
+ "to use as the eContentType value in the signed message.\n"
+ "\n"
+ "The optional \"flags\" parameters should be an integer holding a bitmask,\n"
+ "and can include the following flags:\n"
+ "\n"
+ " * CMS_NOCERTS\n"
+ " * CMS_NOATTR\n"
+ ;
static PyObject *
cms_object_sign(cms_object *self, PyObject *args)
@@ -4571,28 +3206,23 @@ cms_object_sign(cms_object *self, PyObject *args)
}
static char cms_object_verify__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>CMS</memberof>\n"
-" <name>verify</name>\n"
-" <parameter>store</parameter>\n"
-" <optional>\n"
-" <parameter>certs</parameter>\n"
-" <parameter>flags</parameter>\n"
-" </optional>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method verifies a message against a trusted store.\n"
-" The optional certs parameter is a set of certificates to search\n"
-" for the signer's certificate.\n"
-" Supported flags: CMS_NOINTERN, CMS_NOCRL,\n"
-" CMS_NO_SIGNER_CERT_VERIFY, CMS_NO_ATTR_VERIFY,\n"
-" CMS_NO_CONTENT_VERIFY.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method verifies a message against a trusted store.\n"
+ "\n"
+ "The \"store\" parameter is an X509Store object, the trusted certificate\n"
+ "store to use in verification.\n"
+ "\n"
+ "The optional \"certs\" parameter is a set of certificates to search\n"
+ "for the signer's certificate.\n"
+ "\n"
+ "The optional \"flags\" parameter is an integer of bit flags,\n"
+ "containing zero or more of the following:\n"
+ "\n"
+ " * CMS_NOINTERN\n"
+ " * CMS_NOCRL\n"
+ " * CMS_NO_SIGNER_CERT_VERIFY\n"
+ " * CMS_NO_ATTR_VERIFY\n"
+ " * CMS_NO_CONTENT_VERIFY\n"
+ ;
static PyObject *
cms_object_verify(cms_object *self, PyObject *args)
@@ -4638,18 +3268,8 @@ cms_object_verify(cms_object *self, PyObject *args)
}
static char cms_object_eContentType__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>CMS</memberof>\n"
-" <name>get_eContentType</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns the eContentType of a CMS message.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns the eContentType of a CMS message.\n"
+ ;
static PyObject *
cms_object_eContentType(cms_object *self)
@@ -4674,18 +3294,8 @@ cms_object_eContentType(cms_object *self)
}
static char cms_object_signingTime__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>CMS</memberof>\n"
-" <name>get_signingTime</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns the signingTime of a CMS message.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns the signingTime of a CMS message.\n"
+ ;
static PyObject *
cms_object_signingTime(cms_object *self)
@@ -4739,19 +3349,8 @@ cms_object_signingTime(cms_object *self)
}
static char cms_object_pprint__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>CMS</memberof>\n"
-" <name>pprint</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns a formatted string showing the information\n"
-" held in the certificate.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns a pretty-printed representation of a CMS message.\n"
+ ;
static PyObject *
cms_object_pprint(cms_object *self)
@@ -4787,18 +3386,10 @@ cms_object_helper_get_cert(void *cert)
}
static char cms_object_certs__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>CMS</memberof>\n"
-" <name>certs</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns any certs embedded in a CMS message.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns any certificates embedded in a CMS message, as a\n"
+ "tuple of X509 objects. This tuple will be empty if the message\n"
+ "wrapper contains no certificates.\n"
+ ;
static PyObject *
cms_object_certs(cms_object *self)
@@ -4833,18 +3424,9 @@ cms_object_helper_get_crl(void *crl)
}
static char cms_object_crls__doc__[] =
-"<method>\n"
-" <header>\n"
-" <memberof>CMS</memberof>\n"
-" <name>crls</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This method returns any CRLs embedded in a CMS message.\n"
-" </para>\n"
-" </body>\n"
-"</method>\n"
-;
+ "This method returns any CRLs embedded in a CMS message, as a tuple of\n"
+ "CRL objects. This tuple will be empty if the message contains no CRLs.\n"
+ ;
static PyObject *
cms_object_crls(cms_object *self)
@@ -4866,9 +3448,9 @@ cms_object_crls(cms_object *self)
}
static struct PyMethodDef cms_object_methods[] = {
- Define_Method(pemWrite, cms_object_pem_write, METH_NOARGS),
+ Define_Method(pemWrite, cms_object_pem_write, METH_NOARGS),
Define_Method(derWrite, cms_object_der_write, METH_NOARGS),
- Define_Method(sign, cms_object_sign, METH_VARARGS),
+ Define_Method(sign, cms_object_sign, METH_VARARGS),
Define_Method(verify, cms_object_verify, METH_VARARGS),
Define_Method(eContentType, cms_object_eContentType, METH_NOARGS),
Define_Method(signingTime, cms_object_signingTime, METH_NOARGS),
@@ -4886,17 +3468,10 @@ cms_object_dealloc(cms_object *self)
}
static char cmstype__doc__[] =
-"<class>\n"
-" <header>\n"
-" <name>CMS</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This class provides basic access OpenSSL's CMS functionality.\n"
-" </para>\n"
-" </body>\n"
-"</class>\n"
-;
+ "This class provides basic access OpenSSL's CMS functionality.\n"
+ "At present this only handes signed objects, as those are the\n"
+ "only kind of CMS objects used in RPKI.\n"
+ ;
static PyTypeObject cmstype = {
PyObject_HEAD_INIT(0)
@@ -4945,39 +3520,44 @@ static PyTypeObject cmstype = {
/*========== module functions ==========*/
static char pow_module_pem_read__doc__[] =
-"<modulefunction>\n"
-" <header>\n"
-" <name>pemRead</name>\n"
-" <parameter>type</parameter>\n"
-" <parameter>string</parameter>\n"
-" <parameter>pass = None</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This function attempts to parse the <parameter>string</parameter> according to the PEM\n"
-" type passed. <parameter>type</parameter> should be one of the\n"
-" following:\n"
-" </para>\n"
-" <simplelist>\n"
-" <member><constant>RSA_PUBLIC_KEY</constant></member>\n"
-" <member><constant>RSA_PRIVATE_KEY</constant></member>\n"
-" <member><constant>X509_CERTIFICATE</constant></member>\n"
-" <member><constant>X509_CRL</constant></member>\n"
-" <member><constant>CMS_MESSAGE</constant></member>\n"
-" </simplelist>\n"
-" <para>\n"
-" <parameter>pass</parameter> should only be provided if an encrypted\n"
-" <classname>Asymmetric</classname> is being loaded. If the password\n"
-" is incorrect an exception will be raised, if no password is provided\n"
-" and the PEM file is encrypted the user will be prompted. If this is\n"
-" not desirable, always supply a password. The object returned will be\n"
-" and instance of <classname>Asymmetric</classname>,\n"
-" <classname>X509</classname>, <classname>X509Crl</classname>,\n"
-" or <classname>CMS</classname>.\n"
-" </para>\n"
-" </body>\n"
-"</modulefunction>\n"
-;
+ "This function should be replaced by class methods for the several\n"
+ "kinds of objects this function currently returns.\n"
+ "\n"
+ "For now, here is the old documentation for this function.\n"
+ "\n"
+ "<modulefunction>\n"
+ " <header>\n"
+ " <name>pemRead</name>\n"
+ " <parameter>type</parameter>\n"
+ " <parameter>string</parameter>\n"
+ " <parameter>pass = None</parameter>\n"
+ " </header>\n"
+ " <body>\n"
+ " <para>\n"
+ " This function attempts to parse the <parameter>string</parameter> according to the PEM\n"
+ " type passed. <parameter>type</parameter> should be one of the\n"
+ " following:\n"
+ " </para>\n"
+ " <simplelist>\n"
+ " <member><constant>RSA_PUBLIC_KEY</constant></member>\n"
+ " <member><constant>RSA_PRIVATE_KEY</constant></member>\n"
+ " <member><constant>X509_CERTIFICATE</constant></member>\n"
+ " <member><constant>X509_CRL</constant></member>\n"
+ " <member><constant>CMS_MESSAGE</constant></member>\n"
+ " </simplelist>\n"
+ " <para>\n"
+ " <parameter>pass</parameter> should only be provided if an encrypted\n"
+ " <classname>Asymmetric</classname> is being loaded. If the password\n"
+ " is incorrect an exception will be raised, if no password is provided\n"
+ " and the PEM file is encrypted the user will be prompted. If this is\n"
+ " not desirable, always supply a password. The object returned will be\n"
+ " and instance of <classname>Asymmetric</classname>,\n"
+ " <classname>X509</classname>, <classname>X509Crl</classname>,\n"
+ " or <classname>CMS</classname>.\n"
+ " </para>\n"
+ " </body>\n"
+ "</modulefunction>\n"
+ ;
static PyObject *
pow_module_pem_read (PyObject *self, PyObject *args)
@@ -5024,33 +3604,38 @@ pow_module_pem_read (PyObject *self, PyObject *args)
}
static char pow_module_der_read__doc__[] =
-"<modulefunction>\n"
-" <header>\n"
-" <name>derRead</name>\n"
-" <parameter>type</parameter>\n"
-" <parameter>string</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This function attempts to parse the <parameter>string</parameter> according to the PEM\n"
-" type passed. <parameter>type</parameter> should be one of the\n"
-" following:\n"
-" </para>\n"
-" <simplelist>\n"
-" <member><constant>RSA_PUBLIC_KEY</constant></member>\n"
-" <member><constant>RSA_PRIVATE_KEY</constant></member>\n"
-" <member><constant>X509_CERTIFICATE</constant></member>\n"
-" <member><constant>X509_CRL</constant></member>\n"
-" <member><constant>CMS_MESSAGE</constant></member>\n"
-" </simplelist>\n"
-" <para>\n"
-" As with the PEM operations, the object returned will be and instance\n"
-" of <classname>Asymmetric</classname>, <classname>X509</classname>,\n"
-" <classname>X509Crl</classname>, or <classname>CMS</classname>.\n"
-" </para>\n"
-" </body>\n"
-"</modulefunction>\n"
-;
+ "This function should be replaced by class methods for the several\n"
+ "kinds of objects this function currently returns.\n"
+ "\n"
+ "For now, here is the old documentation for this function.\n"
+ "\n"
+ "<modulefunction>\n"
+ " <header>\n"
+ " <name>derRead</name>\n"
+ " <parameter>type</parameter>\n"
+ " <parameter>string</parameter>\n"
+ " </header>\n"
+ " <body>\n"
+ " <para>\n"
+ " This function attempts to parse the <parameter>string</parameter> according to the PEM\n"
+ " type passed. <parameter>type</parameter> should be one of the\n"
+ " following:\n"
+ " </para>\n"
+ " <simplelist>\n"
+ " <member><constant>RSA_PUBLIC_KEY</constant></member>\n"
+ " <member><constant>RSA_PRIVATE_KEY</constant></member>\n"
+ " <member><constant>X509_CERTIFICATE</constant></member>\n"
+ " <member><constant>X509_CRL</constant></member>\n"
+ " <member><constant>CMS_MESSAGE</constant></member>\n"
+ " </simplelist>\n"
+ " <para>\n"
+ " As with the PEM operations, the object returned will be and instance\n"
+ " of <classname>Asymmetric</classname>, <classname>X509</classname>,\n"
+ " <classname>X509Crl</classname>, or <classname>CMS</classname>.\n"
+ " </para>\n"
+ " </body>\n"
+ "</modulefunction>\n"
+ ;
static PyObject *
pow_module_der_read (PyObject *self, PyObject *args)
@@ -5091,24 +3676,16 @@ pow_module_der_read (PyObject *self, PyObject *args)
}
static char pow_module_add_object__doc__[] =
-"<modulefunction>\n"
-" <header>\n"
-" <name>addObject</name>\n"
-" <parameter>oid</parameter>\n"
-" <parameter>shortName</parameter>\n"
-" <parameter>longName</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This function can be used to dynamically add new objects to\n"
-" OpenSSL. The <parameter>oid</parameter> should be a string of space separated numbers\n"
-" and <parameter>shortName</parameter> and\n"
-" <parameter>longName</parameter> are the names of the object, ie\n"
-" 'cn' and 'commonName'.\n"
-" </para>\n"
-" </body>\n"
-"</modulefunction>\n"
-;
+ "This function dynamically adds new a new object identifier to OpenSSL's\n"
+ "internal database.\n"
+ "\n"
+ "The \"oid\" should be an ASN.1 object identifer, represented as a string\n"
+ "in dotted-decimal format.\n"
+ "\n"
+ "The \"shortName\" parameter should be the OpenSSL \"short name\" to use.\n"
+ "\n"
+ "The \"longName\" parameter should be the OpenSSL \"long name\" to use.\n"
+ ;
static PyObject *
pow_module_add_object(PyObject *self, PyObject *args)
@@ -5119,7 +3696,7 @@ pow_module_add_object(PyObject *self, PyObject *args)
goto error;
if (!OBJ_create(oid, sn, ln))
- lose("Unable to add object");
+ lose_openssl_error("Unable to add object");
Py_RETURN_NONE;
@@ -5129,51 +3706,29 @@ pow_module_add_object(PyObject *self, PyObject *args)
}
static char pow_module_get_error__doc__[] =
-"<modulefunction>\n"
-" <header>\n"
-" <name>getError</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" Pops an error off the global error stack and returns it as a string.\n"
-" Returns None if the global error stack is empty.\n"
-" </para>\n"
-" </body>\n"
-"</modulefunction>\n"
-;
+ "Pops one error off OpenSSL's global error stack and returns it as a string.\n"
+ "Returns None if the error stack is empty.\n"
+ ;
static PyObject *
pow_module_get_error(PyObject *self)
{
- unsigned long error;
+ unsigned long error = ERR_get_error();
char buf[256];
- error = ERR_get_error();
-
if (!error)
Py_RETURN_NONE;
ERR_error_string_n(error, buf, sizeof(buf));
-
return Py_BuildValue("s", buf);
error:
-
return NULL;
}
static char pow_module_clear_error__doc__[] =
-"<modulefunction>\n"
-" <header>\n"
-" <name>clearError</name>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" Removes all errors from the global error stack.\n"
-" </para>\n"
-" </body>\n"
-"</modulefunction>\n"
-;
+ "Remove all errors from OpenSSL's global error stack.\n"
+ ;
static PyObject *
pow_module_clear_error(PyObject *self)
@@ -5183,39 +3738,22 @@ pow_module_clear_error(PyObject *self)
}
static char pow_module_seed__doc__[] =
-"<modulefunction>\n"
-" <header>\n"
-" <name>seed</name>\n"
-" <parameter>data</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" The <function>seed</function> function adds data to OpenSSLs PRNG\n"
-" state. It is often said the hardest part of cryptography is\n"
-" getting good random data, after all if you don't have good random\n"
-" data, a 1024 bit key is no better than a 512 bit key and neither\n"
-" would provide protection from a targeted brute force attack.\n"
-" The <function>seed</function> and <function>add</function> are very\n"
-" similar, except the entropy of the data is assumed to be equal to\n"
-" the length for <function>seed</function>. One final point to be aware\n"
-" of, only systems which support /dev/urandom are automatically seeded.\n"
-" If your system does not support /dev/urandom it is your responsibility\n"
-" to seed OpenSSL's PRNG.\n"
-" </para>\n"
-" </body>\n"
-"</modulefunction>\n"
-;
+ "Add data to OpenSSL's pseudo-random number generator state.\n"
+ "\n"
+ "The \"data\" parameter is the seed to add. Entropy of the data is\n"
+ "assumed to be equal to the length of the data.\n"
+ ;
static PyObject *
pow_module_seed(PyObject *self, PyObject *args)
{
- char *in = NULL;
- int inl = 0;
+ char *data = NULL;
+ int datalen = 0;
- if (!PyArg_ParseTuple(args, "s#", &in, &inl))
+ if (!PyArg_ParseTuple(args, "s#", &data, &datalen))
goto error;
- RAND_seed(in, inl);
+ RAND_seed(data, datalen);
Py_RETURN_NONE;
@@ -5225,93 +3763,62 @@ pow_module_seed(PyObject *self, PyObject *args)
}
static char pow_module_add__doc__[] =
-"<modulefunction>\n"
-" <header>\n"
-" <name>add</name>\n"
-" <parameter>data</parameter>\n"
-" <parameter>entropy</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" The <function>add</function> function adds data to OpenSSLs PRNG\n"
-" state. <parameter>data</parameter> should be data obtained from a\n"
-" random source and <parameter>entropy</parameter> is an estimation of the number of random\n"
-" bytes in <parameter>data</parameter>.\n"
-" </para>\n"
-" </body>\n"
-"</modulefunction>\n"
-;
+ "Add data to OpenSSL's pseudo-random number generator state.\n"
+ "\n"
+ "The \"data\" parameter is the data to add.\n"
+ "\n"
+ "The \"entropy\" parameter should be an estimate of the number of\n"
+ "random bytes in the data parameter.\n"
+ ;
static PyObject *
pow_module_add(PyObject *self, PyObject *args)
{
- char *in = NULL;
- int inl = 0;
+ char *data = NULL;
+ int datalen = 0;
double entropy = 0;
- if (!PyArg_ParseTuple(args, "s#d", &in, &inl, &entropy))
+ if (!PyArg_ParseTuple(args, "s#d", &data, &datalen, &entropy))
goto error;
- RAND_add(in, inl, entropy);
+ RAND_add(data, datalen, entropy);
Py_RETURN_NONE;
error:
-
return NULL;
}
static char pow_module_write_random_file__doc__[] =
-"<modulefunction>\n"
-" <header>\n"
-" <name>writeRandomFile</name>\n"
-" <parameter>filename</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This function writes the current random state to a file. Clearly\n"
-" this function should be used in conjunction with\n"
-" <function>readRandomFile</function>.\n"
-" </para>\n"
-" </body>\n"
-"</modulefunction>\n"
-;
+ "This function writes the current state of OpenSSL's pseduo-random\n"
+ "number generator to a file.\n"
+ "\n"
+ "The \"filename\" parameter is the name of the file to write.\n"
+ ;
static PyObject *
pow_module_write_random_file(PyObject *self, PyObject *args)
{
- char *file = NULL;
+ char *filename = NULL;
- if (!PyArg_ParseTuple(args, "s", &file))
+ if (!PyArg_ParseTuple(args, "s", &filename))
goto error;
- if (RAND_write_file(file) == -1)
+ if (RAND_write_file(filename) == -1)
lose("Couldn't write random file");
Py_RETURN_NONE;
error:
-
return NULL;
}
static char pow_module_read_random_file__doc__[] =
-"<modulefunction>\n"
-" <header>\n"
-" <name>readRandomFile</name>\n"
-" <parameter>filename</parameter>\n"
-" </header>\n"
-" <body>\n"
-" <para>\n"
-" This function reads a previously saved random state. It can be very\n"
-" useful to improve the quality of random data used by an application.\n"
-" The random data should be added to, using the\n"
-" <function>add</function> function, with data from other\n"
-" suitable random sources.\n"
-" </para>\n"
-" </body>\n"
-"</modulefunction>\n"
-;
+ "This function restores the state of OpenSSLs pseudo-random number\n"
+ "generator from state previously saved to a file.\n"
+ "\n"
+ "The \"filename\" parameter is the name of the file to read.\n"
+ ;
static PyObject *
pow_module_read_random_file(PyObject *self, PyObject *args)
@@ -5366,7 +3873,6 @@ init_POW(void)
Define_Class(x509type);
Define_Class(x509_storetype);
Define_Class(x509_crltype);
- Define_Class(x509_revokedtype);
Define_Class(asymmetrictype);
Define_Class(digesttype);
Define_Class(cmstype);
@@ -5377,9 +3883,9 @@ init_POW(void)
PyModule_AddObject(m, #__name__, ((__name__##Object) \
= PyErr_NewException("POW." #__name__, __parent__, NULL)))
- Define_Exception(Error, NULL);
- Define_Exception(POWError, OpenSSLErrorObject);
- Define_Exception(POWError, ErrorObject);
+ Define_Exception(Error, NULL);
+ Define_Exception(POWError, OpenSSLErrorObject);
+ Define_Exception(POWError, ErrorObject);
Define_Exception(POWOtherError, POWErrorObject);
#undef Define_Exception
@@ -5387,12 +3893,12 @@ init_POW(void)
#define Define_Integer_Constant(__name__) \
PyModule_AddIntConstant(m, #__name__, __name__)
- // object format types
+ /* Object format types */
Define_Integer_Constant(LONGNAME_FORMAT);
Define_Integer_Constant(SHORTNAME_FORMAT);
Define_Integer_Constant(OIDNAME_FORMAT);
- // PEM encoded types
+ /* PEM encoded types */
#ifndef OPENSSL_NO_RSA
Define_Integer_Constant(RSA_PUBLIC_KEY);
Define_Integer_Constant(RSA_PRIVATE_KEY);
@@ -5409,7 +3915,7 @@ init_POW(void)
PyModule_AddIntConstant(m, "X509_CRL", X_X509_CRL);
Define_Integer_Constant(CMS_MESSAGE);
- // asymmetric ciphers
+ /* Asymmetric ciphers */
#ifndef OPENSSL_NO_RSA
Define_Integer_Constant(RSA_CIPHER);
#endif
@@ -5420,7 +3926,7 @@ init_POW(void)
Define_Integer_Constant(DH_CIPHER);
#endif
- // message digests
+ /* Message digests */
Define_Integer_Constant(MD5_DIGEST);
Define_Integer_Constant(SHA_DIGEST);
Define_Integer_Constant(SHA1_DIGEST);
@@ -5428,18 +3934,7 @@ init_POW(void)
Define_Integer_Constant(SHA384_DIGEST);
Define_Integer_Constant(SHA512_DIGEST);
- // general name
- Define_Integer_Constant(GEN_OTHERNAME);
- Define_Integer_Constant(GEN_EMAIL);
- Define_Integer_Constant(GEN_DNS);
- Define_Integer_Constant(GEN_X400);
- Define_Integer_Constant(GEN_DIRNAME);
- Define_Integer_Constant(GEN_EDIPARTY);
- Define_Integer_Constant(GEN_URI);
- Define_Integer_Constant(GEN_IPADD);
- Define_Integer_Constant(GEN_RID);
-
- // CMS flags
+ /* CMS flags */
Define_Integer_Constant(CMS_NOCERTS);
Define_Integer_Constant(CMS_NOATTR);
Define_Integer_Constant(CMS_NOINTERN);
@@ -5450,14 +3945,20 @@ init_POW(void)
#undef Define_Integer_Constant
- // initialise library
- SSL_library_init();
- OpenSSL_add_all_algorithms();
- OpenSSL_add_all_ciphers();
- OpenSSL_add_all_digests();
+ /*
+ * Initialise library.
+ *
+ * We shouldn't need any of the SSL code or error strings anymore.
+ *
+ * If we cared deeply about avoiding references to symmetric cipher
+ * algorithms and digest algorithms we're not using, we could
+ * replace the call to OpenSSL_add_all_algorithms() with calls to
+ * add just the specific algorithms we use rather than all of them.
+ * For now, don't worry about it.
+ */
- // load error strings
- SSL_load_error_strings();
+ OpenSSL_add_all_algorithms();
+ ERR_load_crypto_strings();
if (PyErr_Occurred())
Py_FatalError("Can't initialize module POW");