initial source import
diff --git a/src/crypto/pkcs12.c b/src/crypto/pkcs12.c
new file mode 100644
index 0000000..ab7562d
--- /dev/null
+++ b/src/crypto/pkcs12.c
@@ -0,0 +1,275 @@
+/*
+ * pkcs12.c
+ *
+ * Copyright (C) AB Strakt 2001, All rights reserved
+ *
+ * Certificate transport (PKCS12) handling code,
+ * mostly thin wrappers around OpenSSL.
+ * See the file RATIONALE for a short explanation of why
+ * this module was written.
+ *
+ * Reviewed 2001-07-23
+ */
+#include <Python.h>
+#define crypto_MODULE
+#include "crypto.h"
+
+static char *CVSid = "@(#) $Id: pkcs12.c,v 1.3 2003/01/09 17:08:32 martin Exp $";
+
+/*
+ * PKCS12 is a standard exchange format for digital certificates.
+ * See e.g. the OpenSSL homepage http://www.openssl.org/ for more information
+ */
+
+static void crypto_PKCS12_dealloc(crypto_PKCS12Obj *self);
+
+static char crypto_PKCS12_get_certificate_doc[] = "\n\
+Return certificate portion of the PKCS12 structure\n\
+\n\
+Arguments: self - The PKCS12 object\n\
+ args - The Python argument tuple, should be empty\n\
+Returns: X509 object containing the certificate\n\
+";
+static PyObject *
+crypto_PKCS12_get_certificate(crypto_PKCS12Obj *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":get_certificate"))
+ return NULL;
+
+ Py_INCREF(self->cert);
+ return self->cert;
+}
+
+static char crypto_PKCS12_get_privatekey_doc[] = "\n\
+Return private key portion of the PKCS12 structure\n\
+\n\
+Arguments: self - The PKCS12 object\n\
+ args - The Python argument tuple, should be empty\n\
+Returns: PKey object containing the private key\n\
+";
+static PyObject *
+crypto_PKCS12_get_privatekey(crypto_PKCS12Obj *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":get_privatekey"))
+ return NULL;
+
+ Py_INCREF(self->key);
+ return self->key;
+}
+
+static char crypto_PKCS12_get_ca_certificates_doc[] = "\n\
+Return CA certificates within of the PKCS12 object\n\
+\n\
+Arguments: self - The PKCS12 object\n\
+ args - The Python argument tuple, should be empty\n\
+Returns: A newly created tuple containing the CA certificates in the chain,\n\
+ if any are present, or None if no CA certificates are present.\n\
+";
+static PyObject *
+crypto_PKCS12_get_ca_certificates(crypto_PKCS12Obj *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":get_ca_certificates"))
+ return NULL;
+
+ Py_INCREF(self->cacerts);
+ return self->cacerts;
+}
+
+/*
+ * ADD_METHOD(name) expands to a correct PyMethodDef declaration
+ * { 'name', (PyCFunction)crypto_PKCS12_name, METH_VARARGS, crypto_PKCS12_name_doc }
+ * for convenience
+ */
+#define ADD_METHOD(name) \
+ { #name, (PyCFunction)crypto_PKCS12_##name, METH_VARARGS, crypto_PKCS12_##name##_doc }
+static PyMethodDef crypto_PKCS12_methods[] =
+{
+ ADD_METHOD(get_certificate),
+ ADD_METHOD(get_privatekey),
+ ADD_METHOD(get_ca_certificates),
+ { NULL, NULL }
+};
+#undef ADD_METHOD
+
+/*
+ * Constructor for PKCS12 objects, never called by Python code directly.
+ * The strategy for this object is to create all the Python objects
+ * corresponding to the cert/key/CA certs right away
+ *
+ * Arguments: p12 - A "real" PKCS12 object
+ * passphrase - Passphrase to use when decrypting the PKCS12 object
+ * Returns: The newly created PKCS12 object
+ */
+crypto_PKCS12Obj *
+crypto_PKCS12_New(PKCS12 *p12, char *passphrase)
+{
+ crypto_PKCS12Obj *self;
+ PyObject *cacertobj = NULL;
+
+ X509 *cert = NULL;
+ EVP_PKEY *pkey = NULL;
+ STACK_OF(X509) *cacerts = NULL;
+
+ int i, cacert_count = 0;
+
+ /* allocate space for the CA cert stack */
+ cacerts = sk_X509_new_null();
+
+ /* parse the PKCS12 lump */
+ if (!(cacerts && PKCS12_parse(p12, passphrase, &pkey, &cert, &cacerts)))
+ {
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ if (!(self = PyObject_GC_New(crypto_PKCS12Obj, &crypto_PKCS12_Type)))
+ return NULL;
+
+ self->cert = NULL;
+ self->key = NULL;
+ Py_INCREF(Py_None);
+ self->cacerts = Py_None;
+
+ if ((self->cert = (PyObject *)crypto_X509_New(cert, 1)) == NULL)
+ goto error;
+
+ if ((self->key = (PyObject *)crypto_PKey_New(pkey, 1)) == NULL)
+ goto error;
+
+ /* Make a tuple for the CA certs */
+ cacert_count = sk_X509_num(cacerts);
+ if (cacert_count > 0)
+ {
+ Py_DECREF(self->cacerts);
+ if ((self->cacerts = PyTuple_New(cacert_count)) == NULL)
+ goto error;
+
+ for (i = 0; i < cacert_count; i++)
+ {
+ cert = sk_X509_value(cacerts, i);
+ if ((cacertobj = (PyObject *)crypto_X509_New(cert, 1)) == NULL)
+ goto error;
+ PyTuple_SET_ITEM(self->cacerts, i, cacertobj);
+ }
+ }
+
+ sk_X509_free(cacerts); /* don't free the certs, just the stack */
+ PyObject_GC_Track(self);
+
+ return self;
+error:
+ crypto_PKCS12_dealloc(self);
+ return NULL;
+}
+
+/*
+ * Find attribute
+ *
+ * Arguments: self - The PKCS12 object
+ * name - The attribute name
+ * Returns: A Python object for the attribute, or NULL if something went
+ * wrong
+ */
+static PyObject *
+crypto_PKCS12_getattr(crypto_PKCS12Obj *self, char *name)
+{
+ return Py_FindMethod(crypto_PKCS12_methods, (PyObject *)self, name);
+}
+
+/*
+ * Call the visitproc on all contained objects.
+ *
+ * Arguments: self - The PKCS12 object
+ * visit - Function to call
+ * arg - Extra argument to visit
+ * Returns: 0 if all goes well, otherwise the return code from the first
+ * call that gave non-zero result.
+ */
+static int
+crypto_PKCS12_traverse(crypto_PKCS12Obj *self, visitproc visit, void *arg)
+{
+ int ret = 0;
+
+ if (ret == 0 && self->cert != NULL)
+ ret = visit(self->cert, arg);
+ if (ret == 0 && self->key != NULL)
+ ret = visit(self->key, arg);
+ if (ret == 0 && self->cacerts != NULL)
+ ret = visit(self->cacerts, arg);
+ return ret;
+}
+
+/*
+ * Decref all contained objects and zero the pointers.
+ *
+ * Arguments: self - The PKCS12 object
+ * Returns: Always 0.
+ */
+static int
+crypto_PKCS12_clear(crypto_PKCS12Obj *self)
+{
+ Py_XDECREF(self->cert);
+ self->cert = NULL;
+ Py_XDECREF(self->key);
+ self->key = NULL;
+ Py_XDECREF(self->cacerts);
+ self->cacerts = NULL;
+ return 0;
+}
+
+/*
+ * Deallocate the memory used by the PKCS12 object
+ *
+ * Arguments: self - The PKCS12 object
+ * Returns: None
+ */
+static void
+crypto_PKCS12_dealloc(crypto_PKCS12Obj *self)
+{
+ PyObject_GC_UnTrack(self);
+ crypto_PKCS12_clear(self);
+ PyObject_GC_Del(self);
+}
+
+PyTypeObject crypto_PKCS12_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "PKCS12",
+ sizeof(crypto_PKCS12Obj),
+ 0,
+ (destructor)crypto_PKCS12_dealloc,
+ NULL, /* print */
+ (getattrfunc)crypto_PKCS12_getattr,
+ NULL, /* setattr */
+ NULL, /* compare */
+ NULL, /* repr */
+ NULL, /* as_number */
+ NULL, /* as_sequence */
+ NULL, /* as_mapping */
+ NULL, /* hash */
+ NULL, /* call */
+ NULL, /* str */
+ NULL, /* getattro */
+ NULL, /* setattro */
+ NULL, /* as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
+ NULL, /* doc */
+ (traverseproc)crypto_PKCS12_traverse,
+ (inquiry)crypto_PKCS12_clear,
+};
+
+/*
+ * Initialize the PKCS12 part of the crypto sub module
+ *
+ * Arguments: dict - The crypto module dictionary
+ * Returns: None
+ */
+int
+init_crypto_pkcs12(PyObject *dict)
+{
+ crypto_PKCS12_Type.ob_type = &PyType_Type;
+ Py_INCREF(&crypto_PKCS12_Type);
+ PyDict_SetItemString(dict, "PKCS12Type", (PyObject *)&crypto_PKCS12_Type);
+ return 1;
+}
+