diff options
-rwxr-xr-x | configure | 4 | ||||
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | rpkid/ext/POW.c | 3355 |
3 files changed, 932 insertions, 2431 deletions
@@ -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"); |