aboutsummaryrefslogtreecommitdiff
path: root/rpkid/ext/POW.c
diff options
context:
space:
mode:
Diffstat (limited to 'rpkid/ext/POW.c')
-rw-r--r--rpkid/ext/POW.c9253
1 files changed, 0 insertions, 9253 deletions
diff --git a/rpkid/ext/POW.c b/rpkid/ext/POW.c
deleted file mode 100644
index b5d9ccaf..00000000
--- a/rpkid/ext/POW.c
+++ /dev/null
@@ -1,9253 +0,0 @@
-/*
- * 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--2013 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$ */
-
-#define PY_SSIZE_T_CLEAN 1
-#include <Python.h>
-#include <datetime.h>
-
-#include <openssl/opensslconf.h>
-#include <openssl/crypto.h>
-#include <openssl/rand.h>
-#include <openssl/asn1.h>
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-#include <openssl/pem.h>
-#include <openssl/evp.h>
-#include <openssl/err.h>
-#include <openssl/md5.h>
-#include <openssl/sha.h>
-#include <openssl/cms.h>
-
-#include <rpki/roa.h>
-#include <rpki/manifest.h>
-
-#include <time.h>
-#include <string.h>
-#include <arpa/inet.h>
-#include <sys/socket.h>
-
-/*
- * GCC attribute to let us tell GCC not to whine about unused formal
- * parameters when we're in maximal warning mode.
- */
-#ifdef __GNUC__
-#define GCC_UNUSED __attribute__((unused))
-#else
-define GCC_UNUSED
-#endif
-
-/*
- * Maximum size of a raw IP (v4 or v6) address, in bytes.
- */
-#define RAW_IPADDR_BUFLEN 16
-
-/*
- * Maximum size of an ASN.1 Integer converted from a Python Long, in bytes.
- */
-#define MAX_ASN1_INTEGER_LEN 20
-
-/* Digests */
-#define MD5_DIGEST 2
-#define SHA_DIGEST 3
-#define SHA1_DIGEST 4
-#define SHA256_DIGEST 6
-#define SHA384_DIGEST 7
-#define SHA512_DIGEST 8
-
-/* Object format */
-#define SHORTNAME_FORMAT 1
-#define LONGNAME_FORMAT 2
-#define OIDNAME_FORMAT 3
-
-/* AsymmetricParam EC curves */
-#define EC_P256_CURVE NID_X9_62_prime256v1
-
-/* Object check functions */
-#define POW_X509_Check(op) PyObject_TypeCheck(op, &POW_X509_Type)
-#define POW_X509Store_Check(op) PyObject_TypeCheck(op, &POW_X509Store_Type)
-#define POW_X509StoreCTX_Check(op) PyObject_TypeCheck(op, &POW_X509StoreCTX_Type)
-#define POW_CRL_Check(op) PyObject_TypeCheck(op, &POW_CRL_Type)
-#define POW_Asymmetric_Check(op) PyObject_TypeCheck(op, &POW_Asymmetric_Type)
-#define POW_AsymmetricParams_Check(op) PyObject_TypeCheck(op, &POW_AsymmetricParams_Type)
-#define POW_Digest_Check(op) PyObject_TypeCheck(op, &POW_Digest_Type)
-#define POW_CMS_Check(op) PyObject_TypeCheck(op, &POW_CMS_Type)
-#define POW_IPAddress_Check(op) PyObject_TypeCheck(op, &POW_IPAddress_Type)
-#define POW_ROA_Check(op) PyObject_TypeCheck(op, &POW_ROA_Type)
-#define POW_Manifest_Check(op) PyObject_TypeCheck(op, &POW_Manifest_Type)
-#define POW_ROA_Check(op) PyObject_TypeCheck(op, &POW_ROA_Type)
-
-static char pow_module__doc__ [] =
- "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"
-
-/*
- * Handle NIDs we wish OpenSSL knew about. This is carefully (we
- * hope) written to do nothing at all for any NID that OpenSSL knows
- * about; the intent is just to add definitions for things OpenSSL
- * doesn't know about yet. Of necessity, this is a bit gross, since
- * it confounds runtime static variables with predefined macro names,
- * but we try to put all the magic associated with this in one place.
- */
-
-#ifndef NID_rpkiManifest
-static int NID_rpkiManifest;
-#endif
-
-#ifndef NID_signedObject
-static int NID_signedObject;
-#endif
-
-static const struct {
- int *nid;
- const char *oid;
- const char *sn;
- const char *ln;
-} missing_nids[] = {
-
-#ifndef NID_rpkiManifest
- {&NID_rpkiManifest, "1.3.6.1.5.5.7.48.10", "id-ad-rpkiManifest", "RPKI Manifest"},
-#endif
-
-#ifndef NID_signedObject
- {&NID_signedObject, "1.3.6.1.5.5.7.48.11", "id-ad-signedObject", "Signed Object"}
-#endif
-
-};
-
-/*
- * IP versions.
- */
-
-typedef struct ipaddress_version {
- unsigned version;
- unsigned afi;
- unsigned af;
- unsigned length;
-} ipaddress_version;
-
-static const ipaddress_version ipaddress_version_4 = {
- 4, IANA_AFI_IPV4, AF_INET, 4
-};
-
-static const ipaddress_version ipaddress_version_6 = {
- 6, IANA_AFI_IPV6, AF_INET6, 16
-};
-
-static const ipaddress_version * const ipaddress_versions[] = {
- &ipaddress_version_4, &ipaddress_version_6
-};
-
-/*
- * Names of bits in the KeyUsage BitString (RFC 5280 4.2.1.3).
- */
-
-static const char * const key_usage_bit_names[] = {
- "digitalSignature", /* (0) */
- "nonRepudiation", /* (1) */
- "keyEncipherment", /* (2) */
- "dataEncipherment", /* (3) */
- "keyAgreement", /* (4) */
- "keyCertSign", /* (5) */
- "cRLSign", /* (6) */
- "encipherOnly", /* (7) */
- "decipherOnly", /* (8) */
- NULL
-};
-
-/*
- * Exception objects.
- */
-
-static PyObject
- *ErrorObject,
- *OpenSSLErrorObject,
- *POWErrorObject,
- *NotVerifiedErrorObject;
-
-/*
- * Constructor for customized datetime class.
- */
-
-static PyObject *custom_datetime;
-
-/*
- * "ex_data" index for pointer we want to attach to X509_STORE_CTX so
- * we can extract it in callbacks.
- */
-
-static int x509_store_ctx_ex_data_idx = -1;
-
-/*
- * Declarations of type objects (definitions come later).
- */
-
-static PyTypeObject
- POW_X509_Type,
- POW_X509Store_Type,
- POW_X509StoreCTX_Type,
- POW_CRL_Type,
- POW_Asymmetric_Type,
- POW_AsymmetricParams_Type,
- POW_Digest_Type,
- POW_CMS_Type,
- POW_IPAddress_Type,
- POW_ROA_Type,
- POW_Manifest_Type,
- POW_ROA_Type,
- POW_PKCS10_Type;
-
-/*
- * Object internals.
- */
-
-typedef struct {
- PyObject_HEAD
- unsigned char address[16];
- const struct ipaddress_version *type;
-} ipaddress_object;
-
-typedef struct {
- PyObject_HEAD
- X509 *x509;
-} x509_object;
-
-typedef struct {
- PyObject_HEAD
- X509_STORE *store;
- PyObject *ctxclass;
-} x509_store_object;
-
-typedef struct {
- PyObject_HEAD
- X509_STORE_CTX *ctx;
- x509_store_object *store;
-} x509_store_ctx_object;
-
-typedef struct {
- PyObject_HEAD
- X509_CRL *crl;
-} crl_object;
-
-typedef struct {
- PyObject_HEAD
- EVP_PKEY *pkey;
-} asymmetric_object;
-
-typedef struct {
- PyObject_HEAD
- EVP_PKEY *pkey;
-} asymmetric_params_object;
-
-typedef struct {
- PyObject_HEAD
- EVP_MD_CTX digest_ctx;
- int digest_type;
-} digest_object;
-
-typedef struct {
- PyObject_HEAD
- CMS_ContentInfo *cms;
-} cms_object;
-
-typedef struct {
- cms_object cms; /* Subclass of CMS */
- ROA *roa;
-} roa_object;
-
-typedef struct {
- cms_object cms; /* Subclass of CMS */
- Manifest *manifest;
-} manifest_object;
-
-typedef struct {
- PyObject_HEAD
- X509_REQ *pkcs10;
- X509_EXTENSIONS *exts;
-} pkcs10_object;
-
-
-
-/*
- * Utility functions.
- */
-
-/*
- * Minimal intervention debug-by-printf() hack, use only for good.
- */
-
-#if 0
-#define KVETCH(_msg_) write(2, _msg_ "\n", sizeof(_msg_))
-#else
-#define KVETCH(_msg_) ((void) 0)
-#endif
-
-#if 0
-#define ENTERING(_name_) KVETCH("Entering " #_name_ "()")
-#else
-#define ENTERING(_name_) ((void) 0)
-#endif
-
-/*
- * Error handling macros. All of macros assume that there's a cleanup
- * label named "error" which these macros can use as a goto target.
- */
-
-#define lose(_msg_) \
- do { \
- PyErr_SetString(POWErrorObject, (_msg_)); \
- goto error; \
- } while (0)
-
-#define lose_no_memory() \
- do { \
- PyErr_NoMemory(); \
- goto error; \
- } while (0)
-
-#define lose_type_error(_msg_) \
- do { \
- PyErr_SetString(PyExc_TypeError, (_msg_)); \
- goto error; \
- } while (0)
-
-#define lose_value_error(_msg_) \
- do { \
- PyErr_SetString(PyExc_ValueError, (_msg_)); \
- goto error; \
- } while (0)
-
-#define lose_openssl_error(_msg_) \
- do { \
- set_openssl_exception(OpenSSLErrorObject, (_msg_), 0); \
- goto error; \
- } while (0)
-
-#define lose_not_verified(_msg_) \
- do { \
- PyErr_SetString(NotVerifiedErrorObject, (_msg_)); \
- goto error; \
- } while (0)
-
-#define assert_no_unhandled_openssl_errors() \
- do { \
- if (ERR_peek_error()) { \
- set_openssl_exception(OpenSSLErrorObject, NULL, __LINE__); \
- goto error; \
- } \
- } while (0)
-
-#define POW_assert(_cond_) \
- do { \
- if (!(_cond_)) { \
- (void) PyErr_Format(POWErrorObject, \
- "Assertion %s failed at " __FILE__ ":%d", \
- #_cond_, __LINE__); \
- goto error; \
- } \
- } while (0)
-
-/*
- * Consolidate some tedious EVP-related switch statements.
- */
-
-static const EVP_MD *
-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();
- default: return NULL;
- }
-}
-
-/*
- * Raise an exception with data pulled from the OpenSSL error stack.
- * Exception value is a tuple with some internal structure.
- *
- * If a string error message is supplied, that string is the first
- * element of the exception value tuple.
- *
- * If a non-zero line number is supplied, a string listing this as an
- * unhandled exception detected at that line will be the next element
- * of the exception value tuple (or the first, if no error message was
- * supplied).
- *
- * Remainder of exception value tuple is zero or more tuples, each
- * representing one error from the stack.
- *
- * Each error tuple contains six slots:
- * - the numeric error code
- * - string translation of numeric error code ("reason")
- * - name of library in which error occurred
- * - name of function in which error occurred
- * - name of file in which error occurred
- * - line number in file where error occurred
- */
-
-static void
-set_openssl_exception(PyObject *error_class, const char *msg, const int unhandled_line)
-{
- PyObject *errtuple = NULL;
- PyObject *errlist = NULL;
- unsigned long err;
- const char *file;
- int line;
-
- if ((errlist = PyList_New(0)) == NULL)
- return;
-
- if (msg) {
- PyObject *s = PyString_FromString(msg);
- (void) PyList_Append(errlist, s);
- Py_XDECREF(s);
- }
-
- if (unhandled_line) {
- PyObject *s = PyString_FromFormat("Unhandled OpenSSL error at " __FILE__ ":%d!", unhandled_line);
- (void) PyList_Append(errlist, s);
- Py_XDECREF(s);
- }
-
- while ((err = ERR_get_error_line(&file, &line)) != 0) {
- PyObject *t = Py_BuildValue("(issssi)",
- err,
- ERR_reason_error_string(err),
- ERR_lib_error_string(err),
- ERR_func_error_string(err),
- file,
- line);
- (void) PyList_Append(errlist, t);
- Py_XDECREF(t);
- }
-
- if ((errtuple = PyList_AsTuple(errlist)) != NULL)
- PyErr_SetObject(error_class, errtuple);
-
- Py_XDECREF(errtuple);
- Py_XDECREF(errlist);
-}
-
-static X509_NAME *
-x509_object_helper_set_name(PyObject *dn_obj)
-{
- PyObject *rdn_obj = NULL;
- PyObject *pair_obj = NULL;
- PyObject *type_obj = NULL;
- PyObject *value_obj = NULL;
- X509_NAME *name = NULL;
- char *type_str, *value_str;
- int asn1_type, i, j;
-
- if ((name = X509_NAME_new()) == NULL)
- lose_no_memory();
-
- for (i = 0; i < PySequence_Size(dn_obj); i++) {
-
- if ((rdn_obj = PySequence_GetItem(dn_obj, i)) == NULL)
- goto error;
-
- if (!PySequence_Check(rdn_obj) || PySequence_Size(rdn_obj) == 0)
- lose_type_error("each RDN must be a sequence with at least one element");
-
- for (j = 0; j < PySequence_Size(rdn_obj); j++) {
-
- if ((pair_obj = PySequence_GetItem(rdn_obj, j)) == NULL)
- goto error;
-
- if (!PySequence_Check(pair_obj) || PySequence_Size(pair_obj) != 2)
- lose_type_error("each name entry must be a two-element sequence");
-
- if ((type_obj = PySequence_GetItem(pair_obj, 0)) == NULL ||
- (type_str = PyString_AsString(type_obj)) == NULL ||
- (value_obj = PySequence_GetItem(pair_obj, 1)) == NULL ||
- (value_str = PyString_AsString(value_obj)) == NULL)
- goto error;
-
- if ((asn1_type = ASN1_PRINTABLE_type((unsigned char *) value_str, -1)) != V_ASN1_PRINTABLESTRING)
- asn1_type = V_ASN1_UTF8STRING;
-
- if (!X509_NAME_add_entry_by_txt(name, type_str, asn1_type,
- (unsigned char *) value_str,
- strlen((char *) value_str),
- -1, (j ? -1 : 0)))
- lose("Unable to add name entry");
-
- Py_XDECREF(pair_obj);
- Py_XDECREF(type_obj);
- Py_XDECREF(value_obj);
- pair_obj = type_obj = value_obj = NULL;
- }
-
- Py_XDECREF(rdn_obj);
- rdn_obj = NULL;
- }
-
- return name;
-
- error:
- X509_NAME_free(name);
- Py_XDECREF(rdn_obj);
- Py_XDECREF(pair_obj);
- Py_XDECREF(type_obj);
- Py_XDECREF(value_obj);
- return NULL;
-}
-
-static PyObject *
-x509_object_helper_get_name(X509_NAME *name, int format)
-{
- X509_NAME_ENTRY *entry = NULL;
- PyObject *result = NULL;
- PyObject *rdn = NULL;
- PyObject *item = NULL;
- const char *oid = NULL;
- char oidbuf[512];
- int i, set = -1;
-
- /*
- * Overall theory here: multi-value RDNs are very rare in the wild.
- * We should support them, so we don't throw an exception if handed
- * one in a BPKI certificate, but with minimal effort. What we care
- * about here is optimizing for the common case of single-valued RDNs.
- */
-
- if ((result = PyTuple_New(X509_NAME_entry_count(name))) == NULL)
- goto error;
-
- for (i = 0; i < X509_NAME_entry_count(name); i++) {
-
- if ((entry = X509_NAME_get_entry(name, i)) == NULL)
- lose("Couldn't get certificate name");
-
- if (entry->set < 0 || entry->set < set || entry->set > set + 1)
- lose("X509_NAME->set value out of expected range");
-
- switch (format) {
- case SHORTNAME_FORMAT:
- oid = OBJ_nid2sn(OBJ_obj2nid(entry->object));
- break;
- case LONGNAME_FORMAT:
- oid = OBJ_nid2ln(OBJ_obj2nid(entry->object));
- break;
- case OIDNAME_FORMAT:
- oid = NULL;
- break;
- default:
- lose("Unknown name format");
- }
-
- if (oid == NULL) {
- if (OBJ_obj2txt(oidbuf, sizeof(oidbuf), entry->object, 1) <= 0)
- lose_openssl_error("Couldn't translate OID");
- oid = oidbuf;
- }
-
- if (entry->set > set) {
-
- set++;
- if ((item = Py_BuildValue("((ss#))", oid, ASN1_STRING_data(entry->value),
- (Py_ssize_t) ASN1_STRING_length(entry->value))) == NULL)
- goto error;
- PyTuple_SET_ITEM(result, set, item);
- item = NULL;
-
- } else {
-
- if ((rdn = PyTuple_GetItem(result, set)) == NULL)
- goto error;
- (void) _PyTuple_Resize(&rdn, PyTuple_Size(rdn) + 1);
- PyTuple_SET_ITEM(result, set, rdn);
- if (rdn == NULL)
- goto error;
- if ((item = Py_BuildValue("(ss#)", oid, ASN1_STRING_data(entry->value),
- (Py_ssize_t) ASN1_STRING_length(entry->value))) == NULL)
- goto error;
- PyTuple_SetItem(rdn, PyTuple_Size(rdn) - 1, item);
- rdn = item = NULL;
-
- }
- }
-
- if (++set != PyTuple_Size(result)) {
- if (set < 0 || set > PyTuple_Size(result))
- lose("Impossible set count for DN, something went horribly wrong");
- _PyTuple_Resize(&result, set);
- }
-
- return result;
-
- error:
- Py_XDECREF(item);
- Py_XDECREF(result);
- return NULL;
-}
-
-static STACK_OF(X509) *
-x509_helper_iterable_to_stack(PyObject *iterable)
-{
- STACK_OF(X509) *stack = NULL;
- PyObject *iterator = NULL;
- PyObject *item = NULL;
-
- if ((stack = sk_X509_new_null()) == NULL)
- lose_no_memory();
-
- if (iterable != Py_None) {
-
- if ((iterator = PyObject_GetIter(iterable)) == NULL)
- goto error;
-
- while ((item = PyIter_Next(iterator)) != NULL) {
-
- if (!POW_X509_Check(item))
- lose_type_error("Inapropriate type");
-
- if (!sk_X509_push(stack, ((x509_object *) item)->x509))
- lose("Couldn't add X509 object to stack");
-
- Py_XDECREF(item);
- item = NULL;
- }
- }
-
- Py_XDECREF(iterator);
- return stack;
-
- error:
- Py_XDECREF(iterator);
- Py_XDECREF(item);
- sk_X509_free(stack);
- return NULL;
-}
-
-/*
- * Pull items off an OpenSSL STACK and put them into a Python tuple.
- * Assumes that handler is stealing the OpenSSL references to the
- * items in the STACK, so shifts consumed frames off the stack so that
- * the appropriate _pop_free() destructor can clean up on failures.
- * This is OK because all current uses of this function are processing
- * the result of OpenSSL xxx_get1_xxx() methods which we have to free
- * in any case.
- */
-
-static x509_object *x509_object_new_helper(PyTypeObject *, X509 *);
-static crl_object *crl_object_new_helper (PyTypeObject *, X509_CRL *);
-
-static PyObject *
-stack_to_tuple_helper(_STACK *sk, PyObject *(*handler)(void *))
-{
- PyObject *result = NULL;
- PyObject *obj = NULL;
- int i;
-
- if ((result = PyTuple_New(sk_num(sk))) == NULL)
- goto error;
-
- for (i = 0; sk_num(sk); i++) {
- if ((obj = handler(sk_value(sk, 0))) == NULL)
- goto error;
- sk_shift(sk);
- if (PyTuple_SetItem(result, i, obj) != 0)
- goto error;
- obj = NULL;
- }
-
- return result;
-
- error:
-
- Py_XDECREF(obj);
- return NULL;
-}
-
-static PyObject *
-stack_to_tuple_helper_get_x509(void *cert)
-{
- x509_object *obj;
-
- ENTERING(stack_to_tuple_helper_get_x509);
-
- if ((obj = x509_object_new_helper(NULL, cert)) == NULL)
- return NULL;
-
- return (PyObject *) obj;
-}
-
-static PyObject *
-stack_to_tuple_helper_get_crl(void *crl)
-{
- crl_object *obj;
-
- ENTERING(stack_to_tuple_helper_get_crl);
-
- if ((obj = crl_object_new_helper(NULL, crl)) == NULL)
- return NULL;
-
- return (PyObject *) obj;
-}
-
-/*
- * Time conversion functions. Obvious mapping into Python data types
- * is datetime, or, rather, our customized rpki.sundial.datetime.
- *
- * Unsuprisingly, it's easiest for us to map between GeneralizedTime
- * (as restricted by RFC 5280) and datetime. Conversion between
- * GeneralizedTime and UTCTime is handled automatically according to
- * the RFC 5280 rules for those ASN.1 types where it's required.
- */
-
-static PyObject *
-ASN1_TIME_to_Python(ASN1_TIME *t)
-{
- ASN1_GENERALIZEDTIME *g = NULL;
- PyObject *result = NULL;
- int year, month, day, hour, minute, second;
-
- if ((g = ASN1_TIME_to_generalizedtime(t, NULL)) == NULL)
- lose_openssl_error("Couldn't convert ASN.1 TIME");
-
- if (sscanf((char *) g->data, "%4d%2d%2d%2d%2d%2dZ",
- &year, &month, &day, &hour, &minute, &second) != 6)
- lose("Couldn't scan ASN.1 TIME value");
-
- if (custom_datetime != NULL && custom_datetime != Py_None)
- result = PyObject_CallFunction(custom_datetime, "iiiiii",
- year, month, day, hour, minute, second);
- else
- result = PyDateTime_FromDateAndTime(year, month, day, hour, minute, second, 0);
-
- error:
- ASN1_GENERALIZEDTIME_free(g);
- return result;
-}
-
-static ASN1_TIME *
-Python_to_ASN1_TIME(PyObject *arg, const int object_requires_utctime)
-{
- char buf[sizeof("20010401123456Z") + 1];
- ASN1_TIME *result = NULL;
- const char *s = NULL;
- int ok;
-
- if (PyDateTime_Check(arg)) {
- if (snprintf(buf, sizeof(buf), "%4d%02d%02d%02d%02d%02dZ",
- PyDateTime_GET_YEAR(arg),
- PyDateTime_GET_MONTH(arg),
- PyDateTime_GET_DAY(arg),
- PyDateTime_DATE_GET_HOUR(arg),
- PyDateTime_DATE_GET_MINUTE(arg),
- PyDateTime_DATE_GET_SECOND(arg)) >= (int) sizeof(buf))
- lose("Internal error -- GeneralizedTime buffer too small");
- s = buf;
- }
-
- if (s == NULL && (s = PyString_AsString(arg)) == NULL)
- goto error;
-
- if (strlen(s) < 10)
- lose_type_error("String is too short to parse as a valid ASN.1 TIME");
-
- if ((result = ASN1_TIME_new()) == NULL)
- lose_no_memory();
-
- if (object_requires_utctime &&
- ((s[0] == '1' && s[1] == '9' && s[2] > '4') ||
- (s[0] == '2' && s[1] == '0' && s[2] < '5')))
- ok = ASN1_UTCTIME_set_string(result, s + 2);
- else
- ok = ASN1_GENERALIZEDTIME_set_string(result, s);
-
- if (ok)
- return result;
-
- error:
- ASN1_TIME_free(result);
- return NULL;
-}
-
-/*
- * Extract a Python string from a memory BIO.
- */
-static PyObject *
-BIO_to_PyString_helper(BIO *bio)
-{
- char *ptr = NULL;
- Py_ssize_t len = 0;
-
- if ((len = BIO_get_mem_data(bio, &ptr)) == 0)
- lose_openssl_error("Unable to get BIO data");
-
- return Py_BuildValue("s#", ptr, len);
-
- error:
- return NULL;
-}
-
-static PyObject *
-read_from_string_helper(PyObject *(*object_read_helper)(PyTypeObject *, BIO *),
- PyTypeObject *type,
- PyObject *args)
-{
- PyObject *result = NULL;
- char *src = NULL;
- BIO *bio = NULL;
- Py_ssize_t len = 0;
-
- if (!PyArg_ParseTuple(args, "s#", &src, &len))
- goto error;
-
- if ((bio = BIO_new_mem_buf(src, len)) == NULL)
- lose_no_memory();
-
- result = object_read_helper(type, bio);
-
- error:
- BIO_free(bio);
- return result;
-}
-
-static PyObject *
-read_from_file_helper(PyObject *(*object_read_helper)(PyTypeObject *, BIO *),
- PyTypeObject *type,
- PyObject *args)
-{
- const char *filename = NULL;
- PyObject *result = NULL;
- BIO *bio = NULL;
-
- if (!PyArg_ParseTuple(args, "s", &filename))
- goto error;
-
- if ((bio = BIO_new_file(filename, "rb")) == NULL)
- lose_openssl_error("Could not open file");
-
- result = object_read_helper(type, bio);
-
- error:
- BIO_free(bio);
- return result;
-}
-
-/*
- * Simplify entries in method definition tables. See the "Common
- * Object Structures" section of the API manual for available flags.
- */
-#define Define_Method(__python_name__, __c_name__, __flags__) \
- { #__python_name__, (PyCFunction) __c_name__, __flags__, __c_name__##__doc__ }
-
-#define Define_Class_Method(__python_name__, __c_name__, __flags__) \
- Define_Method(__python_name__, __c_name__, (__flags__) | METH_CLASS)
-
-/*
- * Convert an ASN1_INTEGER into a Python integer or long.
- */
-static PyObject *
-ASN1_INTEGER_to_PyLong(ASN1_INTEGER *arg)
-{
- PyObject *result = NULL;
- PyObject *obj = NULL;
-
- if ((obj = _PyLong_FromByteArray(ASN1_STRING_data(arg),
- ASN1_STRING_length(arg),
- 0, 0)) != NULL)
- result = PyNumber_Int(obj);
-
- Py_XDECREF(obj);
- return result;
-}
-
-/*
- * Convert a Python long to an ASN1_INTEGER.
- * This is just nasty, do not read on a full stomach.
- *
- * Maximum size of integer to be converted here is taken from RFC 5280
- * 4.1.2.2, which sets a maximum of 20 octets for an X.509 certificate
- * serial number.
- *
- * In theory we could use _PyLong_NumBits() to determine the length of
- * the long before converting, and raise OverflowError if it's too big.
- * Hmm.
- */
-static ASN1_INTEGER *
-PyLong_to_ASN1_INTEGER(PyObject *arg)
-{
- PyObject *obj = NULL;
- ASN1_INTEGER *a = NULL;
- unsigned char buf[MAX_ASN1_INTEGER_LEN];
- size_t len;
-
- memset(buf, 0, sizeof(buf));
-
- /*
- * Make sure argument is a PyLong small enough that its length (in
- * bits!) doesn't overflow a size_t (which is a mis-use of size_t,
- * but take that up with whoever wrote _PyLong_NumBits()...).
- */
- if ((obj = PyNumber_Long(arg)) == NULL ||
- (len = _PyLong_NumBits(obj)) == (size_t) -1)
- goto error;
-
- /*
- * Next make sure it's a non-negative integer small enough to fit in
- * our buffer. If we really thought we needed to support larger
- * integers we could allocate this dynamically, but we don't, so
- * it's not worth the overhead.
- *
- * Paranoia: We can't convert len to bytes yet, because that
- * requires rounding up and we don't know yet that we have enough
- * headroom to do that arithmetic without overflowing a size_t.
- */
- if (_PyLong_Sign(obj) < 0 || (len / 8) + 1 > sizeof(buf)) {
- PyErr_SetObject(PyExc_OverflowError, obj);
- goto error;
- }
-
- /*
- * Now that we know we're dealing with a sane number of bits,
- * convert it to bytes.
- */
- len = (len + 7) / 8;
-
- /*
- * Extract that many bytes.
- */
- if (_PyLong_AsByteArray((PyLongObject *) obj, buf, len, 0, 0) < 0)
- goto error;
-
- /*
- * We're done with the PyLong now.
- */
- Py_XDECREF(obj);
- obj = NULL;
-
- /*
- * Generate the ASN1_INTEGER and return it.
- */
- if ((a = ASN1_INTEGER_new()) == NULL ||
- (a->length < (int) len + 1 && (a->data = OPENSSL_realloc(a->data, len + 1)) == NULL))
- lose_no_memory();
-
- a->type = V_ASN1_INTEGER;
- a->length = len;
- a->data[len] = 0;
- memcpy(a->data, buf, len);
-
- return a;
-
- error:
- Py_XDECREF(obj);
- ASN1_INTEGER_free(a);
- return NULL;
-}
-
-/*
- * Handle missing NIDs.
- */
-
-static int
-create_missing_nids(void)
-{
- int i;
-
- for (i = 0; i < (int) (sizeof(missing_nids) / sizeof(*missing_nids)); i++)
- if ((*missing_nids[i].nid = OBJ_txt2nid(missing_nids[i].oid)) == NID_undef &&
- (*missing_nids[i].nid = OBJ_create(missing_nids[i].oid,
- missing_nids[i].sn,
- missing_nids[i].ln)) == NID_undef)
- return 0;
-
- return 1;
-}
-
-static PyObject *
-ASN1_OBJECT_to_PyString(const ASN1_OBJECT *oid)
-{
- PyObject *result = NULL;
- char buf[512];
-
- ENTERING(ASN1_OBJECT_to_PyString);
-
- if (OBJ_obj2txt(buf, sizeof(buf), oid, 1) <= 0)
- lose_openssl_error("Couldn't translate OID");
-
- result = PyString_FromString(buf);
-
- error:
- return result;
-}
-
-
-
-/*
- * Extension functions. Calling sequence here is a little weird,
- * because it turns out that the simplest way to avoid massive
- * duplication of code between classes is to work directly with
- * X509_EXTENSIONS objects.
- */
-
-static PyObject *
-extension_get_key_usage(X509_EXTENSIONS **exts)
-{
- ASN1_BIT_STRING *ext = NULL;
- PyObject *result = NULL;
- PyObject *token = NULL;
- int bit = -1;
-
- ENTERING(extension_get_key_usage);
-
- if (!exts)
- goto error;
-
- if ((ext = X509V3_get_d2i(*exts, NID_key_usage, NULL, NULL)) == NULL)
- Py_RETURN_NONE;
-
- if ((result = PyFrozenSet_New(NULL)) == NULL)
- goto error;
-
- for (bit = 0; key_usage_bit_names[bit] != NULL; bit++) {
- if (ASN1_BIT_STRING_get_bit(ext, bit) &&
- ((token = PyString_FromString(key_usage_bit_names[bit])) == NULL ||
- PySet_Add(result, token) < 0))
- goto error;
- Py_XDECREF(token);
- token = NULL;
- }
-
- ASN1_BIT_STRING_free(ext);
- return result;
-
- error:
- ASN1_BIT_STRING_free(ext);
- Py_XDECREF(token);
- Py_XDECREF(result);
- return NULL;
-}
-
-static PyObject *
-extension_set_key_usage(X509_EXTENSIONS **exts, PyObject *args)
-{
- ASN1_BIT_STRING *ext = NULL;
- PyObject *iterable = NULL;
- PyObject *critical = Py_True;
- PyObject *iterator = NULL;
- PyObject *item = NULL;
- const char *token;
- int bit = -1;
- int ok = 0;
-
- ENTERING(extension_set_key_usage);
-
- if (!exts)
- goto error;
-
- if ((ext = ASN1_BIT_STRING_new()) == NULL)
- lose_no_memory();
-
- if (!PyArg_ParseTuple(args, "O|O", &iterable, &critical) ||
- (iterator = PyObject_GetIter(iterable)) == NULL)
- goto error;
-
- while ((item = PyIter_Next(iterator)) != NULL) {
-
- if ((token = PyString_AsString(item)) == NULL)
- goto error;
-
- for (bit = 0; key_usage_bit_names[bit] != NULL; bit++)
- if (!strcmp(token, key_usage_bit_names[bit]))
- break;
-
- if (key_usage_bit_names[bit] == NULL)
- lose("Unrecognized KeyUsage token");
-
- if (!ASN1_BIT_STRING_set_bit(ext, bit, 1))
- lose_no_memory();
-
- Py_XDECREF(item);
- item = NULL;
- }
-
- if (!X509V3_add1_i2d(exts, NID_key_usage, ext,
- PyObject_IsTrue(critical),
- X509V3_ADD_REPLACE))
- lose_openssl_error("Couldn't add KeyUsage extension to OpenSSL object");
-
- ok = 1;
-
- error: /* Fall through */
- ASN1_BIT_STRING_free(ext);
- Py_XDECREF(iterator);
- Py_XDECREF(item);
-
- if (ok)
- Py_RETURN_NONE;
- else
- return NULL;
-}
-
-static PyObject *
-extension_get_basic_constraints(X509_EXTENSIONS **exts)
-{
- BASIC_CONSTRAINTS *ext = NULL;
- PyObject *result = NULL;
-
- ENTERING(extension_get_basic_constraints);
-
- if (!exts)
- goto error;
-
- if ((ext = X509V3_get_d2i(*exts, NID_basic_constraints, NULL, NULL)) == NULL)
- Py_RETURN_NONE;
-
- if (ext->pathlen == NULL)
- result = Py_BuildValue("(NO)", PyBool_FromLong(ext->ca), Py_None);
- else
- result = Py_BuildValue("(Nl)", PyBool_FromLong(ext->ca), ASN1_INTEGER_get(ext->pathlen));
-
- error:
- BASIC_CONSTRAINTS_free(ext);
- return result;
-}
-
-static PyObject *
-extension_set_basic_constraints(X509_EXTENSIONS **exts, PyObject *args)
-{
- BASIC_CONSTRAINTS *ext = NULL;
- PyObject *is_ca = NULL;
- PyObject *pathlen_obj = Py_None;
- PyObject *critical = Py_True;
- long pathlen = -1;
- int ok = 0;
-
- ENTERING(extension_set_basic_constraints);
-
- if (!exts)
- goto error;
-
- if (!PyArg_ParseTuple(args, "O|OO", &is_ca, &pathlen_obj, &critical))
- goto error;
-
- if (pathlen_obj != Py_None && (pathlen = PyInt_AsLong(pathlen_obj)) < 0)
- lose_type_error("Bad pathLenConstraint value");
-
- if ((ext = BASIC_CONSTRAINTS_new()) == NULL)
- lose_no_memory();
-
- ext->ca = PyObject_IsTrue(is_ca) ? 0xFF : 0;
-
- if (pathlen_obj != Py_None &&
- ((ext->pathlen == NULL && (ext->pathlen = ASN1_INTEGER_new()) == NULL) ||
- !ASN1_INTEGER_set(ext->pathlen, pathlen)))
- lose_no_memory();
-
- if (!X509V3_add1_i2d(exts, NID_basic_constraints, ext,
- PyObject_IsTrue(critical), X509V3_ADD_REPLACE))
- lose_openssl_error("Couldn't add BasicConstraints extension to OpenSSL object");
-
- ok = 1;
-
- error:
- BASIC_CONSTRAINTS_free(ext);
-
- if (ok)
- Py_RETURN_NONE;
- else
- return NULL;
-}
-
-static PyObject *
-extension_get_sia(X509_EXTENSIONS **exts)
-{
- AUTHORITY_INFO_ACCESS *ext = NULL;
- PyObject *result = NULL;
- PyObject *result_caRepository = NULL;
- PyObject *result_rpkiManifest = NULL;
- PyObject *result_signedObject = NULL;
- int n_caRepository = 0;
- int n_rpkiManifest = 0;
- int n_signedObject = 0;
- const char *uri;
- PyObject *obj;
- int i, nid;
-
- ENTERING(pkcs10_object_get_sia);
-
- if (!exts)
- goto error;
-
- if ((ext = X509V3_get_d2i(*exts, NID_sinfo_access, NULL, NULL)) == NULL)
- Py_RETURN_NONE;
-
- /*
- * Easiest to do this in two passes, first pass just counts URIs.
- */
-
- for (i = 0; i < sk_ACCESS_DESCRIPTION_num(ext); i++) {
- ACCESS_DESCRIPTION *a = sk_ACCESS_DESCRIPTION_value(ext, i);
- if (a->location->type != GEN_URI)
- continue;
- nid = OBJ_obj2nid(a->method);
- if (nid == NID_caRepository) {
- n_caRepository++;
- continue;
- }
- if (nid == NID_rpkiManifest) {
- n_rpkiManifest++;
- continue;
- }
- if (nid == NID_signedObject) {
- n_signedObject++;
- continue;
- }
- }
-
- if (((result_caRepository = PyTuple_New(n_caRepository)) == NULL) ||
- ((result_rpkiManifest = PyTuple_New(n_rpkiManifest)) == NULL) ||
- ((result_signedObject = PyTuple_New(n_signedObject)) == NULL))
- goto error;
-
- n_caRepository = n_rpkiManifest = n_signedObject = 0;
-
- for (i = 0; i < sk_ACCESS_DESCRIPTION_num(ext); i++) {
- ACCESS_DESCRIPTION *a = sk_ACCESS_DESCRIPTION_value(ext, i);
- if (a->location->type != GEN_URI)
- continue;
- nid = OBJ_obj2nid(a->method);
- uri = (char *) ASN1_STRING_data(a->location->d.uniformResourceIdentifier);
- if (nid == NID_caRepository) {
- if ((obj = PyString_FromString(uri)) == NULL)
- goto error;
- PyTuple_SET_ITEM(result_caRepository, n_caRepository++, obj);
- continue;
- }
- if (nid == NID_rpkiManifest) {
- if ((obj = PyString_FromString(uri)) == NULL)
- goto error;
- PyTuple_SET_ITEM(result_rpkiManifest, n_rpkiManifest++, obj);
- continue;
- }
- if (nid == NID_signedObject) {
- if ((obj = PyString_FromString(uri)) == NULL)
- goto error;
- PyTuple_SET_ITEM(result_signedObject, n_signedObject++, obj);
- continue;
- }
- }
-
- result = Py_BuildValue("(OOO)",
- result_caRepository,
- result_rpkiManifest,
- result_signedObject);
-
- error:
- AUTHORITY_INFO_ACCESS_free(ext);
- Py_XDECREF(result_caRepository);
- Py_XDECREF(result_rpkiManifest);
- Py_XDECREF(result_signedObject);
- return result;
-}
-
-static PyObject *
-extension_set_sia(X509_EXTENSIONS **exts, PyObject *args, PyObject *kwds)
-{
- static char *kwlist[] = {"caRepository", "rpkiManifest", "signedObject", NULL};
- AUTHORITY_INFO_ACCESS *ext = NULL;
- PyObject *caRepository = Py_None;
- PyObject *rpkiManifest = Py_None;
- PyObject *signedObject = Py_None;
- PyObject *iterator = NULL;
- ASN1_OBJECT *oid = NULL;
- PyObject **pobj = NULL;
- PyObject *item = NULL;
- ACCESS_DESCRIPTION *a = NULL;
- int i, nid = NID_undef, ok = 0;
- Py_ssize_t urilen;
- char *uri;
-
- ENTERING(extension_set_sia);
-
- if (!exts)
- goto error;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", kwlist,
- &caRepository, &rpkiManifest, &signedObject))
- goto error;
-
- if ((ext = AUTHORITY_INFO_ACCESS_new()) == NULL)
- lose_no_memory();
-
- /*
- * This is going to want refactoring, because it's ugly, because we
- * want to reuse code for AIA, and because it'd be nice to support a
- * single URI as an abbreviation for a collection containing one URI.
- */
-
- for (i = 0; i < 3; i++) {
- switch (i) {
- case 0: pobj = &caRepository; nid = NID_caRepository; break;
- case 1: pobj = &rpkiManifest; nid = NID_rpkiManifest; break;
- case 2: pobj = &signedObject; nid = NID_signedObject; break;
- }
-
- if (*pobj == Py_None)
- continue;
-
- if ((oid = OBJ_nid2obj(nid)) == NULL)
- lose_openssl_error("Couldn't find SIA accessMethod OID");
-
- if ((iterator = PyObject_GetIter(*pobj)) == NULL)
- goto error;
-
- while ((item = PyIter_Next(iterator)) != NULL) {
-
- if (PyString_AsStringAndSize(item, &uri, &urilen) < 0)
- goto error;
-
- if ((a = ACCESS_DESCRIPTION_new()) == NULL ||
- (a->method = OBJ_dup(oid)) == NULL ||
- (a->location->d.uniformResourceIdentifier = ASN1_IA5STRING_new()) == NULL ||
- !ASN1_OCTET_STRING_set(a->location->d.uniformResourceIdentifier, (unsigned char *) uri, urilen))
- lose_no_memory();
-
- a->location->type = GEN_URI;
-
- if (!sk_ACCESS_DESCRIPTION_push(ext, a))
- lose_no_memory();
-
- a = NULL;
- Py_XDECREF(item);
- item = NULL;
- }
-
- Py_XDECREF(iterator);
- iterator = NULL;
- }
-
- if (!X509V3_add1_i2d(exts, NID_sinfo_access, ext, 0, X509V3_ADD_REPLACE))
- lose_openssl_error("Couldn't add SIA extension to OpenSSL object");
-
- ok = 1;
-
- error:
- AUTHORITY_INFO_ACCESS_free(ext);
- ACCESS_DESCRIPTION_free(a);
- Py_XDECREF(item);
- Py_XDECREF(iterator);
-
- if (ok)
- Py_RETURN_NONE;
- else
- return NULL;
-}
-
-static PyObject *
-extension_get_eku(X509_EXTENSIONS **exts)
-{
- EXTENDED_KEY_USAGE *ext = NULL;
- PyObject *result = NULL;
- PyObject *oid = NULL;
- int i;
-
- ENTERING(extension_get_eku);
-
- if (!exts)
- goto error;
-
- if ((ext = X509V3_get_d2i(*exts, NID_ext_key_usage, NULL, NULL)) == NULL)
- Py_RETURN_NONE;
-
- if ((result = PyFrozenSet_New(NULL)) == NULL)
- goto error;
-
- for (i = 0; i < sk_ASN1_OBJECT_num(ext); i++) {
- if ((oid = ASN1_OBJECT_to_PyString(sk_ASN1_OBJECT_value(ext, i))) == NULL ||
- PySet_Add(result, oid) < 0)
- goto error;
- Py_XDECREF(oid);
- oid = NULL;
- }
-
- sk_ASN1_OBJECT_pop_free(ext, ASN1_OBJECT_free);
- return result;
-
- error:
- sk_ASN1_OBJECT_pop_free(ext, ASN1_OBJECT_free);
- Py_XDECREF(oid);
- Py_XDECREF(result);
- return NULL;
-}
-
-static PyObject *
-extension_set_eku(X509_EXTENSIONS **exts, PyObject *args)
-{
- EXTENDED_KEY_USAGE *ext = NULL;
- PyObject *iterable = NULL;
- PyObject *critical = Py_False;
- PyObject *iterator = NULL;
- PyObject *item = NULL;
- ASN1_OBJECT *obj = NULL;
- const char *txt;
- int ok = 0;
-
- ENTERING(extension_set_eku);
-
- if (!exts)
- goto error;
-
- if ((ext = sk_ASN1_OBJECT_new_null()) == NULL)
- lose_no_memory();
-
- if (!PyArg_ParseTuple(args, "O|O", &iterable, &critical) ||
- (iterator = PyObject_GetIter(iterable)) == NULL)
- goto error;
-
- while ((item = PyIter_Next(iterator)) != NULL) {
-
- if ((txt = PyString_AsString(item)) == NULL)
- goto error;
-
- if ((obj = OBJ_txt2obj(txt, 1)) == NULL)
- lose("Couldn't parse OID");
-
- if (!sk_ASN1_OBJECT_push(ext, obj))
- lose_no_memory();
-
- obj = NULL;
- Py_XDECREF(item);
- item = NULL;
- }
-
- if (sk_ASN1_OBJECT_num(ext) < 1)
- lose("Empty ExtendedKeyUsage extension");
-
- if (!X509V3_add1_i2d(exts, NID_ext_key_usage, ext,
- PyObject_IsTrue(critical),
- X509V3_ADD_REPLACE))
- lose_openssl_error("Couldn't add ExtendedKeyUsage extension to OpenSSL object");
-
- ok = 1;
-
- error: /* Fall through */
- sk_ASN1_OBJECT_pop_free(ext, ASN1_OBJECT_free);
- Py_XDECREF(item);
- Py_XDECREF(iterator);
-
- if (ok)
- Py_RETURN_NONE;
- else
- return NULL;
-}
-
-static PyObject *
-extension_get_ski(X509_EXTENSIONS **exts)
-{
- ASN1_OCTET_STRING *ext = NULL;
- PyObject *result = NULL;
-
- ENTERING(extension_get_ski);
-
- if (!exts)
- goto error;
-
- if ((ext = X509V3_get_d2i(*exts, NID_subject_key_identifier, NULL, NULL)) == NULL)
- Py_RETURN_NONE;
-
- result = Py_BuildValue("s#", ASN1_STRING_data(ext),
- (Py_ssize_t) ASN1_STRING_length(ext));
-
- error: /* Fall through */
- ASN1_OCTET_STRING_free(ext);
- return result;
-}
-
-static PyObject *
-extension_set_ski(X509_EXTENSIONS **exts, PyObject *args)
-{
- ASN1_OCTET_STRING *ext = NULL;
- const unsigned char *buf = NULL;
- Py_ssize_t len;
- int ok = 0;
-
- ENTERING(extension_set_ski);
-
- if (!exts)
- goto error;
-
- if (!PyArg_ParseTuple(args, "s#", &buf, &len))
- goto error;
-
- if ((ext = ASN1_OCTET_STRING_new()) == NULL ||
- !ASN1_OCTET_STRING_set(ext, buf, len))
- lose_no_memory();
-
- /*
- * RFC 5280 says this MUST be non-critical.
- */
-
- if (!X509V3_add1_i2d(exts, NID_subject_key_identifier,
- ext, 0, X509V3_ADD_REPLACE))
- lose_openssl_error("Couldn't add SKI extension to OpenSSL object");
-
- ok = 1;
-
- error:
- ASN1_OCTET_STRING_free(ext);
-
- if (ok)
- Py_RETURN_NONE;
- else
- return NULL;
-}
-
-static PyObject *
-extension_get_aki(X509_EXTENSIONS **exts)
-{
- AUTHORITY_KEYID *ext = NULL;
- PyObject *result = NULL;
-
- ENTERING(extension_get_aki);
-
- if (!exts)
- goto error;
-
- if ((ext = X509V3_get_d2i(*exts, NID_authority_key_identifier, NULL, NULL)) == NULL)
- Py_RETURN_NONE;
-
- result = Py_BuildValue("s#", ASN1_STRING_data(ext->keyid),
- (Py_ssize_t) ASN1_STRING_length(ext->keyid));
-
- error: /* Fall through */
- AUTHORITY_KEYID_free(ext);
- return result;
-}
-
-static PyObject *
-extension_set_aki(X509_EXTENSIONS **exts, PyObject *args)
-{
- AUTHORITY_KEYID *ext = NULL;
- const unsigned char *buf = NULL;
- Py_ssize_t len;
- int ok = 0;
-
- ENTERING(extension_set_aki);
-
- assert (exts);
-
- if (!PyArg_ParseTuple(args, "s#", &buf, &len))
- goto error;
-
- if ((ext = AUTHORITY_KEYID_new()) == NULL ||
- (ext->keyid == NULL && (ext->keyid = ASN1_OCTET_STRING_new()) == NULL) ||
- !ASN1_OCTET_STRING_set(ext->keyid, buf, len))
- lose_no_memory();
-
- /*
- * RFC 5280 says this MUST be non-critical.
- */
-
- if (!X509V3_add1_i2d(exts, NID_authority_key_identifier,
- ext, 0, X509V3_ADD_REPLACE))
- lose_openssl_error("Couldn't add AKI extension to OpenSSL object");
-
- ok = 1;
-
- error:
- AUTHORITY_KEYID_free(ext);
-
- if (ok)
- Py_RETURN_NONE;
- else
- return NULL;
-}
-
-
-
-/*
- * IPAddress object.
- */
-
-static PyObject *
-ipaddress_object_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- static char *kwlist[] = {"initializer", "version", NULL};
- ipaddress_object *self = NULL;
- PyObject *init = NULL;
- PyObject *pylong = NULL;
- int version = 0;
- const char *s = NULL;
- int v;
-
- ENTERING(ipaddress_object_new);
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &init, &version) ||
- (self = (ipaddress_object *) type->tp_alloc(type, 0)) == NULL)
- goto error;
-
- if (POW_IPAddress_Check(init)) {
- ipaddress_object *src = (ipaddress_object *) init;
- memcpy(self->address, src->address, sizeof(self->address));
- self->type = src->type;
- return (PyObject *) self;
- }
-
- if ((s = PyString_AsString(init)) == NULL)
- PyErr_Clear();
- else if (version == 0)
- version = strchr(s, ':') ? 6 : 4;
-
- self->type = NULL;
-
- for (v = 0; v < (int) (sizeof(ipaddress_versions)/sizeof(*ipaddress_versions)); v++)
- if ((unsigned) version == ipaddress_versions[v]->version)
- self->type = ipaddress_versions[v];
-
- if (self->type == NULL)
- lose("Unknown IP version number");
-
- if (s != NULL) {
- if (inet_pton(self->type->af, s, self->address) <= 0)
- lose("Couldn't parse IP address");
- return (PyObject *) self;
- }
-
- if ((pylong = PyNumber_Long(init)) != NULL) {
- if (_PyLong_AsByteArray((PyLongObject *) pylong, self->address, self->type->length, 0, 0) < 0)
- goto error;
- Py_XDECREF(pylong);
- return (PyObject *) self;
- }
-
- lose_type_error("Couldn't convert initializer to IPAddress");
-
- error:
- Py_XDECREF(self);
- Py_XDECREF(pylong);
- return NULL;
-}
-
-static PyObject *
-ipaddress_object_str(ipaddress_object *self)
-{
- char addrstr[sizeof("aaaa:bbbb:cccc:dddd:eeee:ffff:255.255.255.255") + 1];
-
- ENTERING(ipaddress_object_str);
-
- if (!inet_ntop(self->type->af, self->address, addrstr, sizeof(addrstr)))
- lose("Couldn't convert IP address");
-
- return PyString_FromString(addrstr);
-
- error:
- return NULL;
-}
-
-static PyObject *
-ipaddress_object_repr(ipaddress_object *self)
-{
- char addrstr[sizeof("aaaa:bbbb:cccc:dddd:eeee:ffff:255.255.255.255") + 1];
-
- ENTERING(ipaddress_object_repr);
-
- if (!inet_ntop(self->type->af, self->address, addrstr, sizeof(addrstr)))
- lose("Couldn't convert IP address");
-
- return PyString_FromFormat("<%s object %s at %p>",
- self->ob_type->tp_name, addrstr, self);
-
- error:
- return NULL;
-}
-
-static int
-ipaddress_object_compare(PyObject *arg1, PyObject *arg2)
-{
- PyObject *obj1 = PyNumber_Long(arg1);
- PyObject *obj2 = PyNumber_Long(arg2);
- int cmp = -1;
-
- ENTERING(ipaddress_object_compare);
-
- if (obj1 != NULL && obj2 != NULL)
- cmp = PyObject_Compare(obj1, obj2);
-
- Py_XDECREF(obj1);
- Py_XDECREF(obj2);
- return cmp;
-}
-
-static PyObject *
-ipaddress_object_richcompare(PyObject *arg1, PyObject *arg2, int op)
-{
- PyObject *obj1 = PyNumber_Long(arg1);
- PyObject *obj2 = PyNumber_Long(arg2);
- PyObject *result = NULL;
-
- ENTERING(ipaddress_object_richcompare);
-
- if (obj1 != NULL && obj2 != NULL)
- result = PyObject_RichCompare(obj1, obj2, op);
-
- Py_XDECREF(obj1);
- Py_XDECREF(obj2);
- return result;
-}
-
-static long
-ipaddress_object_hash(ipaddress_object *self)
-{
- unsigned long h = 0;
- int i;
-
- ENTERING(ipaddress_object_hash);
-
- for (i = 0; (unsigned) i < self->type->length; i++)
- h ^= self->address[i] << ((i & 3) << 3);
-
- return (long) h == -1 ? 0 : (long) h;
-}
-
-static char ipaddress_object_from_bytes__doc__[] =
- "Construct an IPAddress object from a sequence of bytes.\n"
- "\n"
- "Argument must be a Python string of exactly 4 or 16 bytes.\n"
- ;
-
-static PyObject *
-ipaddress_object_from_bytes(PyTypeObject *type, PyObject *args)
-{
- ipaddress_object *result = NULL;
- char *bytes = NULL;
- Py_ssize_t len;
- int v;
-
- ENTERING(ipaddress_object_from_bytes);
-
- if (!PyArg_ParseTuple(args, "s#", &bytes, &len))
- goto error;
-
- if ((result = (ipaddress_object *) type->tp_alloc(type, 0)) == NULL)
- goto error;
-
- result->type = NULL;
-
- for (v = 0; v < (int) (sizeof(ipaddress_versions)/sizeof(*ipaddress_versions)); v++)
- if (len == ipaddress_versions[v]->length)
- result->type = ipaddress_versions[v];
-
- if (result->type == NULL)
- lose("Unknown IP version number");
-
- memcpy(result->address, bytes, len);
- return (PyObject *) result;
-
- error:
- Py_XDECREF(result);
- return NULL;
-}
-
-static char ipaddress_object_to_bytes__doc__[] =
- "Return the binary value of this IPAddress as a Python string\n"
- "of exactly 4 or 16 bytes.\n"
- ;
-
-static PyObject *
-ipaddress_object_to_bytes(ipaddress_object *self)
-{
- ENTERING(ipaddress_object_from_bytes);
- return PyString_FromStringAndSize((char *) self->address, self->type->length);
-}
-
-static PyObject *
-ipaddress_object_get_bits(ipaddress_object *self, GCC_UNUSED void *closure)
-{
- ENTERING(ipaddress_object_get_bits);
- return PyInt_FromLong(self->type->length * 8);
-}
-
-static PyObject *
-ipaddress_object_get_version(ipaddress_object *self, GCC_UNUSED void *closure)
-{
- ENTERING(ipaddress_object_get_version);
- return PyInt_FromLong(self->type->version);
-}
-
-static PyObject *
-ipaddress_object_number_binary_helper(binaryfunc function, PyObject *arg1, PyObject *arg2)
-{
- ipaddress_object *addr = NULL;
- ipaddress_object *addr1 = NULL;
- ipaddress_object *addr2 = NULL;
- ipaddress_object *result = NULL;
- PyObject *obj1 = NULL;
- PyObject *obj2 = NULL;
- PyObject *obj3 = NULL;
- PyObject *obj4 = NULL;
-
- if (POW_IPAddress_Check(arg1))
- addr1 = (ipaddress_object *) arg1;
-
- if (POW_IPAddress_Check(arg2))
- addr2 = (ipaddress_object *) arg2;
-
- if ((addr1 == NULL && addr2 == NULL) ||
- (addr1 != NULL && addr2 != NULL && addr1->type != addr2->type) ||
- (obj1 = PyNumber_Long(arg1)) == NULL ||
- (obj2 = PyNumber_Long(arg2)) == NULL) {
- result = (ipaddress_object *) Py_NotImplemented;
- Py_INCREF(result);
- goto error;
- }
-
- if ((obj3 = function(obj1, obj2)) == NULL)
- goto error;
-
- if ((obj4 = PyNumber_Long(obj3)) == NULL)
- lose("Couldn't convert result");
-
- addr = addr1 != NULL ? addr1 : addr2;
-
- if ((result = (ipaddress_object *) addr->ob_type->tp_alloc(addr->ob_type, 0)) == NULL)
- goto error;
-
- result->type = addr->type;
-
- if (_PyLong_AsByteArray((PyLongObject *) obj4, result->address, result->type->length, 0, 0) < 0) {
- Py_XDECREF(result);
- result = NULL;
- }
-
- error: /* Fall through */
- Py_XDECREF(obj1);
- Py_XDECREF(obj2);
- Py_XDECREF(obj3);
- Py_XDECREF(obj4);
-
- return (PyObject *) result;
-}
-
-static PyObject *
-ipaddress_object_number_long(PyObject *arg)
-{
- ipaddress_object *addr = (ipaddress_object *) arg;
-
- ENTERING(ipaddress_object_number_long);
-
- if (!POW_IPAddress_Check(arg))
- return Py_INCREF(Py_NotImplemented), Py_NotImplemented;
-
- return _PyLong_FromByteArray(addr->address, addr->type->length, 0, 0);
-}
-
-static PyObject *
-ipaddress_object_number_int(PyObject *arg)
-{
- ENTERING(ipaddress_object_number_int);
- return ipaddress_object_number_long(arg);
-}
-
-static PyObject *
-ipaddress_object_number_add(PyObject *arg1, PyObject *arg2)
-{
- ENTERING(ipaddress_object_number_add);
- return ipaddress_object_number_binary_helper(PyNumber_Add, arg1, arg2);
-}
-
-static PyObject *
-ipaddress_object_number_subtract(PyObject *arg1, PyObject *arg2)
-{
- ENTERING(ipaddress_object_number_subtract);
- return ipaddress_object_number_binary_helper(PyNumber_Subtract, arg1, arg2);
-}
-
-static PyObject *
-ipaddress_object_number_lshift(PyObject *arg1, PyObject *arg2)
-{
- ENTERING(ipaddress_object_number_lshift);
- return ipaddress_object_number_binary_helper(PyNumber_Lshift, arg1, arg2);
-}
-
-static PyObject *
-ipaddress_object_number_rshift(PyObject *arg1, PyObject *arg2)
-{
- ENTERING(ipaddress_object_number_rshift);
- return ipaddress_object_number_binary_helper(PyNumber_Rshift, arg1, arg2);
-}
-
-static PyObject *
-ipaddress_object_number_and(PyObject *arg1, PyObject *arg2)
-{
- ENTERING(ipaddress_object_number_and);
- return ipaddress_object_number_binary_helper(PyNumber_And, arg1, arg2);
-}
-
-static PyObject *
-ipaddress_object_number_xor(PyObject *arg1, PyObject *arg2)
-{
- ENTERING(ipaddress_object_number_xor);
- return ipaddress_object_number_binary_helper(PyNumber_Xor, arg1, arg2);
-}
-
-static PyObject *
-ipaddress_object_number_or(PyObject *arg1, PyObject *arg2)
-{
- ENTERING(ipaddress_object_number_or);
- return ipaddress_object_number_binary_helper(PyNumber_Or, arg1, arg2);
-}
-
-static int
-ipaddress_object_number_nonzero(ipaddress_object *self)
-{
- int i;
-
- ENTERING(ipaddress_object_number_nonzero);
-
- for (i = 0; (unsigned) i < self->type->length; i++)
- if (self->address[i] != 0)
- return 1;
- return 0;
-}
-
-static PyObject *
-ipaddress_object_number_invert(ipaddress_object *self)
-{
- ipaddress_object *result = NULL;
- int i;
-
- ENTERING(ipaddress_object_number_invert);
-
- if ((result = (ipaddress_object *) self->ob_type->tp_alloc(self->ob_type, 0)) == NULL)
- goto error;
-
- result->type = self->type;
-
- for (i = 0; (unsigned) i < self->type->length; i++)
- result->address[i] = ~self->address[i];
-
- error: /* Fall through */
- return (PyObject *) result;
-}
-
-static char ipaddress_object_copy__doc__[] =
- ""
- ;
-
-static PyObject *
-ipaddress_object_copy(ipaddress_object *self, GCC_UNUSED PyObject *args)
-{
- ipaddress_object *result = NULL;
-
- ENTERING(ipaddress_object_copy);
-
- if ((result = (ipaddress_object *) self->ob_type->tp_alloc(self->ob_type, 0)) == NULL)
- goto error;
-
- memcpy(result->address, self->address, sizeof(result->address));
- result->type = self->type;
-
- error:
- return (PyObject *) result;
-}
-
-static struct PyMethodDef ipaddress_object_methods[] = {
- Define_Method(__copy__, ipaddress_object_copy, METH_VARARGS),
- Define_Method(__deepcopy__, ipaddress_object_copy, METH_VARARGS),
- Define_Method(toBytes, ipaddress_object_to_bytes, METH_NOARGS),
- Define_Class_Method(fromBytes, ipaddress_object_from_bytes, METH_VARARGS),
- {NULL}
-};
-
-static PyGetSetDef ipaddress_object_getsetters[] = {
- {"bits", (getter) ipaddress_object_get_bits},
- {"version", (getter) ipaddress_object_get_version},
- {NULL}
-};
-
-static PyNumberMethods ipaddress_NumberMethods = {
- ipaddress_object_number_add, /* nb_add */
- ipaddress_object_number_subtract, /* nb_subtract */
- 0, /* nb_multiply */
- 0, /* nb_divide */
- 0, /* nb_remainder */
- 0, /* nb_divmod */
- 0, /* nb_power */
- 0, /* nb_negative */
- 0, /* nb_positive */
- 0, /* nb_absolute */
- (inquiry) ipaddress_object_number_nonzero, /* nb_nonzero */
- (unaryfunc) ipaddress_object_number_invert, /* nb_invert */
- ipaddress_object_number_lshift, /* nb_lshift */
- ipaddress_object_number_rshift, /* nb_rshift */
- ipaddress_object_number_and, /* nb_and */
- ipaddress_object_number_xor, /* nb_xor */
- ipaddress_object_number_or, /* nb_or */
- 0, /* nb_coerce */
- ipaddress_object_number_int, /* nb_int */
- ipaddress_object_number_long, /* nb_long */
- 0, /* nb_float */
- 0, /* nb_oct */
- 0, /* nb_hex */
- 0, /* nb_inplace_add */
- 0, /* nb_inplace_subtract */
- 0, /* nb_inplace_multiply */
- 0, /* nb_inplace_divide */
- 0, /* nb_inplace_remainder */
- 0, /* nb_inplace_power */
- 0, /* nb_inplace_lshift */
- 0, /* nb_inplace_rshift */
- 0, /* nb_inplace_and */
- 0, /* nb_inplace_xor */
- 0, /* nb_inplace_or */
- 0, /* nb_floor_divide */
- 0, /* nb_true_divide */
- 0, /* nb_inplace_floor_divide */
- 0, /* nb_inplace_true_divide */
- 0, /* nb_index */
-};
-
-static PyTypeObject POW_IPAddress_Type = {
- PyObject_HEAD_INIT(NULL)
- 0, /* ob_size */
- "rpki.POW.IPAddress", /* tp_name */
- sizeof(ipaddress_object), /* tp_basicsize */
- 0, /* tp_itemsize */
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- ipaddress_object_compare, /* tp_compare */
- (reprfunc) ipaddress_object_repr, /* tp_repr */
- &ipaddress_NumberMethods, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- (hashfunc) ipaddress_object_hash, /* tp_hash */
- 0, /* tp_call */
- (reprfunc) ipaddress_object_str, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
- 0, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- ipaddress_object_richcompare, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- ipaddress_object_methods, /* tp_methods */
- 0, /* tp_members */
- ipaddress_object_getsetters, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- ipaddress_object_new, /* tp_new */
-};
-
-
-
-/*
- * X509 object.
- */
-
-static x509_object *
-x509_object_new_helper(PyTypeObject *type, X509 *x)
-{
- x509_object *self;
-
- if (type == NULL)
- type = &POW_X509_Type;
-
- if ((self = (x509_object *) type->tp_alloc(type, 0)) == NULL)
- return NULL;
-
- self->x509 = x;
- return self;
-}
-
-static PyObject *
-x509_object_new(PyTypeObject *type, GCC_UNUSED PyObject *args, GCC_UNUSED PyObject *kwds)
-{
- x509_object *self = NULL;
- X509 *x = NULL;
-
- ENTERING(x509_object_new);
-
- if ((x = X509_new()) == NULL)
- lose_no_memory();
-
- if ((self = x509_object_new_helper(type, x)) == NULL)
- goto error;
-
- return (PyObject *) self;
-
- error:
- X509_free(x);
- return NULL;
-}
-
-static void
-x509_object_dealloc(x509_object *self)
-{
- ENTERING(x509_object_dealloc);
- X509_free(self->x509);
- self->ob_type->tp_free((PyObject*) self);
-}
-
-static PyObject *
-x509_object_pem_read_helper(PyTypeObject *type, BIO *bio)
-{
- x509_object *self = NULL;
-
- ENTERING(x509_object_pem_read_helper);
-
- if ((self = (x509_object *) x509_object_new(type, NULL, NULL)) == NULL)
- goto error;
-
- if (!PEM_read_bio_X509(bio, &self->x509, NULL, NULL))
- lose_openssl_error("Couldn't load PEM encoded certificate");
-
- return (PyObject *) self;
-
- error:
-
- Py_XDECREF(self);
- return NULL;
-}
-
-static PyObject *
-x509_object_der_read_helper(PyTypeObject *type, BIO *bio)
-{
- x509_object *self;
-
- ENTERING(x509_object_der_read_helper);
-
- if ((self = (x509_object *) x509_object_new(type, NULL, NULL)) == NULL)
- goto error;
-
- if (!d2i_X509_bio(bio, &self->x509))
- lose_openssl_error("Couldn't load DER encoded certificate");
-
- return (PyObject *) self;
-
- error:
- Py_XDECREF(self);
- return NULL;
-}
-
-static char x509_object_pem_read__doc__[] =
- "Read a PEM-encoded X.509 object from a string.\n"
- ;
-
-static PyObject *
-x509_object_pem_read(PyTypeObject *type, PyObject *args)
-{
- ENTERING(x509_object_pem_read);
- return read_from_string_helper(x509_object_pem_read_helper, type, args);
-}
-
-static char x509_object_pem_read_file__doc__[] =
- "Read a PEM-encoded X.509 object from a file.\n"
- ;
-
-static PyObject *
-x509_object_pem_read_file(PyTypeObject *type, PyObject *args)
-{
- ENTERING(x509_object_pem_read_file);
- return read_from_file_helper(x509_object_pem_read_helper, type, args);
-}
-
-static char x509_object_der_read__doc__[] =
- "Read a DER-encoded X.509 object from a string.\n"
- ;
-
-static PyObject *
-x509_object_der_read(PyTypeObject *type, PyObject *args)
-{
- ENTERING(x509_object_der_read);
- return read_from_string_helper(x509_object_der_read_helper, type, args);
-}
-
-static char x509_object_der_read_file__doc__[] =
- "Read a DER-encoded X.509 object from a file.\n"
- ;
-
-static PyObject *
-x509_object_der_read_file(PyTypeObject *type, PyObject *args)
-{
- ENTERING(x509_object_der_read_file);
- return read_from_file_helper(x509_object_der_read_helper, type, args);
-}
-
-static char x509_object_pem_write__doc__[] =
- "Return the PEM encoding of this certificate, as a string.\n"
- ;
-
-static PyObject *
-x509_object_pem_write(x509_object *self)
-{
- PyObject *result = NULL;
- BIO *bio = NULL;
-
- ENTERING(x509_object_pem_write);
-
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
- lose_no_memory();
-
- if (!PEM_write_bio_X509(bio, self->x509))
- lose_openssl_error("Unable to write certificate");
-
- result = BIO_to_PyString_helper(bio);
-
- error: /* Fall through */
- BIO_free(bio);
- return result;
-}
-
-static char x509_object_der_write__doc__[] =
- "Return the DER encoding of this certificate, as a string.\n"
- ;
-
-static PyObject *
-x509_object_der_write(x509_object *self)
-{
- PyObject *result = NULL;
- BIO *bio = NULL;
-
- ENTERING(x509_object_der_write);
-
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
- lose_no_memory();
-
- if (!i2d_X509_bio(bio, self->x509))
- lose_openssl_error("Unable to write certificate");
-
- result = BIO_to_PyString_helper(bio);
-
- error: /* Fall through */
- BIO_free(bio);
- return result;
-}
-
-static X509_EXTENSIONS **
-x509_object_extension_helper(x509_object *self)
-{
- if (self && self->x509 && self->x509->cert_info)
- return &self->x509->cert_info->extensions;
- PyErr_SetString(PyExc_ValueError, "Can't find X509_EXTENSIONS in X509 object");
- return NULL;
-}
-
-static char x509_object_get_public_key__doc__[] =
- "Return the public key from this certificate object,\n"
- "as an Asymmetric object.\n"
- ;
-
-static PyObject *
-x509_object_get_public_key(x509_object *self)
-{
- PyTypeObject *type = &POW_Asymmetric_Type;
- asymmetric_object *asym = NULL;
-
- ENTERING(x509_object_get_public_key);
-
- if ((asym = (asymmetric_object *) type->tp_alloc(type, 0)) == NULL)
- goto error;
-
- if ((asym->pkey = X509_get_pubkey(self->x509)) == NULL)
- lose_openssl_error("Couldn't extract public key from certificate");
-
- return (PyObject *) asym;
-
- error:
- Py_XDECREF(asym);
- return NULL;
-}
-
-static char x509_object_set_public_key__doc__[] =
- "Set the public key of this certificate object.\n"
- "\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)
-{
- asymmetric_object *asym;
-
- ENTERING(x509_object_set_public_key);
-
- if (!PyArg_ParseTuple(args, "O!", &POW_Asymmetric_Type, &asym))
- goto error;
-
- if (!X509_set_pubkey(self->x509, asym->pkey))
- lose_openssl_error("Couldn't set certificate's public key");
-
- Py_RETURN_NONE;
-
- error:
- return NULL;
-}
-
-static char x509_object_sign__doc__[] =
- "Sign 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)
-{
- asymmetric_object *asym;
- int digest_type = SHA256_DIGEST;
- const EVP_MD *digest_method = NULL;
-
- ENTERING(x509_object_sign);
-
- if (!PyArg_ParseTuple(args, "O!|i", &POW_Asymmetric_Type, &asym, &digest_type))
- goto error;
-
- if ((digest_method = evp_digest_factory(digest_type)) == NULL)
- lose("Unsupported digest algorithm");
-
- if (!X509_sign(self->x509, asym->pkey, digest_method))
- lose_openssl_error("Couldn't sign certificate");
-
- Py_RETURN_NONE;
-
- error:
- return NULL;
-}
-
-static char x509_object_get_version__doc__[] =
- "Return version number of this certificate.\n"
- ;
-
-static PyObject *
-x509_object_get_version(x509_object *self)
-{
- ENTERING(x509_object_get_version);
- return Py_BuildValue("l", X509_get_version(self->x509));
-}
-
-static char x509_object_set_version__doc__[] =
- "Set version number of this certificate.\n"
- "\n"
- "The \"version\" parameter should be an integer.\n"
- ;
-
-static PyObject *
-x509_object_set_version(x509_object *self, PyObject *args)
-{
- long version = 0;
-
- ENTERING(x509_object_set_version);
-
- if (!PyArg_ParseTuple(args, "l", &version))
- goto error;
-
- if (!X509_set_version(self->x509, version))
- lose("Couldn't set certificate version");
-
- Py_RETURN_NONE;
-
- error:
-
- return NULL;
-}
-
-static char x509_object_get_serial__doc__[] =
- "Return the serial number of this certificate.\n"
- ;
-
-static PyObject *
-x509_object_get_serial(x509_object *self)
-{
- ENTERING(x509_object_get_serial);
- return Py_BuildValue("N", ASN1_INTEGER_to_PyLong(X509_get_serialNumber(self->x509)));
-}
-
-static char x509_object_set_serial__doc__[] =
- "Set the serial number of this certificate.\n"
- "\n"
- "The \"serial\" parameter should ba an integer.\n"
- ;
-
-static PyObject *
-x509_object_set_serial(x509_object *self, PyObject *args)
-{
- ASN1_INTEGER *a_serial = NULL;
- PyObject *p_serial = NULL;
- int ok = 0;
-
- ENTERING(x509_object_set_serial);
-
- if (!PyArg_ParseTuple(args, "O", &p_serial) ||
- (a_serial = PyLong_to_ASN1_INTEGER(p_serial)) == NULL)
- goto error;
-
- if (!X509_set_serialNumber(self->x509, a_serial))
- lose_no_memory();
-
- ok = 1;
-
- error:
- ASN1_INTEGER_free(a_serial);
-
- if (ok)
- Py_RETURN_NONE;
- else
- return NULL;
-}
-
-static char x509_object_get_issuer__doc__[] =
- "Return this certificate's issuer name, represented as a tuple.\n"
- "\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"
- "\n"
- "In practice, RDNs containing multiple attributes are rare, thus the RDN\n"
- "tuples will usually be exactly one element long, but using the\n"
- "tuple-of-tuples-of-tuples format lets us 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)
-{
- PyObject *result = NULL;
- int format = OIDNAME_FORMAT;
-
- ENTERING(x509_object_get_issuer);
-
- if (!PyArg_ParseTuple(args, "|i", &format))
- goto error;
-
- result = x509_object_helper_get_name(X509_get_issuer_name(self->x509),
- format);
-
- error: /* Fall through */
- return result;
-}
-
-static char x509_object_get_subject__doc__[] =
- "Return this certificate's subject name, as a tuple.\n"
- "\n"
- "See the documentation for the \"getIssuer\" method for details on the\n"
- "structure of the return value and use of the optional \"format\"\n"
- "parameter.\n"
- ;
-
-static PyObject *
-x509_object_get_subject(x509_object *self, PyObject *args)
-{
- PyObject *result = NULL;
- int format = OIDNAME_FORMAT;
-
- ENTERING(x509_object_get_subject);
-
- if (!PyArg_ParseTuple(args, "|i", &format))
- goto error;
-
- result = x509_object_helper_get_name(X509_get_subject_name(self->x509),
- format);
-
- error: /* Fall through */
- return result;
-}
-
-static char x509_object_set_subject__doc__[] =
- "Set this certificate's subject name.\n"
- "\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)
-{
- PyObject *name_sequence = NULL;
- X509_NAME *name = NULL;
-
- ENTERING(x509_object_set_subject);
-
- if (!PyArg_ParseTuple(args, "O", &name_sequence))
- goto error;
-
- if (!PySequence_Check(name_sequence))
- lose_type_error("Inapropriate type");
-
- if ((name = x509_object_helper_set_name(name_sequence)) == NULL)
- goto error;
-
- if (!X509_set_subject_name(self->x509, name))
- lose("Unable to set subject name");
-
- X509_NAME_free(name);
-
- Py_RETURN_NONE;
-
- error:
- X509_NAME_free(name);
- return NULL;
-}
-
-static char x509_object_set_issuer__doc__[] =
- "Set this certificate's issuer name.\n"
- "\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)
-{
- PyObject *name_sequence = NULL;
- X509_NAME *name = NULL;
-
- ENTERING(x509_object_set_issuer);
-
- if (!PyArg_ParseTuple(args, "O", &name_sequence))
- goto error;
-
- if (!PySequence_Check(name_sequence))
- lose_type_error("Inapropriate type");
-
- if ((name = x509_object_helper_set_name(name_sequence)) == NULL)
- goto error;
-
- if (!X509_set_issuer_name(self->x509, name))
- lose("Unable to set issuer name");
-
- X509_NAME_free(name);
-
- Py_RETURN_NONE;
-
- error:
- X509_NAME_free(name);
- return NULL;
-}
-
-static char x509_object_get_not_before__doc__[] =
- "Return this certificate's \"notBefore\" value as a datetime.\n"
- ;
-
-static PyObject *
-x509_object_get_not_before (x509_object *self)
-{
- ENTERING(x509_object_get_not_before);
- return ASN1_TIME_to_Python(X509_get_notBefore(self->x509));
-}
-
-static char x509_object_get_not_after__doc__[] =
- "Return this certificate's \"notAfter\" value as a datetime.\n"
- ;
-
-static PyObject *
-x509_object_get_not_after (x509_object *self)
-{
- ENTERING(x509_object_get_not_after);
- return ASN1_TIME_to_Python(X509_get_notAfter(self->x509));
-}
-
-static char x509_object_set_not_after__doc__[] =
- "Set this certificate's \"notAfter\" value.\n"
- "\n"
- "The \"time\" parameter should be a datetime object.\n"
- ;
-
-static PyObject *
-x509_object_set_not_after (x509_object *self, PyObject *args)
-{
- PyObject *o = NULL;
- ASN1_TIME *t = NULL;
-
- ENTERING(x509_object_set_not_after);
-
- if (!PyArg_ParseTuple(args, "O", &o))
- goto error;
-
- if ((t = Python_to_ASN1_TIME(o, 1)) == 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__[] =
- "Set this certificate's \"notBefore\" value.\n"
- "\n"
- "The \"time\" parameter should be a datetime object.\n"
- ;
-
-static PyObject *
-x509_object_set_not_before (x509_object *self, PyObject *args)
-{
- PyObject *o = NULL;
- ASN1_TIME *t = NULL;
-
- ENTERING(x509_object_set_not_before);
-
- if (!PyArg_ParseTuple(args, "O", &o))
- goto error;
-
- if ((t = Python_to_ASN1_TIME(o, 1)) == 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_clear_extensions__doc__[] =
- "Clear all extensions attached to this certificate.\n"
- ;
-
-static PyObject *
-x509_object_clear_extensions(x509_object *self)
-{
- X509_EXTENSION *ext;
-
- ENTERING(x509_object_clear_extensions);
-
- while ((ext = X509_delete_ext(self->x509, 0)) != NULL)
- X509_EXTENSION_free(ext);
-
- Py_RETURN_NONE;
-}
-
-static char x509_object_get_ski__doc__[] =
- "Return the Subject Key Identifier (SKI) value for this\n"
- "certificate, or None if the certificate has no SKI extension.\n"
- ;
-
-static PyObject *
-x509_object_get_ski(x509_object *self)
-{
- return extension_get_ski(x509_object_extension_helper(self));
-}
-
-static char x509_object_set_ski__doc__[] =
- "Set the Subject Key Identifier (SKI) value for this certificate.\n"
- ;
-
-static PyObject *
-x509_object_set_ski(x509_object *self, PyObject *args)
-{
- return extension_set_ski(x509_object_extension_helper(self), args);
-}
-
-static char x509_object_get_aki__doc__[] =
- "Return the Authority Key Identifier (AKI) keyid value for this\n"
- "certificate, or None if the certificate has no AKI extension or has an\n"
- "AKI extension with no keyIdentifier value.\n"
- ;
-
-static PyObject *
-x509_object_get_aki(x509_object *self)
-{
- return extension_get_aki(x509_object_extension_helper(self));
-}
-
-static char x509_object_set_aki__doc__[] =
- "Set the Authority Key Identifier (AKI) value for this certificate.\n"
- "\n"
- "We only support the keyIdentifier method, as that's the only form\n"
- "which is legal for RPKI certificates.\n"
- ;
-
-static PyObject *
-x509_object_set_aki(x509_object *self, PyObject *args)
-{
- return extension_set_aki(x509_object_extension_helper(self), args);
-}
-
-static char x509_object_get_key_usage__doc__[] =
- "Return a FrozenSet of strings representing the KeyUsage\n"
- "settings for this certificate, or None if the certificate has no\n"
- "KeyUsage extension. The bits have the same names as in RFC 5280.\n"
- ;
-
-static PyObject *
-x509_object_get_key_usage(x509_object *self)
-{
- return extension_get_key_usage(x509_object_extension_helper(self));
-}
-
-static char x509_object_set_key_usage__doc__[] =
- "Set the KeyUsage extension for this certificate.\n"
- "\n"
- "Argument \"iterable\" should be an iterable object which returns zero or more\n"
- "strings naming bits to be enabled. The bits have the same names as in RFC 5280.\n"
- "\n"
- "Optional argument \"critical\" is a boolean indicating whether the extension\n"
- "should be marked as critical or not. RFC 5280 4.2.1.3 says this extension SHOULD\n"
- "be marked as critical when used, so the default is True.\n"
- ;
-
-static PyObject *
-x509_object_set_key_usage(x509_object *self, PyObject *args)
-{
- return extension_set_key_usage(x509_object_extension_helper(self), args);
-}
-
-static char x509_object_get_eku__doc__[] =
- "Return a FrozenSet of object identifiers representing the\n"
- "ExtendedKeyUsage settings for this certificate, or None if\n"
- "the certificate has no ExtendedKeyUsage extension.\n"
- ;
-
-static PyObject *
-x509_object_get_eku(x509_object *self)
-{
- return extension_get_eku(x509_object_extension_helper(self));
-}
-
-static char x509_object_set_eku__doc__[] =
- "Set the ExtendedKeyUsage extension for this certificate.\n"
- "\n"
- "Argument \"iterable\" should be an iterable object which returns one or more\n"
- "object identifiers.\n"
- "\n"
- "Optional argument \"critical\" is a boolean indicating whether the extension\n"
- "should be marked as critical or not. RFC 6487 4.8.5 says this extension\n"
- "MUST NOT be marked as non-critical when used, so the default is False.\n"
- ;
-
-static PyObject *
-x509_object_set_eku(x509_object *self, PyObject *args)
-{
- return extension_set_eku(x509_object_extension_helper(self), args);
-}
-
-static char x509_object_get_rfc3779__doc__[] =
- "Return this certificate's RFC 3779 resources.\n"
- "\n"
- "Return value is a three-element tuple: the first element is the ASN\n"
- "resources, the second is the IPv4 resources, the third is the IPv6\n"
- "resources. Each of these elements in turn is either the string\n"
- "\"inherit\" or a tuple representing a set of ranges of ASNs or IP\n"
- "addresses.\n"
- "\n"
- "Each range is a two-element tuple, respectively representing the low\n"
- "and high ends of the range, inclusive. ASN ranges are represented by\n"
- "pairs of integers, IP address ranges are represented by pairs of\n"
- "IPAddress objects.\n"
- ;
-
-static PyObject *
-x509_object_get_rfc3779(x509_object *self)
-{
- PyObject *result = NULL;
- PyObject *asn_result = NULL;
- PyObject *ipv4_result = NULL;
- PyObject *ipv6_result = NULL;
- PyObject *range = NULL;
- PyObject *range_b = NULL;
- PyObject *range_e = NULL;
- ASIdentifiers *asid = NULL;
- IPAddrBlocks *addr = NULL;
- int i, j;
-
- ENTERING(x509_object_get_rfc3779);
-
- if ((asid = X509_get_ext_d2i(self->x509, NID_sbgp_autonomousSysNum, NULL, NULL)) != NULL &&
- asid->asnum != NULL) {
- switch (asid->asnum->type) {
-
- case ASIdentifierChoice_inherit:
- if ((asn_result = PyString_FromString("inherit")) == NULL)
- goto error;
- break;
-
- case ASIdentifierChoice_asIdsOrRanges:
-
- if ((asn_result = PyTuple_New(sk_ASIdOrRange_num(asid->asnum->u.asIdsOrRanges))) == NULL)
- goto error;
-
- for (i = 0; i < sk_ASIdOrRange_num(asid->asnum->u.asIdsOrRanges); i++) {
- ASIdOrRange *aor = sk_ASIdOrRange_value(asid->asnum->u.asIdsOrRanges, i);
- ASN1_INTEGER *b = NULL;
- ASN1_INTEGER *e = NULL;
-
- switch (aor->type) {
-
- case ASIdOrRange_id:
- b = e = aor->u.id;
- break;
-
- case ASIdOrRange_range:
- b = aor->u.range->min;
- e = aor->u.range->max;
- break;
-
- default:
- lose_type_error("Unexpected asIdsOrRanges type");
- }
-
- if (ASN1_STRING_type(b) == V_ASN1_NEG_INTEGER ||
- ASN1_STRING_type(e) == V_ASN1_NEG_INTEGER)
- lose_type_error("I don't believe in negative ASNs");
-
- if ((range_b = ASN1_INTEGER_to_PyLong(b)) == NULL ||
- (range_e = ASN1_INTEGER_to_PyLong(e)) == NULL ||
- (range = Py_BuildValue("(NN)", range_b, range_e)) == NULL)
- goto error;
-
- PyTuple_SET_ITEM(asn_result, i, range);
- range = range_b = range_e = NULL;
- }
-
- break;
-
- default:
- lose_type_error("Unexpected ASIdentifierChoice type");
- }
- }
-
- if ((addr = X509_get_ext_d2i(self->x509, NID_sbgp_ipAddrBlock, NULL, NULL)) != NULL) {
- for (i = 0; i < sk_IPAddressFamily_num(addr); i++) {
- IPAddressFamily *f = sk_IPAddressFamily_value(addr, i);
- const struct ipaddress_version *ip_type = NULL;
- const unsigned int afi = v3_addr_get_afi(f);
- PyObject **result_obj = NULL;
- int addr_len = 0;
-
- switch (afi) {
- case IANA_AFI_IPV4: result_obj = &ipv4_result; ip_type = &ipaddress_version_4; break;
- case IANA_AFI_IPV6: result_obj = &ipv6_result; ip_type = &ipaddress_version_6; break;
- default: lose_type_error("Unknown AFI");
- }
-
- if (*result_obj != NULL)
- lose_type_error("Duplicate IPAddressFamily");
-
- if (f->addressFamily->length > 2)
- lose_type_error("Unsupported SAFI");
-
- switch (f->ipAddressChoice->type) {
-
- case IPAddressChoice_inherit:
- if ((*result_obj = PyString_FromString("inherit")) == NULL)
- goto error;
- continue;
-
- case IPAddressChoice_addressesOrRanges:
- break;
-
- default:
- lose_type_error("Unexpected IPAddressChoice type");
- }
-
- if ((*result_obj = PyTuple_New(sk_IPAddressOrRange_num(f->ipAddressChoice->u.addressesOrRanges))) == NULL)
- goto error;
-
- for (j = 0; j < sk_IPAddressOrRange_num(f->ipAddressChoice->u.addressesOrRanges); j++) {
- IPAddressOrRange *aor = sk_IPAddressOrRange_value(f->ipAddressChoice->u.addressesOrRanges, j);
- ipaddress_object *addr_b = NULL;
- ipaddress_object *addr_e = NULL;
-
- if ((range_b = POW_IPAddress_Type.tp_alloc(&POW_IPAddress_Type, 0)) == NULL ||
- (range_e = POW_IPAddress_Type.tp_alloc(&POW_IPAddress_Type, 0)) == NULL)
- goto error;
-
- addr_b = (ipaddress_object *) range_b;
- addr_e = (ipaddress_object *) range_e;
-
- if ((addr_len = v3_addr_get_range(aor, afi, addr_b->address, addr_e->address,
- sizeof(addr_b->address))) == 0)
- lose_type_error("Couldn't unpack IP addresses from BIT STRINGs");
-
- addr_b->type = addr_e->type = ip_type;
-
- if ((range = Py_BuildValue("(NN)", range_b, range_e)) == NULL)
- goto error;
-
- PyTuple_SET_ITEM(*result_obj, j, range);
- range = range_b = range_e = NULL;
- }
- }
- }
-
- result = Py_BuildValue("(OOO)",
- (asn_result == NULL ? Py_None : asn_result),
- (ipv4_result == NULL ? Py_None : ipv4_result),
- (ipv6_result == NULL ? Py_None : ipv6_result));
-
- error: /* Fall through */
- ASIdentifiers_free(asid);
- sk_IPAddressFamily_pop_free(addr, IPAddressFamily_free);
- Py_XDECREF(range_b);
- Py_XDECREF(range_e);
- Py_XDECREF(range);
- Py_XDECREF(asn_result);
- Py_XDECREF(ipv4_result);
- Py_XDECREF(ipv6_result);
-
- return result;
-}
-
-static char x509_object_set_rfc3779__doc__[] =
- "Set this certificate's RFC 3779 resources.\n"
- "\n"
- "This method takes three arguments: \"asn\", \"ipv4\", and \"ipv6\".\n"
- "\n"
- "Each of these arguments can be:\n"
- "\n"
- "* None, to omit this kind of resource;\n"
- "\n"
- "* The string \"inherit\", to specify RFC 3779 resource inheritance; or\n"
- "\n"
- "* An iterable object which returns range pairs of the appropriate type.\n"
- "\n"
- "Range pairs are as returned by the .getRFC3779() method.\n"
- ;
-
-static PyObject *
-x509_object_set_rfc3779(x509_object *self, PyObject *args, PyObject *kwds)
-{
- static char *kwlist[] = {"asn", "ipv4", "ipv6", NULL};
- PyObject *asn_arg = Py_None;
- PyObject *ipv4_arg = Py_None;
- PyObject *ipv6_arg = Py_None;
- PyObject *iterator = NULL;
- PyObject *item = NULL;
- PyObject *fast = NULL;
- ASIdentifiers *asid = NULL;
- IPAddrBlocks *addr = NULL;
- ASN1_INTEGER *asid_b = NULL;
- ASN1_INTEGER *asid_e = NULL;
- ipaddress_object *addr_b = NULL;
- ipaddress_object *addr_e = NULL;
- int empty = 0;
-
- ENTERING(x509_object_set_rfc3779);
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", kwlist, &asn_arg, &ipv4_arg, &ipv6_arg))
- goto error;
-
- if (asn_arg != Py_None) {
-
- empty = 1;
-
- if ((asid = ASIdentifiers_new()) == NULL)
- lose_no_memory();
-
- if (PyString_Check(asn_arg)) {
-
- if (strcmp(PyString_AsString(asn_arg), "inherit"))
- lose_type_error("ASID must be an iterable that returns range pairs, or the string \"inherit\"");
-
- if (!v3_asid_add_inherit(asid, V3_ASID_ASNUM))
- lose_no_memory();
-
- empty = 0;
-
- } else {
-
- if ((iterator = PyObject_GetIter(asn_arg)) == NULL)
- goto error;
-
- while ((item = PyIter_Next(iterator)) != NULL) {
-
- if ((fast = PySequence_Fast(item, "ASN range must be a sequence")) == NULL)
- goto error;
-
- if (PySequence_Fast_GET_SIZE(fast) != 2)
- lose_type_error("ASN range must be two-element sequence");
-
- if ((asid_b = PyLong_to_ASN1_INTEGER(PySequence_Fast_GET_ITEM(fast, 0))) == NULL)
- goto error;
-
- switch (PyObject_RichCompareBool(PySequence_Fast_GET_ITEM(fast, 0),
- PySequence_Fast_GET_ITEM(fast, 1), Py_EQ)) {
- case 0:
- if ((asid_e = PyLong_to_ASN1_INTEGER(PySequence_Fast_GET_ITEM(fast, 1))) == NULL)
- goto error;
- break;
- case 1:
- break;
- default:
- goto error;
- }
-
- if (!v3_asid_add_id_or_range(asid, V3_ASID_ASNUM, asid_b, asid_e))
- lose_openssl_error("Couldn't add range to ASID");
-
- asid_b = asid_e = NULL;
- Py_XDECREF(item);
- Py_XDECREF(fast);
- item = fast = NULL;
- empty = 0;
- }
-
- Py_XDECREF(iterator);
- iterator = NULL;
- }
-
- if (!empty && (!v3_asid_canonize(asid) ||
- !X509_add1_ext_i2d(self->x509, NID_sbgp_autonomousSysNum,
- asid, 1, X509V3_ADD_REPLACE)))
- lose_openssl_error("Couldn't add ASID extension to certificate");
- }
-
- if (ipv4_arg != Py_None || ipv6_arg != Py_None) {
- int v;
-
- empty = 1;
-
- if ((addr = sk_IPAddressFamily_new_null()) == NULL)
- lose_no_memory();
-
- /*
- * Cheap trick to let us inline all of this instead of being
- * forced to use a separate function. Refactor, some day.
- */
-
- for (v = 0; v < (int) (sizeof(ipaddress_versions)/sizeof(*ipaddress_versions)); v++) {
- const struct ipaddress_version *ip_type = ipaddress_versions[v];
- PyObject **argp;
-
- switch (ip_type->version) {
- case 4: argp = &ipv4_arg; break;
- case 6: argp = &ipv6_arg; break;
- default: continue; /* Never happens */
- }
-
- if (PyString_Check(*argp)) {
-
- if (strcmp(PyString_AsString(*argp), "inherit"))
- lose_type_error("Argument must be an iterable that returns range pairs, or the string \"inherit\"");
-
- if (!v3_addr_add_inherit(addr, ip_type->afi, NULL))
- lose_no_memory();
-
- empty = 0;
-
- } else {
-
- if ((iterator = PyObject_GetIter(*argp)) == NULL)
- goto error;
-
- while ((item = PyIter_Next(iterator)) != NULL) {
-
- if ((fast = PySequence_Fast(item, "Address range must be a sequence")) == NULL)
- goto error;
-
- if (PySequence_Fast_GET_SIZE(fast) != 2 ||
- !POW_IPAddress_Check(PySequence_Fast_GET_ITEM(fast, 0)) ||
- !POW_IPAddress_Check(PySequence_Fast_GET_ITEM(fast, 1)))
- lose_type_error("Address range must be two-element sequence of IPAddress objects");
-
- addr_b = (ipaddress_object *) PySequence_Fast_GET_ITEM(fast, 0);
- addr_e = (ipaddress_object *) PySequence_Fast_GET_ITEM(fast, 1);
-
- if (addr_b->type != ip_type ||
- addr_e->type != ip_type ||
- memcmp(addr_b->address, addr_e->address, ip_type->length) > 0)
- lose("Address range must be two-element sequence of IPAddress objects in ascending order");
-
- if (!v3_addr_add_range(addr, ip_type->afi, NULL, addr_b->address, addr_e->address))
- lose_openssl_error("Couldn't add range to IPAddrBlock");
-
- Py_XDECREF(item);
- Py_XDECREF(fast);
- item = fast = NULL;
- addr_b = addr_e = NULL;
- empty = 0;
- }
-
- Py_XDECREF(iterator);
- iterator = NULL;
- }
- }
-
- if (!empty && (!v3_addr_canonize(addr) ||
- !X509_add1_ext_i2d(self->x509, NID_sbgp_ipAddrBlock,
- addr, 1, X509V3_ADD_REPLACE)))
- lose_openssl_error("Couldn't add IPAddrBlock extension to certificate");
- }
-
- Py_RETURN_NONE;
-
- error:
- ASN1_INTEGER_free(asid_b);
- ASN1_INTEGER_free(asid_e);
- ASIdentifiers_free(asid);
- sk_IPAddressFamily_pop_free(addr, IPAddressFamily_free);
- Py_XDECREF(iterator);
- Py_XDECREF(item);
- Py_XDECREF(fast);
- return NULL;
-}
-
-static char x509_object_get_basic_constraints__doc__[] =
- "Return BasicConstraints for this certificate.\n"
- "\n"
- "If this certificate has no BasicConstraints extension, this method\n"
- "returns None.\n"
- "\n"
- "Otherwise, this method returns a two-element tuple. The first element\n"
- "of the tuple is a boolean representing the extension's cA value; the\n"
- "second element of the tuple is either an integer representing the\n"
- "pathLenConstraint value or None if there is no pathLenConstraint.\n"
- ;
-
-static PyObject *
-x509_object_get_basic_constraints(x509_object *self)
-{
- return extension_get_basic_constraints(x509_object_extension_helper(self));
-}
-
-static char x509_object_set_basic_constraints__doc__[] =
- "Set BasicConstraints for this certificate.\n"
- "\n"
- "First argument \"ca\" is a boolean indicating whether the certificate\n"
- "is a CA certificate or not.\n"
- "\n"
- "Optional second argument \"pathLenConstraint\" is a non-negative integer\n"
- "specifying the pathLenConstraint value for this certificate; this value\n"
- "may only be set for CA certificates."
- "\n"
- "Optional third argument \"critical\" specifies whether the extension\n"
- "should be marked as critical. RFC 5280 4.2.1.9 requires that CA\n"
- "certificates mark this extension as critical, so the default is True.\n"
- ;
-
-static PyObject *
-x509_object_set_basic_constraints(x509_object *self, PyObject *args)
-{
- return extension_set_basic_constraints(x509_object_extension_helper(self), args);
-}
-
-static char x509_object_get_sia__doc__[] =
- "Get SIA values for this certificate.\n"
- "\n"
- "If the certificate has no SIA extension, this method returns None.\n"
- "\n"
- "Otherwise, it returns a tuple containing three values:\n"
- "caRepository URIs, rpkiManifest URIs, and signedObject URIs.\n"
- "Each of these values is a tuple of strings, representing an ordered\n"
- "sequence of URIs. Any or all of these sequences may be empty.\n"
- "\n"
- "Any other accessMethods are ignored, as are any non-URI\n"
- "accessLocations.\n"
- ;
-
-static PyObject *
-x509_object_get_sia(x509_object *self)
-{
- return extension_get_sia(x509_object_extension_helper(self));
-}
-
-static char x509_object_set_sia__doc__[] =
- "Set SIA values for this certificate. Takes three arguments:\n"
- "\"caRepository\", \"rpkiManifest\", and \"signedObject\".\n"
- "Each of these should be an iterable which returns URIs.\n"
- "\n"
- "None is acceptable as an alternate way of specifying an empty\n"
- "collection of URIs for a particular argument.\n"
- ;
-
-static PyObject *
-x509_object_set_sia(x509_object *self, PyObject *args, PyObject *kwds)
-{
- return extension_set_sia(x509_object_extension_helper(self), args, kwds);
-}
-
-static char x509_object_get_aia__doc__[] =
- "Get this certificate's AIA values.\n"
- "\n"
- "If the certificate has no AIA extension, this method returns None.\n"
- "\n"
- "Otherwise, this returns a sequence of caIssuers URIs.\n"
- "\n"
- "Any other accessMethods are ignored, as are any non-URI\n"
- "accessLocations.\n"
- ;
-
-static PyObject *
-x509_object_get_aia(x509_object *self)
-{
- AUTHORITY_INFO_ACCESS *ext = NULL;
- PyObject *result = NULL;
- const char *uri;
- PyObject *obj;
- int i, n = 0;
-
- ENTERING(x509_object_get_aia);
-
- if ((ext = X509_get_ext_d2i(self->x509, NID_info_access, NULL, NULL)) == NULL)
- Py_RETURN_NONE;
-
- for (i = 0; i < sk_ACCESS_DESCRIPTION_num(ext); i++) {
- ACCESS_DESCRIPTION *a = sk_ACCESS_DESCRIPTION_value(ext, i);
- if (a->location->type == GEN_URI &&
- OBJ_obj2nid(a->method) == NID_ad_ca_issuers)
- n++;
- }
-
- if (((result = PyTuple_New(n)) == NULL))
- goto error;
-
- n = 0;
-
- for (i = 0; i < sk_ACCESS_DESCRIPTION_num(ext); i++) {
- ACCESS_DESCRIPTION *a = sk_ACCESS_DESCRIPTION_value(ext, i);
- if (a->location->type == GEN_URI && OBJ_obj2nid(a->method) == NID_ad_ca_issuers) {
- uri = (char *) ASN1_STRING_data(a->location->d.uniformResourceIdentifier);
- if ((obj = PyString_FromString(uri)) == NULL)
- goto error;
- PyTuple_SET_ITEM(result, n++, obj);
- }
- }
-
- AUTHORITY_INFO_ACCESS_free(ext);
- return result;
-
- error:
- AUTHORITY_INFO_ACCESS_free(ext);
- Py_XDECREF(result);
- return NULL;
-}
-
-static char x509_object_set_aia__doc__[] =
- "Set AIA URIs for this certificate.\n"
- "\n"
- "Argument is a iterable which returns caIssuers URIs.\n"
- ;
-
-static PyObject *
-x509_object_set_aia(x509_object *self, PyObject *args)
-{
- AUTHORITY_INFO_ACCESS *ext = NULL;
- PyObject *caIssuers = NULL;
- PyObject *iterator = NULL;
- ASN1_OBJECT *oid = NULL;
- PyObject *item = NULL;
- ACCESS_DESCRIPTION *a = NULL;
- int ok = 0;
- Py_ssize_t urilen;
- char *uri;
-
- ENTERING(x509_object_set_aia);
-
- if (!PyArg_ParseTuple(args, "O", &caIssuers))
- goto error;
-
- if ((ext = AUTHORITY_INFO_ACCESS_new()) == NULL)
- lose_no_memory();
-
- if ((oid = OBJ_nid2obj(NID_ad_ca_issuers)) == NULL)
- lose_openssl_error("Couldn't find AIA accessMethod OID");
-
- if ((iterator = PyObject_GetIter(caIssuers)) == NULL)
- goto error;
-
- while ((item = PyIter_Next(iterator)) != NULL) {
-
- if (PyString_AsStringAndSize(item, &uri, &urilen) < 0)
- goto error;
-
- if ((a = ACCESS_DESCRIPTION_new()) == NULL ||
- (a->method = OBJ_dup(oid)) == NULL ||
- (a->location->d.uniformResourceIdentifier = ASN1_IA5STRING_new()) == NULL ||
- !ASN1_OCTET_STRING_set(a->location->d.uniformResourceIdentifier, (unsigned char *) uri, urilen))
- lose_no_memory();
-
- a->location->type = GEN_URI;
-
- if (!sk_ACCESS_DESCRIPTION_push(ext, a))
- lose_no_memory();
-
- a = NULL;
- Py_XDECREF(item);
- item = NULL;
- }
-
- Py_XDECREF(iterator);
- iterator = NULL;
-
- if (!X509_add1_ext_i2d(self->x509, NID_info_access, ext, 0, X509V3_ADD_REPLACE))
- lose_openssl_error("Couldn't add AIA extension to certificate");
-
- ok = 1;
-
- error:
- AUTHORITY_INFO_ACCESS_free(ext);
- ACCESS_DESCRIPTION_free(a);
- Py_XDECREF(item);
- Py_XDECREF(iterator);
-
- if (ok)
- Py_RETURN_NONE;
- else
- return NULL;
-}
-
-static char x509_object_get_crldp__doc__[] =
- "Get CRL Distribution Point (CRLDP) values for this certificate.\n"
- "\n"
- "If the certificate has no CRLDP extension, this method returns None.\n"
- "\n"
- "Otherwise, it returns a sequence of URIs representing distributionPoint\n"
- "fullName values found in the first Distribution Point. Other CRLDP\n"
- "fields are ignored, as are subsequent Distribution Points and any non-URI\n"
- "fullName values.\n"
- ;
-
-static PyObject *
-x509_object_get_crldp(x509_object *self)
-{
- CRL_DIST_POINTS *ext = NULL;
- DIST_POINT *dp = NULL;
- PyObject *result = NULL;
- const char *uri;
- PyObject *obj;
- int i, n = 0;
-
- ENTERING(x509_object_get_crldp);
-
- if ((ext = X509_get_ext_d2i(self->x509, NID_crl_distribution_points, NULL, NULL)) == NULL ||
- (dp = sk_DIST_POINT_value(ext, 0)) == NULL ||
- dp->distpoint == NULL ||
- dp->distpoint->type != 0)
- Py_RETURN_NONE;
-
- for (i = 0; i < sk_GENERAL_NAME_num(dp->distpoint->name.fullname); i++) {
- GENERAL_NAME *gn = sk_GENERAL_NAME_value(dp->distpoint->name.fullname, i);
- if (gn->type == GEN_URI)
- n++;
- }
-
- if (((result = PyTuple_New(n)) == NULL))
- goto error;
-
- n = 0;
-
- for (i = 0; i < sk_GENERAL_NAME_num(dp->distpoint->name.fullname); i++) {
- GENERAL_NAME *gn = sk_GENERAL_NAME_value(dp->distpoint->name.fullname, i);
- if (gn->type == GEN_URI) {
- uri = (char *) ASN1_STRING_data(gn->d.uniformResourceIdentifier);
- if ((obj = PyString_FromString(uri)) == NULL)
- goto error;
- PyTuple_SET_ITEM(result, n++, obj);
- }
- }
-
- sk_DIST_POINT_pop_free(ext, DIST_POINT_free);
- return result;
-
- error:
- sk_DIST_POINT_pop_free(ext, DIST_POINT_free);
- Py_XDECREF(result);
- return NULL;
-}
-
-static char x509_object_set_crldp__doc__[] =
- "Set CRLDP values for this certificate.\n"
- "\n"
- "Argument is a iterable which returns distributionPoint fullName URIs.\n"
- ;
-
-static PyObject *
-x509_object_set_crldp(x509_object *self, PyObject *args)
-{
- CRL_DIST_POINTS *ext = NULL;
- PyObject *fullNames = NULL;
- PyObject *iterator = NULL;
- PyObject *item = NULL;
- DIST_POINT *dp = NULL;
- GENERAL_NAME *gn = NULL;
- Py_ssize_t urilen;
- char *uri;
- int ok = 0;
-
- ENTERING(x509_object_set_crldp);
-
- if (!PyArg_ParseTuple(args, "O", &fullNames))
- goto error;
-
- if ((ext = sk_DIST_POINT_new_null()) == NULL ||
- (dp = DIST_POINT_new()) == NULL ||
- (dp->distpoint = DIST_POINT_NAME_new()) == NULL ||
- (dp->distpoint->name.fullname = sk_GENERAL_NAME_new_null()) == NULL)
- lose_no_memory();
-
- dp->distpoint->type = 0;
-
- if ((iterator = PyObject_GetIter(fullNames)) == NULL)
- goto error;
-
- while ((item = PyIter_Next(iterator)) != NULL) {
-
- if (PyString_AsStringAndSize(item, &uri, &urilen) < 0)
- goto error;
-
- if ((gn = GENERAL_NAME_new()) == NULL ||
- (gn->d.uniformResourceIdentifier = ASN1_IA5STRING_new()) == NULL ||
- !ASN1_OCTET_STRING_set(gn->d.uniformResourceIdentifier, (unsigned char *) uri, urilen))
- lose_no_memory();
-
- gn->type = GEN_URI;
-
- if (!sk_GENERAL_NAME_push(dp->distpoint->name.fullname, gn))
- lose_no_memory();
-
- gn = NULL;
- Py_XDECREF(item);
- item = NULL;
- }
-
- Py_XDECREF(iterator);
- iterator = NULL;
-
- if (!sk_DIST_POINT_push(ext, dp))
- lose_no_memory();
-
- dp = NULL;
-
- if (!X509_add1_ext_i2d(self->x509, NID_crl_distribution_points, ext, 0, X509V3_ADD_REPLACE))
- lose_openssl_error("Couldn't add CRLDP extension to certificate");
-
- ok = 1;
-
- error:
- sk_DIST_POINT_pop_free(ext, DIST_POINT_free);
- DIST_POINT_free(dp);
- GENERAL_NAME_free(gn);
- Py_XDECREF(item);
- Py_XDECREF(iterator);
-
- if (ok)
- Py_RETURN_NONE;
- else
- return NULL;
-}
-
-static char x509_object_get_certificate_policies__doc__[] =
- "Get Certificate Policies values for this certificate.\n"
- "\n"
- "If this certificate has no Certificate Policies extension, this method\n"
- "returns None.\n"
- "\n"
- "Otherwise, this method returns a sequence of Object Identifiers.\n"
- "\n"
- "Policy qualifiers, if any, are ignored.\n"
- ;
-
-static PyObject *
-x509_object_get_certificate_policies(x509_object *self)
-{
- CERTIFICATEPOLICIES *ext = NULL;
- PyObject *result = NULL;
- PyObject *obj;
- int i;
-
- ENTERING(x509_object_get_certificate_policies);
-
- if ((ext = X509_get_ext_d2i(self->x509, NID_certificate_policies, NULL, NULL)) == NULL)
- Py_RETURN_NONE;
-
- if (((result = PyTuple_New(sk_POLICYINFO_num(ext))) == NULL))
- goto error;
-
- for (i = 0; i < sk_POLICYINFO_num(ext); i++) {
- POLICYINFO *p = sk_POLICYINFO_value(ext, i);
-
- if ((obj = ASN1_OBJECT_to_PyString(p->policyid)) == NULL)
- goto error;
-
- PyTuple_SET_ITEM(result, i, obj);
- }
-
- sk_POLICYINFO_pop_free(ext, POLICYINFO_free);
- return result;
-
- error:
- sk_POLICYINFO_pop_free(ext, POLICYINFO_free);
- Py_XDECREF(result);
- return NULL;
-}
-
-static char x509_object_set_certificate_policies__doc__[] =
- "Set Certificate Policies for this certificate.\n"
- "\n"
- "Argument is a iterable which returns policy OIDs.\n"
- "\n"
- "Policy qualifier are not supported.\n"
- "\n"
- "The extension will be marked as critical, since there's not much point\n"
- "in using this extension without making it critical.\n"
- ;
-
-static PyObject *
-x509_object_set_certificate_policies(x509_object *self, PyObject *args)
-{
- CERTIFICATEPOLICIES *ext = NULL;
- PyObject *policies = NULL;
- PyObject *iterator = NULL;
- POLICYINFO *pol = NULL;
- PyObject *item = NULL;
- const char *oid;
- int ok = 0;
-
- ENTERING(x509_object_set_certificate_policies);
-
- if (!PyArg_ParseTuple(args, "O", &policies))
- goto error;
-
- if ((ext = sk_POLICYINFO_new_null()) == NULL)
- lose_no_memory();
-
- if ((iterator = PyObject_GetIter(policies)) == NULL)
- goto error;
-
- while ((item = PyIter_Next(iterator)) != NULL) {
-
- if ((oid = PyString_AsString(item)) == NULL)
- goto error;
-
- if ((pol = POLICYINFO_new()) == NULL)
- lose_no_memory();
-
- if ((pol->policyid = OBJ_txt2obj(oid, 1)) == NULL)
- lose("Couldn't parse OID");
-
- if (!sk_POLICYINFO_push(ext, pol))
- lose_no_memory();
-
- pol = NULL;
- Py_XDECREF(item);
- item = NULL;
- }
-
- Py_XDECREF(iterator);
- iterator = NULL;
-
- if (!X509_add1_ext_i2d(self->x509, NID_certificate_policies, ext, 1, X509V3_ADD_REPLACE))
- lose_openssl_error("Couldn't add CERTIFICATE_POLICIES extension to certificate");
-
- ok = 1;
-
- error:
- POLICYINFO_free(pol);
- sk_POLICYINFO_pop_free(ext, POLICYINFO_free);
- Py_XDECREF(item);
- Py_XDECREF(iterator);
-
- if (ok)
- Py_RETURN_NONE;
- else
- return NULL;
-}
-
-/*
- * May want EKU handlers eventually, skip for now.
- */
-
-static char x509_object_pprint__doc__[] =
- "Return a pretty-printed rendition of this certificate.\n"
- ;
-
-static PyObject *
-x509_object_pprint(x509_object *self)
-{
- PyObject *result = NULL;
- BIO *bio = NULL;
-
- ENTERING(x509_object_pprint);
-
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
- lose_no_memory();
-
- if (!X509_print(bio, self->x509))
- lose_openssl_error("Unable to pretty-print certificate");
-
- result = BIO_to_PyString_helper(bio);
-
- error: /* Fall through */
- BIO_free(bio);
- return result;
-}
-
-static struct PyMethodDef x509_object_methods[] = {
- Define_Method(pemWrite, x509_object_pem_write, METH_NOARGS),
- Define_Method(derWrite, x509_object_der_write, METH_NOARGS),
- Define_Method(sign, x509_object_sign, METH_VARARGS),
- Define_Method(getPublicKey, x509_object_get_public_key, METH_NOARGS),
- Define_Method(setPublicKey, x509_object_set_public_key, METH_VARARGS),
- Define_Method(getVersion, x509_object_get_version, METH_NOARGS),
- Define_Method(setVersion, x509_object_set_version, METH_VARARGS),
- Define_Method(getSerial, x509_object_get_serial, METH_NOARGS),
- Define_Method(setSerial, x509_object_set_serial, METH_VARARGS),
- Define_Method(getIssuer, x509_object_get_issuer, METH_VARARGS),
- Define_Method(setIssuer, x509_object_set_issuer, METH_VARARGS),
- Define_Method(getSubject, x509_object_get_subject, METH_VARARGS),
- Define_Method(setSubject, x509_object_set_subject, METH_VARARGS),
- Define_Method(getNotBefore, x509_object_get_not_before, METH_NOARGS),
- Define_Method(getNotAfter, x509_object_get_not_after, METH_NOARGS),
- Define_Method(setNotAfter, x509_object_set_not_after, METH_VARARGS),
- Define_Method(setNotBefore, x509_object_set_not_before, METH_VARARGS),
- Define_Method(clearExtensions, x509_object_clear_extensions, METH_NOARGS),
- Define_Method(pprint, x509_object_pprint, METH_NOARGS),
- Define_Method(getSKI, x509_object_get_ski, METH_NOARGS),
- Define_Method(setSKI, x509_object_set_ski, METH_VARARGS),
- Define_Method(getAKI, x509_object_get_aki, METH_NOARGS),
- Define_Method(setAKI, x509_object_set_aki, METH_VARARGS),
- Define_Method(getKeyUsage, x509_object_get_key_usage, METH_NOARGS),
- Define_Method(setKeyUsage, x509_object_set_key_usage, METH_VARARGS),
- Define_Method(getEKU, x509_object_get_eku, METH_NOARGS),
- Define_Method(setEKU, x509_object_set_eku, METH_VARARGS),
- Define_Method(getRFC3779, x509_object_get_rfc3779, METH_NOARGS),
- Define_Method(setRFC3779, x509_object_set_rfc3779, METH_KEYWORDS),
- Define_Method(getBasicConstraints, x509_object_get_basic_constraints, METH_NOARGS),
- Define_Method(setBasicConstraints, x509_object_set_basic_constraints, METH_VARARGS),
- Define_Method(getSIA, x509_object_get_sia, METH_NOARGS),
- Define_Method(setSIA, x509_object_set_sia, METH_KEYWORDS),
- Define_Method(getAIA, x509_object_get_aia, METH_NOARGS),
- Define_Method(setAIA, x509_object_set_aia, METH_VARARGS),
- Define_Method(getCRLDP, x509_object_get_crldp, METH_NOARGS),
- Define_Method(setCRLDP, x509_object_set_crldp, METH_VARARGS),
- Define_Method(getCertificatePolicies, x509_object_get_certificate_policies, METH_NOARGS),
- Define_Method(setCertificatePolicies, x509_object_set_certificate_policies, METH_VARARGS),
- Define_Class_Method(pemRead, x509_object_pem_read, METH_VARARGS),
- Define_Class_Method(pemReadFile, x509_object_pem_read_file, METH_VARARGS),
- Define_Class_Method(derRead, x509_object_der_read, METH_VARARGS),
- Define_Class_Method(derReadFile, x509_object_der_read_file, METH_VARARGS),
- {NULL}
-};
-
-static char POW_X509_Type__doc__[] =
- "This class represents an X.509 certificate.\n"
- "\n"
- LAME_DISCLAIMER_IN_ALL_CLASS_DOCUMENTATION
- ;
-
-static PyTypeObject POW_X509_Type = {
- PyObject_HEAD_INIT(0)
- 0, /* ob_size */
- "rpki.POW.X509", /* tp_name */
- sizeof(x509_object), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor)x509_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 */
- POW_X509_Type__doc__, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- x509_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 */
- 0, /* tp_init */
- 0, /* tp_alloc */
- x509_object_new, /* tp_new */
-};
-
-
-
-/*
- * X509Store object.
- */
-
-static PyObject *
-x509_store_object_new(PyTypeObject *type, GCC_UNUSED PyObject *args, GCC_UNUSED PyObject *kwds)
-{
- x509_store_object *self = NULL;
-
- ENTERING(x509_store_object_new);
-
- if ((self = (x509_store_object *) type->tp_alloc(type, 0)) == NULL)
- goto error;
-
- if ((self->store = X509_STORE_new()) == NULL)
- lose_no_memory();
-
- self->ctxclass = (PyObject *) &POW_X509StoreCTX_Type;
- Py_XINCREF(self->ctxclass);
- return (PyObject *) self;
-
- error:
- Py_XDECREF(self);
- return NULL;
-}
-
-static void
-x509_store_object_dealloc(x509_store_object *self)
-{
- ENTERING(x509_store_object_dealloc);
- X509_STORE_free(self->store);
- Py_XDECREF(self->ctxclass);
- self->ob_type->tp_free((PyObject*) self);
-}
-
-static char x509_store_object_add_trust__doc__[] =
- "Add a trusted certificate to this certificate store object.\n"
- "\n"
- "The \"certificate\" parameter should be an instance of the X509 class.\n"
- ;
-
-static PyObject *
-x509_store_object_add_trust(x509_store_object *self, PyObject *args)
-{
- x509_object *x509 = NULL;
-
- ENTERING(x509_store_object_add_trust);
-
- if (!PyArg_ParseTuple(args, "O!", &POW_X509_Type, &x509))
- goto error;
-
- X509_STORE_add_cert(self->store, x509->x509);
-
- Py_RETURN_NONE;
-
- error:
-
- return NULL;
-}
-
-static char x509_store_object_add_crl__doc__[] =
- "Add a CRL to this certificate store object.\n"
- "\n"
- "The \"crl\" parameter should be an instance of the CRL class.\n"
- ;
-
-static PyObject *
-x509_store_object_add_crl(x509_store_object *self, PyObject *args)
-{
- crl_object *crl = NULL;
-
- ENTERING(x509_store_object_add_crl);
-
- if (!PyArg_ParseTuple(args, "O!", &POW_CRL_Type, &crl))
- goto error;
-
- X509_STORE_add_crl(self->store, crl->crl);
-
- Py_RETURN_NONE;
-
- error:
-
- return NULL;
-}
-
-static char x509_store_object_set_flags__doc__[] =
- "Set validation flags for this X509Store.\n"
- "\n"
- "Argument is an integer containing bit flags to set.\n"
- ;
-
-static PyObject *
-x509_store_object_set_flags (x509_store_object *self, PyObject *args)
-{
- unsigned long flags;
-
- if (!PyArg_ParseTuple(args, "k", &flags))
- goto error;
-
- if (!X509_VERIFY_PARAM_set_flags(self->store->param, flags))
- lose_openssl_error("X509_VERIFY_PARAM_set_flags() failed");
-
- Py_RETURN_NONE;
-
- error:
- return NULL;
-}
-
-static char x509_store_object_clear_flags__doc__[] =
- "Clear validation flags for this X509Store.\n"
- "\n"
- "Argument is an integer containing bit flags to clear.\n"
- ;
-
-static PyObject *
-x509_store_object_clear_flags (x509_store_object *self, PyObject *args)
-{
- unsigned long flags;
-
- if (!PyArg_ParseTuple(args, "k", &flags))
- goto error;
-
- if (!X509_VERIFY_PARAM_clear_flags(self->store->param, flags))
- lose_openssl_error("X509_VERIFY_PARAM_clear_flags() failed");
-
- Py_RETURN_NONE;
-
- error:
- return NULL;
-}
-
-static char x509_store_object_set_context_class__doc__[] =
- "Set validation context class factory for this X509Store.\n"
- "\n"
- "This must be a callable object which takes one argument, an X509Store,\n"
- "and returns a subclass of X509StoreCTX. The callable can be a class\n"
- "object but need not be, so long as calling it returns an instance of an\n"
- "appropriate class. The default is X509StoreCTX.\n"
- ;
-
-static PyObject *
-x509_store_object_set_context_class (x509_store_object *self, PyObject *args)
-{
- PyObject *ctxclass = (PyObject *) &POW_X509StoreCTX_Type;
-
- if (!PyArg_ParseTuple(args, "|O", &ctxclass))
- goto error;
-
- if (!PyCallable_Check(ctxclass))
- lose("Context class must be callable");
-
- Py_XDECREF(self->ctxclass);
- self->ctxclass = ctxclass;
- Py_XINCREF(self->ctxclass);
-
- Py_RETURN_NONE;
-
- error:
- return NULL;
-}
-
-static char x509_store_object_verify__doc__[] =
- "Verify an X509 certificate object using this certificate store.\n"
- "\n"
- "Optional second argument is an iterable that supplies untrusted certificates\n"
- "to be considered when building a chain to the trust anchor.\n"
- "\n"
- "This method returns an instance of the store's verification context class.\n"
- ;
-
-static PyObject *
-x509_store_object_verify(x509_store_object *self, PyObject *args)
-{
- x509_store_ctx_object *ctx = NULL;
- STACK_OF(X509) *stack = NULL;
- x509_object *x509 = NULL;
- PyObject *chain = Py_None;
- int ok;
-
- if (!PyArg_ParseTuple(args, "O!|O", &POW_X509_Type, &x509, &chain))
- goto error;
-
- if ((ctx = (x509_store_ctx_object *) PyObject_CallFunctionObjArgs(self->ctxclass, self, NULL)) == NULL)
- goto error;
-
- if (!POW_X509StoreCTX_Check(ctx))
- lose_type_error("Returned context is not a X509StoreCTX");
-
- if (ctx->ctx == NULL)
- lose("Uninitialized X509StoreCTX");
-
- if (chain != Py_None && (stack = x509_helper_iterable_to_stack(chain)) == NULL)
- goto error;
-
- Py_XINCREF(x509);
- Py_XINCREF(chain);
- X509_STORE_CTX_set_cert(ctx->ctx, x509->x509);
- X509_STORE_CTX_set_chain(ctx->ctx, stack);
-
- ok = X509_verify_cert(ctx->ctx);
-
- X509_STORE_CTX_set_chain(ctx->ctx, NULL);
- X509_STORE_CTX_set_cert(ctx->ctx, NULL);
- Py_XDECREF(chain);
- Py_XDECREF(x509);
-
- sk_X509_free(stack);
-
- if (PyErr_Occurred())
- goto error;
-
- if (ok < 0)
- lose_openssl_error("X509_verify_cert() raised an exception");
-
- return (PyObject *) ctx;
-
- error: /* fall through */
- Py_XDECREF(ctx);
- return NULL;
-}
-
-static struct PyMethodDef x509_store_object_methods[] = {
- Define_Method(addTrust, x509_store_object_add_trust, METH_VARARGS),
- Define_Method(addCrl, x509_store_object_add_crl, METH_VARARGS),
- Define_Method(setContextClass,x509_store_object_set_context_class, METH_VARARGS),
- Define_Method(setFlags, x509_store_object_set_flags, METH_VARARGS),
- Define_Method(clearFlags, x509_store_object_clear_flags, METH_VARARGS),
- Define_Method(verify, x509_store_object_verify, METH_VARARGS),
- {NULL}
-};
-
-static char POW_X509Store_Type__doc__[] =
- "This class holds the OpenSSL certificate store objects used in CMS\n"
- "and certificate verification.\n"
- "\n"
- LAME_DISCLAIMER_IN_ALL_CLASS_DOCUMENTATION
- ;
-
-static PyTypeObject POW_X509Store_Type = {
- PyObject_HEAD_INIT(0)
- 0, /* ob_size */
- "rpki.POW.X509Store", /* tp_name */
- sizeof(x509_store_object), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor)x509_store_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 */
- POW_X509Store_Type__doc__, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- x509_store_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 */
- 0, /* tp_init */
- 0, /* tp_alloc */
- x509_store_object_new, /* tp_new */
-};
-
-
-
-/*
- * X509StoreCTX object.
- */
-
-static int
-x509_store_ctx_object_verify_cb(int ok, X509_STORE_CTX *ctx)
-{
- static char method_name[] = "verify_callback";
- PyObject *self = X509_STORE_CTX_get_ex_data(ctx, x509_store_ctx_ex_data_idx);
- PyObject *result = NULL;
-
- if (self == NULL || !PyObject_HasAttrString(self, method_name))
- return ok;
-
- if ((result = PyObject_CallMethod(self, method_name, "i", ok)) == NULL)
- return -1;
-
- ok = PyObject_IsTrue(result);
- Py_XDECREF(result);
- return ok;
-}
-
-static PyObject *
-x509_store_ctx_object_new(PyTypeObject *type, GCC_UNUSED PyObject *args, GCC_UNUSED PyObject *kwds)
-{
- x509_store_ctx_object *self = NULL;
-
- ENTERING(x509_store_ctx_object_new);
-
- if ((self = (x509_store_ctx_object *) type->tp_alloc(type, 0)) == NULL)
- goto error;
-
- self->ctx = NULL;
- self->store = NULL;
- return (PyObject *) self;
-
- error:
- Py_XDECREF(self);
- return NULL;
-}
-
-static int
-x509_store_ctx_object_init(x509_store_ctx_object *self, PyObject *args, GCC_UNUSED PyObject *kwds)
-{
- x509_store_object *store = NULL;
-
- if (!PyArg_ParseTuple(args, "|O!", &POW_X509Store_Type, &store))
- goto error;
-
- if ((self->ctx = X509_STORE_CTX_new()) == NULL)
- lose_no_memory();
-
- if (!X509_STORE_CTX_init(self->ctx, store ? store->store : NULL, NULL, NULL))
- lose_openssl_error("Couldn't initialize X509_STORE_CTX");
-
- if (!X509_STORE_CTX_set_ex_data(self->ctx, x509_store_ctx_ex_data_idx, self))
- lose_openssl_error("Couldn't set X509_STORE_CTX ex_data");
-
- Py_XDECREF(self->store);
- self->store = store;
- Py_XINCREF(self->store);
-
- X509_VERIFY_PARAM_set_flags(self->ctx->param, X509_V_FLAG_X509_STRICT);
- X509_STORE_CTX_set_verify_cb(self->ctx, x509_store_ctx_object_verify_cb);
- return 0;
-
- error:
- return -1;
-}
-
-static void
-x509_store_ctx_object_dealloc(x509_store_ctx_object *self)
-{
- ENTERING(x509_store_ctx_object_dealloc);
- X509_STORE_CTX_free(self->ctx);
- Py_XDECREF(self->store);
- self->ob_type->tp_free((PyObject*) self);
-}
-
-static PyObject *
-x509_store_ctx_object_get_store (x509_store_ctx_object *self, GCC_UNUSED void *closure)
-{
- return Py_BuildValue("O", self->store == NULL ? Py_None : (PyObject *) self->store);
-}
-
-static char x509_store_ctx_object_get_error__doc__[] =
- "Extract verification error code from this X509StoreCTX.\n"
- ;
-
-static PyObject*
-x509_store_ctx_object_get_error (x509_store_ctx_object *self)
-{
- return Py_BuildValue("i", X509_STORE_CTX_get_error(self->ctx));
-}
-
-static char x509_store_ctx_object_get_error_string__doc__[] =
- "Extract verification error code from this X509StoreCTX.\n"
- ;
-
-static PyObject*
-x509_store_ctx_object_get_error_string (x509_store_ctx_object *self)
-{
- return Py_BuildValue("s", X509_verify_cert_error_string(X509_STORE_CTX_get_error(self->ctx)));
-}
-
-static char x509_store_ctx_object_get_error_depth__doc__[] =
- "Extract verification error depth from this X509StoreCTX.\n"
- ;
-
-static PyObject*
-x509_store_ctx_object_get_error_depth (x509_store_ctx_object *self)
-{
- return Py_BuildValue("i", X509_STORE_CTX_get_error_depth(self->ctx));
-}
-
-static char x509_store_ctx_object_get_current_certificate__doc__[] =
- "Extract the certificate which caused the current validation error,\n"
- "or None if no certificate is relevant.\n"
- ;
-
-static PyObject *
-x509_store_ctx_object_get_current_certificate (x509_store_ctx_object *self)
-{
- X509 *x = X509_STORE_CTX_get_current_cert(self->ctx);
- x509_object *obj = NULL;
-
- if (x == NULL)
- Py_RETURN_NONE;
-
- if ((x = X509_dup(x)) == NULL)
- lose_no_memory();
-
- if ((obj = x509_object_new_helper(NULL, x)) == NULL)
- goto error;
-
- return (PyObject *) obj;
-
- error:
- Py_XDECREF(obj);
- X509_free(x);
- return NULL;
-}
-
-static char x509_store_ctx_object_get_chain__doc__[] =
- "Extract certificate chain from X509StoreCTX. If validation\n"
- "completed succesfully, this is the complete validation chain;\n"
- "otherwise, the returned chain may be invalid or incomplete.\n"
- ;
-
-static PyObject *
-x509_store_ctx_object_get_chain (x509_store_ctx_object *self)
-{
- STACK_OF(X509) *chain = NULL;
- PyObject *result = NULL;
-
- if ((chain = X509_STORE_CTX_get1_chain(self->ctx)) == NULL)
- lose_openssl_error("X509_STORE_CTX_get1_chain() failed");
-
- result = stack_to_tuple_helper(CHECKED_PTR_OF(STACK_OF(X509), chain),
- stack_to_tuple_helper_get_x509);
-
- error: /* fall through */
- sk_X509_pop_free(chain, X509_free);
- return result;
-}
-
-/*
- * For some reason, there are no methods for the policy mechanism for
- * X509_STORE, only for X509_STORE_CTX. Presumably we can whack these
- * anyway using the X509_VERIFY_PARAM_*() calls, the question is
- * whether there's a good reason for this omission.
- *
- * For the moment, I'm just going to leave the policy stuff
- * unimplemented, until we figure out whether it belongs in X509Store
- * or X509StoreCTX.
- */
-
-#define IMPLEMENT_X509StoreCTX_POLICY 0
-
-#if IMPLEMENT_X509StoreCTX_POLICY
-
-static char x509_store_ctx_object_set_policy__doc__[] =
- "Set this X509StoreCTX to require a specified certificate policy.\n"
- ;
-
-static PyObject*
-x509_store_ctx_object_set_policy (x509_store_ctx_object *self, PyObject *args)
-{
- ASN1_OBJECT *policy = NULL;
- char *oid = NULL;
-
- if (!PyArg_ParseTuple(args, "s", &oid))
- goto error;
-
- if ((policy = OBJ_txt2obj(oid, 1)) == NULL)
- lose_openssl_error("Couldn't parse OID");
-
- if (!X509_VERIFY_PARAM_set_flags(self->ctx->param, X509_V_FLAG_POLICY_CHECK | X509_V_FLAG_EXPLICIT_POLICY))
- lose_openssl_error("Couldn't set policy flags");
-
- if (!X509_VERIFY_PARAM_add0_policy(self->ctx->param, policy))
- lose_openssl_error("Couldn't set policy");
-
- Py_RETURN_NONE;
-
- error:
- ASN1_OBJECT_free(policy);
- return NULL;
-}
-
-#endif /* IMPLEMENT_X509StoreCTX_POLICY */
-
-/*
- * See (omnibus) man page for X509_STORE_CTX_get_error() for other
- * query methods we might want to expose. Someday we might want to
- * support X509_V_FLAG_USE_CHECK_TIME too.
- */
-
-static struct PyMethodDef x509_store_ctx_object_methods[] = {
- Define_Method(getError, x509_store_ctx_object_get_error, METH_NOARGS),
- Define_Method(getErrorString, x509_store_ctx_object_get_error_string, METH_NOARGS),
- Define_Method(getErrorDepth, x509_store_ctx_object_get_error_depth, METH_NOARGS),
- Define_Method(getCurrentCertificate, x509_store_ctx_object_get_current_certificate, METH_NOARGS),
- Define_Method(getChain, x509_store_ctx_object_get_chain, METH_NOARGS),
-
-#if IMPLEMENT_X509StoreCTX_POLICY
- Define_Method(setPolicy, x509_store_ctx_object_set_policy, METH_VARARGS),
-#endif
- {NULL}
-};
-
-static PyGetSetDef x509_store_ctx_object_getsetters[] = {
- {"store", (getter) x509_store_ctx_object_get_store},
- {NULL}
-};
-
-static char POW_X509StoreCTX_Type__doc__[] =
- "This class holds the state of an OpenSSL certificate verification\n"
- "operation. Ordinarily, the user will never have cause to instantiate\n"
- "this class directly, instead, an object of this class will be returned\n"
- "by X509Store.verify().\n"
- "\n"
- "If you need to see OpenSSL's verification callbacks, you can do so\n"
- "by subclassing X509StoreCTX and attaching your subclass to an X509Store\n"
- "object using X509Store.setContextClass(). Your subclass should provide\n"
- "a .verify_callback() method, wich should expect to receive one argument:\n"
- "the integer \"ok\" value passed by OpenSSL's verification callbacks.\n"
- "\n"
- "The return value from your .verify_callback() method will be is interpreted\n"
- "as a boolean value: anything which evaluates to True will be result in a\n"
- "return value of 1 to OpenSSL, while anything which evaluates to False will\n"
- "result in a return value of 0 to OpenSSL.\n"
- ;
-
-static PyTypeObject POW_X509StoreCTX_Type = {
- PyObject_HEAD_INIT(0)
- 0, /* ob_size */
- "rpki.POW.X509StoreCTX", /* tp_name */
- sizeof(x509_store_ctx_object), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor)x509_store_ctx_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 */
- POW_X509StoreCTX_Type__doc__, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- x509_store_ctx_object_methods, /* tp_methods */
- 0, /* tp_members */
- x509_store_ctx_object_getsetters, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc) x509_store_ctx_object_init, /* tp_init */
- 0, /* tp_alloc */
- x509_store_ctx_object_new, /* tp_new */
-};
-
-
-
-/*
- * CRL object.
- */
-
-static crl_object *
-crl_object_new_helper(PyTypeObject *type, X509_CRL *crl)
-{
- crl_object *self = NULL;
-
- if (type == NULL)
- type = &POW_CRL_Type;
-
- if ((self = (crl_object *) type->tp_alloc(type, 0)) == NULL)
- return NULL;
-
- self->crl = crl;
- return self;
-}
-
-static PyObject *
-crl_object_new(PyTypeObject *type, GCC_UNUSED PyObject *args, GCC_UNUSED PyObject *kwds)
-{
- crl_object *self = NULL;
- X509_CRL *crl = NULL;
-
- ENTERING(crl_object_new);
-
- if ((crl = X509_CRL_new()) == NULL)
- lose_no_memory();
-
- if ((self = crl_object_new_helper(type, crl)) == NULL)
- goto error;
-
- return (PyObject *) self;
-
- error:
- X509_CRL_free(crl);
- return NULL;
-}
-
-static void
-crl_object_dealloc(crl_object *self)
-{
- ENTERING(crl_object_dealloc);
- X509_CRL_free(self->crl);
- self->ob_type->tp_free((PyObject*) self);
-}
-
-static PyObject *
-crl_object_pem_read_helper(PyTypeObject *type, BIO *bio)
-{
- crl_object *self;
-
- ENTERING(crl_object_pem_read_helper);
-
- if ((self = (crl_object *) crl_object_new(type, NULL, NULL)) == NULL)
- goto error;
-
- if (!PEM_read_bio_X509_CRL(bio, &self->crl, NULL, NULL))
- lose_openssl_error("Couldn't PEM encoded load CRL");
-
- return (PyObject *) self;
-
- error:
- Py_XDECREF(self);
- return NULL;
-}
-
-static PyObject *
-crl_object_der_read_helper(PyTypeObject *type, BIO *bio)
-{
- crl_object *self;
-
- ENTERING(crl_object_der_read_helper);
-
- if ((self = (crl_object *) crl_object_new(type, NULL, NULL)) == NULL)
- goto error;
-
- if (!d2i_X509_CRL_bio(bio, &self->crl))
- lose_openssl_error("Couldn't load DER encoded CRL");
-
- return (PyObject *) self;
-
- error:
- Py_XDECREF(self);
- return NULL;
-}
-
-static char crl_object_pem_read__doc__[] =
- "Read a PEM-encoded CRL object from a string.\n"
- ;
-
-static PyObject *
-crl_object_pem_read(PyTypeObject *type, PyObject *args)
-{
- ENTERING(crl_object_pem_read);
- return read_from_string_helper(crl_object_pem_read_helper, type, args);
-}
-
-static char crl_object_pem_read_file__doc__[] =
- "Read a PEM-encoded CRL object from a file.\n"
- ;
-
-static PyObject *
-crl_object_pem_read_file(PyTypeObject *type, PyObject *args)
-{
- ENTERING(crl_object_pem_read_file);
- return read_from_file_helper(crl_object_pem_read_helper, type, args);
-}
-
-static char crl_object_der_read__doc__[] =
- "Read a DER-encoded CRL object from a string.\n"
- ;
-
-static PyObject *
-crl_object_der_read(PyTypeObject *type, PyObject *args)
-{
- ENTERING(crl_object_der_read);
- return read_from_string_helper(crl_object_der_read_helper, type, args);
-}
-
-static char crl_object_der_read_file__doc__[] =
- "Read a DER-encoded CRL object from a file.\n"
- ;
-
-static PyObject *
-crl_object_der_read_file(PyTypeObject *type, PyObject *args)
-{
- ENTERING(crl_object_der_read_file);
- return read_from_file_helper(crl_object_der_read_helper, type, args);
-}
-
-static X509_EXTENSIONS **
-crl_object_extension_helper(crl_object *self)
-{
- if (self && self->crl && self->crl->crl)
- return &self->crl->crl->extensions;
- PyErr_SetString(PyExc_ValueError, "Can't find X509_EXTENSIONS in CRL object");
- return NULL;
-}
-
-static char crl_object_get_version__doc__[] =
- "return the version number of this CRL.\n"
- ;
-
-static PyObject *
-crl_object_get_version(crl_object *self)
-{
- ENTERING(crl_object_get_version);
- return Py_BuildValue("l", X509_CRL_get_version(self->crl));
-}
-
-static char crl_object_set_version__doc__[] =
- "Set the version number of this CRL.\n"
- "\n"
- "The \"version\" parameter should be a positive integer.\n"
- ;
-
-static PyObject *
-crl_object_set_version(crl_object *self, PyObject *args)
-{
- long version = 0;
-
- ENTERING(crl_object_set_version);
-
- if (!PyArg_ParseTuple(args, "i", &version))
- goto error;
-
- if (!X509_CRL_set_version(self->crl, version))
- lose_no_memory();
-
- Py_RETURN_NONE;
-
- error:
- return NULL;
-}
-
-static char crl_object_get_issuer__doc__[] =
- "Return issuer name of this CRL.\n"
- "\n"
- "See the \"getIssuer()\" method of the X509 class for more details.\n"
- ;
-
-static PyObject *
-crl_object_get_issuer(crl_object *self, PyObject *args)
-{
- PyObject *result = NULL;
- int format = OIDNAME_FORMAT;
-
- ENTERING(crl_object_get_issuer);
-
- if (!PyArg_ParseTuple(args, "|i", &format))
- goto error;
-
- result = x509_object_helper_get_name(X509_CRL_get_issuer(self->crl), format);
-
- error: /* Fall through */
- return result;
-}
-
-static char crl_object_set_issuer__doc__[] =
- "Set this CRL's issuer name.\n"
- "\n"
- "See the \"setIssuer()\" method of the X509 class for details.\n"
- ;
-
-static PyObject *
-crl_object_set_issuer(crl_object *self, PyObject *args)
-{
- PyObject *name_sequence = NULL;
- X509_NAME *name = NULL;
-
- ENTERING(crl_object_set_issuer);
-
- if (!PyArg_ParseTuple(args, "O", &name_sequence))
- goto error;
-
- if (!PySequence_Check(name_sequence))
- lose_type_error("Inapropriate type");
-
- if ((name = x509_object_helper_set_name(name_sequence)) == NULL)
- goto error;
-
- if (!X509_CRL_set_issuer_name(self->crl, name))
- lose_openssl_error("Unable to set issuer name");
-
- X509_NAME_free(name);
-
- Py_RETURN_NONE;
-
- error:
- X509_NAME_free(name);
- 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 crl_object_set_this_update__doc__[] =
- "Set this CRL's \"thisUpdate\" value.\n"
- "\n"
- "The \"time\" parameter should be a datetime object.\n"
- ;
-
-static PyObject *
-crl_object_set_this_update (crl_object *self, PyObject *args)
-{
- PyObject *o = NULL;
- ASN1_TIME *t = NULL;
-
- ENTERING(crl_object_set_this_update);
-
- if (!PyArg_ParseTuple(args, "O", &o))
- goto error;
-
- if ((t = Python_to_ASN1_TIME(o, 1)) == 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 crl_object_get_this_update__doc__[] =
- "Return this CRL's \"thisUpdate\" value as a datetime.\n"
- ;
-
-static PyObject *
-crl_object_get_this_update (crl_object *self)
-{
- ENTERING(crl_object_get_this_update);
- return ASN1_TIME_to_Python(X509_CRL_get_lastUpdate(self->crl)); /* sic */
-}
-
-static char crl_object_set_next_update__doc__[] =
- "Set this CRL's \"nextUpdate\" value.\n"
- "\n"
- "The \"time\" parameter should be a datetime object.\n"
- ;
-
-static PyObject *
-crl_object_set_next_update (crl_object *self, PyObject *args)
-{
- PyObject *o = NULL;
- ASN1_TIME *t = NULL;
-
- ENTERING(crl_object_set_next_update);
-
- if (!PyArg_ParseTuple(args, "O", &o))
- goto error;
-
- if ((t = Python_to_ASN1_TIME(o, 1)) == NULL)
- lose("Couldn't parse nextUpdate string");
-
- 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 crl_object_get_next_update__doc__[] =
- "Returns this CRL's \"nextUpdate\" value as a datetime.\n"
- ;
-
-static PyObject *
-crl_object_get_next_update (crl_object *self)
-{
- ENTERING(crl_object_get_next_update);
- return ASN1_TIME_to_Python(X509_CRL_get_nextUpdate(self->crl));
-}
-
-static char 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 which returns\n"
- "two-element sequences. The first element of each pair should be the\n"
- "revoked serial number (an integer), the second element should be the\n"
- "revocation date (a datetime object).\n"
- ;
-
-static PyObject *
-crl_object_add_revocations(crl_object *self, PyObject *args)
-{
- PyObject *iterable = NULL;
- PyObject *iterator = NULL;
- PyObject *item = NULL;
- PyObject *fast = NULL;
- X509_REVOKED *revoked = NULL;
- ASN1_INTEGER *serial = NULL;
- ASN1_TIME *date = NULL;
- int ok = 0;
-
- ENTERING(crl_object_add_revocations);
-
- if (!PyArg_ParseTuple(args, "O", &iterable) ||
- (iterator = PyObject_GetIter(iterable)) == NULL)
- goto error;
-
- while ((item = PyIter_Next(iterator)) != NULL) {
-
- if ((fast = PySequence_Fast(item, "Revocation entry must be a sequence")) == NULL)
- goto error;
-
- if (PySequence_Fast_GET_SIZE(fast) != 2)
- lose_type_error("Revocation entry must be two-element sequence");
-
- if ((serial = PyLong_to_ASN1_INTEGER(PySequence_Fast_GET_ITEM(fast, 0))) == NULL ||
- (date = Python_to_ASN1_TIME(PySequence_Fast_GET_ITEM(fast, 1), 1)) == NULL)
- goto error;
-
- if ((revoked = X509_REVOKED_new()) == NULL ||
- !X509_REVOKED_set_serialNumber(revoked, serial) ||
- !X509_REVOKED_set_revocationDate(revoked, date))
- lose_no_memory();
-
- ASN1_INTEGER_free(serial);
- serial = NULL;
-
- ASN1_TIME_free(date);
- date = NULL;
-
- if (!X509_CRL_add0_revoked(self->crl, revoked))
- lose_no_memory();
-
- revoked = NULL;
- Py_XDECREF(item);
- Py_XDECREF(fast);
- item = fast = NULL;
- }
-
- if (!X509_CRL_sort(self->crl))
- lose_openssl_error("Couldn't sort CRL");
-
- ok = 1;
-
- error:
- Py_XDECREF(iterator);
- Py_XDECREF(item);
- Py_XDECREF(fast);
- X509_REVOKED_free(revoked);
- ASN1_INTEGER_free(serial);
- ASN1_TIME_free(date);
-
- if (ok)
- Py_RETURN_NONE;
- else
- return NULL;
-}
-
-static char crl_object_get_revoked__doc__[] =
- "Return a sequence of two-element tuples representing the sequence of\n"
- "revoked certificates listed in this CRL.\n"
- "\n"
- "The first element of each pair is the serialNumber of the revoked\n"
- "certificate, the second element is the revocationDate.\n"
- ;
-
-static PyObject *
-crl_object_get_revoked(crl_object *self)
-{
- STACK_OF(X509_REVOKED) *revoked = NULL;
- X509_REVOKED *r = NULL;
- PyObject *result = NULL;
- PyObject *item = NULL;
- PyObject *serial = NULL;
- PyObject *date = NULL;
- int i;
-
- ENTERING(crl_object_get_revoked);
-
- if ((revoked = X509_CRL_get_REVOKED(self->crl)) == NULL)
- lose("Inexplicable NULL revocation list pointer");
-
- if ((result = PyTuple_New(sk_X509_REVOKED_num(revoked))) == NULL)
- goto error;
-
- for (i = 0; i < sk_X509_REVOKED_num(revoked); i++) {
- r = sk_X509_REVOKED_value(revoked, i);
-
- if ((serial = ASN1_INTEGER_to_PyLong(r->serialNumber)) == NULL ||
- (date = ASN1_TIME_to_Python(r->revocationDate)) == NULL ||
- (item = Py_BuildValue("(NN)", serial, date)) == NULL)
- goto error;
-
- PyTuple_SET_ITEM(result, i, item);
- item = serial = date = NULL;
- }
-
- return result;
-
- error:
- Py_XDECREF(result);
- Py_XDECREF(item);
- Py_XDECREF(serial);
- Py_XDECREF(date);
- return NULL;
-}
-
-static char crl_object_clear_extensions__doc__[] =
- "Clear all extensions attached to this CRL.\n"
- ;
-
-static PyObject *
-crl_object_clear_extensions(crl_object *self)
-{
- X509_EXTENSION *ext;
-
- ENTERING(crl_object_clear_extensions);
-
- while ((ext = X509_CRL_delete_ext(self->crl, 0)) != NULL)
- X509_EXTENSION_free(ext);
-
- Py_RETURN_NONE;
-}
-
-static char crl_object_sign__doc__[] =
- "Sign this 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 *
-crl_object_sign(crl_object *self, PyObject *args)
-{
- asymmetric_object *asym;
- int digest_type = SHA256_DIGEST;
- const EVP_MD *digest_method = NULL;
-
- ENTERING(crl_object_sign);
-
- if (!PyArg_ParseTuple(args, "O!|i", &POW_Asymmetric_Type, &asym, &digest_type))
- goto error;
-
- if ((digest_method = evp_digest_factory(digest_type)) == NULL)
- lose("Unsupported digest algorithm");
-
- if (!X509_CRL_sign(self->crl, asym->pkey, digest_method))
- lose_openssl_error("Couldn't sign CRL");
-
- Py_RETURN_NONE;
-
- error:
- return NULL;
-}
-
-static char crl_object_verify__doc__[] =
- "Verify this CRL's signature.\n"
- "\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 *
-crl_object_verify(crl_object *self, PyObject *args)
-{
- asymmetric_object *asym;
-
- ENTERING(crl_object_verify);
-
- if (!PyArg_ParseTuple(args, "O!", &POW_Asymmetric_Type, &asym))
- goto error;
-
- return PyBool_FromLong(X509_CRL_verify(self->crl, asym->pkey));
-
- error:
- return NULL;
-}
-
-static char crl_object_pem_write__doc__[] =
- "Return the PEM encoding of this CRL, as a string.\n"
- ;
-
-static PyObject *
-crl_object_pem_write(crl_object *self)
-{
- PyObject *result = NULL;
- BIO *bio = NULL;
-
- ENTERING(crl_object_pem_write);
-
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
- lose_no_memory();
-
- if (!PEM_write_bio_X509_CRL(bio, self->crl))
- lose_openssl_error("Unable to write CRL");
-
- result = BIO_to_PyString_helper(bio);
-
- error: /* Fall through */
- BIO_free(bio);
- return result;
-}
-
-static char crl_object_der_write__doc__[] =
- "Return the DER encoding of this CRL, as a string.\n"
- ;
-
-static PyObject *
-crl_object_der_write(crl_object *self)
-{
- PyObject *result = NULL;
- BIO *bio = NULL;
-
- ENTERING(crl_object_der_write);
-
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
- lose_no_memory();
-
- if (!i2d_X509_CRL_bio(bio, self->crl))
- lose_openssl_error("Unable to write CRL");
-
- result = BIO_to_PyString_helper(bio);
-
- error: /* Fall through */
- BIO_free(bio);
- return result;
-}
-
-static char crl_object_get_aki__doc__[] =
- "Return the Authority Key Identifier (AKI) keyid value for\n"
- "this CRL, or None if the CRL has no AKI extension\n"
- "or has an AKI extension with no keyIdentifier value.\n"
- ;
-
-static PyObject *
-crl_object_get_aki(crl_object *self)
-{
- return extension_get_aki(crl_object_extension_helper(self));
-}
-
-static char crl_object_set_aki__doc__[] =
- "Set the Authority Key Identifier (AKI) value for this\n"
- "CRL. We only support the keyIdentifier method, as that's\n"
- "the only form which is legal for RPKI certificates.\n"
- ;
-
-static PyObject *
-crl_object_set_aki(crl_object *self, PyObject *args)
-{
- return extension_set_aki(crl_object_extension_helper(self), args);
-}
-
-static char crl_object_get_crl_number__doc__[] =
- "Return the CRL Number extension value from this CRL, an integer.\n"
- ;
-
-static PyObject *
-crl_object_get_crl_number(crl_object *self)
-{
- ASN1_INTEGER *ext = X509_CRL_get_ext_d2i(self->crl, NID_crl_number, NULL, NULL);
- PyObject *result = NULL;
-
- ENTERING(crl_object_get_crl_number);
-
- if (ext == NULL)
- Py_RETURN_NONE;
-
- result = Py_BuildValue("N", ASN1_INTEGER_to_PyLong(ext));
- ASN1_INTEGER_free(ext);
- return result;
-}
-
-static char crl_object_set_crl_number__doc__[] =
- "Set the CRL Number extension value in this CRL.\n"
- "\n"
- "The \"number\" parameter should be an integer.\n"
- ;
-
-static PyObject *
-crl_object_set_crl_number(crl_object *self, PyObject *args)
-{
- ASN1_INTEGER *ext = NULL;
- PyObject *crl_number = NULL;
-
- ENTERING(crl_object_set_crl_number);
-
- if (!PyArg_ParseTuple(args, "O", &crl_number) ||
- (ext = PyLong_to_ASN1_INTEGER(crl_number)) == NULL)
- goto error;
-
- if (!X509_CRL_add1_ext_i2d(self->crl, NID_crl_number, ext, 0, X509V3_ADD_REPLACE))
- lose_openssl_error("Couldn't add CRL Number extension to CRL");
-
- ASN1_INTEGER_free(ext);
- Py_RETURN_NONE;
-
- error:
- ASN1_INTEGER_free(ext);
- return NULL;
-}
-
-static char crl_object_pprint__doc__[] =
- "Return a pretty-printed rendition of this CRL.\n"
- ;
-
-static PyObject *
-crl_object_pprint(crl_object *self)
-{
- PyObject *result = NULL;
- BIO *bio = NULL;
-
- ENTERING(crl_object_pprint);
-
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
- lose_no_memory();
-
- if (!X509_CRL_print(bio, self->crl))
- lose_openssl_error("Unable to pretty-print CRL");
-
- result = BIO_to_PyString_helper(bio);
-
- error: /* Fall through */
- BIO_free(bio);
- return result;
-}
-
-static struct PyMethodDef crl_object_methods[] = {
- Define_Method(sign, crl_object_sign, METH_VARARGS),
- Define_Method(verify, crl_object_verify, METH_VARARGS),
- Define_Method(getVersion, crl_object_get_version, METH_NOARGS),
- Define_Method(setVersion, crl_object_set_version, METH_VARARGS),
- Define_Method(getIssuer, crl_object_get_issuer, METH_VARARGS),
- Define_Method(setIssuer, crl_object_set_issuer, METH_VARARGS),
- Define_Method(getThisUpdate, crl_object_get_this_update, METH_NOARGS),
- Define_Method(setThisUpdate, crl_object_set_this_update, METH_VARARGS),
- Define_Method(getNextUpdate, crl_object_get_next_update, METH_NOARGS),
- Define_Method(setNextUpdate, crl_object_set_next_update, METH_VARARGS),
- Define_Method(getRevoked, crl_object_get_revoked, METH_NOARGS),
- Define_Method(addRevocations, crl_object_add_revocations, METH_VARARGS),
- Define_Method(clearExtensions, crl_object_clear_extensions, METH_NOARGS),
- Define_Method(pemWrite, crl_object_pem_write, METH_NOARGS),
- Define_Method(derWrite, crl_object_der_write, METH_NOARGS),
- Define_Method(pprint, crl_object_pprint, METH_NOARGS),
- Define_Method(getAKI, crl_object_get_aki, METH_NOARGS),
- Define_Method(setAKI, crl_object_set_aki, METH_VARARGS),
- Define_Method(getCRLNumber, crl_object_get_crl_number, METH_NOARGS),
- Define_Method(setCRLNumber, crl_object_set_crl_number, METH_VARARGS),
- Define_Class_Method(pemRead, crl_object_pem_read, METH_VARARGS),
- Define_Class_Method(pemReadFile, crl_object_pem_read_file, METH_VARARGS),
- Define_Class_Method(derRead, crl_object_der_read, METH_VARARGS),
- Define_Class_Method(derReadFile, crl_object_der_read_file, METH_VARARGS),
- {NULL}
-};
-
-static char POW_CRL_Type__doc__[] =
- "Container for OpenSSL's X509 CRL management facilities.\n"
- ;
-
-static PyTypeObject POW_CRL_Type = {
- PyObject_HEAD_INIT(0)
- 0, /* ob_size */
- "rpki.POW.CRL", /* tp_name */
- sizeof(crl_object), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor)crl_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 */
- POW_CRL_Type__doc__, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- crl_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 */
- 0, /* tp_init */
- 0, /* tp_alloc */
- crl_object_new, /* tp_new */
-};
-
-
-
-/*
- * Asymmetric object.
- */
-
-static PyObject *
-asymmetric_object_new(PyTypeObject *type, GCC_UNUSED PyObject *args, GCC_UNUSED PyObject *kwds)
-{
- asymmetric_object *self = NULL;
-
- ENTERING(asymmetric_object_new);
-
- if ((self = (asymmetric_object *) type->tp_alloc(type, 0)) == NULL)
- goto error;
-
- self->pkey = NULL;
-
- return (PyObject *) self;
-
- error:
-
- Py_XDECREF(self);
- return NULL;
-}
-
-static int
-asymmetric_object_init(asymmetric_object *self, PyObject *args, PyObject *kwds)
-{
- static char *kwlist[] = {NULL};
-
- ENTERING(asymmetric_object_init);
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist))
- goto error;
-
- /*
- * We used to take arguments to generate an RSA key, but that's
- * now in the .generateRSA() class method.
- */
-
- return 0;
-
- error:
- return -1;
-}
-
-static void
-asymmetric_object_dealloc(asymmetric_object *self)
-{
- ENTERING(asymmetric_object_dealloc);
- EVP_PKEY_free(self->pkey);
- self->ob_type->tp_free((PyObject*) self);
-}
-
-static PyObject *
-asymmetric_object_pem_read_private_helper(PyTypeObject *type, BIO *bio, char *pass)
-{
- asymmetric_object *self = NULL;
-
- ENTERING(asymmetric_object_pem_read_private_helper);
-
- if ((self = (asymmetric_object *) asymmetric_object_new(type, NULL, NULL)) == NULL)
- goto error;
-
- if (!PEM_read_bio_PrivateKey(bio, &self->pkey, NULL, pass))
- lose_openssl_error("Couldn't load private key");
-
- return (PyObject *) self;
-
- error:
- Py_XDECREF(self);
- return NULL;
-}
-
-/*
- * We can't use the generic read_from_*_helper() functions here
- * because of optional the PEM password, so we just code the two PEM
- * read cases for private keys directly. Other than the passphrase,
- * code is pretty much the same as the generic functions.
- *
- * It turns out that OpenSSL is moving away from its old raw PKCS #1.5
- * private key format in favor of PKCS #8. This makes sense, but it
- * leaves us with a minor mess to track. Many OpenSSL functions that
- * originally expected PKCS #1.5 now also accept PKCS #8, so there's
- * no tearing hurry about this, but at some point we might want to
- * switch to writing PKCS #8. It looks like this would be relatively
- * straightforward: see functions i2d_PKCS8PrivateKey_bio() and
- * PEM_write_bio_PKCS8PrivateKey(), and note that PKCS #8 supports
- * encrypted private keys in DER format, so the DER methods should
- * take a passphrase argument as the PEM methods do.
- */
-
-static char asymmetric_object_pem_read_private__doc__[] =
- "Read a PEM-encoded private key from a string.\n"
- "\n"
- "Optional second argument is a passphrase for the key.\n"
- ;
-
-static PyObject *
-asymmetric_object_pem_read_private(PyTypeObject *type, PyObject *args)
-{
- PyObject *result = NULL;
- char *pass = NULL;
- char *src = NULL;
- BIO *bio = NULL;
- Py_ssize_t len = 0;
-
- ENTERING(asymmetric_object_pem_read_private);
-
- if (!PyArg_ParseTuple(args, "s#|s", &src, &len, &pass))
- goto error;
-
- if ((bio = BIO_new_mem_buf(src, len)) == NULL)
- lose_no_memory();
-
- result = asymmetric_object_pem_read_private_helper(type, bio, pass);
-
- error:
- BIO_free(bio);
- return result;
-}
-
-static char asymmetric_object_pem_read_private_file__doc__[] =
- "Read a PEM-encoded private key from a file.\n"
- "\n"
- "Optional second argument is a passphrase for the key.\n"
- ;
-
-static PyObject *
-asymmetric_object_pem_read_private_file(PyTypeObject *type, PyObject *args)
-{
- const char *filename = NULL;
- PyObject *result = NULL;
- char *pass = NULL;
- BIO *bio = NULL;
-
- ENTERING(asymmetric_object_pem_read_private_file);
-
- if (!PyArg_ParseTuple(args, "s|s", &filename, &pass))
- goto error;
-
- if ((bio = BIO_new_file(filename, "rb")) == NULL)
- lose_openssl_error("Could not open file");
-
- result = asymmetric_object_pem_read_private_helper(type, bio, pass);
-
- error:
- BIO_free(bio);
- return result;
-}
-
-static PyObject *
-asymmetric_object_der_read_private_helper(PyTypeObject *type, BIO *bio)
-{
- asymmetric_object *self = NULL;
-
- ENTERING(asymmetric_object_der_read_private_helper);
-
- if ((self = (asymmetric_object *) asymmetric_object_new(type, NULL, NULL)) == NULL)
- goto error;
-
- if (!d2i_PrivateKey_bio(bio, &self->pkey))
- lose_openssl_error("Couldn't load private key");
-
- return (PyObject *) self;
-
- error:
-
- Py_XDECREF(self);
- return NULL;
-}
-
-static char asymmetric_object_der_read_private__doc__[] =
- "Read a DER-encoded private key from a string.\n"
- ;
-
-static PyObject *
-asymmetric_object_der_read_private(PyTypeObject *type, PyObject *args)
-{
- ENTERING(asymmetric_object_der_read_private);
- return read_from_string_helper(asymmetric_object_der_read_private_helper, type, args);
-}
-
-static char asymmetric_object_der_read_private_file__doc__[] =
- "Read a DER-encoded private key from a file.\n"
- ;
-
-static PyObject *
-asymmetric_object_der_read_private_file(PyTypeObject *type, PyObject *args)
-{
- ENTERING(asymmetric_object_der_read_private_file);
- return read_from_file_helper(asymmetric_object_der_read_private_helper, type, args);
-}
-
-static PyObject *
-asymmetric_object_pem_read_public_helper(PyTypeObject *type, BIO *bio)
-{
- asymmetric_object *self = NULL;
-
- ENTERING(asymmetric_object_pem_read_public_helper);
-
- if ((self = (asymmetric_object *) asymmetric_object_new(type, NULL, NULL)) == NULL)
- goto error;
-
- if (!PEM_read_bio_PUBKEY(bio, &self->pkey, NULL, NULL))
- lose_openssl_error("Couldn't load public key");
-
- return (PyObject *) self;
-
- error:
- Py_XDECREF(self);
- return NULL;
-}
-
-static PyObject *
-asymmetric_object_der_read_public_helper(PyTypeObject *type, BIO *bio)
-{
- asymmetric_object *self = NULL;
-
- ENTERING(asymmetric_object_der_read_public_helper);
-
- if ((self = (asymmetric_object *) asymmetric_object_new(type, NULL, NULL)) == NULL)
- goto error;
-
- if (!d2i_PUBKEY_bio(bio, &self->pkey))
- lose_openssl_error("Couldn't load public key");
-
- return (PyObject *) self;
-
- error:
-
- Py_XDECREF(self);
- return NULL;
-}
-
-static char asymmetric_object_pem_read_public__doc__[] =
- "Read a PEM-encoded public key from a string.\n"
- ;
-
-static PyObject *
-asymmetric_object_pem_read_public(PyTypeObject *type, PyObject *args)
-{
- ENTERING(asymmetric_object_pem_read_public);
- return read_from_string_helper(asymmetric_object_pem_read_public_helper, type, args);
-}
-
-static char asymmetric_object_pem_read_public_file__doc__[] =
- "Read a PEM-encoded public key from a file.\n"
- ;
-
-static PyObject *
-asymmetric_object_pem_read_public_file(PyTypeObject *type, PyObject *args)
-{
- ENTERING(asymmetric_object_pem_read_public_file);
- return read_from_file_helper(asymmetric_object_pem_read_public_helper, type, args);
-}
-
-static char asymmetric_object_der_read_public__doc__[] =
- "Read a DER-encoded public key from a string.\n"
- ;
-
-static PyObject *
-asymmetric_object_der_read_public(PyTypeObject *type, PyObject *args)
-{
- ENTERING(asymmetric_object_der_read_public);
- return read_from_string_helper(asymmetric_object_der_read_public_helper, type, args);
-}
-
-static char asymmetric_object_der_read_public_file__doc__[] =
- "Read a DER-encoded public key from a file.\n"
- ;
-
-static PyObject *
-asymmetric_object_der_read_public_file(PyTypeObject *type, PyObject *args)
-{
- ENTERING(asymmetric_object_der_read_public_file);
- return read_from_file_helper(asymmetric_object_der_read_public_helper, type, args);
-}
-
-static char asymmetric_object_pem_write_private__doc__[] =
- "Return the PEM encoding of an \"Asymmetric\" private key.\n"
- "\n"
- "This method takes an optional parameter \"passphrase\" which, if\n"
- "specified, will be used to encrypt the private key with AES-256-CBC.\n"
- "\n"
- "If you don't specify a passphrase, the key will not be encrypted.\n"
- ;
-
-static PyObject *
-asymmetric_object_pem_write_private(asymmetric_object *self, PyObject *args)
-{
- PyObject *result = NULL;
- char *passphrase = NULL;
- const EVP_CIPHER *evp_method = NULL;
- BIO *bio = NULL;
-
- ENTERING(asymmetric_object_pem_write_private);
-
- if (!PyArg_ParseTuple(args, "|s", &passphrase))
- goto error;
-
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
- lose_no_memory();
-
- if (passphrase)
- evp_method = EVP_aes_256_cbc();
-
- if (!PEM_write_bio_PrivateKey(bio, self->pkey, evp_method, NULL, 0, NULL, passphrase))
- lose_openssl_error("Unable to write key");
-
- result = BIO_to_PyString_helper(bio);
-
- error: /* Fall through */
- BIO_free(bio);
- return result;
-}
-
-static char asymmetric_object_pem_write_public__doc__[] =
- "Return the PEM encoding of an \"Asymmetric\" public key.\n"
- ;
-
-static PyObject *
-asymmetric_object_pem_write_public(asymmetric_object *self)
-{
- PyObject *result = NULL;
- BIO *bio = NULL;
-
- ENTERING(asymmetric_object_pem_write_public);
-
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
- lose_no_memory();
-
- if (!PEM_write_bio_PUBKEY(bio, self->pkey))
- lose_openssl_error("Unable to write key");
-
- result = BIO_to_PyString_helper(bio);
-
- error: /* Fall through */
- BIO_free(bio);
- return result;
-}
-
-static char asymmetric_object_der_write_private__doc__[] =
- "Return the DER encoding of an \"Asymmetric\" private key.\n"
- ;
-
-static PyObject *
-asymmetric_object_der_write_private(asymmetric_object *self)
-{
- PyObject *result = NULL;
- BIO *bio = NULL;
-
- ENTERING(asymmetric_object_der_write_private);
-
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
- lose_no_memory();
-
- if (!i2d_PrivateKey_bio(bio, self->pkey))
- lose_openssl_error("Unable to write private key");
-
- result = BIO_to_PyString_helper(bio);
-
- error: /* Fall through */
- BIO_free(bio);
- return result;
-}
-
-static char asymmetric_object_der_write_public__doc__[] =
- "Return the DER encoding of an \"Asymmetric\" public key.\n"
- ;
-
-static PyObject *
-asymmetric_object_der_write_public(asymmetric_object *self)
-{
- PyObject *result = NULL;
- BIO *bio = NULL;
-
- ENTERING(asymmetric_object_der_write_public);
-
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
- lose_no_memory();
-
- if (!i2d_PUBKEY_bio(bio, self->pkey))
- lose_openssl_error("Unable to write public key");
-
- result = BIO_to_PyString_helper(bio);
-
- error: /* Fall through */
- BIO_free(bio);
- return result;
-}
-
-static char asymmetric_object_generate_rsa__doc__[] =
- "Generate a new RSA keypair.\n"
- "\n"
- "Optional argument key_size is the desired key size, in bits;\n"
- "if not specified, the default is 2048."
- ;
-
-static PyObject *
-asymmetric_object_generate_rsa(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- static char *kwlist[] = {"key_size", NULL};
- asymmetric_object *self = NULL;
- EVP_PKEY_CTX *ctx = NULL;
- int key_size = 2048;
- int ok = 0;
-
- ENTERING(asymmetric_object_generate_rsa);
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &key_size))
- goto error;
-
- if ((self = (asymmetric_object *) asymmetric_object_new(type, NULL, NULL)) == NULL)
- goto error;
-
- /*
- * Explictly setting RSA_F4 would be tedious, as it requires messing
- * about with bignums, and F4 is the default, so we leave it alone.
- * In case this ever changes, the required sequence would be:
- * BN_new(), BN_set_word(), EVP_PKEY_CTX_set_rsa_keygen_pubexp(),
- * BN_free().
- */
-
- if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL ||
- EVP_PKEY_keygen_init(ctx) <= 0 ||
- EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, key_size) <= 0 ||
- EVP_PKEY_keygen(ctx, &self->pkey) <= 0)
- lose_openssl_error("Couldn't generate new RSA key");
-
- ok = 1;
-
- error:
- EVP_PKEY_CTX_free(ctx);
-
- if (ok)
- return (PyObject *) self;
-
- Py_XDECREF(self);
- return NULL;
-}
-
-static char asymmetric_object_generate_from_params__doc__[] =
- "Generate a new keypair using an AsymmetricParams object.\n"
- ;
-
-static PyObject *
-asymmetric_object_generate_from_params(PyTypeObject *type, PyObject *args)
-{
- asymmetric_params_object *params = NULL;
- asymmetric_object *self = NULL;
- EVP_PKEY_CTX *ctx = NULL;
- int ok = 0;
-
- ENTERING(asymmetric_object_generate_from_params);
-
- if (!PyArg_ParseTuple(args, "O!", &POW_AsymmetricParams_Type, &params))
- goto error;
-
- if ((self = (asymmetric_object *) asymmetric_object_new(type, NULL, NULL)) == NULL)
- goto error;
-
- if ((ctx = EVP_PKEY_CTX_new(params->pkey, NULL)) == NULL ||
- EVP_PKEY_keygen_init(ctx) <= 0 ||
- EVP_PKEY_keygen(ctx, &self->pkey) <= 0)
- lose_openssl_error("Couldn't generate new key");
-
- ok = 1;
-
- error:
- EVP_PKEY_CTX_free(ctx);
-
- if (ok)
- return (PyObject *) self;
-
- Py_XDECREF(self);
- return NULL;
-}
-
-static char asymmetric_object_calculate_ski__doc__[] =
- "Calculate SKI value for this key.\n"
- "\n"
- "The SKI is the SHA-1 hash of key's SubjectPublicKey value.\n"
- ;
-
-static PyObject *
-asymmetric_object_calculate_ski(asymmetric_object *self)
-{
- PyObject *result = NULL;
- X509_PUBKEY *pubkey = NULL;
- unsigned char digest[EVP_MAX_MD_SIZE];
- unsigned digest_length;
-
- ENTERING(asymmetric_object_calculate_ski);
-
- if (!X509_PUBKEY_set(&pubkey, self->pkey))
- lose_openssl_error("Couldn't extract public key");
-
- if (!EVP_Digest(pubkey->public_key->data, pubkey->public_key->length,
- digest, &digest_length, EVP_sha1(), NULL))
- lose_openssl_error("Couldn't calculate SHA-1 digest of public key");
-
- result = PyString_FromStringAndSize((char *) digest, digest_length);
-
- error:
- X509_PUBKEY_free(pubkey);
- return result;
-}
-
-static struct PyMethodDef asymmetric_object_methods[] = {
- Define_Method(pemWritePrivate, asymmetric_object_pem_write_private, METH_VARARGS),
- Define_Method(pemWritePublic, asymmetric_object_pem_write_public, METH_NOARGS),
- Define_Method(derWritePrivate, asymmetric_object_der_write_private, METH_NOARGS),
- Define_Method(derWritePublic, asymmetric_object_der_write_public, METH_NOARGS),
- Define_Method(calculateSKI, asymmetric_object_calculate_ski, METH_NOARGS),
- Define_Class_Method(pemReadPublic, asymmetric_object_pem_read_public, METH_VARARGS),
- Define_Class_Method(pemReadPublicFile, asymmetric_object_pem_read_public_file, METH_VARARGS),
- Define_Class_Method(derReadPublic, asymmetric_object_der_read_public, METH_VARARGS),
- Define_Class_Method(derReadPublicFile, asymmetric_object_der_read_public_file, METH_VARARGS),
- Define_Class_Method(pemReadPrivate, asymmetric_object_pem_read_private, METH_VARARGS),
- Define_Class_Method(pemReadPrivateFile, asymmetric_object_pem_read_private_file, METH_VARARGS),
- Define_Class_Method(derReadPrivate, asymmetric_object_der_read_private, METH_VARARGS),
- Define_Class_Method(derReadPrivateFile, asymmetric_object_der_read_private_file, METH_VARARGS),
- Define_Class_Method(generateRSA, asymmetric_object_generate_rsa, METH_KEYWORDS),
- Define_Class_Method(generateFromParams, asymmetric_object_generate_from_params, METH_VARARGS),
- {NULL}
-};
-
-static char POW_Asymmetric_Type__doc__[] =
- "Container for OpenSSL's EVP_PKEY asymmetric key classes.\n"
- "\n"
- LAME_DISCLAIMER_IN_ALL_CLASS_DOCUMENTATION
- ;
-
-static PyTypeObject POW_Asymmetric_Type = {
- PyObject_HEAD_INIT(0)
- 0, /* ob_size */
- "rpki.POW.Asymmetric", /* tp_name */
- sizeof(asymmetric_object), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor)asymmetric_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 */
- POW_Asymmetric_Type__doc__, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- asymmetric_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) asymmetric_object_init, /* tp_init */
- 0, /* tp_alloc */
- asymmetric_object_new, /* tp_new */
-};
-
-
-
-/*
- * AsymmetricParams object.
- */
-
-static PyObject *
-asymmetric_params_object_new(PyTypeObject *type, GCC_UNUSED PyObject *args, GCC_UNUSED PyObject *kwds)
-{
- asymmetric_params_object *self = NULL;
-
- ENTERING(asymmetric_params_object_new);
-
- if ((self = (asymmetric_params_object *) type->tp_alloc(type, 0)) == NULL)
- goto error;
-
- self->pkey = NULL;
-
- return (PyObject *) self;
-
- error:
-
- Py_XDECREF(self);
- return NULL;
-}
-
-static int
-asymmetric_params_object_init(asymmetric_params_object *self, PyObject *args, PyObject *kwds)
-{
- static char *kwlist[] = {NULL};
-
- ENTERING(asymmetric_params_object_init);
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist))
- goto error;
-
- return 0;
-
- error:
- return -1;
-}
-
-static void
-asymmetric_params_object_dealloc(asymmetric_params_object *self)
-{
- ENTERING(asymmetric_params_object_dealloc);
- EVP_PKEY_free(self->pkey);
- self->ob_type->tp_free((PyObject*) self);
-}
-
-static PyObject *
-asymmetric_params_object_pem_read_helper(PyTypeObject *type, BIO *bio)
-{
- asymmetric_params_object *self = NULL;
-
- ENTERING(asymmetric_params_object_pem_read_helper);
-
- if ((self = (asymmetric_params_object *) asymmetric_params_object_new(type, NULL, NULL)) == NULL)
- goto error;
-
- if (!PEM_read_bio_Parameters(bio, &self->pkey))
- lose_openssl_error("Couldn't load PEM encoded key parameters");
-
- return (PyObject *) self;
-
- error:
-
- Py_XDECREF(self);
- return NULL;
-}
-
-static char asymmetric_params_object_pem_read__doc__[] =
- "Read PEM-encoded key parameters from a string.\n"
- ;
-
-static PyObject *
-asymmetric_params_object_pem_read(PyTypeObject *type, PyObject *args)
-{
- ENTERING(asymmetric_params_object_pem_read);
- return read_from_string_helper(asymmetric_params_object_pem_read_helper, type, args);
-}
-
-static char asymmetric_params_object_pem_read_file__doc__[] =
- "Read PEM-encoded key parameters from a file.\n"
- ;
-
-static PyObject *
-asymmetric_params_object_pem_read_file(PyTypeObject *type, PyObject *args)
-{
- ENTERING(asymmetric_params_object_pem_read_file);
- return read_from_file_helper(asymmetric_params_object_pem_read_helper, type, args);
-}
-
-static char asymmetric_params_object_pem_write__doc__[] =
- "Return the PEM encoding of this set of key parameters, as a string.\n"
- ;
-
-static PyObject *
-asymmetric_params_object_pem_write(asymmetric_params_object *self)
-{
- PyObject *result = NULL;
- BIO *bio = NULL;
-
- ENTERING(asymmetric_params_object_pem_write);
-
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
- lose_no_memory();
-
- if (PEM_write_bio_Parameters(bio, self->pkey) <= 0)
- lose_openssl_error("Unable to write key parameters");
-
- result = BIO_to_PyString_helper(bio);
-
- error: /* Fall through */
- BIO_free(bio);
- return result;
-}
-
-static char asymmetric_params_object_generate_ec__doc__[] =
- "Generate a new set of EC parameters.\n"
- "\n"
- "Optional argument curve is a numeric code representing the curve to use;\n"
- "if not specified, the default is P-256."
- ;
-
-static PyObject *
-asymmetric_params_object_generate_ec(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- static char *kwlist[] = {"curve", NULL};
- asymmetric_params_object *self = NULL;
- EVP_PKEY_CTX *ctx = NULL;
- int curve = NID_X9_62_prime256v1;
- int ok = 0;
-
- ENTERING(asymmetric_params_object_generate_ec);
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &curve))
- goto error;
-
- if ((self = (asymmetric_params_object *) asymmetric_params_object_new(type, NULL, NULL)) == NULL)
- goto error;
-
- if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) == NULL ||
- EVP_PKEY_paramgen_init(ctx) <= 0 ||
- EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, curve) <= 0 ||
- EVP_PKEY_paramgen(ctx, &self->pkey) <= 0)
- lose_openssl_error("Couldn't generate key parameters");
-
- ok = 1;
-
- error:
- EVP_PKEY_CTX_free(ctx);
-
- if (ok)
- return (PyObject *) self;
-
- Py_XDECREF(self);
- return NULL;
-}
-
-static char asymmetric_params_object_generate_dh__doc__[] =
- "Generate a new set of DH parameters.\n"
- "\n"
- "Optional argument prime_length is length of the DH prime parameter\n"
- "to use, in bits; if not specified, the default is 2048 bits.\n"
- "\n"
- "Be warned that generating DH parameters with a 2048-bit prime may\n"
- "take a ridiculously long time.\n"
- ;
-
-static PyObject *
-asymmetric_params_object_generate_dh(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- static char *kwlist[] = {"prime_length", NULL};
- asymmetric_params_object *self = NULL;
- EVP_PKEY_CTX *ctx = NULL;
- int prime_length = 2048;
- int ok = 0;
-
- ENTERING(asymmetric_params_object_generate_dh);
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &prime_length))
- goto error;
-
- if ((self = (asymmetric_params_object *) asymmetric_params_object_new(type, NULL, NULL)) == NULL)
- goto error;
-
- if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, NULL)) == NULL ||
- EVP_PKEY_paramgen_init(ctx) <= 0 ||
- EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, prime_length) <= 0 ||
- EVP_PKEY_paramgen(ctx, &self->pkey) <= 0)
- lose_openssl_error("Couldn't generate key parameters");
-
- ok = 1;
-
- error:
- EVP_PKEY_CTX_free(ctx);
-
- if (ok)
- return (PyObject *) self;
-
- Py_XDECREF(self);
- return NULL;
-}
-
-static char asymmetric_params_object_generate_dsa__doc__[] =
- "Generate a new set of DSA parameters.\n"
- "\n"
- "Optional argument key_length is the length of the key to generate, in bits;\n"
- "if not specified, the default is 2048 bits."
- ;
-
-static PyObject *
-asymmetric_params_object_generate_dsa(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- static char *kwlist[] = {"key_length", NULL};
- asymmetric_params_object *self = NULL;
- EVP_PKEY_CTX *ctx = NULL;
- int key_length = 2048;
- int ok = 0;
-
- ENTERING(asymmetric_params_object_generate_dsa);
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &key_length))
- goto error;
-
- if ((self = (asymmetric_params_object *) asymmetric_params_object_new(type, NULL, NULL)) == NULL)
- goto error;
-
- if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL)) == NULL ||
- EVP_PKEY_paramgen_init(ctx) <= 0 ||
- EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, key_length) <= 0 ||
- EVP_PKEY_paramgen(ctx, &self->pkey) <= 0)
- lose_openssl_error("Couldn't generate key parameters");
-
- ok = 1;
-
- error:
- EVP_PKEY_CTX_free(ctx);
-
- if (ok)
- return (PyObject *) self;
-
- Py_XDECREF(self);
- return NULL;
-}
-
-static struct PyMethodDef asymmetric_params_object_methods[] = {
- Define_Method(pemWrite, asymmetric_params_object_pem_write, METH_NOARGS),
- Define_Class_Method(pemRead, asymmetric_params_object_pem_read, METH_VARARGS),
- Define_Class_Method(pemReadFile, asymmetric_params_object_pem_read_file, METH_VARARGS),
- Define_Class_Method(generateEC, asymmetric_params_object_generate_ec, METH_KEYWORDS),
- Define_Class_Method(generateDH, asymmetric_params_object_generate_dh, METH_KEYWORDS),
- Define_Class_Method(generateDSA, asymmetric_params_object_generate_dsa, METH_KEYWORDS),
- {NULL}
-};
-
-static char POW_AsymmetricParams_Type__doc__[] =
- "Container for OpenSSL's EVP_PKEY asymmetric key parameter classes.\n"
- "\n"
- LAME_DISCLAIMER_IN_ALL_CLASS_DOCUMENTATION
- ;
-
-static PyTypeObject POW_AsymmetricParams_Type = {
- PyObject_HEAD_INIT(0)
- 0, /* ob_size */
- "rpki.POW.AsymmetricParams", /* tp_name */
- sizeof(asymmetric_params_object), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor)asymmetric_params_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 */
- POW_AsymmetricParams_Type__doc__, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- asymmetric_params_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) asymmetric_params_object_init, /* tp_init */
- 0, /* tp_alloc */
- asymmetric_params_object_new, /* tp_new */
-};
-
-
-
-/*
- * Digest object.
- */
-
-static PyObject *
-digest_object_new(PyTypeObject *type, GCC_UNUSED PyObject *args, GCC_UNUSED PyObject *kwds)
-{
- digest_object *self = NULL;
-
- ENTERING(digest_object_new);
-
- if ((self = (digest_object *) type->tp_alloc(type, 0)) == NULL)
- goto error;
-
- self->digest_type = 0;
-
- return (PyObject *) self;
-
- error:
- return NULL;
-}
-
-static int
-digest_object_init(digest_object *self, PyObject *args, PyObject *kwds)
-{
- static char *kwlist[] = {"digest_type", NULL};
- const EVP_MD *digest_method = NULL;
- int digest_type = 0;
-
- ENTERING(digest_object_init);
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &digest_type))
- goto error;
-
- if ((digest_method = evp_digest_factory(digest_type)) == NULL)
- lose("Unsupported digest algorithm");
-
- self->digest_type = digest_type;
- if (!EVP_DigestInit(&self->digest_ctx, digest_method))
- lose_openssl_error("Couldn't initialize digest");
-
- return 0;
-
- error:
- return -1;
-}
-
-static void
-digest_object_dealloc(digest_object *self)
-{
- ENTERING(digest_object_dealloc);
- EVP_MD_CTX_cleanup(&self->digest_ctx);
- self->ob_type->tp_free((PyObject*) self);
-}
-
-static char digest_object_update__doc__[] =
- "Add data to this 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)
-{
- char *data = NULL;
- Py_ssize_t len = 0;
-
- ENTERING(digest_object_update);
-
- if (!PyArg_ParseTuple(args, "s#", &data, &len))
- goto error;
-
- if (!EVP_DigestUpdate(&self->digest_ctx, data, len))
- lose_openssl_error("EVP_DigestUpdate() failed");
-
- Py_RETURN_NONE;
-
- error:
- return NULL;
-}
-
-static char digest_object_copy__doc__[] =
- "Return a copy of this Digest object.\n"
- ;
-
-static PyObject *
-digest_object_copy(digest_object *self)
-{
- digest_object *new = NULL;
-
- ENTERING(digest_object_copy);
-
- if ((new = (digest_object *) digest_object_new(&POW_Digest_Type, NULL, NULL)) == NULL)
- goto error;
-
- new->digest_type = self->digest_type;
- if (!EVP_MD_CTX_copy(&new->digest_ctx, &self->digest_ctx))
- lose_openssl_error("Couldn't copy digest");
-
- return (PyObject*) new;
-
- error:
-
- Py_XDECREF(new);
- return NULL;
-}
-
-static char digest_object_digest__doc__[] =
- "Return the digest of all the data which this Digest object has processed.\n"
- "\n"
- "This method can be called at any time and will not effect the internal\n"
- "state 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)
-{
- unsigned char digest_text[EVP_MAX_MD_SIZE];
- EVP_MD_CTX ctx;
- unsigned digest_len = 0;
-
- ENTERING(digest_object_digest);
-
- if (!EVP_MD_CTX_copy(&ctx, &self->digest_ctx))
- lose_openssl_error("Couldn't copy digest");
-
- EVP_DigestFinal(&ctx, digest_text, &digest_len);
-
- EVP_MD_CTX_cleanup(&ctx);
-
- return Py_BuildValue("s#", digest_text, (Py_ssize_t) digest_len);
-
- error:
- return NULL;
-}
-
-static struct PyMethodDef digest_object_methods[] = {
- Define_Method(update, digest_object_update, METH_VARARGS),
- Define_Method(digest, digest_object_digest, METH_NOARGS),
- Define_Method(copy, digest_object_copy, METH_NOARGS),
- {NULL}
-};
-
-static char POW_Digest_Type__doc__[] =
- "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 POW_Digest_Type = {
- PyObject_HEAD_INIT(0)
- 0, /* ob_size */
- "rpki.POW.Digest", /* tp_name */
- sizeof(digest_object), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor)digest_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 */
- POW_Digest_Type__doc__, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- digest_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) digest_object_init, /* tp_init */
- 0, /* tp_alloc */
- digest_object_new, /* tp_new */
-};
-
-
-
-/*
- * CMS object.
- */
-
-static PyObject *
-cms_object_new(PyTypeObject *type, GCC_UNUSED PyObject *args, GCC_UNUSED PyObject *kwds)
-{
- cms_object *self;
-
- ENTERING(cms_object_new);
-
- if ((self = (cms_object *) type->tp_alloc(type, 0)) != NULL)
- return (PyObject *) self;
-
- Py_XDECREF(self);
- return NULL;
-}
-
-static void
-cms_object_dealloc(cms_object *self)
-{
- ENTERING(cms_object_dealloc);
- CMS_ContentInfo_free(self->cms);
- self->ob_type->tp_free((PyObject*) self);
-}
-
-static PyObject *
-cms_object_pem_read_helper(PyTypeObject *type, BIO *bio)
-{
- cms_object *self;
-
- ENTERING(cms_object_pem_read_helper);
-
- if ((self = (cms_object *) type->tp_new(type, NULL, NULL)) == NULL)
- goto error;
-
- if (!PEM_read_bio_CMS(bio, &self->cms, NULL, NULL))
- lose_openssl_error("Couldn't load PEM encoded CMS message");
-
- return (PyObject *) self;
-
- error:
- Py_XDECREF(self);
- return NULL;
-}
-
-static PyObject *
-cms_object_der_read_helper(PyTypeObject *type, BIO *bio)
-{
- cms_object *self;
-
- ENTERING(cms_object_der_read_helper);
-
- if ((self = (cms_object *) type->tp_new(type, NULL, NULL)) == NULL)
- goto error;
-
- if (!d2i_CMS_bio(bio, &self->cms))
- lose_openssl_error("Couldn't load DER encoded CMS message");
-
- return (PyObject *) self;
-
- error:
- Py_XDECREF(self);
- return NULL;
-}
-
-static char cms_object_pem_read__doc__[] =
- "Read a PEM-encoded CMS object from a string.\n"
- ;
-
-static PyObject *
-cms_object_pem_read(PyTypeObject *type, PyObject *args)
-{
- ENTERING(cms_object_pem_read);
- return read_from_string_helper(cms_object_pem_read_helper, type, args);
-}
-
-static char cms_object_pem_read_file__doc__[] =
- "Read a PEM-encoded CMS object from a file.\n"
- ;
-
-static PyObject *
-cms_object_pem_read_file(PyTypeObject *type, PyObject *args)
-{
- ENTERING(cms_object_pem_read_file);
- return read_from_file_helper(cms_object_pem_read_helper, type, args);
-}
-
-static char cms_object_der_read__doc__[] =
- "Read a DER-encoded CMS object from a string.\n"
- ;
-
-static PyObject *
-cms_object_der_read(PyTypeObject *type, PyObject *args)
-{
- ENTERING(cms_object_der_read);
- return read_from_string_helper(cms_object_der_read_helper, type, args);
-}
-
-static char cms_object_der_read_file__doc__[] =
- "Read a DER-encoded CMS object from a file.\n"
- ;
-
-static PyObject *
-cms_object_der_read_file(PyTypeObject *type, PyObject *args)
-{
- ENTERING(cms_object_der_read_file);
- return read_from_file_helper(cms_object_der_read_helper, type, args);
-}
-
-static char cms_object_pem_write__doc__[] =
- "Return the DER encoding of this CMS message.\n"
- ;
-
-static PyObject *
-cms_object_pem_write(cms_object *self)
-{
- PyObject *result = NULL;
- BIO *bio = NULL;
-
- ENTERING(cms_object_pem_write);
-
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
- lose_no_memory();
-
- if (!PEM_write_bio_CMS(bio, self->cms))
- lose_openssl_error("Unable to write CMS object");
-
- result = BIO_to_PyString_helper(bio);
-
- error: /* Fall through */
- BIO_free(bio);
- return result;
-}
-
-static char cms_object_der_write__doc__[] =
- "Return the DER encoding of this CMS message.\n"
- ;
-
-static PyObject *
-cms_object_der_write(cms_object *self)
-{
- PyObject *result = NULL;
- BIO *bio = NULL;
-
- ENTERING(cms_object_der_write);
-
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
- lose_no_memory();
-
- if (!i2d_CMS_bio(bio, self->cms))
- lose_openssl_error("Unable to write CMS object");
-
- result = BIO_to_PyString_helper(bio);
-
- error: /* Fall through */
- BIO_free(bio);
- return result;
-}
-
-static int
-cms_object_sign_helper(cms_object *self,
- BIO *bio,
- x509_object *signcert,
- asymmetric_object *signkey,
- PyObject *x509_iterable,
- PyObject *crl_iterable,
- char *oid,
- unsigned flags)
-{
- STACK_OF(X509) *x509_stack = NULL;
- ASN1_OBJECT *econtent_type = NULL;
- CMS_ContentInfo *cms = NULL;
- PyObject *iterator = NULL;
- PyObject *item = NULL;
- int ok = 0;
-
- ENTERING(cms_object_sign_helper);
-
- assert_no_unhandled_openssl_errors();
-
- flags &= CMS_NOCERTS | CMS_NOATTR;
- flags |= CMS_BINARY | CMS_NOSMIMECAP | CMS_PARTIAL | CMS_USE_KEYID;
-
- if ((x509_stack = x509_helper_iterable_to_stack(x509_iterable)) == NULL)
- goto error;
-
- assert_no_unhandled_openssl_errors();
-
- if (oid && (econtent_type = OBJ_txt2obj(oid, 1)) == NULL)
- lose_openssl_error("Couldn't parse OID");
-
- assert_no_unhandled_openssl_errors();
-
- if ((cms = CMS_sign(NULL, NULL, x509_stack, bio, flags)) == NULL)
- lose_openssl_error("Couldn't create CMS message");
-
- assert_no_unhandled_openssl_errors();
-
- if (econtent_type)
- CMS_set1_eContentType(cms, econtent_type);
-
- assert_no_unhandled_openssl_errors();
-
- if (!CMS_add1_signer(cms, signcert->x509, signkey->pkey, EVP_sha256(), flags))
- lose_openssl_error("Couldn't sign CMS message");
-
- assert_no_unhandled_openssl_errors();
-
- if (crl_iterable != Py_None) {
-
- if ((iterator = PyObject_GetIter(crl_iterable)) == NULL)
- goto error;
-
- while ((item = PyIter_Next(iterator)) != NULL) {
-
- if (!POW_CRL_Check(item))
- lose_type_error("Inappropriate type");
-
- if (!CMS_add1_crl(cms, ((crl_object *) item)->crl))
- lose_openssl_error("Couldn't add CRL to CMS");
-
- assert_no_unhandled_openssl_errors();
-
- Py_XDECREF(item);
- item = NULL;
- }
- }
-
- if (!CMS_final(cms, bio, NULL, flags))
- lose_openssl_error("Couldn't finalize CMS signatures");
-
- assert_no_unhandled_openssl_errors();
-
- CMS_ContentInfo_free(self->cms);
- self->cms = cms;
- cms = NULL;
-
- ok = 1;
-
- error: /* fall through */
- CMS_ContentInfo_free(cms);
- sk_X509_free(x509_stack);
- ASN1_OBJECT_free(econtent_type);
- Py_XDECREF(iterator);
- Py_XDECREF(item);
-
- return ok;
-}
-
-static char cms_object_sign__doc__[] =
- "Sign this CMS message 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 an iterable supplying X509 objects\n"
- "to be included in the signed message.\n"
- "\n"
- "The optional \"crls\" parameter should be an iterable supplying 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)
-{
- asymmetric_object *signkey = NULL;
- x509_object *signcert = NULL;
- PyObject *x509_iterable = Py_None;
- PyObject *crl_iterable = Py_None;
- char *buf = NULL, *oid = NULL;
- Py_ssize_t len;
- unsigned flags = 0;
- BIO *bio = NULL;
- int ok = 0;
-
- ENTERING(cms_object_sign);
-
- if (!PyArg_ParseTuple(args, "O!O!s#|OOsI",
- &POW_X509_Type, &signcert,
- &POW_Asymmetric_Type, &signkey,
- &buf, &len,
- &x509_iterable,
- &crl_iterable,
- &oid,
- &flags))
- goto error;
-
- assert_no_unhandled_openssl_errors();
-
- if ((bio = BIO_new_mem_buf(buf, len)) == NULL)
- lose_no_memory();
-
- assert_no_unhandled_openssl_errors();
-
- if (!cms_object_sign_helper(self, bio, signcert, signkey,
- x509_iterable, crl_iterable, oid, flags))
- lose_openssl_error("Couldn't sign CMS object");
-
- assert_no_unhandled_openssl_errors();
-
- ok = 1;
-
- error:
- BIO_free(bio);
-
- if (ok)
- Py_RETURN_NONE;
- else
- return NULL;
-}
-
-static BIO *
-cms_object_verify_helper(cms_object *self, PyObject *args, PyObject *kwds)
-{
- static char *kwlist[] = {"store", "certs", "flags", NULL};
- x509_store_object *store = NULL;
- PyObject *certs_iterable = Py_None;
- STACK_OF(X509) *certs_stack = NULL;
- unsigned flags = 0, ok = 0;
- BIO *bio = NULL;
-
- ENTERING(cms_object_verify_helper);
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|OI", kwlist,
- &POW_X509Store_Type, &store, &certs_iterable, &flags))
- goto error;
-
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
- lose_no_memory();
-
- assert_no_unhandled_openssl_errors();
-
- flags &= (CMS_NOINTERN | CMS_NOCRL | CMS_NO_SIGNER_CERT_VERIFY |
- CMS_NO_ATTR_VERIFY | CMS_NO_CONTENT_VERIFY);
-
- if (certs_iterable != Py_None &&
- (certs_stack = x509_helper_iterable_to_stack(certs_iterable)) == NULL)
- goto error;
-
- assert_no_unhandled_openssl_errors();
-
- if (CMS_verify(self->cms, certs_stack, store->store, NULL, bio, flags) <= 0)
- lose_openssl_error("Couldn't verify CMS message");
-
- assert_no_unhandled_openssl_errors();
-
- ok = 1;
-
- error: /* fall through */
- sk_X509_free(certs_stack);
-
- if (ok)
- return bio;
-
- BIO_free(bio);
- return NULL;
-}
-
-static char cms_object_verify__doc__[] =
- "Verify this CMS message against a trusted certificate 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, PyObject *kwds)
-{
- PyObject *result = NULL;
- BIO *bio = NULL;
-
- ENTERING(cms_object_verify);
-
- if ((bio = cms_object_verify_helper(self, args, kwds)) != NULL)
- result = BIO_to_PyString_helper(bio);
-
- BIO_free(bio);
- return result;
-}
-
-static char cms_object_eContentType__doc__[] =
- "Return the eContentType OID of this CMS message.\n"
- ;
-
-static PyObject *
-cms_object_eContentType(cms_object *self)
-{
- const ASN1_OBJECT *oid = NULL;
- PyObject *result = NULL;
-
- ENTERING(cms_object_eContentType);
-
- if ((oid = CMS_get0_eContentType(self->cms)) == NULL)
- lose_openssl_error("Couldn't extract eContentType from CMS message");
-
- assert_no_unhandled_openssl_errors();
-
- result = ASN1_OBJECT_to_PyString(oid);
-
- error:
- return result;
-}
-
-static char cms_object_signingTime__doc__[] =
- "Return the signingTime of this CMS message.\n"
- ;
-
-static PyObject *
-cms_object_signingTime(cms_object *self)
-{
- PyObject *result = NULL;
- STACK_OF(CMS_SignerInfo) *sis = NULL;
- CMS_SignerInfo *si = NULL;
- X509_ATTRIBUTE *xa = NULL;
- ASN1_TYPE *so = NULL;
- int i;
-
- ENTERING(cms_object_signingTime);
-
- if ((sis = CMS_get0_SignerInfos(self->cms)) == NULL)
- lose_openssl_error("Couldn't extract signerInfos from CMS message[1]");
-
- if (sk_CMS_SignerInfo_num(sis) != 1)
- lose_openssl_error("Couldn't extract signerInfos from CMS message[2]");
-
- si = sk_CMS_SignerInfo_value(sis, 0);
-
- if ((i = CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1)) < 0)
- lose_openssl_error("Couldn't extract signerInfos from CMS message[3]");
-
- if ((xa = CMS_signed_get_attr(si, i)) == NULL)
- lose_openssl_error("Couldn't extract signerInfos from CMS message[4]");
-
- if (xa->single)
- lose("Couldn't extract signerInfos from CMS message[5]");
-
- if (sk_ASN1_TYPE_num(xa->value.set) != 1)
- lose("Couldn't extract signerInfos from CMS message[6]");
-
- if ((so = sk_ASN1_TYPE_value(xa->value.set, 0)) == NULL)
- lose("Couldn't extract signerInfos from CMS message[7]");
-
- switch (so->type) {
- case V_ASN1_UTCTIME:
- result = ASN1_TIME_to_Python(so->value.utctime);
- break;
- case V_ASN1_GENERALIZEDTIME:
- result = ASN1_TIME_to_Python(so->value.generalizedtime);
- break;
- default:
- lose("Couldn't extract signerInfos from CMS message[8]");
- }
-
- error:
- return result;
-}
-
-static char cms_object_pprint__doc__[] =
- "Return a pretty-printed representation of this CMS message.\n"
- ;
-
-static PyObject *
-cms_object_pprint(cms_object *self)
-{
- BIO *bio = NULL;
- PyObject *result = NULL;
-
- ENTERING(cms_object_pprint);
-
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
- lose_no_memory();
-
- if (!CMS_ContentInfo_print_ctx(bio, self->cms, 0, NULL))
- lose_openssl_error("Unable to pretty-print CMS object");
-
- result = BIO_to_PyString_helper(bio);
-
- error:
- BIO_free(bio);
- return result;
-}
-
-static char cms_object_certs__doc__[] =
- "Return any certificates embedded in this 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)
-{
- STACK_OF(X509) *certs = NULL;
- PyObject *result = NULL;
-
- ENTERING(cms_object_certs);
-
- if ((certs = CMS_get1_certs(self->cms)) != NULL)
- result = stack_to_tuple_helper(CHECKED_PTR_OF(STACK_OF(X509), certs),
- stack_to_tuple_helper_get_x509);
- else if (!ERR_peek_error())
- result = Py_BuildValue("()");
- else
- lose_openssl_error("Couldn't extract certs from CMS message");
-
- error: /* fall through */
- sk_X509_pop_free(certs, X509_free);
- return result;
-}
-
-static char cms_object_crls__doc__[] =
- "Return any CRLs embedded in this 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)
-{
- STACK_OF(X509_CRL) *crls = NULL;
- PyObject *result = NULL;
-
- ENTERING(cms_object_crls);
-
- if ((crls = CMS_get1_crls(self->cms)) != NULL)
- result = stack_to_tuple_helper(CHECKED_PTR_OF(STACK_OF(X509_CRL), crls),
- stack_to_tuple_helper_get_crl);
- else if (!ERR_peek_error())
- result = Py_BuildValue("()");
- else
- lose_openssl_error("Couldn't extract CRLs from CMS message");
-
- error: /* fall through */
- sk_X509_CRL_pop_free(crls, X509_CRL_free);
- return result;
-}
-
-static struct PyMethodDef cms_object_methods[] = {
- 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(verify, cms_object_verify, METH_KEYWORDS),
- Define_Method(eContentType, cms_object_eContentType, METH_NOARGS),
- Define_Method(signingTime, cms_object_signingTime, METH_NOARGS),
- Define_Method(pprint, cms_object_pprint, METH_NOARGS),
- Define_Method(certs, cms_object_certs, METH_NOARGS),
- Define_Method(crls, cms_object_crls, METH_NOARGS),
- Define_Class_Method(pemRead, cms_object_pem_read, METH_VARARGS),
- Define_Class_Method(pemReadFile, cms_object_pem_read_file, METH_VARARGS),
- Define_Class_Method(derRead, cms_object_der_read, METH_VARARGS),
- Define_Class_Method(derReadFile, cms_object_der_read_file, METH_VARARGS),
- {NULL}
-};
-
-static char POW_CMS_Type__doc__[] =
- "Wrapper for OpenSSL's CMS class. At present this only handes signed\n"
- "objects, as those are the only kind of CMS objects used in RPKI.\n"
- ;
-
-static PyTypeObject POW_CMS_Type = {
- PyObject_HEAD_INIT(0)
- 0, /* ob_size */
- "rpki.POW.CMS", /* tp_name */
- sizeof(cms_object), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor)cms_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 */
- POW_CMS_Type__doc__, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- cms_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 */
- 0, /* tp_init */
- 0, /* tp_alloc */
- cms_object_new, /* tp_new */
-};
-
-
-
-/*
- * Manifest object.
- */
-
-static PyObject *
-manifest_object_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- manifest_object *self = NULL;
-
- ENTERING(manifest_object_new);
-
- if ((self = (manifest_object *) cms_object_new(type, args, kwds)) != NULL &&
- (self->manifest = Manifest_new()) != NULL)
- return (PyObject *) self;
-
- Py_XDECREF(self);
- return NULL;
-}
-
-static void
-manifest_object_dealloc(manifest_object *self)
-{
- ENTERING(manifest_object_dealloc);
- Manifest_free(self->manifest);
- cms_object_dealloc(&self->cms);
-}
-
-static char manifest_object_verify__doc__[] =
- "Verify this manifest. See the CMS class's .verify() method for details.\n"
- ;
-
-static PyObject *
-manifest_object_verify(manifest_object *self, PyObject *args, PyObject *kwds)
-{
- BIO *bio = NULL;
- int ok = 0;
-
- ENTERING(manifest_object_verify);
-
- if ((bio = cms_object_verify_helper(&self->cms, args, kwds)) == NULL)
- goto error;
-
- if (!ASN1_item_d2i_bio(ASN1_ITEM_rptr(Manifest), bio, &self->manifest))
- lose_openssl_error("Couldn't decode manifest");
-
- ok = 1;
-
- error:
- BIO_free(bio);
-
- if (ok)
- Py_RETURN_NONE;
- else
- return NULL;
-}
-
-static PyObject *
-manifest_object_der_read_helper(PyTypeObject *type, BIO *bio)
-{
- manifest_object *self;
-
- ENTERING(manifest_object_der_read_helper);
-
- if ((self = (manifest_object *) cms_object_der_read_helper(type, bio)) != NULL)
- self->manifest = NULL;
-
- return (PyObject *) self;
-}
-
-static char manifest_object_der_read__doc__[] =
- "Read a DER-encoded manifest object from a string.\n"
- ;
-
-static PyObject *
-manifest_object_der_read(PyTypeObject *type, PyObject *args)
-{
- ENTERING(manifest_object_der_read);
- return read_from_string_helper(manifest_object_der_read_helper, type, args);
-}
-
-static char manifest_object_der_read_file__doc__[] =
- "Read a DER-encoded manifest object from a file.\n"
- ;
-
-static PyObject *
-manifest_object_der_read_file(PyTypeObject *type, PyObject *args)
-{
- ENTERING(manifest_object_der_read_file);
- return read_from_file_helper(manifest_object_der_read_helper, type, args);
-}
-
-static PyObject *
-manifest_object_pem_read_helper(PyTypeObject *type, BIO *bio)
-{
- manifest_object *self;
-
- ENTERING(manifest_object_pem_read_helper);
-
- if ((self = (manifest_object *) cms_object_pem_read_helper(type, bio)) != NULL)
- self->manifest = NULL;
-
- return (PyObject *) self;
-}
-
-static char manifest_object_pem_read__doc__[] =
- "Read a PEM-encoded manifest object from a string.\n"
- ;
-
-static PyObject *
-manifest_object_pem_read(PyTypeObject *type, PyObject *args)
-{
- ENTERING(manifest_object_pem_read);
- return read_from_string_helper(manifest_object_pem_read_helper, type, args);
-}
-
-static char manifest_object_pem_read_file__doc__[] =
- "Read a PEM-encoded manifest object from a file.\n"
- ;
-
-static PyObject *
-manifest_object_pem_read_file(PyTypeObject *type, PyObject *args)
-{
- ENTERING(manifest_object_pem_read_file);
- return read_from_file_helper(manifest_object_pem_read_helper, type, args);
-}
-
-static char manifest_object_get_version__doc__[] =
- "Return the version number of this manifest.\n"
- ;
-
-static PyObject *
-manifest_object_get_version(manifest_object *self)
-{
- ENTERING(manifest_object_get_version);
-
- if (self->manifest == NULL)
- lose_not_verified("Can't report version of unverified manifest");
-
- if (self->manifest->version)
- return Py_BuildValue("N", ASN1_INTEGER_to_PyLong(self->manifest->version));
- else
- return PyInt_FromLong(0);
-
- error:
- return NULL;
-}
-
-static char manifest_object_set_version__doc__[] =
- "Set the version number of this manifest.\n"
- "\n"
- "The \"version\" parameter should be a non-negative integer.\n"
- "\n"
- "As of this writing, zero is both the default and the only defined version.\n"
- "Attempting to set any version number other than zero will fail, as we\n"
- "don't understand how to write other versions, by definition.\n"
- ;
-
-static PyObject *
-manifest_object_set_version(manifest_object *self, PyObject *args)
-{
- int version = 0;
-
- ENTERING(manifest_object_set_version);
-
- if (!PyArg_ParseTuple(args, "|i", &version))
- goto error;
-
- if (version != 0)
- lose("RFC 6486 only defines RPKI manifest version zero");
-
- if (self->manifest == NULL)
- lose_not_verified("Can't set version of unverified manifest");
-
- ASN1_INTEGER_free(self->manifest->version);
- self->manifest->version = NULL;
-
- Py_RETURN_NONE;
-
- error:
- return NULL;
-}
-
-static char manifest_object_get_manifest_number__doc__[] =
- "Return the manifestNumber of this manifest.\n"
- ;
-
-static PyObject *
-manifest_object_get_manifest_number(manifest_object *self)
-{
- ENTERING(manifest_object_get_manifest_number);
-
- if (self->manifest == NULL)
- lose_not_verified("Can't get manifestNumber of unverified manifest");
-
- return Py_BuildValue("N", ASN1_INTEGER_to_PyLong(self->manifest->manifestNumber));
-
- error:
- return NULL;
-}
-
-static char manifest_object_set_manifest_number__doc__[] =
- "Set the manifestNumber of this manifest.\n"
- "\n"
- "The \"manifestNumber\" parameter should be a non-negative integer.\n"
- ;
-
-static PyObject *
-manifest_object_set_manifest_number(manifest_object *self, PyObject *args)
-{
- PyObject *manifestNumber = NULL;
- PyObject *zero = NULL;
- int ok = 0;
-
- ENTERING(manifest_object_set_manifest_number);
-
- if (!PyArg_ParseTuple(args, "O", &manifestNumber))
- goto error;
-
- if ((zero = PyInt_FromLong(0)) == NULL)
- goto error;
-
- switch (PyObject_RichCompareBool(manifestNumber, zero, Py_GE)) {
- case -1:
- goto error;
- case 0:
- lose("Negative manifest number is not allowed");
- }
-
- if (self->manifest == NULL)
- lose_not_verified("Can't set manifestNumber of unverified manifest");
-
- ASN1_INTEGER_free(self->manifest->manifestNumber);
-
- if ((self->manifest->manifestNumber = PyLong_to_ASN1_INTEGER(manifestNumber)) == NULL)
- goto error;
-
- ok = 1;
-
- error:
- Py_XDECREF(zero);
-
- if (ok)
- Py_RETURN_NONE;
- else
- return NULL;
-}
-
-static char manifest_object_set_this_update__doc__[] =
- "Set this manifest's \"thisUpdate\" value.\n"
- "\n"
- "The \"time\" parameter should be a datetime object.\n"
- ;
-
-static PyObject *
-manifest_object_set_this_update (manifest_object *self, PyObject *args)
-{
- ASN1_TIME *t = NULL;
- PyObject *o = NULL;
-
- ENTERING(manifest_object_set_this_update);
-
- if (!PyArg_ParseTuple(args, "O", &o))
- goto error;
-
- if (self->manifest == NULL)
- lose_not_verified("Can't set thisUpdate value of unverified manifest");
-
- if ((t = Python_to_ASN1_TIME(o, 0)) == NULL)
- lose("Couldn't convert thisUpdate string");
-
- ASN1_TIME_free(self->manifest->thisUpdate);
- self->manifest->thisUpdate = t;
- Py_RETURN_NONE;
-
- error:
- ASN1_TIME_free(t);
- return NULL;
-}
-
-static char manifest_object_get_this_update__doc__[] =
- "Return this manifest's \"thisUpdate\" value as a datetime.\n"
- ;
-
-static PyObject *
-manifest_object_get_this_update (manifest_object *self)
-{
- ENTERING(manifest_object_get_this_update);
-
- if (self->manifest == NULL)
- lose_not_verified("Can't get thisUpdate value of unverified manifest");
-
- return ASN1_TIME_to_Python(self->manifest->thisUpdate);
-
- error:
- return NULL;
-}
-
-static char manifest_object_set_next_update__doc__[] =
- "Set this manifest's \"nextUpdate\" value.\n"
- "\n"
- "The \"time\" parameter should be a datetime object.\n"
- ;
-
-static PyObject *
-manifest_object_set_next_update (manifest_object *self, PyObject *args)
-{
- ASN1_TIME *t = NULL;
- PyObject *o = NULL;
-
- ENTERING(manifest_object_set_next_update);
-
- if (!PyArg_ParseTuple(args, "O", &o))
- goto error;
-
- if (self->manifest == NULL)
- lose_not_verified("Can't set nextUpdate value of unverified manifest");
-
- if ((t = Python_to_ASN1_TIME(o, 0)) == NULL)
- lose("Couldn't parse nextUpdate string");
-
- ASN1_TIME_free(self->manifest->nextUpdate);
- self->manifest->nextUpdate = t;
- Py_RETURN_NONE;
-
- error:
- ASN1_TIME_free(t);
- return NULL;
-}
-
-static char manifest_object_get_next_update__doc__[] =
- "Return this manifest's \"nextUpdate\" value as a datetime.\n"
- ;
-
-static PyObject *
-manifest_object_get_next_update (manifest_object *self)
-{
- ENTERING(manifest_object_get_next_update);
-
- if (self->manifest == NULL)
- lose_not_verified("Can't extract nextUpdate value of unverified manifest");
-
- return ASN1_TIME_to_Python(self->manifest->nextUpdate);
-
- error:
- return NULL;
-}
-
-static char manifest_object_get_algorithm__doc__[] =
- "Return this manifest's fileHashAlg OID.\n"
- ;
-
-static PyObject *
-manifest_object_get_algorithm(manifest_object *self)
-{
- PyObject *result = NULL;
-
- ENTERING(manifest_object_get_algorithm);
-
- if (self->manifest == NULL)
- lose_not_verified("Can't extract algorithm OID of unverified manifest");
-
- result = ASN1_OBJECT_to_PyString(self->manifest->fileHashAlg);
-
- error:
- return result;
-}
-
-static char manifest_object_set_algorithm__doc__[] =
- "Set this manifest's fileHashAlg OID.\n"
- ;
-
-static PyObject *
-manifest_object_set_algorithm(manifest_object *self, PyObject *args)
-{
- ASN1_OBJECT *oid = NULL;
- const char *s = NULL;
-
- ENTERING(manifest_object_set_algorithm);
-
- if (!PyArg_ParseTuple(args, "s", &s))
- goto error;
-
- if (self->manifest == NULL)
- lose_not_verified("Can't set algorithm OID for unverified manifest");
-
- if ((oid = OBJ_txt2obj(s, 1)) == NULL)
- lose_no_memory();
-
- ASN1_OBJECT_free(self->manifest->fileHashAlg);
- self->manifest->fileHashAlg = oid;
- Py_RETURN_NONE;
-
- error:
- ASN1_OBJECT_free(oid);
- return NULL;
-}
-
-static char manifest_object_add_files__doc__[] =
- "Add a collection of <filename, hash> pairs to this manifest.\n"
- "\n"
- "The \"iterable\" parameter should be an iterable object supplying\n"
- "returning two-element sequences; the first element of each sequence\n"
- "should be the filename (a text string), the second element should be the\n"
- "hash (a binary string).\n"
- ;
-
-static PyObject *
-manifest_object_add_files(manifest_object *self, PyObject *args)
-{
- PyObject *iterable = NULL;
- PyObject *iterator = NULL;
- PyObject *item = NULL;
- PyObject *fast = NULL;
- FileAndHash *fah = NULL;
- char *file = NULL;
- char *hash = NULL;
- Py_ssize_t filelen, hashlen;
- int ok = 0;
-
- ENTERING(manifest_object_add_files);
-
- if (self->manifest == NULL)
- lose_not_verified("Can't add files to unverified manifest");
-
- if (!PyArg_ParseTuple(args, "O", &iterable) ||
- (iterator = PyObject_GetIter(iterable)) == NULL)
- goto error;
-
- while ((item = PyIter_Next(iterator)) != NULL) {
-
- if ((fast = PySequence_Fast(item, "FileAndHash entry must be a sequence")) == NULL)
- goto error;
-
- if (PySequence_Fast_GET_SIZE(fast) != 2)
- lose_type_error("FileAndHash entry must be two-element sequence");
-
- if (PyString_AsStringAndSize(PySequence_Fast_GET_ITEM(fast, 0), &file, &filelen) < 0 ||
- PyString_AsStringAndSize(PySequence_Fast_GET_ITEM(fast, 1), &hash, &hashlen) < 0)
- goto error;
-
- if ((fah = FileAndHash_new()) == NULL ||
- !ASN1_OCTET_STRING_set(fah->file, (unsigned char *) file, filelen) ||
- !ASN1_BIT_STRING_set(fah->hash, (unsigned char *) hash, hashlen) ||
- !sk_FileAndHash_push(self->manifest->fileList, fah))
- lose_no_memory();
-
- fah->hash->flags &= ~7;
- fah->hash->flags |= ASN1_STRING_FLAG_BITS_LEFT;
-
- fah = NULL;
- Py_XDECREF(item);
- Py_XDECREF(fast);
- item = fast = NULL;
- }
-
- ok = 1;
-
- error:
- Py_XDECREF(iterator);
- Py_XDECREF(item);
- Py_XDECREF(fast);
- FileAndHash_free(fah);
-
- if (ok)
- Py_RETURN_NONE;
- else
- return NULL;
-}
-
-static char manifest_object_get_files__doc__[] =
- "Return a tuple of <filename, hash> pairs representing the contents of\n"
- "this manifest.\n"
- ;
-
-static PyObject *
-manifest_object_get_files(manifest_object *self)
-{
- PyObject *result = NULL;
- PyObject *item = NULL;
- int i;
-
- ENTERING(manifest_object_get_files);
-
- if (self->manifest == NULL)
- lose_not_verified("Can't get files from unverified manifest");
-
- if (self->manifest->fileList == NULL)
- lose("Inexplicable NULL manifest fileList pointer");
-
- if ((result = PyTuple_New(sk_FileAndHash_num(self->manifest->fileList))) == NULL)
- goto error;
-
- for (i = 0; i < sk_FileAndHash_num(self->manifest->fileList); i++) {
- FileAndHash *fah = sk_FileAndHash_value(self->manifest->fileList, i);
-
- item = Py_BuildValue("(s#s#)",
- ASN1_STRING_data(fah->file),
- (Py_ssize_t) ASN1_STRING_length(fah->file),
- ASN1_STRING_data(fah->hash),
- (Py_ssize_t) ASN1_STRING_length(fah->hash));
- if (item == NULL)
- goto error;
-
- PyTuple_SET_ITEM(result, i, item);
- item = NULL;
- }
-
- return result;
-
- error:
- Py_XDECREF(result);
- Py_XDECREF(item);
- return NULL;
-}
-
-static char manifest_object_sign__doc__[] =
- "Sign this manifest. See the CMS class's .sign() method for details.\n"
- ;
-
-static PyObject *
-manifest_object_sign(manifest_object *self, PyObject *args)
-{
- asymmetric_object *signkey = NULL;
- x509_object *signcert = NULL;
- PyObject *x509_iterable = Py_None;
- PyObject *crl_iterable = Py_None;
- char *oid = NULL;
- unsigned flags = 0;
- BIO *bio = NULL;
- int ok = 0;
-
- ENTERING(manifest_object_sign);
-
- if (!PyArg_ParseTuple(args, "O!O!|OOsI",
- &POW_X509_Type, &signcert,
- &POW_Asymmetric_Type, &signkey,
- &x509_iterable,
- &crl_iterable,
- &oid,
- &flags))
- goto error;
-
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
- lose_no_memory();
-
- assert_no_unhandled_openssl_errors();
-
- if (!ASN1_item_i2d_bio(ASN1_ITEM_rptr(Manifest), bio, self->manifest))
- lose_openssl_error("Couldn't encode manifest");
-
- assert_no_unhandled_openssl_errors();
-
- if (!cms_object_sign_helper(&self->cms, bio, signcert, signkey,
- x509_iterable, crl_iterable, oid, flags))
- lose_openssl_error("Couldn't sign manifest");
-
- assert_no_unhandled_openssl_errors();
-
- ok = 1;
-
- error:
- BIO_free(bio);
-
- if (ok)
- Py_RETURN_NONE;
- else
- return NULL;
-}
-
-static struct PyMethodDef manifest_object_methods[] = {
- Define_Method(getVersion, manifest_object_get_version, METH_NOARGS),
- Define_Method(setVersion, manifest_object_set_version, METH_VARARGS),
- Define_Method(getManifestNumber, manifest_object_get_manifest_number, METH_NOARGS),
- Define_Method(setManifestNumber, manifest_object_set_manifest_number, METH_VARARGS),
- Define_Method(getThisUpdate, manifest_object_get_this_update, METH_NOARGS),
- Define_Method(setThisUpdate, manifest_object_set_this_update, METH_VARARGS),
- Define_Method(getNextUpdate, manifest_object_get_next_update, METH_NOARGS),
- Define_Method(setNextUpdate, manifest_object_set_next_update, METH_VARARGS),
- Define_Method(getAlgorithm, manifest_object_get_algorithm, METH_NOARGS),
- Define_Method(setAlgorithm, manifest_object_set_algorithm, METH_VARARGS),
- Define_Method(getFiles, manifest_object_get_files, METH_NOARGS),
- Define_Method(addFiles, manifest_object_add_files, METH_VARARGS),
- Define_Method(sign, manifest_object_sign, METH_VARARGS),
- Define_Method(verify, manifest_object_verify, METH_KEYWORDS),
- Define_Class_Method(pemRead, manifest_object_pem_read, METH_VARARGS),
- Define_Class_Method(pemReadFile, manifest_object_pem_read_file, METH_VARARGS),
- Define_Class_Method(derRead, manifest_object_der_read, METH_VARARGS),
- Define_Class_Method(derReadFile, manifest_object_der_read_file, METH_VARARGS),
- {NULL}
-};
-
-static char POW_Manifest_Type__doc__[] =
- "This class provides access to RPKI manifest payload.\n"
- "Most methods are inherited from or share code with the CMS class.\n"
- ;
-
-static PyTypeObject POW_Manifest_Type = {
- PyObject_HEAD_INIT(0)
- 0, /* ob_size */
- "rpki.POW.Manifest", /* tp_name */
- sizeof(manifest_object), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor)manifest_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 */
- POW_Manifest_Type__doc__, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- manifest_object_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- &POW_CMS_Type, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- manifest_object_new, /* tp_new */
-};
-
-
-
-/*
- * ROA object.
- */
-
-static PyObject *
-roa_object_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- roa_object *self = NULL;
-
- ENTERING(roa_object_new);
-
- if ((self = (roa_object *) cms_object_new(type, args, kwds)) != NULL &&
- (self->roa = ROA_new()) != NULL)
- return (PyObject *) self;
-
- Py_XDECREF(self);
- return NULL;
-}
-
-static void
-roa_object_dealloc(roa_object *self)
-{
- ENTERING(roa_object_dealloc);
- ROA_free(self->roa);
- cms_object_dealloc(&self->cms);
-}
-
-static char roa_object_verify__doc__[] =
- "Verify this ROA. See CMS.verify() for details.\n"
- ;
-
-static PyObject *
-roa_object_verify(roa_object *self, PyObject *args, PyObject *kwds)
-{
- BIO *bio = NULL;
- int ok = 0;
-
- ENTERING(roa_object_verify);
-
- if ((bio = cms_object_verify_helper(&self->cms, args, kwds)) == NULL)
- goto error;
-
- if (!ASN1_item_d2i_bio(ASN1_ITEM_rptr(ROA), bio, &self->roa))
- lose_openssl_error("Couldn't decode ROA");
-
- ok = 1;
-
- error:
- BIO_free(bio);
-
- if (ok)
- Py_RETURN_NONE;
- else
- return NULL;
-}
-
-static PyObject *
-roa_object_pem_read_helper(PyTypeObject *type, BIO *bio)
-{
- roa_object *self;
-
- ENTERING(roa_object_pem_read_helper);
-
- if ((self = (roa_object *) cms_object_pem_read_helper(type, bio)) != NULL)
- self->roa = NULL;
-
- return (PyObject *) self;
-}
-
-static PyObject *
-roa_object_der_read_helper(PyTypeObject *type, BIO *bio)
-{
- roa_object *self;
-
- ENTERING(roa_object_der_read_helper);
-
- if ((self = (roa_object *) cms_object_der_read_helper(type, bio)) != NULL)
- self->roa = NULL;
-
- return (PyObject *) self;
-}
-
-static char roa_object_pem_read__doc__[] =
- "Read a PEM-encoded ROA object from a string.\n"
- ;
-
-static PyObject *
-roa_object_pem_read(PyTypeObject *type, PyObject *args)
-{
- ENTERING(roa_object_pem_read);
- return read_from_string_helper(roa_object_pem_read_helper, type, args);
-}
-
-static char roa_object_pem_read_file__doc__[] =
- "Read a PEM-encoded ROA object from a file.\n"
- ;
-
-static PyObject *
-roa_object_pem_read_file(PyTypeObject *type, PyObject *args)
-{
- ENTERING(roa_object_pem_read_file);
- return read_from_file_helper(roa_object_pem_read_helper, type, args);
-}
-
-static char roa_object_der_read__doc__[] =
- "Read a DER-encoded ROA object from a string.\n"
- ;
-
-static PyObject *
-roa_object_der_read(PyTypeObject *type, PyObject *args)
-{
- ENTERING(roa_object_der_read);
- return read_from_string_helper(roa_object_der_read_helper, type, args);
-}
-
-static char roa_object_der_read_file__doc__[] =
- "Read a DER-encoded ROA object from a file.\n"
- ;
-
-static PyObject *
-roa_object_der_read_file(PyTypeObject *type, PyObject *args)
-{
- ENTERING(roa_object_der_read_file);
- return read_from_file_helper(roa_object_der_read_helper, type, args);
-}
-
-static char roa_object_get_version__doc__[] =
- "Return the version number of this ROA.\n"
- ;
-
-static PyObject *
-roa_object_get_version(roa_object *self)
-{
- ENTERING(roa_object_get_version);
-
- if (self->roa == NULL)
- lose_not_verified("Can't get version of unverified ROA");
-
- if (self->roa->version)
- return Py_BuildValue("N", ASN1_INTEGER_to_PyLong(self->roa->version));
- else
- return PyInt_FromLong(0);
-
- error:
- return NULL;
-}
-
-static char roa_object_set_version__doc__[] =
- "Set the version number of this ROA.\n"
- "\n"
- "The \"version\" parameter should be a non-negative integer.\n"
- "\n"
- "As of this writing, zero is both the default and the only defined version.\n"
- "Attempting to set any version number other than zero will fail, as we\n"
- "don't understand how to write other versions, by definition.\n"
- ;
-
-static PyObject *
-roa_object_set_version(roa_object *self, PyObject *args)
-{
- int version = 0;
-
- ENTERING(roa_object_set_version);
-
- if (self->roa == NULL)
- lose_not_verified("Can't set version of unverified ROA");
-
- if (!PyArg_ParseTuple(args, "|i", &version))
- goto error;
-
- if (version != 0)
- lose("RFC 6482 only defines ROA version zero");
-
- ASN1_INTEGER_free(self->roa->version);
- self->roa->version = NULL;
-
- Py_RETURN_NONE;
-
- error:
- return NULL;
-}
-
-static char roa_object_get_asid__doc__[] =
- "Return the Autonomous System ID of this ROA.\n"
- ;
-
-static PyObject *
-roa_object_get_asid(roa_object *self)
-{
- ENTERING(roa_object_get_asid);
-
- if (self->roa == NULL)
- lose_not_verified("Can't get ASN of unverified ROA");
-
- return Py_BuildValue("N", ASN1_INTEGER_to_PyLong(self->roa->asID));
-
- error:
- return NULL;
-}
-
-static char roa_object_set_asid__doc__[] =
- "Sets the Autonomous System ID of this ROA.\n"
- "\n"
- "The \"asID\" parameter should be a non-negative integer.\n"
- ;
-
-static PyObject *
-roa_object_set_asid(roa_object *self, PyObject *args)
-{
- PyObject *asID = NULL;
- PyObject *zero = NULL;
- int ok = 0;
-
- ENTERING(roa_object_set_asid);
-
- if (self->roa == NULL)
- lose_not_verified("Can't set ASN of unverified ROA");
-
- if (!PyArg_ParseTuple(args, "O", &asID))
- goto error;
-
- if ((zero = PyInt_FromLong(0)) == NULL)
- goto error;
-
- switch (PyObject_RichCompareBool(asID, zero, Py_GE)) {
- case -1:
- goto error;
- case 0:
- lose("Negative asID is not allowed");
- }
-
- ASN1_INTEGER_free(self->roa->asID);
-
- if ((self->roa->asID = PyLong_to_ASN1_INTEGER(asID)) == NULL)
- goto error;
-
- ok = 1;
-
- error:
- Py_XDECREF(zero);
-
- if (ok)
- Py_RETURN_NONE;
- else
- return NULL;
-}
-
-static char roa_object_get_prefixes__doc__[] =
- "Return this ROA's prefix list. This is a two-element\n"
- "tuple: the first element is the IPv4 prefix set, the second is the\n"
- "IPv6 prefix set.\n"
- "\n"
- "Each prefix set is either None, if there are no prefixes for this IP\n"
- "version, or a sequence of three-element tuple representing ROA prefix\n"
- "entries.\n"
- "\n"
- "Each ROA prefix entry consists of the prefix itself (an IPAddress),\n"
- "the prefix length (an integer), and the maxPrefixLen value, which is\n"
- "either an integer or None depending on whether the maxPrefixLen value\n"
- "is set for this prefix.\n"
- ;
-
-static PyObject *
-roa_object_get_prefixes(roa_object *self)
-{
- PyObject *result = NULL;
- PyObject *ipv4_result = NULL;
- PyObject *ipv6_result = NULL;
- PyObject *item = NULL;
- ipaddress_object *addr = NULL;
- int i, j;
-
- ENTERING(roa_object_get_prefixes);
-
- if (self->roa == NULL)
- lose_not_verified("Can't get prefixes from unverified ROA");
-
- for (i = 0; i < sk_ROAIPAddressFamily_num(self->roa->ipAddrBlocks); i++) {
- ROAIPAddressFamily *fam = sk_ROAIPAddressFamily_value(self->roa->ipAddrBlocks, i);
- const unsigned afi = (fam->addressFamily->data[0] << 8) | (fam->addressFamily->data[1]);
- const ipaddress_version *ip_type = NULL;
- PyObject **resultp = NULL;
-
- switch (afi) {
- case IANA_AFI_IPV4: resultp = &ipv4_result; ip_type = &ipaddress_version_4; break;
- case IANA_AFI_IPV6: resultp = &ipv6_result; ip_type = &ipaddress_version_6; break;
- default: lose_type_error("Unknown AFI");
- }
-
- if (fam->addressFamily->length > 2)
- lose_type_error("Unsupported SAFI");
-
- if (*resultp != NULL)
- lose_type_error("Duplicate ROAIPAddressFamily");
-
- if ((*resultp = PyTuple_New(sk_ROAIPAddress_num(fam->addresses))) == NULL)
- goto error;
-
- for (j = 0; j < sk_ROAIPAddress_num(fam->addresses); j++) {
- ROAIPAddress *a = sk_ROAIPAddress_value(fam->addresses, j);
- unsigned prefixlen = ((a->IPAddress)->length * 8 - ((a->IPAddress)->flags & 7));
-
- if ((addr = (ipaddress_object *) POW_IPAddress_Type.tp_alloc(&POW_IPAddress_Type, 0)) == NULL)
- goto error;
-
- addr->type = ip_type;
-
- memset(addr->address, 0, sizeof(addr->address));
-
- if ((unsigned) a->IPAddress->length > addr->type->length)
- lose("ROAIPAddress BIT STRING too long for AFI");
-
- if (a->IPAddress->length > 0) {
- memcpy(addr->address, a->IPAddress->data, a->IPAddress->length);
-
- if ((a->IPAddress->flags & 7) != 0) {
- unsigned char mask = 0xFF >> (8 - (a->IPAddress->flags & 7));
- addr->address[a->IPAddress->length - 1] &= ~mask;
- }
- }
-
- if (a->maxLength == NULL)
- item = Py_BuildValue("(NIO)", addr, prefixlen, Py_None);
- else
- item = Py_BuildValue("(NIl)", addr, prefixlen, ASN1_INTEGER_get(a->maxLength));
-
- if (item == NULL)
- goto error;
-
- PyTuple_SET_ITEM(*resultp, j, item);
- item = NULL;
- addr = NULL;
- }
- }
-
- result = Py_BuildValue("(OO)",
- (ipv4_result == NULL ? Py_None : ipv4_result),
- (ipv6_result == NULL ? Py_None : ipv6_result));
-
- error: /* Fall through */
- Py_XDECREF(addr);
- Py_XDECREF(item);
- Py_XDECREF(ipv4_result);
- Py_XDECREF(ipv6_result);
-
- return result;
-}
-
-static char roa_object_set_prefixes__doc__[] =
- "Set this ROA's prefix list.\n"
- "\n"
- "This method takes two arguments, \"ipv4\" and \"ipv6\". Each of these\n"
- "is either None, if no prefixes should be set for this IP version, or\n"
- "an iterable object returning ROA prefix entries in the same format as\n"
- "returned by the .getPrefixes() method. The maxPrefixLen value may be\n"
- "omitted (that is, the ROA prefix entry tuple may be of length two\n"
- "rather than of length three); this will be taken as equivalent to\n"
- "specifying a maxPrefixLen value of None.\n"
- ;
-
-static PyObject *
-roa_object_set_prefixes(roa_object *self, PyObject *args, PyObject *kwds)
-{
- static char *kwlist[] = {"ipv4", "ipv6", NULL};
- STACK_OF(ROAIPAddressFamily) *prefixes = NULL;
- ROAIPAddressFamily *fam = NULL;
- ROAIPAddress *a = NULL;
- PyObject *ipv4_arg = Py_None;
- PyObject *ipv6_arg = Py_None;
- PyObject *iterator = NULL;
- PyObject *item = NULL;
- PyObject *fast = NULL;
- int ok = 0;
- int v;
-
- ENTERING(roa_object_set_prefixes);
-
- if (self->roa == NULL)
- lose_not_verified("Can't set prefixes of unverified ROA");
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &ipv4_arg, &ipv6_arg))
- goto error;
-
- if ((prefixes = sk_ROAIPAddressFamily_new_null()) == NULL)
- lose_no_memory();
-
- for (v = 0; v < (int) (sizeof(ipaddress_versions)/sizeof(*ipaddress_versions)); v++) {
- const struct ipaddress_version *ip_type = ipaddress_versions[v];
- unsigned char afibuf[2];
- PyObject **argp;
-
- switch (ip_type->version) {
- case 4: argp = &ipv4_arg; break;
- case 6: argp = &ipv6_arg; break;
- default: continue;
- }
-
- if (*argp == Py_None)
- continue;
-
- afibuf[0] = (ip_type->afi >> 8) & 0xFF;
- afibuf[1] = (ip_type->afi ) & 0xFF;
-
- if ((iterator = PyObject_GetIter(*argp)) == NULL)
- goto error;
-
- while ((item = PyIter_Next(iterator)) != NULL) {
- unsigned prefixlen, maxprefixlen, bitlen, bytelen;
- ipaddress_object *addr = NULL;
- PyObject *maxlenobj = Py_None;
-
- if ((fast = PySequence_Fast(item, "ROA prefix must be a sequence")) == NULL)
- goto error;
-
- switch (PySequence_Fast_GET_SIZE(fast)) {
- case 3:
- maxlenobj = PySequence_Fast_GET_ITEM(fast, 2);
- /* Fall through */
- case 2:
- if (!POW_IPAddress_Check(PySequence_Fast_GET_ITEM(fast, 0)))
- lose_type_error("First element of ROA prefix must be an IPAddress object");
- addr = (ipaddress_object *) PySequence_Fast_GET_ITEM(fast, 0);
- prefixlen = (unsigned) PyInt_AsLong(PySequence_Fast_GET_ITEM(fast, 1));
- if (PyErr_Occurred())
- goto error;
- break;
- default:
- lose_type_error("ROA prefix must be a two- or three-element sequence");
- }
-
- if (maxlenobj == Py_None) {
- maxprefixlen = prefixlen;
- } else {
- maxprefixlen = (unsigned) PyInt_AsLong(maxlenobj);
- if (PyErr_Occurred())
- goto error;
- }
-
- if (addr->type != ip_type)
- lose_type_error("Bad ROA prefix");
-
- if (prefixlen > addr->type->length * 8)
- lose("Bad prefix length");
-
- if (maxprefixlen > addr->type->length * 8 || maxprefixlen < prefixlen)
- lose("Bad maxLength value");
-
- bytelen = (prefixlen + 7) / 8;
- bitlen = prefixlen % 8;
-
- if ((a = ROAIPAddress_new()) == NULL ||
- (a->IPAddress == NULL && (a->IPAddress = ASN1_BIT_STRING_new()) == NULL) ||
- !ASN1_BIT_STRING_set(a->IPAddress, addr->address, bytelen))
- lose_no_memory();
-
- a->IPAddress->flags &= ~7;
- a->IPAddress->flags |= ASN1_STRING_FLAG_BITS_LEFT;
- if (bitlen > 0) {
- a->IPAddress->data[bytelen - 1] &= ~(0xFF >> bitlen);
- a->IPAddress->flags |= 8 - bitlen;
- }
-
- if (prefixlen != maxprefixlen &&
- ((a->maxLength = ASN1_INTEGER_new()) == NULL ||
- !ASN1_INTEGER_set(a->maxLength, maxprefixlen)))
- lose_no_memory();
-
- if (fam == NULL &&
- ((fam = ROAIPAddressFamily_new()) == NULL ||
- !sk_ROAIPAddressFamily_push(prefixes, fam) ||
- !ASN1_OCTET_STRING_set(fam->addressFamily, afibuf, sizeof(afibuf))))
- lose_no_memory();
-
- if (!sk_ROAIPAddress_push(fam->addresses, a))
- lose_no_memory();
-
- a = NULL;
- Py_XDECREF(item);
- Py_XDECREF(fast);
- item = fast = NULL;
- }
-
- fam = NULL;
- Py_XDECREF(iterator);
- iterator = NULL;
- }
-
- sk_ROAIPAddressFamily_pop_free(self->roa->ipAddrBlocks, ROAIPAddressFamily_free);
- self->roa->ipAddrBlocks = prefixes;
- prefixes = NULL;
-
- ok = 1;
-
- error:
- sk_ROAIPAddressFamily_pop_free(prefixes, ROAIPAddressFamily_free);
- ROAIPAddressFamily_free(fam);
- ROAIPAddress_free(a);
- Py_XDECREF(iterator);
- Py_XDECREF(item);
- Py_XDECREF(fast);
-
- if (ok)
- Py_RETURN_NONE;
- else
- return NULL;
-}
-
-static char roa_object_sign__doc__[] =
- "Sign this ROA. See CMS.sign() for details.\n"
- ;
-
-static PyObject *
-roa_object_sign(roa_object *self, PyObject *args)
-{
- asymmetric_object *signkey = NULL;
- x509_object *signcert = NULL;
- PyObject *x509_iterable = Py_None;
- PyObject *crl_iterable = Py_None;
- char *oid = NULL;
- unsigned flags = 0;
- BIO *bio = NULL;
- int ok = 0;
-
- ENTERING(roa_object_sign);
-
- if (!PyArg_ParseTuple(args, "O!O!|OOsI",
- &POW_X509_Type, &signcert,
- &POW_Asymmetric_Type, &signkey,
- &x509_iterable,
- &crl_iterable,
- &oid,
- &flags))
- goto error;
-
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
- lose_no_memory();
-
- assert_no_unhandled_openssl_errors();
-
- if (!ASN1_item_i2d_bio(ASN1_ITEM_rptr(ROA), bio, self->roa))
- lose_openssl_error("Couldn't encode ROA");
-
- assert_no_unhandled_openssl_errors();
-
- if (!cms_object_sign_helper(&self->cms, bio, signcert, signkey,
- x509_iterable, crl_iterable, oid, flags))
- lose_openssl_error("Couldn't sign ROA");
-
- assert_no_unhandled_openssl_errors();
-
- ok = 1;
-
- error:
- BIO_free(bio);
-
- if (ok)
- Py_RETURN_NONE;
- else
- return NULL;
-}
-
-static struct PyMethodDef roa_object_methods[] = {
- Define_Method(getVersion, roa_object_get_version, METH_NOARGS),
- Define_Method(setVersion, roa_object_set_version, METH_VARARGS),
- Define_Method(getASID, roa_object_get_asid, METH_NOARGS),
- Define_Method(setASID, roa_object_set_asid, METH_VARARGS),
- Define_Method(getPrefixes, roa_object_get_prefixes, METH_NOARGS),
- Define_Method(setPrefixes, roa_object_set_prefixes, METH_KEYWORDS),
- Define_Method(sign, roa_object_sign, METH_VARARGS),
- Define_Method(verify, roa_object_verify, METH_KEYWORDS),
- Define_Class_Method(pemRead, roa_object_pem_read, METH_VARARGS),
- Define_Class_Method(pemReadFile, roa_object_pem_read_file, METH_VARARGS),
- Define_Class_Method(derRead, roa_object_der_read, METH_VARARGS),
- Define_Class_Method(derReadFile, roa_object_der_read_file, METH_VARARGS),
- {NULL}
-};
-
-static char POW_ROA_Type__doc__[] =
- "This class provides access to RPKI ROA payload.\n"
- "Most methods are inherited from or share code with the CMS class.\n"
- ;
-
-static PyTypeObject POW_ROA_Type = {
- PyObject_HEAD_INIT(0)
- 0, /* ob_size */
- "rpki.POW.ROA", /* tp_name */
- sizeof(roa_object), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor)roa_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 */
- POW_ROA_Type__doc__, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- roa_object_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- &POW_CMS_Type, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- roa_object_new, /* tp_new */
-};
-
-
-
-/*
- * PKCS10 object.
- */
-
-static PyObject *
-pkcs10_object_new(PyTypeObject *type, GCC_UNUSED PyObject *args, GCC_UNUSED PyObject *kwds)
-{
- pkcs10_object *self;
-
- ENTERING(pkcs10_object_new);
-
- if ((self = (pkcs10_object *) type->tp_alloc(type, 0)) != NULL &&
- (self->pkcs10 = X509_REQ_new()) != NULL &&
- (self->exts = sk_X509_EXTENSION_new_null()) != NULL)
- return (PyObject *) self;
-
- Py_XDECREF(self);
- return NULL;
-}
-
-static void
-pkcs10_object_dealloc(pkcs10_object *self)
-{
- ENTERING(pkcs10_object_dealloc);
- X509_REQ_free(self->pkcs10);
- sk_X509_EXTENSION_pop_free(self->exts, X509_EXTENSION_free);
- self->ob_type->tp_free((PyObject*) self);
-}
-
-static PyObject *
-pkcs10_object_pem_read_helper(PyTypeObject *type, BIO *bio)
-{
- pkcs10_object *self = NULL;
-
- ENTERING(pkcs10_object_pem_read_helper);
-
- assert_no_unhandled_openssl_errors();
-
- if ((self = (pkcs10_object *) pkcs10_object_new(type, NULL, NULL)) == NULL)
- goto error;
-
- assert_no_unhandled_openssl_errors();
-
- if (!PEM_read_bio_X509_REQ(bio, &self->pkcs10, NULL, NULL))
- lose_openssl_error("Couldn't load PEM encoded PKCS#10 request");
-
- sk_X509_EXTENSION_pop_free(self->exts, X509_EXTENSION_free);
- self->exts = X509_REQ_get_extensions(self->pkcs10);
-
- assert_no_unhandled_openssl_errors();
-
- return (PyObject *) self;
-
- error:
-
- Py_XDECREF(self);
- return NULL;
-}
-
-static PyObject *
-pkcs10_object_der_read_helper(PyTypeObject *type, BIO *bio)
-{
- pkcs10_object *self = NULL;
-
- ENTERING(pkcs10_object_der_read_helper);
-
- assert_no_unhandled_openssl_errors();
-
- if ((self = (pkcs10_object *) pkcs10_object_new(type, NULL, NULL)) == NULL)
- goto error;
-
- assert_no_unhandled_openssl_errors();
-
- if (!d2i_X509_REQ_bio(bio, &self->pkcs10))
- lose_openssl_error("Couldn't load DER encoded PKCS#10 request");
-
- sk_X509_EXTENSION_pop_free(self->exts, X509_EXTENSION_free);
- self->exts = X509_REQ_get_extensions(self->pkcs10);
-
- assert_no_unhandled_openssl_errors();
-
- return (PyObject *) self;
-
- error:
- Py_XDECREF(self);
- return NULL;
-}
-
-static char pkcs10_object_pem_read__doc__[] =
- "Read a PEM-encoded PKCS#10 object from a string.\n"
- ;
-
-static PyObject *
-pkcs10_object_pem_read(PyTypeObject *type, PyObject *args)
-{
- ENTERING(pkcs10_object_pem_read);
- return read_from_string_helper(pkcs10_object_pem_read_helper, type, args);
-}
-
-static char pkcs10_object_pem_read_file__doc__[] =
- "Read a PEM-encoded PKCS#10 object from a file.\n"
- ;
-
-static PyObject *
-pkcs10_object_pem_read_file(PyTypeObject *type, PyObject *args)
-{
- ENTERING(pkcs10_object_pem_read_file);
- return read_from_file_helper(pkcs10_object_pem_read_helper, type, args);
-}
-
-static char pkcs10_object_der_read__doc__[] =
- "Read a DER-encoded PKCS#10 object from a string.\n"
- ;
-
-static PyObject *
-pkcs10_object_der_read(PyTypeObject *type, PyObject *args)
-{
- ENTERING(pkcs10_object_der_read);
- return read_from_string_helper(pkcs10_object_der_read_helper, type, args);
-}
-
-static char pkcs10_object_der_read_file__doc__[] =
- "Read a DER-encoded PKCS#10 object from a file.\n"
- ;
-
-static PyObject *
-pkcs10_object_der_read_file(PyTypeObject *type, PyObject *args)
-{
- ENTERING(pkcs10_object_der_read_file);
- return read_from_file_helper(pkcs10_object_der_read_helper, type, args);
-}
-
-static char pkcs10_object_pem_write__doc__[] =
- "Returns the PEM encoding of this PKCS#10 object.\n"
- ;
-
-static PyObject *
-pkcs10_object_pem_write(pkcs10_object *self)
-{
- PyObject *result = NULL;
- BIO *bio = NULL;
-
- ENTERING(pkcs10_object_pem_write);
-
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
- lose_no_memory();
-
- if (!PEM_write_bio_X509_REQ(bio, self->pkcs10))
- lose_openssl_error("Unable to write PKCS#10 request");
-
- result = BIO_to_PyString_helper(bio);
-
- error: /* Fall through */
- BIO_free(bio);
- return result;
-}
-
-static char pkcs10_object_der_write__doc__[] =
- "Return the DER encoding of this PKCS#10 object.\n"
- ;
-
-static PyObject *
-pkcs10_object_der_write(pkcs10_object *self)
-{
- PyObject *result = NULL;
- BIO *bio = NULL;
-
- ENTERING(pkcs10_object_der_write);
-
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
- lose_no_memory();
-
- if (!i2d_X509_REQ_bio(bio, self->pkcs10))
- lose_openssl_error("Unable to write PKCS#10 request");
-
- result = BIO_to_PyString_helper(bio);
-
- error: /* Fall through */
- BIO_free(bio);
- return result;
-}
-
-static X509_EXTENSIONS **
-pkcs10_object_extension_helper(pkcs10_object *self)
-{
- return &self->exts;
-}
-
-static char pkcs10_object_get_public_key__doc__[] =
- "Return the public key from this PKCS#10 request, as an Asymmetric\n"
- "object.\n"
- ;
-
-static PyObject *
-pkcs10_object_get_public_key(pkcs10_object *self)
-{
- PyTypeObject *type = &POW_Asymmetric_Type;
- asymmetric_object *asym = NULL;
-
- ENTERING(pkcs10_object_get_public_key);
-
- if ((asym = (asymmetric_object *) type->tp_alloc(type, 0)) == NULL)
- goto error;
-
- if ((asym->pkey = X509_REQ_get_pubkey(self->pkcs10)) == NULL)
- lose_openssl_error("Couldn't extract public key from PKCS#10 request");
-
- return (PyObject *) asym;
-
- error:
- Py_XDECREF(asym);
- return NULL;
-}
-
-static char pkcs10_object_set_public_key__doc__[] =
- "Set the public key for this PKCS#10 request.\n"
- "\n"
- "The \"key\" parameter should be an instance of the Asymmetric class,\n"
- "containing a public key.\n"
- ;
-
-static PyObject *
-pkcs10_object_set_public_key(pkcs10_object *self, PyObject *args)
-{
- asymmetric_object *asym;
-
- ENTERING(pkcs10_object_set_public_key);
-
- if (!PyArg_ParseTuple(args, "O!", &POW_Asymmetric_Type, &asym))
- goto error;
-
- if (!X509_REQ_set_pubkey(self->pkcs10, asym->pkey))
- lose_openssl_error("Couldn't set certificate's PKCS#10 request");
-
- Py_RETURN_NONE;
-
- error:
- return NULL;
-}
-
-static char pkcs10_object_sign__doc__[] =
- "Sign a PKCS#10 request 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 *
-pkcs10_object_sign(pkcs10_object *self, PyObject *args)
-{
- asymmetric_object *asym;
- int loc, digest_type = SHA256_DIGEST;
- const EVP_MD *digest_method = NULL;
-
- ENTERING(pkcs10_object_sign);
-
- if (!PyArg_ParseTuple(args, "O!|i", &POW_Asymmetric_Type, &asym, &digest_type))
- goto error;
-
- if ((digest_method = evp_digest_factory(digest_type)) == NULL)
- lose("Unsupported digest algorithm");
-
- while ((loc = X509_REQ_get_attr_by_NID(self->pkcs10, NID_ext_req, -1)) >= 0)
- X509_ATTRIBUTE_free(X509_REQ_delete_attr(self->pkcs10, loc));
-
- if (sk_X509_EXTENSION_num(self->exts) > 0 &&
- !X509_REQ_add_extensions(self->pkcs10, self->exts))
- lose_openssl_error("Couldn't add extensions block to PKCS#10 request");
-
- if (!X509_REQ_sign(self->pkcs10, asym->pkey, digest_method))
- lose_openssl_error("Couldn't sign PKCS#10 request");
-
- Py_RETURN_NONE;
-
- error:
- return NULL;
-}
-
-static char pkcs10_object_verify__doc__[] =
- "Verify a PKCS#10 request.\n"
- "\n"
- "This calls OpenSSL's X509_REQ_verify() method to check the request's\n"
- "self-signature.\n"
- ;
-
-static PyObject *
-pkcs10_object_verify(pkcs10_object *self)
-{
- EVP_PKEY *pkey = NULL;
- int status;
-
- ENTERING(pkcs10_object_verify);
-
- if ((pkey = X509_REQ_get_pubkey(self->pkcs10)) == NULL)
- lose_openssl_error("Couldn't extract public key from PKCS#10 for verification");
-
- if ((status = X509_REQ_verify(self->pkcs10, pkey)) < 0)
- lose_openssl_error("Couldn't verify PKCS#10 signature");
-
- EVP_PKEY_free(pkey);
- return PyBool_FromLong(status);
-
- error:
- EVP_PKEY_free(pkey);
- return NULL;
-}
-
-static char pkcs10_object_get_version__doc__[] =
- "Return the version number of this PKCS#10 request.\n"
- ;
-
-static PyObject *
-pkcs10_object_get_version(pkcs10_object *self)
-{
- ENTERING(pkcs10_object_get_version);
- return Py_BuildValue("l", X509_REQ_get_version(self->pkcs10));
-}
-
-static char pkcs10_object_set_version__doc__[] =
- "Set the version number of this PKCS#10 request.\n"
- "\n"
- "The \"version\" parameter should be an integer, but the only defined\n"
- "value is zero, so this field is optional and defaults to zero.\n"
-;
-
-static PyObject *
-pkcs10_object_set_version(pkcs10_object *self, PyObject *args)
-{
- long version = 0;
-
- ENTERING(pkcs10_object_set_version);
-
- if (!PyArg_ParseTuple(args, "|l", &version))
- goto error;
-
- if (version != 0)
- lose("RFC 6487 6.1.1 forbids non-zero values for this field");
-
- if (!X509_REQ_set_version(self->pkcs10, version))
- lose("Couldn't set certificate version");
-
- Py_RETURN_NONE;
-
- error:
-
- return NULL;
-}
-
-static char pkcs10_object_get_subject__doc__[] =
- "Return this PKCS #10 request's subject name.\n"
- "\n"
- "See the X509.getIssuer() method for details of the return value and\n"
- "use of the optional \"format\" parameter.\n"
- ;
-
-static PyObject *
-pkcs10_object_get_subject(pkcs10_object *self, PyObject *args)
-{
- PyObject *result = NULL;
- int format = OIDNAME_FORMAT;
-
- ENTERING(pkcs10_object_get_subject);
-
- if (!PyArg_ParseTuple(args, "|i", &format))
- goto error;
-
- result = x509_object_helper_get_name(X509_REQ_get_subject_name(self->pkcs10),
- format);
-
- error: /* Fall through */
- return result;
-}
-
-static char pkcs10_object_set_subject__doc__[] =
- "Set this PKCS#10 request's subject name.\n"
- "\n"
- "The \"name\" parameter should be in the same format as the return\n"
- "value from the \"getSubject\" method.\n"
- ;
-
-static PyObject *
-pkcs10_object_set_subject(pkcs10_object *self, PyObject *args)
-{
- PyObject *name_sequence = NULL;
- X509_NAME *name = NULL;
-
- ENTERING(pkcs10_object_set_subject);
-
- if (!PyArg_ParseTuple(args, "O", &name_sequence))
- goto error;
-
- if (!PySequence_Check(name_sequence))
- lose_type_error("Inapropriate type");
-
- if ((name = x509_object_helper_set_name(name_sequence)) == NULL)
- goto error;
-
- if (!X509_REQ_set_subject_name(self->pkcs10, name))
- lose("Unable to set subject name");
-
- X509_NAME_free(name);
-
- Py_RETURN_NONE;
-
- error:
- X509_NAME_free(name);
- return NULL;
-}
-
-static char pkcs10_object_get_key_usage__doc__[] =
- "Return a FrozenSet of strings representing the KeyUsage settings for\n"
- "this PKCS#10 request, or None if the request has no KeyUsage\n"
- "extension. The bits have the same names as in RFC 5280.\n"
- ;
-
-static PyObject *
-pkcs10_object_get_key_usage(pkcs10_object *self)
-{
- return extension_get_key_usage(pkcs10_object_extension_helper(self));
-}
-
-static char pkcs10_object_set_key_usage__doc__[] =
- "Set the KeyUsage extension for this PKCS#10 request.\n"
- "\n"
- "Argument \"iterable\" should be an iterable object which returns zero or more\n"
- "strings naming bits to be enabled. The bits have the same names as in RFC 5280.\n"
- "\n"
- "Optional argument \"critical\" is a boolean indicating whether the extension\n"
- "should be marked as critical or not. RFC 5280 4.2.1.3 says this extension SHOULD\n"
- "be marked as critical when used, so the default is True.\n"
- ;
-
-static PyObject *
-pkcs10_object_set_key_usage(pkcs10_object *self, PyObject *args)
-{
- return extension_set_key_usage(pkcs10_object_extension_helper(self), args);
-}
-
-static char pkcs10_object_get_eku__doc__[] =
- "Return a FrozenSet of object identifiers representing the\n"
- "ExtendedKeyUsage settings for this PKCS #10 requst, or None if\n"
- "the request has no ExtendedKeyUsage extension.\n"
- ;
-
-static PyObject *
-pkcs10_object_get_eku(pkcs10_object *self)
-{
- return extension_get_eku(pkcs10_object_extension_helper(self));
-}
-
-static char pkcs10_object_set_eku__doc__[] =
- "Set the ExtendedKeyUsage extension for this PKCS #10 request.\n"
- "\n"
- "Argument \"iterable\" should be an iterable object which returns one or more\n"
- "object identifiers.\n"
- "\n"
- "Optional argument \"critical\" is a boolean indicating whether the extension\n"
- "should be marked as critical or not. RFC 6487 4.8.5 says this extension\n"
- "MUST NOT be marked as non-critical when used, so the default is False.\n"
- ;
-
-static PyObject *
-pkcs10_object_set_eku(pkcs10_object *self, PyObject *args)
-{
- return extension_set_eku(pkcs10_object_extension_helper(self), args);
-}
-
-static char pkcs10_object_get_basic_constraints__doc__[] =
- "Return BasicConstraints value for this PKCS#10 request.\n"
- "\n"
- "If this request has no BasicConstraints extension, this method returns\n"
- "None.\n"
- "\n"
- "Otherwise, this method returns a two-element tuple. The first element\n"
- "of the tuple is a boolean representing the extension's cA value; the\n"
- "second element of the tuple is either an integer representing\n"
- "thepathLenConstraint value or None if there is no pathLenConstraint.\n"
- ;
-
-static PyObject *
-pkcs10_object_get_basic_constraints(pkcs10_object *self)
-{
- return extension_get_basic_constraints(pkcs10_object_extension_helper(self));
-}
-
-static char pkcs10_object_set_basic_constraints__doc__[] =
- "Set BasicConstraints value for this PKCS#10 request.\n"
- "\n"
- "First argument \"ca\" is a boolean indicating whether the request\n"
- "is for a CA certificate or not.\n"
- "\n"
- "Optional second argument \"pathLenConstraint\" is None or a\n"
- "non-negative integer specifying the pathLenConstraint value for this\n"
- "certificate. Per RFC 5280, this value may only be set to an integer\n"
- "value for CA certificates."
- "\n"
- "Optional third argument \"critical\" specifies whether the extension\n"
- "should be marked as critical. RFC 5280 4.2.1.9 requires that CA\n"
- "certificates mark this extension as critical, so the default is True.\n"
- ;
-
-static PyObject *
-pkcs10_object_set_basic_constraints(pkcs10_object *self, PyObject *args)
-{
- return extension_set_basic_constraints(pkcs10_object_extension_helper(self), args);
-}
-
-static char pkcs10_object_get_sia__doc__[] =
- "Return the SIA values for this PKCS#10 request.\n"
- "\n"
- "If this request has no SIA extension, this method returns None.\n"
- "\n"
- "Otherwise, this returns a tuple containing three sequences:\n"
- "caRepository URIs, rpkiManifest URIs, and signedObject URIs.\n"
- "Any other accessMethods are ignored, as are any non-URI\n"
- "accessLocations.\n"
- ;
-
-static PyObject *
-pkcs10_object_get_sia(pkcs10_object *self)
-{
- return extension_get_sia(pkcs10_object_extension_helper(self));
-}
-
-static char pkcs10_object_set_sia__doc__[] =
- "Set SIA values for this PKCS#10 request.\n"
- "\n"
- "Takes three arguments: caRepository, rpkiManifest, and signedObject.\n"
- "\n"
- "Each of these should be an iterable which returns URIs.\n"
- "\n"
- "None is acceptable as an alternate way of specifying an empty\n"
- "collection of URIs for a particular argument.\n"
- ;
-
-static PyObject *
-pkcs10_object_set_sia(pkcs10_object *self, PyObject *args, PyObject *kwds)
-{
- return extension_set_sia(pkcs10_object_extension_helper(self), args, kwds);
-}
-
-static char pkcs10_object_get_signature_algorithm__doc__[] =
- "Return this PKCS #10 reqeuest's signature algorithm OID.\n"
- ;
-
-static PyObject *
-pkcs10_object_get_signature_algorithm(pkcs10_object *self)
-{
- ASN1_OBJECT *oid = NULL;
-
- ENTERING(pkcs10_object_get_signature_algorithm);
-
- X509_ALGOR_get0(&oid, NULL, NULL, self->pkcs10->sig_alg);
-
- return ASN1_OBJECT_to_PyString(oid);
-}
-
-static char pkcs10_object_get_extension_oids__doc__[] =
- "Return the set of extension OIDs used in this request. This is mostly\n"
- "useful for enforcing restrictions on what extensions are allowed to be\n"
- "present, eg, to conform with the RPKI profile.\n"
- ;
-
-static PyObject *
-pkcs10_object_get_extension_oids(pkcs10_object *self)
-{
- PyObject *result = NULL;
- PyObject *oid = NULL;
- int i;
-
- ENTERING(pkcs10_object_get_extension_oids);
-
- if ((result = PyFrozenSet_New(NULL)) == NULL)
- goto error;
-
- for (i = 0; i < sk_X509_EXTENSION_num(self->exts); i++) {
- X509_EXTENSION *ext = sk_X509_EXTENSION_value(self->exts, i);
- if ((oid = ASN1_OBJECT_to_PyString(ext->object)) == NULL ||
- PySet_Add(result, oid) < 0)
- goto error;
- Py_XDECREF(oid);
- oid = NULL;
- }
-
- return result;
-
- error:
- Py_XDECREF(result);
- Py_XDECREF(oid);
- return NULL;
-}
-
-/*
- * May want EKU handlers eventually, skip for now.
- */
-
-static char pkcs10_object_pprint__doc__[] =
- "Return a pretty-printed rendition of this PKCS#10 request.\n"
- ;
-
-static PyObject *
-pkcs10_object_pprint(pkcs10_object *self)
-{
- PyObject *result = NULL;
- BIO *bio = NULL;
-
- ENTERING(pkcs10_object_pprint);
-
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
- lose_no_memory();
-
- if (!X509_REQ_print(bio, self->pkcs10))
- lose_openssl_error("Unable to pretty-print PKCS#10 request");
-
- result = BIO_to_PyString_helper(bio);
-
- error: /* Fall through */
- BIO_free(bio);
- return result;
-}
-
-static struct PyMethodDef pkcs10_object_methods[] = {
- Define_Method(pemWrite, pkcs10_object_pem_write, METH_NOARGS),
- Define_Method(derWrite, pkcs10_object_der_write, METH_NOARGS),
- Define_Method(sign, pkcs10_object_sign, METH_VARARGS),
- Define_Method(verify, pkcs10_object_verify, METH_NOARGS),
- Define_Method(getPublicKey, pkcs10_object_get_public_key, METH_NOARGS),
- Define_Method(setPublicKey, pkcs10_object_set_public_key, METH_VARARGS),
- Define_Method(getVersion, pkcs10_object_get_version, METH_NOARGS),
- Define_Method(setVersion, pkcs10_object_set_version, METH_VARARGS),
- Define_Method(getSubject, pkcs10_object_get_subject, METH_VARARGS),
- Define_Method(setSubject, pkcs10_object_set_subject, METH_VARARGS),
- Define_Method(pprint, pkcs10_object_pprint, METH_NOARGS),
- Define_Method(getKeyUsage, pkcs10_object_get_key_usage, METH_NOARGS),
- Define_Method(setKeyUsage, pkcs10_object_set_key_usage, METH_VARARGS),
- Define_Method(getEKU, pkcs10_object_get_eku, METH_NOARGS),
- Define_Method(setEKU, pkcs10_object_set_eku, METH_VARARGS),
- Define_Method(getBasicConstraints, pkcs10_object_get_basic_constraints, METH_NOARGS),
- Define_Method(setBasicConstraints, pkcs10_object_set_basic_constraints, METH_VARARGS),
- Define_Method(getSIA, pkcs10_object_get_sia, METH_NOARGS),
- Define_Method(setSIA, pkcs10_object_set_sia, METH_KEYWORDS),
- Define_Method(getSignatureAlgorithm, pkcs10_object_get_signature_algorithm, METH_NOARGS),
- Define_Method(getExtensionOIDs, pkcs10_object_get_extension_oids, METH_NOARGS),
- Define_Class_Method(pemRead, pkcs10_object_pem_read, METH_VARARGS),
- Define_Class_Method(pemReadFile, pkcs10_object_pem_read_file, METH_VARARGS),
- Define_Class_Method(derRead, pkcs10_object_der_read, METH_VARARGS),
- Define_Class_Method(derReadFile, pkcs10_object_der_read_file, METH_VARARGS),
- {NULL}
-};
-
-static char POW_PKCS10_Type__doc__[] =
- "This class represents a PKCS#10 request.\n"
- "\n"
- LAME_DISCLAIMER_IN_ALL_CLASS_DOCUMENTATION
- ;
-
-static PyTypeObject POW_PKCS10_Type = {
- PyObject_HEAD_INIT(0)
- 0, /* ob_size */
- "rpki.POW.PKCS10", /* tp_name */
- sizeof(pkcs10_object), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor)pkcs10_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 */
- POW_PKCS10_Type__doc__, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- pkcs10_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 */
- 0, /* tp_init */
- 0, /* tp_alloc */
- pkcs10_object_new, /* tp_new */
-};
-
-
-
-/*
- * Module functions.
- */
-
-static char pow_module_add_object__doc__[] =
- "Add new a new object identifier to OpenSSL's 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(GCC_UNUSED PyObject *self, PyObject *args)
-{
- char *oid = NULL, *sn = NULL, *ln = NULL;
-
- ENTERING(pow_module_add_object);
-
- if (!PyArg_ParseTuple(args, "sss", &oid, &sn, &ln))
- goto error;
-
- if (!OBJ_create(oid, sn, ln))
- lose_openssl_error("Unable to add object");
-
- Py_RETURN_NONE;
-
- error:
-
- return NULL;
-}
-
-static char pow_module_get_error__doc__[] =
- "Pop one error off OpenSSL's global error stack and returns it as a string.\n"
- "\n"
- "Returns None if the error stack is empty.\n"
- ;
-
-static PyObject *
-pow_module_get_error(GCC_UNUSED PyObject *self)
-{
- unsigned long error = ERR_get_error();
- char buf[256];
-
- ENTERING(pow_module_get_error);
-
- if (!error)
- Py_RETURN_NONE;
-
- ERR_error_string_n(error, buf, sizeof(buf));
- return Py_BuildValue("s", buf);
-}
-
-static char pow_module_clear_error__doc__[] =
- "Remove all errors from OpenSSL's global error stack.\n"
- ;
-
-static PyObject *
-pow_module_clear_error(GCC_UNUSED PyObject *self)
-{
- ENTERING(pow_module_clear_error);
- ERR_clear_error();
- Py_RETURN_NONE;
-}
-
-static char pow_module_seed__doc__[] =
- "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(GCC_UNUSED PyObject *self, PyObject *args)
-{
- char *data = NULL;
- Py_ssize_t datalen = 0;
-
- ENTERING(pow_module_seed);
-
- if (!PyArg_ParseTuple(args, "s#", &data, &datalen))
- goto error;
-
- RAND_seed(data, datalen);
-
- Py_RETURN_NONE;
-
- error:
-
- return NULL;
-}
-
-static char pow_module_add__doc__[] =
- "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(GCC_UNUSED PyObject *self, PyObject *args)
-{
- char *data = NULL;
- Py_ssize_t datalen = 0;
- double entropy = 0;
-
- ENTERING(pow_module_add);
-
- if (!PyArg_ParseTuple(args, "s#d", &data, &datalen, &entropy))
- goto error;
-
- RAND_add(data, datalen, entropy);
-
- Py_RETURN_NONE;
-
- error:
- return NULL;
-}
-
-static char pow_module_write_random_file__doc__[] =
- "Write the current state of OpenSSL's pseduo-random number generator to\n"
- "a file.\n"
- "\n"
- "The \"filename\" parameter is the name of the file to write.\n"
- ;
-
-static PyObject *
-pow_module_write_random_file(GCC_UNUSED PyObject *self, PyObject *args)
-{
- char *filename = NULL;
-
- ENTERING(pow_module_write_random_file);
-
- if (!PyArg_ParseTuple(args, "s", &filename))
- goto error;
-
- 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__[] =
- "Restore the state of OpenSSLs pseudo-random number generator from\n"
- "data 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(GCC_UNUSED PyObject *self, PyObject *args)
-{
- char *file = NULL;
- int len = -1;
-
- ENTERING(pow_module_read_random_file);
-
- if (!PyArg_ParseTuple(args, "s|i", &file, &len))
- goto error;
-
- if (!RAND_load_file(file, len))
- lose("Couldn't load random file");
-
- Py_RETURN_NONE;
-
- error:
- return NULL;
-}
-
-static char pow_module_custom_datetime__doc__[] =
- "Set constructor callback for customized datetime class.\n"
- ;
-
-static PyObject *
-pow_module_custom_datetime(GCC_UNUSED PyObject *self, PyObject *args)
-{
- PyObject *cb = NULL;
-
- ENTERING(pow_module_custom_datetime);
-
- if (!PyArg_ParseTuple(args, "O", &cb))
- goto error;
-
- Py_XINCREF(cb);
- Py_XDECREF(custom_datetime);
- custom_datetime = cb;
-
- Py_RETURN_NONE;
-
- error:
- return NULL;
-}
-
-
-static struct PyMethodDef pow_module_methods[] = {
- Define_Method(getError, pow_module_get_error, METH_NOARGS),
- Define_Method(clearError, pow_module_clear_error, METH_NOARGS),
- Define_Method(seed, pow_module_seed, METH_VARARGS),
- Define_Method(add, pow_module_add, METH_VARARGS),
- Define_Method(readRandomFile, pow_module_read_random_file, METH_VARARGS),
- Define_Method(writeRandomFile, pow_module_write_random_file, METH_VARARGS),
- Define_Method(addObject, pow_module_add_object, METH_VARARGS),
- Define_Method(customDatetime, pow_module_custom_datetime, METH_VARARGS),
- {NULL}
-};
-
-
-
-/*
- * Module initialization.
- */
-
-void
-init_POW(void)
-{
- PyObject *m = Py_InitModule3("_POW", pow_module_methods, pow_module__doc__);
- int OpenSSL_ok = 1;
-
- /*
- * Python encourages us to use these functions instead of the ones
- * in libc, and OpenSSL allows us to do this. The result seems to
- * work, and, in theory, gives Python's memory allocator a better
- * idea of how much memory we're really using. Not sure why it
- * cares, but let's try to be nice about it.
- *
- * Note that this must be done BEFORE anything in OpenSSL uses
- * dynamic memory, and that this will probably fail in horrible ways
- * without the build-time code (-Bsymbolic, etc) which isolates our
- * copy of the OpenSSL code from any system shared libraries.
- * Enough other things already fail in horrible ways without that
- * isolation that adding one more doesn't make much difference, but
- * if you tinker with the build script and start seeing nasty
- * memory-related issues, this might be the cause.
- */
- CRYPTO_set_mem_functions(PyMem_Malloc, PyMem_Realloc, PyMem_Free);
-
- /*
- * Import the DateTime API
- */
-
- PyDateTime_IMPORT;
-
-#define Define_Class(__type__) \
- do { \
- char *__name__ = strrchr(__type__.tp_name, '.'); \
- if (PyType_Ready(&__type__) == 0 && __name__ != NULL) { \
- Py_INCREF(&__type__); \
- PyModule_AddObject(m, __name__+1, (PyObject *) &__type__); \
- } \
- } while (0)
-
- Define_Class(POW_X509_Type);
- Define_Class(POW_X509Store_Type);
- Define_Class(POW_X509StoreCTX_Type);
- Define_Class(POW_CRL_Type);
- Define_Class(POW_Asymmetric_Type);
- Define_Class(POW_AsymmetricParams_Type);
- Define_Class(POW_Digest_Type);
- Define_Class(POW_CMS_Type);
- Define_Class(POW_IPAddress_Type);
- Define_Class(POW_Manifest_Type);
- Define_Class(POW_ROA_Type);
- Define_Class(POW_PKCS10_Type);
-
-#undef Define_Class
-
-#define Define_Exception(__name__, __parent__) \
- PyModule_AddObject(m, #__name__, ((__name__##Object) \
- = PyErr_NewException("rpki.POW." #__name__, __parent__, NULL)))
-
- Define_Exception(Error, NULL);
- Define_Exception(OpenSSLError, ErrorObject);
- Define_Exception(POWError, ErrorObject);
- Define_Exception(NotVerifiedError, ErrorObject);
-
-#undef Define_Exception
-
-#define Define_Integer_Constant(__name__) \
- PyModule_AddIntConstant(m, #__name__, __name__)
-
- /* Object format types */
- Define_Integer_Constant(LONGNAME_FORMAT);
- Define_Integer_Constant(SHORTNAME_FORMAT);
- Define_Integer_Constant(OIDNAME_FORMAT);
-
- /* Message digests */
- Define_Integer_Constant(MD5_DIGEST);
- Define_Integer_Constant(SHA_DIGEST);
- Define_Integer_Constant(SHA1_DIGEST);
- Define_Integer_Constant(SHA256_DIGEST);
- Define_Integer_Constant(SHA384_DIGEST);
- Define_Integer_Constant(SHA512_DIGEST);
-
- /* CMS flags */
- Define_Integer_Constant(CMS_NOCERTS);
- Define_Integer_Constant(CMS_NOATTR);
- Define_Integer_Constant(CMS_NOINTERN);
- Define_Integer_Constant(CMS_NOCRL);
- Define_Integer_Constant(CMS_NO_SIGNER_CERT_VERIFY);
- Define_Integer_Constant(CMS_NO_ATTR_VERIFY);
- Define_Integer_Constant(CMS_NO_CONTENT_VERIFY);
-
- /* X509 validation flags */
- Define_Integer_Constant(X509_V_FLAG_CB_ISSUER_CHECK);
- Define_Integer_Constant(X509_V_FLAG_USE_CHECK_TIME);
- Define_Integer_Constant(X509_V_FLAG_CRL_CHECK);
- Define_Integer_Constant(X509_V_FLAG_CRL_CHECK_ALL);
- Define_Integer_Constant(X509_V_FLAG_IGNORE_CRITICAL);
- Define_Integer_Constant(X509_V_FLAG_X509_STRICT);
- Define_Integer_Constant(X509_V_FLAG_ALLOW_PROXY_CERTS);
- Define_Integer_Constant(X509_V_FLAG_POLICY_CHECK);
- Define_Integer_Constant(X509_V_FLAG_EXPLICIT_POLICY);
- Define_Integer_Constant(X509_V_FLAG_INHIBIT_ANY);
- Define_Integer_Constant(X509_V_FLAG_INHIBIT_MAP);
- Define_Integer_Constant(X509_V_FLAG_NOTIFY_POLICY);
- Define_Integer_Constant(X509_V_FLAG_CHECK_SS_SIGNATURE);
-
- /* X509 validation error codes */
- Define_Integer_Constant(X509_V_OK);
- Define_Integer_Constant(X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT);
- Define_Integer_Constant(X509_V_ERR_UNABLE_TO_GET_CRL);
- Define_Integer_Constant(X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE);
- Define_Integer_Constant(X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE);
- Define_Integer_Constant(X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY);
- Define_Integer_Constant(X509_V_ERR_CERT_SIGNATURE_FAILURE);
- Define_Integer_Constant(X509_V_ERR_CRL_SIGNATURE_FAILURE);
- Define_Integer_Constant(X509_V_ERR_CERT_NOT_YET_VALID);
- Define_Integer_Constant(X509_V_ERR_CERT_HAS_EXPIRED);
- Define_Integer_Constant(X509_V_ERR_CRL_NOT_YET_VALID);
- Define_Integer_Constant(X509_V_ERR_CRL_HAS_EXPIRED);
- Define_Integer_Constant(X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD);
- Define_Integer_Constant(X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD);
- Define_Integer_Constant(X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD);
- Define_Integer_Constant(X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD);
- Define_Integer_Constant(X509_V_ERR_OUT_OF_MEM);
- Define_Integer_Constant(X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT);
- Define_Integer_Constant(X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN);
- Define_Integer_Constant(X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY);
- Define_Integer_Constant(X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE);
- Define_Integer_Constant(X509_V_ERR_CERT_CHAIN_TOO_LONG);
- Define_Integer_Constant(X509_V_ERR_CERT_REVOKED);
- Define_Integer_Constant(X509_V_ERR_INVALID_CA);
- Define_Integer_Constant(X509_V_ERR_PATH_LENGTH_EXCEEDED);
- Define_Integer_Constant(X509_V_ERR_INVALID_PURPOSE);
- Define_Integer_Constant(X509_V_ERR_CERT_UNTRUSTED);
- Define_Integer_Constant(X509_V_ERR_CERT_REJECTED);
- Define_Integer_Constant(X509_V_ERR_SUBJECT_ISSUER_MISMATCH);
- Define_Integer_Constant(X509_V_ERR_AKID_SKID_MISMATCH);
- Define_Integer_Constant(X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH);
- Define_Integer_Constant(X509_V_ERR_KEYUSAGE_NO_CERTSIGN);
- Define_Integer_Constant(X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER);
- Define_Integer_Constant(X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION);
- Define_Integer_Constant(X509_V_ERR_KEYUSAGE_NO_CRL_SIGN);
- Define_Integer_Constant(X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION);
- Define_Integer_Constant(X509_V_ERR_INVALID_NON_CA);
- Define_Integer_Constant(X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED);
- Define_Integer_Constant(X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE);
- Define_Integer_Constant(X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED);
- Define_Integer_Constant(X509_V_ERR_INVALID_EXTENSION);
- Define_Integer_Constant(X509_V_ERR_INVALID_POLICY_EXTENSION);
- Define_Integer_Constant(X509_V_ERR_NO_EXPLICIT_POLICY);
- Define_Integer_Constant(X509_V_ERR_UNNESTED_RESOURCE);
- Define_Integer_Constant(X509_V_ERR_APPLICATION_VERIFICATION);
-
- /* AsymmetricParam EC curve codes */
- Define_Integer_Constant(EC_P256_CURVE);
-
-#undef Define_Integer_Constant
-
- /*
- * 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.
- */
-
- OpenSSL_add_all_algorithms();
- ERR_load_crypto_strings();
-
- OpenSSL_ok &= create_missing_nids();
-
- x509_store_ctx_ex_data_idx = X509_STORE_CTX_get_ex_new_index(0, "x590_store_ctx_object for verify callback",
- NULL, NULL, NULL);
-
- if (PyErr_Occurred() || !OpenSSL_ok)
- Py_FatalError("Can't initialize module POW");
-}
-
-/*
- * Local Variables:
- * indent-tabs-mode: nil
- * End:
- */