initial source import
diff --git a/src/crypto/crypto.c b/src/crypto/crypto.c
new file mode 100644
index 0000000..4fed5ba
--- /dev/null
+++ b/src/crypto/crypto.c
@@ -0,0 +1,738 @@
+/*
+ * crypto.c
+ *
+ * Copyright (C) AB Strakt 2001, All rights reserved
+ *
+ * Main file of crypto sub module.
+ * 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 crypto_doc[] = "\n\
+Main file of crypto sub module.\n\
+See the file RATIONALE for a short explanation of why this module was written.\n\
+";
+
+static char *CVSid = "@(#) $Id: crypto.c,v 1.28 2004/08/09 14:56:05 martin Exp $";
+
+void **ssl_API;
+
+PyObject *crypto_Error;
+
+static int
+global_passphrase_callback(char *buf, int len, int rwflag, void *cb_arg)
+{
+ PyObject *func, *argv, *ret;
+ int nchars;
+
+ func = (PyObject *)cb_arg;
+ argv = Py_BuildValue("(i)", rwflag);
+ ret = PyEval_CallObject(func, argv);
+ Py_DECREF(argv);
+ if (ret == NULL)
+ return 0;
+ if (!PyString_Check(ret))
+ {
+ PyErr_SetString(PyExc_ValueError, "String expected");
+ return 0;
+ }
+ nchars = PyString_Size(ret);
+ if (nchars > len)
+ nchars = len;
+ strncpy(buf, PyString_AsString(ret), nchars);
+ return nchars;
+}
+
+static char crypto_load_privatekey_doc[] = "\n\
+Load a private key from a buffer\n\
+\n\
+Arguments: spam - Always NULL\n\
+ args - The Python argument tuple, should be:\n\
+ type - The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
+ buffer - The buffer the key is stored in\n\
+ passphrase - (optional) if encrypted PEM format, this can be\n\
+ either the passphrase to use, or a callback for\n\
+ providing the passphrase.\n\
+Returns: The PKey object\n\
+";
+
+static PyObject *
+crypto_load_privatekey(PyObject *spam, PyObject *args)
+{
+ crypto_PKeyObj *crypto_PKey_New(EVP_PKEY *, int);
+ int type, len;
+ char *buffer;
+ PyObject *pw = NULL;
+ pem_password_cb *cb = NULL;
+ void *cb_arg = NULL;
+ BIO *bio;
+ EVP_PKEY *pkey;
+
+ if (!PyArg_ParseTuple(args, "is#|O:load_privatekey", &type, &buffer, &len, &pw))
+ return NULL;
+
+ if (pw != NULL)
+ {
+ if (PyString_Check(pw))
+ {
+ cb = NULL;
+ cb_arg = PyString_AsString(pw);
+ }
+ else if (PyCallable_Check(pw))
+ {
+ cb = global_passphrase_callback;
+ cb_arg = pw;
+ }
+ else
+ {
+ PyErr_SetString(PyExc_TypeError, "Last argument must be string or callable");
+ return NULL;
+ }
+ }
+
+ bio = BIO_new_mem_buf(buffer, len);
+ switch (type)
+ {
+ case X509_FILETYPE_PEM:
+ pkey = PEM_read_bio_PrivateKey(bio, NULL, cb, cb_arg);
+ break;
+
+ case X509_FILETYPE_ASN1:
+ pkey = d2i_PrivateKey_bio(bio, NULL);
+ break;
+
+ default:
+ PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
+ BIO_free(bio);
+ return NULL;
+ }
+ BIO_free(bio);
+
+ if (pkey == NULL)
+ {
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ return (PyObject *)crypto_PKey_New(pkey, 1);
+}
+
+static char crypto_dump_privatekey_doc[] = "\n\
+Dump a private key to a buffer\n\
+\n\
+Arguments: spam - Always NULL\n\
+ args - The Python argument tuple, should be:\n\
+ type - The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
+ pkey - The PKey to dump\n\
+ cipher - (optional) if encrypted PEM format, the cipher to\n\
+ use\n\
+ passphrase - (optional) if encrypted PEM format, this can be either\n\
+ the passphrase to use, or a callback for providing the\n\
+ passphrase.\n\
+Returns: The buffer with the dumped key in\n\
+";
+
+static PyObject *
+crypto_dump_privatekey(PyObject *spam, PyObject *args)
+{
+ int type, ret, buf_len;
+ char *temp;
+ PyObject *buffer;
+ char *cipher_name = NULL;
+ const EVP_CIPHER *cipher = NULL;
+ PyObject *pw = NULL;
+ pem_password_cb *cb = NULL;
+ void *cb_arg = NULL;
+ BIO *bio;
+ crypto_PKeyObj *pkey;
+
+ if (!PyArg_ParseTuple(args, "iO!|sO:dump_privatekey", &type,
+ &crypto_PKey_Type, &pkey, &cipher_name, &pw))
+ return NULL;
+
+ if (cipher_name != NULL && pw == NULL)
+ {
+ PyErr_SetString(PyExc_ValueError, "Illegal number of arguments");
+ return NULL;
+ }
+ if (cipher_name != NULL)
+ {
+ cipher = EVP_get_cipherbyname(cipher_name);
+ if (cipher == NULL)
+ {
+ PyErr_SetString(PyExc_ValueError, "Invalid cipher name");
+ return NULL;
+ }
+ if (PyString_Check(pw))
+ {
+ cb = NULL;
+ cb_arg = PyString_AsString(pw);
+ }
+ else if (PyCallable_Check(pw))
+ {
+ cb = global_passphrase_callback;
+ cb_arg = pw;
+ }
+ else
+ {
+ PyErr_SetString(PyExc_TypeError, "Last argument must be string or callable");
+ return NULL;
+ }
+ }
+
+ bio = BIO_new(BIO_s_mem());
+ switch (type)
+ {
+ case X509_FILETYPE_PEM:
+ ret = PEM_write_bio_PrivateKey(bio, pkey->pkey, cipher, NULL, 0, cb, cb_arg);
+ if (PyErr_Occurred())
+ {
+ BIO_free(bio);
+ return NULL;
+ }
+ break;
+
+ case X509_FILETYPE_ASN1:
+ ret = i2d_PrivateKey_bio(bio, pkey->pkey);
+ break;
+
+ default:
+ PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
+ BIO_free(bio);
+ return NULL;
+ }
+
+ if (ret == 0)
+ {
+ BIO_free(bio);
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ buf_len = BIO_get_mem_data(bio, &temp);
+ buffer = PyString_FromStringAndSize(temp, buf_len);
+ BIO_free(bio);
+
+ return buffer;
+}
+
+static char crypto_load_certificate_doc[] = "\n\
+Load a certificate from a buffer\n\
+\n\
+Arguments: spam - Always NULL\n\
+ args - The Python argument tuple, should be:\n\
+ type - The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
+ buffer - The buffer the certificate is stored in\n\
+Returns: The X509 object\n\
+";
+
+static PyObject *
+crypto_load_certificate(PyObject *spam, PyObject *args)
+{
+ crypto_X509Obj *crypto_X509_New(X509 *, int);
+ int type, len;
+ char *buffer;
+ BIO *bio;
+ X509 *cert;
+
+ if (!PyArg_ParseTuple(args, "is#:load_certificate", &type, &buffer, &len))
+ return NULL;
+
+ bio = BIO_new_mem_buf(buffer, len);
+ switch (type)
+ {
+ case X509_FILETYPE_PEM:
+ cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
+ break;
+
+ case X509_FILETYPE_ASN1:
+ cert = d2i_X509_bio(bio, NULL);
+ break;
+
+ default:
+ PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
+ BIO_free(bio);
+ return NULL;
+ }
+ BIO_free(bio);
+
+ if (cert == NULL)
+ {
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ return (PyObject *)crypto_X509_New(cert, 1);
+}
+
+static char crypto_dump_certificate_doc[] = "\n\
+Dump a certificate to a buffer\n\
+\n\
+Arguments: spam - Always NULL\n\
+ args - The Python argument tuple, should be:\n\
+ type - The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
+ cert - The certificate to dump\n\
+Returns: The buffer with the dumped certificate in\n\
+";
+
+static PyObject *
+crypto_dump_certificate(PyObject *spam, PyObject *args)
+{
+ int type, ret, buf_len;
+ char *temp;
+ PyObject *buffer;
+ BIO *bio;
+ crypto_X509Obj *cert;
+
+ if (!PyArg_ParseTuple(args, "iO!:dump_certificate", &type,
+ &crypto_X509_Type, &cert))
+ return NULL;
+
+ bio = BIO_new(BIO_s_mem());
+ switch (type)
+ {
+ case X509_FILETYPE_PEM:
+ ret = PEM_write_bio_X509(bio, cert->x509);
+ break;
+
+ case X509_FILETYPE_ASN1:
+ ret = i2d_X509_bio(bio, cert->x509);
+ break;
+
+ default:
+ PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
+ BIO_free(bio);
+ return NULL;
+ }
+
+ if (ret == 0)
+ {
+ BIO_free(bio);
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ buf_len = BIO_get_mem_data(bio, &temp);
+ buffer = PyString_FromStringAndSize(temp, buf_len);
+ BIO_free(bio);
+
+ return buffer;
+}
+
+static char crypto_load_certificate_request_doc[] = "\n\
+Load a certificate request from a buffer\n\
+\n\
+Arguments: spam - Always NULL\n\
+ args - The Python argument tuple, should be:\n\
+ type - The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
+ buffer - The buffer the certificate request is stored in\n\
+Returns: The X509Req object\n\
+";
+
+static PyObject *
+crypto_load_certificate_request(PyObject *spam, PyObject *args)
+{
+ crypto_X509ReqObj *crypto_X509Req_New(X509_REQ *, int);
+ int type, len;
+ char *buffer;
+ BIO *bio;
+ X509_REQ *req;
+
+ if (!PyArg_ParseTuple(args, "is#:load_certificate_request", &type, &buffer, &len))
+ return NULL;
+
+ bio = BIO_new_mem_buf(buffer, len);
+ switch (type)
+ {
+ case X509_FILETYPE_PEM:
+ req = PEM_read_bio_X509_REQ(bio, NULL, NULL, NULL);
+ break;
+
+ case X509_FILETYPE_ASN1:
+ req = d2i_X509_REQ_bio(bio, NULL);
+ break;
+
+ default:
+ PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
+ BIO_free(bio);
+ return NULL;
+ }
+ BIO_free(bio);
+
+ if (req == NULL)
+ {
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ return (PyObject *)crypto_X509Req_New(req, 1);
+}
+
+static char crypto_dump_certificate_request_doc[] = "\n\
+Dump a certificate request to a buffer\n\
+\n\
+Arguments: spam - Always NULL\n\
+ args - The Python argument tuple, should be:\n\
+ type - The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
+ req - The certificate request to dump\n\
+Returns: The buffer with the dumped certificate request in\n\
+";
+
+static PyObject *
+crypto_dump_certificate_request(PyObject *spam, PyObject *args)
+{
+ int type, ret, buf_len;
+ char *temp;
+ PyObject *buffer;
+ BIO *bio;
+ crypto_X509ReqObj *req;
+
+ if (!PyArg_ParseTuple(args, "iO!:dump_certificate_request", &type,
+ &crypto_X509Req_Type, &req))
+ return NULL;
+
+ bio = BIO_new(BIO_s_mem());
+ switch (type)
+ {
+ case X509_FILETYPE_PEM:
+ ret = PEM_write_bio_X509_REQ(bio, req->x509_req);
+ break;
+
+ case X509_FILETYPE_ASN1:
+ ret = i2d_X509_REQ_bio(bio, req->x509_req);
+ break;
+
+ default:
+ PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
+ BIO_free(bio);
+ return NULL;
+ }
+
+ if (ret == 0)
+ {
+ BIO_free(bio);
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ buf_len = BIO_get_mem_data(bio, &temp);
+ buffer = PyString_FromStringAndSize(temp, buf_len);
+ BIO_free(bio);
+
+ return buffer;
+}
+
+static char crypto_load_pkcs7_data_doc[] = "\n\
+Load pkcs7 data from a buffer\n\
+\n\
+Arguments: spam - Always NULL\n\
+ args - The argument tuple, should be:\n\
+ type - The file type (one of FILETYPE_PEM or FILETYPE_ASN1)\n\
+ buffer - The buffer with the pkcs7 data.\n\
+Returns: The PKCS7 object\n\
+";
+
+static PyObject *
+crypto_load_pkcs7_data(PyObject *spam, PyObject *args)
+{
+ int type, len;
+ char *buffer;
+ BIO *bio;
+ PKCS7 *pkcs7 = NULL;
+
+ if (!PyArg_ParseTuple(args, "is#:load_pkcs7_data", &type, &buffer, &len))
+ return NULL;
+
+ /*
+ * Try to read the pkcs7 data from the bio
+ */
+ bio = BIO_new_mem_buf(buffer, len);
+ switch (type)
+ {
+ case X509_FILETYPE_PEM:
+ pkcs7 = PEM_read_bio_PKCS7(bio, NULL, NULL, NULL);
+ break;
+
+ case X509_FILETYPE_ASN1:
+ pkcs7 = d2i_PKCS7_bio(bio, NULL);
+ break;
+
+ default:
+ PyErr_SetString(PyExc_ValueError,
+ "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
+ return NULL;
+ }
+ BIO_free(bio);
+
+ /*
+ * Check if we got a PKCS7 structure
+ */
+ if (pkcs7 == NULL)
+ {
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ return (PyObject *)crypto_PKCS7_New(pkcs7, 1);
+}
+
+static char crypto_load_pkcs12_doc[] = "\n\
+Load a PKCS12 object from a buffer\n\
+\n\
+Arguments: spam - Always NULL\n\
+ args - The Python argument tuple, should be:\n\
+ buffer - The buffer the certificate is stored in\n\
+ passphrase (Optional) - The password to decrypt the PKCS12 lump\n\
+Returns: The PKCS12 object\n\
+";
+
+static PyObject *
+crypto_load_pkcs12(PyObject *spam, PyObject *args)
+{
+ crypto_PKCS12Obj *crypto_PKCS12_New(PKCS12 *, char *);
+ int len;
+ char *buffer, *passphrase = NULL;
+ BIO *bio;
+ PKCS12 *p12;
+
+ if (!PyArg_ParseTuple(args, "s#|s:load_pkcs12", &buffer, &len, &passphrase))
+ return NULL;
+
+ bio = BIO_new_mem_buf(buffer, len);
+ if ((p12 = d2i_PKCS12_bio(bio, NULL)) == NULL)
+ {
+ BIO_free(bio);
+ exception_from_error_queue();
+ return NULL;
+ }
+ BIO_free(bio);
+
+ return (PyObject *)crypto_PKCS12_New(p12, passphrase);
+}
+
+
+static char crypto_X509_doc[] = "\n\
+The factory function inserted in the module dictionary to create X509\n\
+objects\n\
+\n\
+Arguments: spam - Always NULL\n\
+ args - The Python argument tuple, should be empty\n\
+Returns: The X509 object\n\
+";
+
+static PyObject *
+crypto_X509(PyObject *spam, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":X509"))
+ return NULL;
+
+ return (PyObject *)crypto_X509_New(X509_new(), 1);
+}
+
+static char crypto_X509Name_doc[] = "\n\
+The factory function inserted in the module dictionary as a copy\n\
+constructor for X509Name objects.\n\
+\n\
+Arguments: spam - Always NULL\n\
+ args - The Python argument tuple, should be:\n\
+ name - An X509Name object to copy\n\
+Returns: The X509Name object\n\
+";
+
+static PyObject *
+crypto_X509Name(PyObject *spam, PyObject *args)
+{
+ crypto_X509NameObj *name;
+
+ if (!PyArg_ParseTuple(args, "O!:X509Name", &crypto_X509Name_Type, &name))
+ return NULL;
+
+ return (PyObject *)crypto_X509Name_New(X509_NAME_dup(name->x509_name), 1);
+}
+
+static char crypto_X509Req_doc[] = "\n\
+The factory function inserted in the module dictionary to create X509Req\n\
+objects\n\
+\n\
+Arguments: spam - Always NULL\n\
+ args - The Python argument tuple, should be empty\n\
+Returns: The X509Req object\n\
+";
+
+static PyObject *
+crypto_X509Req(PyObject *spam, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":X509Req"))
+ return NULL;
+
+ return (PyObject *)crypto_X509Req_New(X509_REQ_new(), 1);
+}
+
+static char crypto_PKey_doc[] = "\n\
+The factory function inserted in the module dictionary to create PKey\n\
+objects\n\
+\n\
+Arguments: spam - Always NULL\n\
+ args - The Python argument tuple, should be empty\n\
+Returns: The PKey object\n\
+";
+
+static PyObject *
+crypto_PKey(PyObject *spam, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":PKey"))
+ return NULL;
+
+ return (PyObject *)crypto_PKey_New(EVP_PKEY_new(), 1);
+}
+
+static char crypto_X509Extension_doc[] = "\n\
+The factory function inserted in the module dictionary to create\n\
+X509Extension objects.\n\
+\n\
+Arguments: spam - Always NULL\n\
+ args - The Python argument tuple, should be\n\
+ typename - ???\n\
+ critical - ???\n\
+ value - ???\n\
+Returns: The X509Extension object\n\
+";
+
+static PyObject *
+crypto_X509Extension(PyObject *spam, PyObject *args)
+{
+ char *type_name, *value;
+ int critical;
+
+ if (!PyArg_ParseTuple(args, "sis:X509Extension", &type_name, &critical,
+ &value))
+ return NULL;
+
+ return (PyObject *)crypto_X509Extension_New(type_name, critical, value);
+}
+
+static char crypto_NetscapeSPKI_doc[] = "\n\
+The factory function inserted in the module dictionary to create NetscapeSPKI\n\
+objects\n\
+\n\
+Arguments: spam - Always NULL\n\
+ args - The Python argument tuple, should be empty or, optionally\n\
+ enc - Base64 encoded NetscapeSPKI object.\n\
+Returns: The NetscapeSPKI object\n\
+";
+
+static PyObject *
+crypto_NetscapeSPKI(PyObject *spam, PyObject *args)
+{
+ char *enc = NULL;
+ int enc_len = -1;
+ NETSCAPE_SPKI *spki;
+
+ if (!PyArg_ParseTuple(args, "|s#:NetscapeSPKI", &enc, &enc_len))
+ return NULL;
+
+ if (enc_len >= 0)
+ spki = NETSCAPE_SPKI_b64_decode(enc, enc_len);
+ else
+ spki = NETSCAPE_SPKI_new();
+ if (spki == NULL)
+ {
+ exception_from_error_queue();
+ return NULL;
+ }
+ return (PyObject *)crypto_NetscapeSPKI_New(spki, 1);
+}
+
+/* Methods in the OpenSSL.crypto module (i.e. none) */
+static PyMethodDef crypto_methods[] = {
+ /* Module functions */
+ { "load_privatekey", (PyCFunction)crypto_load_privatekey, METH_VARARGS, crypto_load_privatekey_doc },
+ { "dump_privatekey", (PyCFunction)crypto_dump_privatekey, METH_VARARGS, crypto_dump_privatekey_doc },
+ { "load_certificate", (PyCFunction)crypto_load_certificate, METH_VARARGS, crypto_load_certificate_doc },
+ { "dump_certificate", (PyCFunction)crypto_dump_certificate, METH_VARARGS, crypto_dump_certificate_doc },
+ { "load_certificate_request", (PyCFunction)crypto_load_certificate_request, METH_VARARGS, crypto_load_certificate_request_doc },
+ { "dump_certificate_request", (PyCFunction)crypto_dump_certificate_request, METH_VARARGS, crypto_dump_certificate_request_doc },
+ { "load_pkcs7_data", (PyCFunction)crypto_load_pkcs7_data, METH_VARARGS, crypto_load_pkcs7_data_doc },
+ { "load_pkcs12", (PyCFunction)crypto_load_pkcs12, METH_VARARGS, crypto_load_pkcs12_doc },
+ /* Factory functions */
+ { "X509", (PyCFunction)crypto_X509, METH_VARARGS, crypto_X509_doc },
+ { "X509Name",(PyCFunction)crypto_X509Name,METH_VARARGS, crypto_X509Name_doc },
+ { "X509Req", (PyCFunction)crypto_X509Req, METH_VARARGS, crypto_X509Req_doc },
+ { "PKey", (PyCFunction)crypto_PKey, METH_VARARGS, crypto_PKey_doc },
+ { "X509Extension", (PyCFunction)crypto_X509Extension, METH_VARARGS, crypto_X509Extension_doc },
+ { "NetscapeSPKI", (PyCFunction)crypto_NetscapeSPKI, METH_VARARGS, crypto_NetscapeSPKI_doc },
+ { NULL, NULL }
+};
+
+/*
+ * Initialize crypto sub module
+ *
+ * Arguments: None
+ * Returns: None
+ */
+void
+initcrypto(void)
+{
+ static void *crypto_API[crypto_API_pointers];
+ PyObject *c_api_object;
+ PyObject *module, *dict;
+
+ ERR_load_crypto_strings();
+ OpenSSL_add_all_algorithms();
+
+ if ((module = Py_InitModule3("crypto", crypto_methods, crypto_doc)) == NULL)
+ return;
+
+ /* Initialize the C API pointer array */
+ crypto_API[crypto_X509_New_NUM] = (void *)crypto_X509_New;
+ crypto_API[crypto_X509Name_New_NUM] = (void *)crypto_X509Name_New;
+ crypto_API[crypto_X509Req_New_NUM] = (void *)crypto_X509Req_New;
+ crypto_API[crypto_X509Store_New_NUM] = (void *)crypto_X509Store_New;
+ crypto_API[crypto_PKey_New_NUM] = (void *)crypto_PKey_New;
+ crypto_API[crypto_X509Extension_New_NUM] = (void *)crypto_X509Extension_New;
+ crypto_API[crypto_PKCS7_New_NUM] = (void *)crypto_PKCS7_New;
+ crypto_API[crypto_NetscapeSPKI_New_NUM] = (void *)crypto_NetscapeSPKI_New;
+ c_api_object = PyCObject_FromVoidPtr((void *)crypto_API, NULL);
+ if (c_api_object != NULL)
+ PyModule_AddObject(module, "_C_API", c_api_object);
+
+ crypto_Error = PyErr_NewException("OpenSSL.crypto.Error", NULL, NULL);
+ if (crypto_Error == NULL)
+ goto error;
+ if (PyModule_AddObject(module, "Error", crypto_Error) != 0)
+ goto error;
+
+ PyModule_AddIntConstant(module, "FILETYPE_PEM", X509_FILETYPE_PEM);
+ PyModule_AddIntConstant(module, "FILETYPE_ASN1", X509_FILETYPE_ASN1);
+
+ PyModule_AddIntConstant(module, "TYPE_RSA", crypto_TYPE_RSA);
+ PyModule_AddIntConstant(module, "TYPE_DSA", crypto_TYPE_DSA);
+
+ dict = PyModule_GetDict(module);
+ if (!init_crypto_x509(dict))
+ goto error;
+ if (!init_crypto_x509name(dict))
+ goto error;
+ if (!init_crypto_x509store(dict))
+ goto error;
+ if (!init_crypto_x509req(dict))
+ goto error;
+ if (!init_crypto_pkey(dict))
+ goto error;
+ if (!init_crypto_x509extension(dict))
+ goto error;
+ if (!init_crypto_pkcs7(dict))
+ goto error;
+ if (!init_crypto_pkcs12(dict))
+ goto error;
+ if (!init_crypto_netscape_spki(dict))
+ goto error;
+
+error:
+ ;
+}
+
diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h
new file mode 100644
index 0000000..0a71d2a
--- /dev/null
+++ b/src/crypto/crypto.h
@@ -0,0 +1,120 @@
+/*
+ * crypto.h
+ *
+ * Copyright (C) AB Strakt 2001, All rights reserved
+ *
+ * Exports from crypto.c.
+ * See the file RATIONALE for a short explanation of why this module was written.
+ *
+ * Reviewed 2001-07-23
+ *
+ * @(#) $Id: crypto.h,v 1.14 2004/08/09 13:41:25 martin Exp $
+ */
+#ifndef PyOpenSSL_CRYPTO_H_
+#define PyOpenSSL_CRYPTO_H_
+
+#include <Python.h>
+#include "x509.h"
+#include "x509name.h"
+#include "netscape_spki.h"
+#include "x509store.h"
+#include "x509req.h"
+#include "pkey.h"
+#include "x509ext.h"
+#include "pkcs7.h"
+#include "pkcs12.h"
+#include "../util.h"
+
+extern PyObject *crypto_Error;
+
+#ifdef exception_from_error_queue
+# undef exception_from_error_queue
+#endif
+#define exception_from_error_queue() do { \
+ PyObject *errlist = error_queue_to_list(); \
+ PyErr_SetObject(crypto_Error, errlist); \
+ Py_DECREF(errlist); \
+} while (0)
+
+#define crypto_X509_New_NUM 0
+#define crypto_X509_New_RETURN crypto_X509Obj *
+#define crypto_X509_New_PROTO (X509 *, int)
+
+#define crypto_X509Req_New_NUM 1
+#define crypto_X509Req_New_RETURN crypto_X509ReqObj *
+#define crypto_X509Req_New_PROTO (X509_REQ *, int)
+
+#define crypto_X509Store_New_NUM 2
+#define crypto_X509Store_New_RETURN crypto_X509StoreObj *
+#define crypto_X509Store_New_PROTO (X509_STORE *, int)
+
+#define crypto_PKey_New_NUM 3
+#define crypto_PKey_New_RETURN crypto_PKeyObj *
+#define crypto_PKey_New_PROTO (EVP_PKEY *, int)
+
+#define crypto_X509Name_New_NUM 4
+#define crypto_X509Name_New_RETURN crypto_X509NameObj *
+#define crypto_X509Name_New_PROTO (X509_NAME *, int)
+
+#define crypto_X509Extension_New_NUM 5
+#define crypto_X509Extension_New_RETURN crypto_X509ExtensionObj *
+#define crypto_X509Extension_New_PROTO (char *, int, char *)
+
+#define crypto_PKCS7_New_NUM 6
+#define crypto_PKCS7_New_RETURN crypto_PKCS7Obj *
+#define crypto_PKCS7_New_PROTO (PKCS7 *, int)
+
+#define crypto_NetscapeSPKI_New_NUM 7
+#define crypto_NetscapeSPKI_New_RETURN crypto_NetscapeSPKIObj *
+#define crypto_NetscapeSPKI_New_PROTO (NETSCAPE_SPKI *, int)
+
+#define crypto_API_pointers 8
+
+#ifdef crypto_MODULE
+
+extern crypto_X509_New_RETURN crypto_X509_New crypto_X509_New_PROTO;
+extern crypto_X509Name_New_RETURN crypto_X509Name_New crypto_X509Name_New_PROTO;
+extern crypto_X509Req_New_RETURN crypto_X509Req_New crypto_X509Req_New_PROTO;
+extern crypto_X509Store_New_RETURN crypto_X509Store_New crypto_X509Store_New_PROTO;
+extern crypto_PKey_New_RETURN crypto_PKey_New crypto_PKey_New_PROTO;
+extern crypto_X509Extension_New_RETURN crypto_X509Extension_New crypto_X509Extension_New_PROTO;
+extern crypto_PKCS7_New_RETURN crypto_PKCS7_New crypto_PKCS7_New_PROTO;
+extern crypto_NetscapeSPKI_New_RETURN crypto_NetscapeSPKI_New crypto_NetscapeSPKI_New_PROTO;
+
+#else /* crypto_MODULE */
+
+extern void **crypto_API;
+
+#define crypto_X509_New \
+ (*(crypto_X509_New_RETURN (*)crypto_X509_New_PROTO) crypto_API[crypto_X509_New_NUM])
+#define crypto_X509Name_New \
+ (*(crypto_X509Name_New_RETURN (*)crypto_X509Name_New_PROTO) crypto_API[crypto_X509Name_New_NUM])
+#define crypto_X509Req_New \
+ (*(crypto_X509Req_New_RETURN (*)crypto_X509Req_New_PROTO) crypto_API[crypto_X509Req_New_NUM])
+#define crypto_X509Store_New \
+ (*(crypto_X509Store_New_RETURN (*)crypto_X509Store_New_PROTO) crypto_API[crypto_X509Store_New_NUM])
+#define crypto_PKey_New \
+ (*(crypto_PKey_New_RETURN (*)crypto_PKey_New_PROTO) crypto_API[crypto_PKey_New_NUM])
+#define crypto_X509Extension_New\
+ (*(crypto_X509Extension_New_RETURN (*)crypto_X509Extension_New_PROTO) crypto_API[crypto_X509Extension_New_NUM])
+#define crypto_PKCS7_New \
+ (*(crypto_PKCS7_New_RETURN (*)crypto_PKCS7_New_PROTO) crypto_API[crypto_PKCS7_New_NUM])
+#define crypto_NetscapeSPKI_New \
+ (*(crypto_NetscapeSPKI_New_RETURN (*)crypto_NetscapeSPKI_New_PROTO) crypto_API[crypto_NetscapeSPKI_New_NUM])
+
+#define import_crypto() \
+{ \
+ PyObject *crypto_module = PyImport_ImportModule("OpenSSL.crypto"); \
+ if (crypto_module != NULL) { \
+ PyObject *crypto_dict, *crypto_api_object; \
+ crypto_dict = PyModule_GetDict(crypto_module); \
+ crypto_api_object = PyDict_GetItemString(crypto_dict, "_C_API"); \
+ if (PyCObject_Check(crypto_api_object)) { \
+ crypto_API = (void **)PyCObject_AsVoidPtr(crypto_api_object); \
+ } \
+ } \
+}
+
+#endif /* crypto_MODULE */
+
+#endif /* PyOpenSSL_CRYPTO_H_ */
diff --git a/src/crypto/netscape_spki.c b/src/crypto/netscape_spki.c
new file mode 100644
index 0000000..cc54783
--- /dev/null
+++ b/src/crypto/netscape_spki.c
@@ -0,0 +1,257 @@
+/*
+ * netscape_spki.c
+ *
+ * Copyright (C) Tollef Fog Heen 2003
+ *
+ * Netscape SPKI handling, thin wrapper
+ */
+#include <Python.h>
+#define crypto_MODULE
+#include "crypto.h"
+
+static char *CVSid = "@(#) $Id: netscape_spki.c,v 1.1 2004/08/09 13:41:25 martin Exp $";
+
+
+/*
+ * Constructor for Nestcape_SPKI, never called by Python code directly
+ *
+ * Arguments: name - A "real" NetscapeSPKI object
+ * dealloc - Boolean value to specify whether the destructor should
+ * free the "real" NetscapeSPKI object
+ * Returns: The newly created NetscapeSPKI object
+ */
+crypto_NetscapeSPKIObj *
+crypto_NetscapeSPKI_New(NETSCAPE_SPKI *name, int dealloc)
+{
+ crypto_NetscapeSPKIObj *self;
+
+ self = PyObject_New(crypto_NetscapeSPKIObj, &crypto_NetscapeSPKI_Type);
+
+ if (self == NULL)
+ return NULL;
+
+ self->netscape_spki = name;
+ self->dealloc = dealloc;
+
+ return self;
+}
+
+/*
+ * Deallocate the memory used by the NetscapeSPKI object
+ *
+ * Arguments: self - The NetscapeSPKI object
+ * Returns: None
+ */
+static void
+crypto_NetscapeSPKI_dealloc(crypto_NetscapeSPKIObj *self)
+{
+ /* Sometimes we don't have to dealloc this */
+ if (self->dealloc)
+ NETSCAPE_SPKI_free(self->netscape_spki);
+
+ PyObject_Del(self);
+}
+
+static char crypto_NetscapeSPKI_sign_doc[] = "\n\
+Sign the certificate request using the supplied key and digest\n\
+\n\
+Arguments: self - The NetscapeSPKI object\n\
+ args - The Python argument tuple, should be:\n\
+ pkey - The key to sign with\n\
+ digest - The message digest to use\n\
+Returns: None\n\
+";
+
+static PyObject *
+crypto_NetscapeSPKI_sign(crypto_NetscapeSPKIObj *self, PyObject *args)
+{
+ crypto_PKeyObj *pkey;
+ char *digest_name;
+ const EVP_MD *digest;
+
+ if (!PyArg_ParseTuple(args, "O!s:sign", &crypto_PKey_Type, &pkey,
+ &digest_name))
+ return NULL;
+
+ if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
+ {
+ PyErr_SetString(PyExc_ValueError, "No such digest method");
+ return NULL;
+ }
+
+ if (!NETSCAPE_SPKI_sign(self->netscape_spki, pkey->pkey, digest))
+ {
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char crypto_NetscapeSPKI_verify_doc[] = "\n\
+Verifies a certificate request using the supplied public key\n\
+ \n\
+Arguments: self - NetscapeSPKI object\n\
+ args - The Python argument tuple, should be:\n\
+ key - a public key\n\
+Returns: True, if the signature is correct, 0 otherwise.\n\
+";
+
+PyObject *
+crypto_NetscapeSPKI_verify(crypto_NetscapeSPKIObj *self, PyObject *args)
+{
+ crypto_PKeyObj *pkey;
+ int answer;
+
+ if (!PyArg_ParseTuple(args, "O!:verify", &crypto_PKey_Type, &pkey))
+ return NULL;
+
+ if ((answer = NETSCAPE_SPKI_verify(self->netscape_spki, pkey->pkey)) < 0)
+ {
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ return PyInt_FromLong((long)answer);
+}
+
+static char crypto_NetscapeSPKI_b64_encode_doc[] = "\n\
+Generate a base64 encoded string from an SPKI\n\
+ \n\
+Arguments: self - NetscapeSPKI object\n\
+ args - The Python argument tuple, should be empty\n\
+Returns: The base64 encoded string\n\
+";
+
+PyObject *
+crypto_NetscapeSPKI_b64_encode(crypto_NetscapeSPKIObj *self, PyObject *args)
+{
+ char *str;
+
+ if (!PyArg_ParseTuple(args, ":b64_encode"))
+ return NULL;
+
+ str = NETSCAPE_SPKI_b64_encode(self->netscape_spki);
+ return PyString_FromString(str);
+}
+
+
+static char crypto_NetscapeSPKI_get_pubkey_doc[] = "\n\
+Get the public key of the certificate\n\
+\n\
+Arguments: self - The NETSCAPE_SPKI object\n\
+ args - The Python argument tuple, should be empty\n\
+Returns: The public key\n\
+";
+
+static PyObject *
+crypto_NetscapeSPKI_get_pubkey(crypto_NetscapeSPKIObj *self, PyObject *args)
+{
+ crypto_PKeyObj *crypto_PKey_New(EVP_PKEY *, int);
+ EVP_PKEY *pkey;
+
+ if (!PyArg_ParseTuple(args, ":get_pubkey"))
+ return NULL;
+
+ if ((pkey = NETSCAPE_SPKI_get_pubkey(self->netscape_spki)) == NULL)
+ {
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ return (PyObject *)crypto_PKey_New(pkey, 0);
+}
+
+static char crypto_NetscapeSPKI_set_pubkey_doc[] = "\n\
+Set the public key of the certificate\n\
+\n\
+Arguments: self - The Netscape SPKI object\n\
+ args - The Python argument tuple, should be:\n\
+ pkey - The public key\n\
+Returns: None\n\
+";
+
+static PyObject *
+crypto_NetscapeSPKI_set_pubkey(crypto_NetscapeSPKIObj *self, PyObject *args)
+{
+ crypto_PKeyObj *pkey;
+
+ if (!PyArg_ParseTuple(args, "O!:set_pubkey", &crypto_PKey_Type, &pkey))
+ return NULL;
+
+ if (!NETSCAPE_SPKI_set_pubkey(self->netscape_spki, pkey->pkey))
+ {
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+/*
+ * ADD_METHOD(name) expands to a correct PyMethodDef declaration
+ * { 'name', (PyCFunction)crypto_NetscapeSPKI_name, METH_VARARGS }
+ * for convenience
+ */
+#define ADD_METHOD(name) \
+ { #name, (PyCFunction)crypto_NetscapeSPKI_##name, METH_VARARGS, crypto_NetscapeSPKI_##name##_doc }
+static PyMethodDef crypto_NetscapeSPKI_methods[] =
+{
+ ADD_METHOD(get_pubkey),
+ ADD_METHOD(set_pubkey),
+ ADD_METHOD(b64_encode),
+ ADD_METHOD(sign),
+ ADD_METHOD(verify),
+ { NULL, NULL }
+};
+#undef ADD_METHOD
+
+/*
+ * Find attribute
+ *
+ * Arguments: self - The NetscapeSPKI object
+ * name - The attribute name
+ * Returns: A Python object for the attribute, or NULL if something went
+ * wrong
+ */
+static PyObject *
+crypto_NetscapeSPKI_getattr(crypto_NetscapeSPKIObj *self, char *name)
+{
+ return Py_FindMethod(crypto_NetscapeSPKI_methods, (PyObject *)self, name);
+}
+
+PyTypeObject crypto_NetscapeSPKI_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "NetscapeSPKI",
+ sizeof(crypto_NetscapeSPKIObj),
+ 0,
+ (destructor)crypto_NetscapeSPKI_dealloc,
+ NULL, /* print */
+ (getattrfunc)crypto_NetscapeSPKI_getattr,
+ NULL, /* setattr */
+ NULL, /* compare */
+ NULL, /* repr */
+ NULL, /* as_number */
+ NULL, /* as_sequence */
+ NULL, /* as_mapping */
+ NULL /* hash */
+};
+
+
+/*
+ * Initialize the X509Name part of the crypto module
+ *
+ * Arguments: dict - The crypto module dictionary
+ * Returns: None
+ */
+int
+init_crypto_netscape_spki(PyObject *dict)
+{
+ crypto_NetscapeSPKI_Type.ob_type = &PyType_Type;
+ Py_INCREF(&crypto_NetscapeSPKI_Type);
+ PyDict_SetItemString(dict, "NetscapeSPKIType", (PyObject *)&crypto_NetscapeSPKI_Type);
+ return 1;
+}
diff --git a/src/crypto/netscape_spki.h b/src/crypto/netscape_spki.h
new file mode 100644
index 0000000..19389d8
--- /dev/null
+++ b/src/crypto/netscape_spki.h
@@ -0,0 +1,29 @@
+/*
+ * netscape_spki.h
+ *
+ * Copyright (C) Tollef Fog Heen 2003, All rights reserved
+ *
+ * Handle Netscape SPKI (challenge response) certificate requests.
+ *
+ *
+ */
+#ifndef PyOpenSSL_crypto_Netscape_SPKI_H_
+#define PyOpenSSL_crypto_Netscape_SPKI_H_
+
+#include <Python.h>
+#include <openssl/ssl.h>
+
+extern int init_crypto_netscape_spki (PyObject *);
+
+extern PyTypeObject crypto_NetscapeSPKI_Type;
+
+#define crypto_NetscapeSPKI_Check(v) ((v)->ob_type == &crypto_NetscapeSPKI_Type)
+
+typedef struct {
+ PyObject_HEAD
+ NETSCAPE_SPKI *netscape_spki;
+ int dealloc;
+} crypto_NetscapeSPKIObj;
+
+
+#endif
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;
+}
+
diff --git a/src/crypto/pkcs12.h b/src/crypto/pkcs12.h
new file mode 100644
index 0000000..32c9ec4
--- /dev/null
+++ b/src/crypto/pkcs12.h
@@ -0,0 +1,30 @@
+/*
+ * pkcs12.h
+ *
+ * Copyright (C) AB Strakt 2001, All rights reserved
+ *
+ * Export PKCS12 functions and data structure.
+ *
+ * @(#) $$
+ */
+#ifndef PyOpenSSL_crypto_PKCS12_H_
+#define PyOpenSSL_crypto_PKCS12_H_
+
+#include <Python.h>
+#include <openssl/pkcs12.h>
+#include <openssl/asn1.h>
+
+extern int init_crypto_pkcs12 (PyObject *);
+
+extern PyTypeObject crypto_PKCS12_Type;
+
+#define crypto_PKCS12_Check(v) ((v)->ob_type == &crypto_PKCS12_Type)
+
+typedef struct {
+ PyObject_HEAD
+ PyObject *cert;
+ PyObject *key;
+ PyObject *cacerts;
+} crypto_PKCS12Obj;
+
+#endif
diff --git a/src/crypto/pkcs7.c b/src/crypto/pkcs7.c
new file mode 100644
index 0000000..1fb20a9
--- /dev/null
+++ b/src/crypto/pkcs7.c
@@ -0,0 +1,223 @@
+/*
+ * pkcs7.c
+ *
+ * Copyright (C) AB Strakt 2002, All rights reserved
+ *
+ * PKCS7 handling code, mostly thin wrappers around OpenSSL.
+ * See the file RATIONALE for a short explanation of why this module was written.
+ *
+ */
+#include <Python.h>
+#define crypto_MODULE
+#include "crypto.h"
+
+static char *CVSid = "@(#) $Id: pkcs7.c,v 1.2 2002/07/09 12:55:13 martin Exp $";
+
+static char crypto_PKCS7_type_is_signed_doc[] = "\n\
+Check if this NID_pkcs7_signed object\n\
+\n\
+Arguments: self - The PKCS7 object\n\
+ args - An empty argument tuple\n\
+Returns: True if the PKCS7 is of type signed\n\
+";
+
+static PyObject *
+crypto_PKCS7_type_is_signed(crypto_PKCS7Obj *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":type_is_signed"))
+ return NULL;
+
+ if (PKCS7_type_is_signed(self->pkcs7))
+ return PyInt_FromLong(1L);
+ else
+ return PyInt_FromLong(0L);
+}
+
+static char crypto_PKCS7_type_is_enveloped_doc[] = "\n\
+Check if this NID_pkcs7_enveloped object\n\
+\n\
+Arguments: self - The PKCS7 object\n\
+ args - An empty argument tuple\n\
+Returns: True if the PKCS7 is of type enveloped\n\
+";
+
+static PyObject *
+crypto_PKCS7_type_is_enveloped(crypto_PKCS7Obj *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":type_is_enveloped"))
+ return NULL;
+
+ if (PKCS7_type_is_enveloped(self->pkcs7))
+ return PyInt_FromLong(1L);
+ else
+ return PyInt_FromLong(0L);
+}
+
+static char crypto_PKCS7_type_is_signedAndEnveloped_doc[] = "\n\
+Check if this NID_pkcs7_signedAndEnveloped object\n\
+\n\
+Arguments: self - The PKCS7 object\n\
+ args - An empty argument tuple\n\
+Returns: True if the PKCS7 is of type signedAndEnveloped\n\
+";
+
+static PyObject *
+crypto_PKCS7_type_is_signedAndEnveloped(crypto_PKCS7Obj *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":type_is_signedAndEnveloped"))
+ return NULL;
+
+ if (PKCS7_type_is_signedAndEnveloped(self->pkcs7))
+ return PyInt_FromLong(1L);
+ else
+ return PyInt_FromLong(0L);
+}
+
+static char crypto_PKCS7_type_is_data_doc[] = "\n\
+Check if this NID_pkcs7_data object\n\
+\n\
+Arguments: self - The PKCS7 object\n\
+ args - An empty argument tuple\n\
+Returns: True if the PKCS7 is of type data\n\
+";
+
+static PyObject *
+crypto_PKCS7_type_is_data(crypto_PKCS7Obj *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":type_is_data"))
+ return NULL;
+
+ if (PKCS7_type_is_data(self->pkcs7))
+ return PyInt_FromLong(1L);
+ else
+ return PyInt_FromLong(0L);
+}
+
+static char crypto_PKCS7_get_type_name_doc[] = "\n\
+Returns the type name of the PKCS7 structure\n\
+\n\
+Arguments: self - The PKCS7 object\n\
+ args - An empty argument tuple\n\
+Returns: A string with the typename\n\
+";
+
+static PyObject *
+crypto_PKCS7_get_type_name(crypto_PKCS7Obj *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":get_type_name"))
+ return NULL;
+
+ /*
+ * return a string with the typename
+ */
+ return PyString_FromString(OBJ_nid2sn(OBJ_obj2nid(self->pkcs7->type)));
+}
+
+/*
+ * ADD_METHOD(name) expands to a correct PyMethodDef declaration
+ * { 'name', (PyCFunction)crypto_PKCS7_name, METH_VARARGS }
+ * for convenience
+ */
+#define ADD_METHOD(name) \
+ { #name, (PyCFunction)crypto_PKCS7_##name, METH_VARARGS, crypto_PKCS7_##name##_doc }
+static PyMethodDef crypto_PKCS7_methods[] =
+{
+ ADD_METHOD(type_is_signed),
+ ADD_METHOD(type_is_enveloped),
+ ADD_METHOD(type_is_signedAndEnveloped),
+ ADD_METHOD(type_is_data),
+ ADD_METHOD(get_type_name),
+ { NULL, NULL }
+};
+#undef ADD_METHOD
+
+
+/*
+ * Constructor for PKCS7 objects, never called by Python code directly
+ *
+ * Arguments: pkcs7 - A "real" pkcs7 certificate object
+ * dealloc - Boolean value to specify whether the destructor should
+ * free the "real" pkcs7 object
+ * Returns: The newly created pkcs7 object
+ */
+crypto_PKCS7Obj *
+crypto_PKCS7_New(PKCS7 *pkcs7, int dealloc)
+{
+ crypto_PKCS7Obj *self;
+
+ self = PyObject_New(crypto_PKCS7Obj, &crypto_PKCS7_Type);
+
+ if (self == NULL)
+ return NULL;
+
+ self->pkcs7 = pkcs7;
+ self->dealloc = dealloc;
+
+ return self;
+}
+
+/*
+ * Deallocate the memory used by the PKCS7 object
+ *
+ * Arguments: self - The PKCS7 object
+ * Returns: None
+ */
+static void
+crypto_PKCS7_dealloc(crypto_PKCS7Obj *self)
+{
+ /* Sometimes we don't have to dealloc the "real" PKCS7 pointer ourselves */
+ if (self->dealloc)
+ PKCS7_free(self->pkcs7);
+
+ PyObject_Del(self);
+}
+
+/*
+ * Find attribute
+ *
+ * Arguments: self - The PKCS7 object
+ * name - The attribute name
+ * Returns: A Python object for the attribute, or NULL if something went
+ * wrong
+ */
+static PyObject *
+crypto_PKCS7_getattr(crypto_PKCS7Obj *self, char *name)
+{
+ return Py_FindMethod(crypto_PKCS7_methods, (PyObject *)self, name);
+}
+
+PyTypeObject crypto_PKCS7_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "PKCS7",
+ sizeof(crypto_PKCS7Obj),
+ 0,
+ (destructor)crypto_PKCS7_dealloc,
+ NULL, /* print */
+ (getattrfunc)crypto_PKCS7_getattr,
+ NULL, /* setattr */
+ NULL, /* compare */
+ NULL, /* repr */
+ NULL, /* as_number */
+ NULL, /* as_sequence */
+ NULL, /* as_mapping */
+ NULL, /* hash */
+ NULL, /* call */
+ NULL /* str */
+};
+
+/*
+ * Initialize the PKCS7 part of the crypto sub module
+ *
+ * Arguments: dict - The crypto module dictionary
+ * Returns: None
+ */
+int
+init_crypto_pkcs7(PyObject *dict)
+{
+ crypto_PKCS7_Type.ob_type = &PyType_Type;
+ Py_INCREF(&crypto_PKCS7_Type);
+ PyDict_SetItemString(dict, "PKCS7Type", (PyObject *)&crypto_PKCS7_Type);
+ return 1;
+}
+
diff --git a/src/crypto/pkcs7.h b/src/crypto/pkcs7.h
new file mode 100644
index 0000000..bdbb425
--- /dev/null
+++ b/src/crypto/pkcs7.h
@@ -0,0 +1,30 @@
+/*
+ * pkcs7.h
+ *
+ * Copyright (C) AB Strakt 2002, All rights reserved
+ *
+ * Export pkcs7 functions and data structure.
+ * See the file RATIONALE for a short explanation of why this module was written.
+ *
+ * @(#) $Id: pkcs7.h,v 1.2 2002/09/04 22:24:59 iko Exp $
+ */
+#ifndef PyOpenSSL_crypto_PKCS7_H_
+#define PyOpenSSL_crypto_PKCS7_H_
+
+#include <Python.h>
+#include <openssl/pkcs7.h>
+
+extern int init_crypto_pkcs7 (PyObject *);
+
+extern PyTypeObject crypto_PKCS7_Type;
+
+#define crypto_PKCS7_Check(v) ((v)->ob_type == &crypto_PKCS7_Type)
+
+typedef struct {
+ PyObject_HEAD
+ PKCS7 *pkcs7;
+ int dealloc;
+} crypto_PKCS7Obj;
+
+
+#endif
diff --git a/src/crypto/pkey.c b/src/crypto/pkey.c
new file mode 100644
index 0000000..201960f
--- /dev/null
+++ b/src/crypto/pkey.c
@@ -0,0 +1,215 @@
+/*
+ * pkey.c
+ *
+ * Copyright (C) AB Strakt 2001, All rights reserved
+ *
+ * Public/rivate key handling code, mostly thin wrappers around OpenSSL.
+ * See the file RATIONALE for a short explanation of why this module was written.
+ *
+ */
+#include <Python.h>
+#define crypto_MODULE
+#include "crypto.h"
+
+static char *CVSid = "@(#) $Id: pkey.c,v 1.9 2002/07/09 13:47:21 martin Exp $";
+
+/*
+ * This is done every time something fails, so turning it into a macro is
+ * really nice.
+ *
+ * Arguments: None
+ * Returns: Doesn't return
+ */
+#define FAIL() \
+do { \
+ exception_from_error_queue(); \
+ return NULL; \
+} while (0)
+
+
+static char crypto_PKey_generate_key_doc[] = "\n\
+Generate a key of a given type, with a given number of a bits\n\
+\n\
+Arguments: self - The PKey object\n\
+ args - The Python argument tuple, should be:\n\
+ type - The key type (TYPE_RSA or TYPE_DSA)\n\
+ bits - The number of bits\n\
+Returns: None\n\
+";
+
+static PyObject *
+crypto_PKey_generate_key(crypto_PKeyObj *self, PyObject *args)
+{
+ int type, bits;
+ RSA *rsa;
+ DSA *dsa;
+
+ if (!PyArg_ParseTuple(args, "ii:generate_key", &type, &bits))
+ return NULL;
+
+ switch (type)
+ {
+ case crypto_TYPE_RSA:
+ if ((rsa = RSA_generate_key(bits, 0x10001, NULL, NULL)) == NULL)
+ FAIL();
+ if (!EVP_PKEY_assign_RSA(self->pkey, rsa))
+ FAIL();
+ Py_INCREF(Py_None);
+ return Py_None;
+
+ case crypto_TYPE_DSA:
+ if ((dsa = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL)) == NULL)
+ FAIL();
+ if (!DSA_generate_key(dsa))
+ FAIL();
+ if (!EVP_PKEY_assign_DSA(self->pkey, dsa))
+ FAIL();
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ PyErr_SetString(crypto_Error, "No such key type");
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char crypto_PKey_bits_doc[] = "\n\
+Returns the number of bits of the key\n\
+\n\
+Arguments: self - The PKey object\n\
+ args - The Python argument tuple, should be empty\n\
+Returns: The number of bits of the key.\n\
+";
+
+static PyObject *
+crypto_PKey_bits(crypto_PKeyObj *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":bits"))
+ return NULL;
+
+ return PyInt_FromLong(EVP_PKEY_bits(self->pkey));
+}
+
+static char crypto_PKey_type_doc[] = "\n\
+Returns the type of the key\n\
+\n\
+Arguments: self - The PKey object\n\
+ args - The Python argument tuple, should be empty\n\
+Returns: The type of the key.\n\
+";
+
+static PyObject *
+crypto_PKey_type(crypto_PKeyObj *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":type"))
+ return NULL;
+
+ return PyInt_FromLong(self->pkey->type);
+}
+
+
+/*
+ * ADD_METHOD(name) expands to a correct PyMethodDef declaration
+ * { 'name', (PyCFunction)crypto_PKey_name, METH_VARARGS }
+ * for convenience
+ */
+#define ADD_METHOD(name) \
+ { #name, (PyCFunction)crypto_PKey_##name, METH_VARARGS, crypto_PKey_##name##_doc }
+static PyMethodDef crypto_PKey_methods[] =
+{
+ ADD_METHOD(generate_key),
+ ADD_METHOD(bits),
+ ADD_METHOD(type),
+ { NULL, NULL }
+};
+#undef ADD_METHOD
+
+
+/*
+ * Constructor for PKey objects, never called by Python code directly
+ *
+ * Arguments: pkey - A "real" EVP_PKEY object
+ * dealloc - Boolean value to specify whether the destructor should
+ * free the "real" EVP_PKEY object
+ * Returns: The newly created PKey object
+ */
+crypto_PKeyObj *
+crypto_PKey_New(EVP_PKEY *pkey, int dealloc)
+{
+ crypto_PKeyObj *self;
+
+ self = PyObject_New(crypto_PKeyObj, &crypto_PKey_Type);
+
+ if (self == NULL)
+ return NULL;
+
+ self->pkey = pkey;
+ self->dealloc = dealloc;
+
+ return self;
+}
+
+/*
+ * Deallocate the memory used by the PKey object
+ *
+ * Arguments: self - The PKey object
+ * Returns: None
+ */
+static void
+crypto_PKey_dealloc(crypto_PKeyObj *self)
+{
+ /* Sometimes we don't have to dealloc the "real" EVP_PKEY pointer ourselves */
+ if (self->dealloc)
+ EVP_PKEY_free(self->pkey);
+
+ PyObject_Del(self);
+}
+
+/*
+ * Find attribute
+ *
+ * Arguments: self - The PKey object
+ * name - The attribute name
+ * Returns: A Python object for the attribute, or NULL if something went
+ * wrong
+ */
+static PyObject *
+crypto_PKey_getattr(crypto_PKeyObj *self, char *name)
+{
+ return Py_FindMethod(crypto_PKey_methods, (PyObject *)self, name);
+}
+
+PyTypeObject crypto_PKey_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "PKey",
+ sizeof(crypto_PKeyObj),
+ 0,
+ (destructor)crypto_PKey_dealloc,
+ NULL, /* print */
+ (getattrfunc)crypto_PKey_getattr,
+ NULL, /* setattr */
+ NULL, /* compare */
+ NULL, /* repr */
+ NULL, /* as_number */
+ NULL, /* as_sequence */
+ NULL, /* as_mapping */
+ NULL, /* hash */
+};
+
+
+/*
+ * Initialize the PKey part of the crypto sub module
+ *
+ * Arguments: dict - The crypto module dictionary
+ * Returns: None
+ */
+int
+init_crypto_pkey(PyObject *dict)
+{
+ crypto_PKey_Type.ob_type = &PyType_Type;
+ Py_INCREF(&crypto_PKey_Type);
+ PyDict_SetItemString(dict, "PKeyType", (PyObject *)&crypto_PKey_Type);
+ return 1;
+}
+
diff --git a/src/crypto/pkey.h b/src/crypto/pkey.h
new file mode 100644
index 0000000..d46e360
--- /dev/null
+++ b/src/crypto/pkey.h
@@ -0,0 +1,29 @@
+/*
+ * pkey.h
+ *
+ * Copyright (C) AB Strakt 2001, All rights reserved
+ *
+ * Export pkey functions and data structure.
+ * See the file RATIONALE for a short explanation of why this module was written.
+ *
+ * @(#) $Id: pkey.h,v 1.5 2002/09/04 22:24:59 iko Exp $
+ */
+#ifndef PyOpenSSL_crypto_PKEY_H_
+#define PyOpenSSL_crypto_PKEY_H_
+
+extern int init_crypto_pkey (PyObject *);
+
+extern PyTypeObject crypto_PKey_Type;
+
+#define crypto_PKey_Check(v) ((v)->ob_type == &crypto_PKey_Type)
+
+typedef struct {
+ PyObject_HEAD
+ EVP_PKEY *pkey;
+ int dealloc;
+} crypto_PKeyObj;
+
+#define crypto_TYPE_RSA EVP_PKEY_RSA
+#define crypto_TYPE_DSA EVP_PKEY_DSA
+
+#endif
diff --git a/src/crypto/x509.c b/src/crypto/x509.c
new file mode 100644
index 0000000..bcae5f6
--- /dev/null
+++ b/src/crypto/x509.c
@@ -0,0 +1,591 @@
+/*
+ * x509.c
+ *
+ * Copyright (C) AB Strakt 2001, All rights reserved
+ *
+ * Certificate (X.509) 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: x509.c,v 1.20 2004/08/10 10:37:31 martin Exp $";
+
+/*
+ * X.509 is a standard for digital certificates. See e.g. the OpenSSL homepage
+ * http://www.openssl.org/ for more information
+ */
+
+static char crypto_X509_get_version_doc[] = "\n\
+Return version number of the certificate\n\
+\n\
+Arguments: self - The X509 object\n\
+ args - The Python argument tuple, should be empty\n\
+Returns: Version number as a Python integer\n\
+";
+
+static PyObject *
+crypto_X509_get_version(crypto_X509Obj *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":get_version"))
+ return NULL;
+
+ return PyInt_FromLong((long)X509_get_version(self->x509));
+}
+
+static char crypto_X509_set_version_doc[] = "\n\
+Set version number of the certificate\n\
+\n\
+Arguments: self - The X509 object\n\
+ args - The Python argument tuple, should be:\n\
+ version - The version number\n\
+Returns: None\n\
+";
+
+static PyObject *
+crypto_X509_set_version(crypto_X509Obj *self, PyObject *args)
+{
+ int version;
+
+ if (!PyArg_ParseTuple(args, "i:set_version", &version))
+ return NULL;
+
+ X509_set_version(self->x509, version);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char crypto_X509_get_serial_number_doc[] = "\n\
+Return serial number of the certificate\n\
+\n\
+Arguments: self - The X509 object\n\
+ args - The Python argument tuple, should be empty\n\
+Returns: Serial number as a Python integer\n\
+";
+
+static PyObject *
+crypto_X509_get_serial_number(crypto_X509Obj *self, PyObject *args)
+{
+ ASN1_INTEGER *asn1_i;
+
+ if (!PyArg_ParseTuple(args, ":get_serial_number"))
+ return NULL;
+
+ asn1_i = X509_get_serialNumber(self->x509);
+ return PyInt_FromLong(ASN1_INTEGER_get(asn1_i));
+}
+
+static char crypto_X509_set_serial_number_doc[] = "\n\
+Set serial number of the certificate\n\
+\n\
+Arguments: self - The X509 object\n\
+ args - The Python argument tuple, should be:\n\
+ serial - The serial number\n\
+Returns: None\n\
+";
+
+static PyObject *
+crypto_X509_set_serial_number(crypto_X509Obj *self, PyObject *args)
+{
+ long serial;
+
+ if (!PyArg_ParseTuple(args, "l:set_serial_number", &serial))
+ return NULL;
+
+ ASN1_INTEGER_set(X509_get_serialNumber(self->x509), serial);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char crypto_X509_get_issuer_doc[] = "\n\
+Create an X509Name object for the issuer of the certificate\n\
+\n\
+Arguments: self - The X509 object\n\
+ args - The Python argument tuple, should be empty\n\
+Returns: An X509Name object\n\
+";
+
+static PyObject *
+crypto_X509_get_issuer(crypto_X509Obj *self, PyObject *args)
+{
+ crypto_X509NameObj *pyname;
+ X509_NAME *name;
+
+ if (!PyArg_ParseTuple(args, ":get_issuer"))
+ return NULL;
+
+ name = X509_get_issuer_name(self->x509);
+ pyname = crypto_X509Name_New(name, 0);
+ if (pyname != NULL)
+ {
+ pyname->parent_cert = (PyObject *)self;
+ Py_INCREF(self);
+ }
+ return (PyObject *)pyname;
+}
+
+static char crypto_X509_set_issuer_doc[] = "\n\
+Set the issuer of the certificate\n\
+\n\
+Arguments: self - The X509 object\n\
+ args - The Python argument tuple, should be:\n\
+ issuer - The issuer name\n\
+Returns: None\n\
+";
+
+static PyObject *
+crypto_X509_set_issuer(crypto_X509Obj *self, PyObject *args)
+{
+ crypto_X509NameObj *issuer;
+
+ if (!PyArg_ParseTuple(args, "O!:set_issuer", &crypto_X509Name_Type,
+ &issuer))
+ return NULL;
+
+ if (!X509_set_issuer_name(self->x509, issuer->x509_name))
+ {
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char crypto_X509_get_subject_doc[] = "\n\
+Create an X509Name object for the subject of the certificate\n\
+\n\
+Arguments: self - The X509 object\n\
+ args - The Python argument tuple, should be empty\n\
+Returns: An X509Name object\n\
+";
+
+static PyObject *
+crypto_X509_get_subject(crypto_X509Obj *self, PyObject *args)
+{
+ crypto_X509NameObj *pyname;
+ X509_NAME *name;
+
+ if (!PyArg_ParseTuple(args, ":get_subject"))
+ return NULL;
+
+ name = X509_get_subject_name(self->x509);
+ pyname = crypto_X509Name_New(name, 0);
+ if (pyname != NULL)
+ {
+ pyname->parent_cert = (PyObject *)self;
+ Py_INCREF(self);
+ }
+ return (PyObject *)pyname;
+}
+
+static char crypto_X509_set_subject_doc[] = "\n\
+Set the subject of the certificate\n\
+\n\
+Arguments: self - The X509 object\n\
+ args - The Python argument tuple, should be:\n\
+ subject - The subject name\n\
+Returns: None\n\
+";
+
+static PyObject *
+crypto_X509_set_subject(crypto_X509Obj *self, PyObject *args)
+{
+ crypto_X509NameObj *subject;
+
+ if (!PyArg_ParseTuple(args, "O!:set_subject", &crypto_X509Name_Type,
+ &subject))
+ return NULL;
+
+ if (!X509_set_subject_name(self->x509, subject->x509_name))
+ {
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char crypto_X509_get_pubkey_doc[] = "\n\
+Get the public key of the certificate\n\
+\n\
+Arguments: self - The X509 object\n\
+ args - The Python argument tuple, should be empty\n\
+Returns: The public key\n\
+";
+
+static PyObject *
+crypto_X509_get_pubkey(crypto_X509Obj *self, PyObject *args)
+{
+ crypto_PKeyObj *crypto_PKey_New(EVP_PKEY *, int);
+ EVP_PKEY *pkey;
+
+ if (!PyArg_ParseTuple(args, ":get_pubkey"))
+ return NULL;
+
+ if ((pkey = X509_get_pubkey(self->x509)) == NULL)
+ {
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ return (PyObject *)crypto_PKey_New(pkey, 0);
+}
+
+static char crypto_X509_set_pubkey_doc[] = "\n\
+Set the public key of the certificate\n\
+\n\
+Arguments: self - The X509 object\n\
+ args - The Python argument tuple, should be:\n\
+ pkey - The public key\n\
+Returns: None\n\
+";
+
+static PyObject *
+crypto_X509_set_pubkey(crypto_X509Obj *self, PyObject *args)
+{
+ crypto_PKeyObj *pkey;
+
+ if (!PyArg_ParseTuple(args, "O!:set_pubkey", &crypto_PKey_Type, &pkey))
+ return NULL;
+
+ if (!X509_set_pubkey(self->x509, pkey->pkey))
+ {
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char crypto_X509_gmtime_adj_notBefore_doc[] = "\n\
+Adjust the time stamp for when the certificate starts being valid\n\
+\n\
+Arguments: self - The X509 object\n\
+ args - The Python argument tuple, should be:\n\
+ i - The adjustment\n\
+Returns: None\n\
+";
+
+static PyObject *
+crypto_X509_gmtime_adj_notBefore(crypto_X509Obj *self, PyObject *args)
+{
+ long i;
+
+ if (!PyArg_ParseTuple(args, "l:gmtime_adj_notBefore", &i))
+ return NULL;
+
+ X509_gmtime_adj(X509_get_notBefore(self->x509), i);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char crypto_X509_gmtime_adj_notAfter_doc[] = "\n\
+Adjust the time stamp for when the certificate stops being valid\n\
+\n\
+Arguments: self - The X509 object\n\
+ args - The Python argument tuple, should be:\n\
+ i - The adjustment\n\
+Returns: None\n\
+";
+
+static PyObject *
+crypto_X509_gmtime_adj_notAfter(crypto_X509Obj *self, PyObject *args)
+{
+ long i;
+
+ if (!PyArg_ParseTuple(args, "l:gmtime_adj_notAfter", &i))
+ return NULL;
+
+ X509_gmtime_adj(X509_get_notAfter(self->x509), i);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char crypto_X509_sign_doc[] = "\n\
+Sign the certificate using the supplied key and digest\n\
+\n\
+Arguments: self - The X509 object\n\
+ args - The Python argument tuple, should be:\n\
+ pkey - The key to sign with\n\
+ digest - The message digest to use\n\
+Returns: None\n\
+";
+
+static PyObject *
+crypto_X509_sign(crypto_X509Obj *self, PyObject *args)
+{
+ crypto_PKeyObj *pkey;
+ char *digest_name;
+ const EVP_MD *digest;
+
+ if (!PyArg_ParseTuple(args, "O!s:sign", &crypto_PKey_Type, &pkey,
+ &digest_name))
+ return NULL;
+
+ if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
+ {
+ PyErr_SetString(PyExc_ValueError, "No such digest method");
+ return NULL;
+ }
+
+ if (!X509_sign(self->x509, pkey->pkey, digest))
+ {
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char crypto_X509_has_expired_doc[] = "\n\
+Check whether the certificate has expired.\n\
+\n\
+Arguments: self - The X509 object\n\
+ args - The Python argument tuple, should be empty\n\
+Returns: True if the certificate has expired, false otherwise\n\
+";
+
+static PyObject *
+crypto_X509_has_expired(crypto_X509Obj *self, PyObject *args)
+{
+ time_t tnow;
+
+ if (!PyArg_ParseTuple(args, ":has_expired"))
+ return NULL;
+
+ tnow = time(NULL);
+ if (ASN1_UTCTIME_cmp_time_t(X509_get_notAfter(self->x509), tnow) < 0)
+ return PyInt_FromLong(1L);
+ else
+ return PyInt_FromLong(0L);
+}
+
+static char crypto_X509_subject_name_hash_doc[] = "\n\
+Return the hash of the X509 subject.\n\
+\n\
+Arguments: self - The X509 object\n\
+ args - The Python argument tuple, should be empty\n\
+Returns: The hash of the subject\n\
+";
+
+static PyObject *
+crypto_X509_subject_name_hash(crypto_X509Obj *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":subject_name_hash"))
+ return NULL;
+
+ return PyLong_FromLong(X509_subject_name_hash(self->x509));
+}
+
+static char crypto_X509_digest_doc[] = "\n\
+Return the digest of the X509 object.\n\
+\n\
+Arguments: self - The X509 object\n\
+ args - The Python argument tuple, should be empty\n\
+Returns: The digest of the object\n\
+";
+
+static PyObject *
+crypto_X509_digest(crypto_X509Obj *self, PyObject *args)
+{
+ unsigned char fp[EVP_MAX_MD_SIZE];
+ char *tmp;
+ char *digest_name;
+ int len,i;
+ PyObject *ret;
+ const EVP_MD *digest;
+
+ if (!PyArg_ParseTuple(args, "s:digest", &digest_name))
+ return NULL;
+
+ if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
+ {
+ PyErr_SetString(PyExc_ValueError, "No such digest method");
+ return NULL;
+ }
+
+ if (!X509_digest(self->x509,digest,fp,&len))
+ {
+ exception_from_error_queue();
+ }
+ tmp = malloc(3*len+1);
+ memset(tmp, 0, 3*len+1);
+ for (i = 0; i < len; i++) {
+ sprintf(tmp+i*3,"%02X:",fp[i]);
+ }
+ tmp[3*len-1] = 0;
+ ret = PyString_FromStringAndSize(tmp,3*len-1);
+ free(tmp);
+ return ret;
+}
+
+
+static char crypto_X509_add_extensions_doc[] = "\n\
+Add extensions to the certificate.\n\
+\n\
+Arguments: self - X509 object\n\
+ args - The Python argument tuple, should be:\n\
+ extensions - a sequence of X509Extension objects\n\
+Returns: None\n\
+";
+
+static PyObject *
+crypto_X509_add_extensions(crypto_X509Obj *self, PyObject *args)
+{
+ PyObject *extensions, *seq;
+ crypto_X509ExtensionObj *ext;
+ int nr_of_extensions, i;
+
+ if (!PyArg_ParseTuple(args, "O:add_extensions", &extensions))
+ return NULL;
+
+ seq = PySequence_Fast(extensions, "Expected a sequence");
+ if (seq == NULL)
+ return NULL;
+
+ nr_of_extensions = PySequence_Fast_GET_SIZE(seq);
+
+ for (i = 0; i < nr_of_extensions; i++)
+ {
+ ext = (crypto_X509ExtensionObj *)PySequence_Fast_GET_ITEM(seq, i);
+ if (!crypto_X509Extension_Check(ext))
+ {
+ Py_DECREF(seq);
+ PyErr_SetString(PyExc_ValueError,
+ "One of the elements is not an X509Extension");
+ return NULL;
+ }
+ if (!X509_add_ext(self->x509, ext->x509_extension, -1))
+ {
+ Py_DECREF(seq);
+ exception_from_error_queue();
+ return NULL;
+ }
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+/*
+ * ADD_METHOD(name) expands to a correct PyMethodDef declaration
+ * { 'name', (PyCFunction)crypto_X509_name, METH_VARARGS }
+ * for convenience
+ */
+#define ADD_METHOD(name) \
+ { #name, (PyCFunction)crypto_X509_##name, METH_VARARGS, crypto_X509_##name##_doc }
+static PyMethodDef crypto_X509_methods[] =
+{
+ ADD_METHOD(get_version),
+ ADD_METHOD(set_version),
+ ADD_METHOD(get_serial_number),
+ ADD_METHOD(set_serial_number),
+ ADD_METHOD(get_issuer),
+ ADD_METHOD(set_issuer),
+ ADD_METHOD(get_subject),
+ ADD_METHOD(set_subject),
+ ADD_METHOD(get_pubkey),
+ ADD_METHOD(set_pubkey),
+ ADD_METHOD(gmtime_adj_notBefore),
+ ADD_METHOD(gmtime_adj_notAfter),
+ ADD_METHOD(sign),
+ ADD_METHOD(has_expired),
+ ADD_METHOD(subject_name_hash),
+ ADD_METHOD(digest),
+ ADD_METHOD(add_extensions),
+ { NULL, NULL }
+};
+#undef ADD_METHOD
+
+
+/*
+ * Constructor for X509 objects, never called by Python code directly
+ *
+ * Arguments: cert - A "real" X509 certificate object
+ * dealloc - Boolean value to specify whether the destructor should
+ * free the "real" X509 object
+ * Returns: The newly created X509 object
+ */
+crypto_X509Obj *
+crypto_X509_New(X509 *cert, int dealloc)
+{
+ crypto_X509Obj *self;
+
+ self = PyObject_New(crypto_X509Obj, &crypto_X509_Type);
+
+ if (self == NULL)
+ return NULL;
+
+ self->x509 = cert;
+ self->dealloc = dealloc;
+
+ return self;
+}
+
+/*
+ * Deallocate the memory used by the X509 object
+ *
+ * Arguments: self - The X509 object
+ * Returns: None
+ */
+static void
+crypto_X509_dealloc(crypto_X509Obj *self)
+{
+ /* Sometimes we don't have to dealloc the "real" X509 pointer ourselves */
+ if (self->dealloc)
+ X509_free(self->x509);
+
+ PyObject_Del(self);
+}
+
+/*
+ * Find attribute
+ *
+ * Arguments: self - The X509 object
+ * name - The attribute name
+ * Returns: A Python object for the attribute, or NULL if something went
+ * wrong
+ */
+static PyObject *
+crypto_X509_getattr(crypto_X509Obj *self, char *name)
+{
+ return Py_FindMethod(crypto_X509_methods, (PyObject *)self, name);
+}
+
+PyTypeObject crypto_X509_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "X509",
+ sizeof(crypto_X509Obj),
+ 0,
+ (destructor)crypto_X509_dealloc,
+ NULL, /* print */
+ (getattrfunc)crypto_X509_getattr,
+};
+
+/*
+ * Initialize the X509 part of the crypto sub module
+ *
+ * Arguments: dict - The crypto module dictionary
+ * Returns: None
+ */
+int
+init_crypto_x509(PyObject *dict)
+{
+ crypto_X509_Type.ob_type = &PyType_Type;
+ Py_INCREF(&crypto_X509_Type);
+ PyDict_SetItemString(dict, "X509Type", (PyObject *)&crypto_X509_Type);
+ return 1;
+}
+
diff --git a/src/crypto/x509.h b/src/crypto/x509.h
new file mode 100644
index 0000000..40768cf
--- /dev/null
+++ b/src/crypto/x509.h
@@ -0,0 +1,32 @@
+/*
+ * x509.h
+ *
+ * Copyright (C) AB Strakt 2001, All rights reserved
+ *
+ * Export x509 functions and data structure.
+ * See the file RATIONALE for a short explanation of why this module was written.
+ *
+ * Reviewed 2001-07-23
+ *
+ * @(#) $Id: x509.h,v 1.9 2002/09/04 22:24:59 iko Exp $
+ */
+#ifndef PyOpenSSL_crypto_X509_H_
+#define PyOpenSSL_crypto_X509_H_
+
+#include <Python.h>
+#include <openssl/ssl.h>
+
+extern int init_crypto_x509 (PyObject *);
+
+extern PyTypeObject crypto_X509_Type;
+
+#define crypto_X509_Check(v) ((v)->ob_type == &crypto_X509_Type)
+
+typedef struct {
+ PyObject_HEAD
+ X509 *x509;
+ int dealloc;
+} crypto_X509Obj;
+
+
+#endif
diff --git a/src/crypto/x509ext.c b/src/crypto/x509ext.c
new file mode 100644
index 0000000..9a628c3
--- /dev/null
+++ b/src/crypto/x509ext.c
@@ -0,0 +1,254 @@
+/*
+ * x509ext.c
+ *
+ * Export X.509 extension functions and data structures.
+ * See the file RATIONALE for a short explanation of why this module was written.
+ *
+ * @(#) $Id: x509ext.c,v 1.1 2002/07/09 13:34:46 martin Exp $
+ */
+
+#include <Python.h>
+#define crypto_MODULE
+#include "crypto.h"
+
+static char *CVSid = "@(#) $Id: x509ext.c,v 1.1 2002/07/09 13:34:46 martin Exp $";
+
+static char crypto_X509Extension_get_critical_doc[] = "\n\
+Returns the critical field of the X509Extension\n\
+\n\
+Arguments: self - The X509Extension object\n\
+ args - The argument tuple, should be empty\n\
+Returns: The critical field.\n\
+";
+
+static PyObject *
+crypto_X509Extension_get_critical(crypto_X509ExtensionObj *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":get_critical"))
+ return NULL;
+
+ return PyInt_FromLong(X509_EXTENSION_get_critical(self->x509_extension));
+}
+
+/*
+ * ADD_METHOD(name) expands to a correct PyMethodDef declaration
+ * { 'name', (PyCFunction)crypto_X509Extension_name, METH_VARARGS }
+ * for convenience
+ */
+#define ADD_METHOD(name) \
+{ #name, (PyCFunction)crypto_X509Extension_##name, METH_VARARGS, crypto_X509Extension_##name##_doc }
+static PyMethodDef crypto_X509Extension_methods[] =
+{
+ ADD_METHOD(get_critical),
+ { NULL, NULL }
+};
+#undef ADD_METHOD
+
+/*
+ * Constructor for X509Extension, never called by Python code directly
+ *
+ * Arguments: type_name - ???
+ * critical - ???
+ * value - ???
+ * Returns: The newly created X509Extension object
+ */
+crypto_X509ExtensionObj *
+crypto_X509Extension_New(char *type_name, int critical, char *value)
+{
+ crypto_X509ExtensionObj *self;
+ int ext_len, ext_nid;
+ unsigned char *ext_der;
+ X509V3_EXT_METHOD *ext_method = NULL;
+ ASN1_OCTET_STRING *ext_oct;
+ STACK_OF(CONF_VALUE) *nval;
+ void * ext_struct;
+ X509_EXTENSION *extension = NULL;
+
+ self = PyObject_New(crypto_X509ExtensionObj, &crypto_X509Extension_Type);
+
+ if (self == NULL)
+ return NULL;
+
+ /* Try to get a NID for the name */
+ if ((ext_nid = OBJ_sn2nid(type_name)) == NID_undef)
+ {
+ PyErr_SetString(PyExc_ValueError, "Unknown extension name");
+ return NULL;
+ }
+
+ /* Lookup the extension method structure */
+ if (!(ext_method = X509V3_EXT_get_nid(ext_nid)))
+ {
+ PyErr_SetString(PyExc_ValueError, "Unknown extension");
+ return NULL;
+ }
+
+ /* Look if it has a function to convert value to an
+ * internal structure.
+ */
+ if (!ext_method->v2i)
+ {
+ PyErr_SetString(PyExc_ValueError, "Can't initialize exception");
+ return NULL;
+ }
+
+ /* Parse the value */
+ nval = X509V3_parse_list(value);
+ if (!nval)
+ {
+ PyErr_SetString(PyExc_ValueError, "Invalid extension string");
+ return NULL;
+ }
+
+ /* And use it to get the internal structure */
+ if(!(ext_struct = ext_method->v2i(ext_method, NULL, nval))) {
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ /* Deallocate the configuration value stack */
+ sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
+
+ /* Find out how much memory we need */
+
+
+ /* Convert internal representation to DER */
+ /* and Allocate */
+ if (ext_method->it) {
+ ext_der = NULL;
+ ext_len = ASN1_item_i2d(ext_struct, &ext_der, ASN1_ITEM_ptr(ext_method->it));
+ if (ext_len < 0) {
+ PyErr_SetString(PyExc_MemoryError, "Could not allocate memory");
+ return NULL;
+ }
+ } else {
+ unsigned char *p;
+ ext_len = ext_method->i2d(ext_struct, NULL);
+ if(!(ext_der = malloc(ext_len))) {
+ PyErr_SetString(PyExc_MemoryError, "Could not allocate memory");
+ return NULL;
+ }
+ p = ext_der;
+ ext_method->i2d(ext_struct, &p);
+ }
+
+ /* And create the ASN1_OCTET_STRING */
+ if(!(ext_oct = M_ASN1_OCTET_STRING_new())) {
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ ext_oct->data = ext_der;
+ ext_oct->length = ext_len;
+
+ /* Now that we got all ingredients, make the extension */
+ extension = X509_EXTENSION_create_by_NID(NULL, ext_nid, critical, ext_oct);
+ if (extension == NULL)
+ {
+ exception_from_error_queue();
+ M_ASN1_OCTET_STRING_free(ext_oct);
+ ext_method->ext_free(ext_struct);
+ return NULL;
+ }
+
+ M_ASN1_OCTET_STRING_free(ext_oct);
+ //ext_method->ext_free(ext_struct);
+
+ self->x509_extension = extension;
+ self->dealloc = 1;
+
+ return self;
+}
+
+/*
+ * Deallocate the memory used by the X509Extension object
+ *
+ * Arguments: self - The X509Extension object
+ * Returns: None
+ */
+static void
+crypto_X509Extension_dealloc(crypto_X509ExtensionObj *self)
+{
+ /* Sometimes we don't have to dealloc this */
+ if (self->dealloc)
+ X509_EXTENSION_free(self->x509_extension);
+
+ PyObject_Del(self);
+}
+
+/*
+ * Find attribute
+ *
+ * Arguments: self - The X509Extension object
+ * name - The attribute name
+ * Returns: A Python object for the attribute, or NULL if something
+ * went wrong.
+ */
+static PyObject *
+crypto_X509Extension_getattr(crypto_X509ExtensionObj *self, char *name)
+{
+ return Py_FindMethod(crypto_X509Extension_methods, (PyObject *)self, name);
+}
+
+/*
+ * Print a nice text representation of the certificate request.
+ */
+static PyObject *
+crypto_X509Extension_str(crypto_X509ExtensionObj *self)
+{
+ int str_len;
+ char *tmp_str;
+ PyObject *str;
+ BIO *bio = BIO_new(BIO_s_mem());
+
+ if (!X509V3_EXT_print(bio, self->x509_extension, 0, 0))
+ {
+ BIO_free(bio);
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ str_len = BIO_get_mem_data(bio, &tmp_str);
+ str = PyString_FromStringAndSize(tmp_str, str_len);
+
+ BIO_free(bio);
+
+ return str;
+}
+
+PyTypeObject crypto_X509Extension_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "X509Extension",
+ sizeof(crypto_X509ExtensionObj),
+ 0,
+ (destructor)crypto_X509Extension_dealloc,
+ NULL, /* print */
+ (getattrfunc)crypto_X509Extension_getattr,
+ NULL, /* setattr (setattrfunc)crypto_X509Name_setattr, */
+ NULL, /* compare */
+ NULL, /* repr */
+ NULL, /* as_number */
+ NULL, /* as_sequence */
+ NULL, /* as_mapping */
+ NULL, /* hash */
+ NULL, /* call */
+ (reprfunc)crypto_X509Extension_str /* str */
+};
+
+/*
+ * Initialize the X509Extension part of the crypto module
+ *
+ * Arguments: dict - The crypto module dictionary
+ * Returns: None
+ */
+int
+init_crypto_x509extension(PyObject *dict)
+{
+ crypto_X509Extension_Type.ob_type = &PyType_Type;
+ Py_INCREF(&crypto_X509Extension_Type);
+ PyDict_SetItemString(dict, "X509ExtensionType",
+ (PyObject *)&crypto_X509Extension_Type);
+ return 1;
+}
+
diff --git a/src/crypto/x509ext.h b/src/crypto/x509ext.h
new file mode 100644
index 0000000..f20e562
--- /dev/null
+++ b/src/crypto/x509ext.h
@@ -0,0 +1,32 @@
+/*
+ * x509ext.h
+ *
+ * Copyright (C) Awanim 2002, All rights reserved
+ *
+ * Export X.509 extension functions and data structures.
+ * See the file RATIONALE for a short explanation of why this module was written.
+ *
+ * @(#) $Id: x509ext.h,v 1.2 2002/09/04 22:24:59 iko Exp $
+ */
+#ifndef PyOpenSSL_crypto_X509EXTENSION_H_
+#define PyOpenSSL_crypto_X509EXTENSION_H_
+
+#include <Python.h>
+#include <openssl/ssl.h>
+#include <openssl/x509v3.h>
+
+extern int init_crypto_x509extension (PyObject *);
+
+extern PyTypeObject crypto_X509Extension_Type;
+
+#define crypto_X509Extension_Check(v) ((v)->ob_type == \
+ &crypto_X509Extension_Type)
+
+typedef struct {
+ PyObject_HEAD
+ X509_EXTENSION *x509_extension;
+ int dealloc;
+} crypto_X509ExtensionObj;
+
+#endif
+
diff --git a/src/crypto/x509name.c b/src/crypto/x509name.c
new file mode 100644
index 0000000..b9c0233
--- /dev/null
+++ b/src/crypto/x509name.c
@@ -0,0 +1,307 @@
+/*
+ * x509name.c
+ *
+ * Copyright (C) AB Strakt 2001, All rights reserved
+ *
+ * X.509 Name handling, mostly thin wrapping.
+ * 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: x509name.c,v 1.16 2003/01/09 17:08:32 martin Exp $";
+
+
+/*
+ * Constructor for X509Name, never called by Python code directly
+ *
+ * Arguments: name - A "real" X509_NAME object
+ * dealloc - Boolean value to specify whether the destructor should
+ * free the "real" X509_NAME object
+ * Returns: The newly created X509Name object
+ */
+crypto_X509NameObj *
+crypto_X509Name_New(X509_NAME *name, int dealloc)
+{
+ crypto_X509NameObj *self;
+
+ self = PyObject_GC_New(crypto_X509NameObj, &crypto_X509Name_Type);
+
+ if (self == NULL)
+ return NULL;
+
+ self->x509_name = name;
+ self->dealloc = dealloc;
+ self->parent_cert = NULL;
+
+ PyObject_GC_Track(self);
+ return self;
+}
+
+/*
+ * Return a name string given a X509_NAME object and a name identifier. Used
+ * by the getattr function.
+ *
+ * Arguments: name - The X509_NAME object
+ * nid - The name identifier
+ * Returns: The name as a Python string object
+ */
+static int
+get_name_by_nid(X509_NAME *name, int nid, char **utf8string)
+{
+ int entry_idx;
+ X509_NAME_ENTRY *entry;
+ ASN1_STRING *data;
+ int len;
+
+ if ((entry_idx = X509_NAME_get_index_by_NID(name, nid, -1)) == -1)
+ {
+ return 0;
+ }
+ entry = X509_NAME_get_entry(name, entry_idx);
+ data = X509_NAME_ENTRY_get_data(entry);
+ if ((len = ASN1_STRING_to_UTF8((unsigned char **)utf8string, data)) < 0)
+ {
+ exception_from_error_queue();
+ return -1;
+ }
+
+ return len;
+}
+
+/*
+ * Given a X509_NAME object and a name identifier, set the corresponding
+ * attribute to the given string. Used by the setattr function.
+ *
+ * Arguments: name - The X509_NAME object
+ * nid - The name identifier
+ * value - The string to set
+ * Returns: 0 for success, -1 on failure
+ */
+static int
+set_name_by_nid(X509_NAME *name, int nid, char *utf8string)
+{
+ X509_NAME_ENTRY *ne;
+ int i, entry_count, temp_nid;
+
+ /* If there's an old entry for this NID, remove it */
+ entry_count = X509_NAME_entry_count(name);
+ for (i = 0; i < entry_count; i++)
+ {
+ ne = X509_NAME_get_entry(name, i);
+ temp_nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(ne));
+ if (temp_nid == nid)
+ {
+ ne = X509_NAME_delete_entry(name, i);
+ X509_NAME_ENTRY_free(ne);
+ break;
+ }
+ }
+
+ /* Add the new entry */
+ if (!X509_NAME_add_entry_by_NID(name, nid, MBSTRING_UTF8, utf8string,
+ -1, -1, 0))
+ {
+ exception_from_error_queue();
+ return -1;
+ }
+ return 0;
+}
+
+
+/*
+ * Find attribute. An X509Name object has the following attributes:
+ * countryName (alias C), stateOrProvince (alias ST), locality (alias L),
+ * organization (alias O), organizationalUnit (alias OU), commonName (alias
+ * CN) and more...
+ *
+ * Arguments: self - The X509Name object
+ * name - The attribute name
+ * Returns: A Python object for the attribute, or NULL if something went
+ * wrong
+ */
+static PyObject *
+crypto_X509Name_getattr(crypto_X509NameObj *self, char *name)
+{
+ int nid, len;
+ char *utf8string;
+
+ if ((nid = OBJ_txt2nid(name)) == NID_undef)
+ {
+ PyErr_SetString(PyExc_AttributeError, "No such attribute");
+ return NULL;
+ }
+
+ len = get_name_by_nid(self->x509_name, nid, &utf8string);
+ if (len < 0)
+ return NULL;
+ else if (len == 0)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ else
+ return PyUnicode_Decode(utf8string, len, "utf-8", NULL);
+}
+
+/*
+ * Set attribute
+ *
+ * Arguments: self - The X509Name object
+ * name - The attribute name
+ * value - The value to set
+ */
+static int
+crypto_X509Name_setattr(crypto_X509NameObj *self, char *name, PyObject *value)
+{
+ int nid;
+ char *buffer;
+
+ if ((nid = OBJ_txt2nid(name)) == NID_undef)
+ {
+ PyErr_SetString(PyExc_AttributeError, "No such attribute");
+ return -1;
+ }
+
+ /* Something of a hack to get nice unicode behaviour */
+ if (!PyArg_Parse(value, "es:setattr", "utf-8", &buffer))
+ return -1;
+
+ return set_name_by_nid(self->x509_name, nid, buffer);
+}
+
+/*
+ * Compare two X509Name structures.
+ *
+ * Arguments: n - The first X509Name
+ * m - The second X509Name
+ * Returns: <0 if n < m, 0 if n == m and >0 if n > m
+ */
+static int
+crypto_X509Name_compare(crypto_X509NameObj *n, crypto_X509NameObj *m)
+{
+ return X509_NAME_cmp(n->x509_name, m->x509_name);
+}
+
+/*
+ * String representation of an X509Name
+ *
+ * Arguments: self - The X509Name object
+ * Returns: A string representation of the object
+ */
+static PyObject *
+crypto_X509Name_repr(crypto_X509NameObj *self)
+{
+ char tmpbuf[512] = "";
+ char realbuf[512+64];
+
+ if (X509_NAME_oneline(self->x509_name, tmpbuf, 512) == NULL)
+ {
+ exception_from_error_queue();
+ return NULL;
+ }
+ else
+ {
+ /* This is safe because tmpbuf is max 512 characters */
+ sprintf(realbuf, "<X509Name object '%s'>", tmpbuf);
+ return PyString_FromString(realbuf);
+ }
+}
+
+/*
+ * Call the visitproc on all contained objects.
+ *
+ * Arguments: self - The Connection 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_X509Name_traverse(crypto_X509NameObj *self, visitproc visit, void *arg)
+{
+ int ret = 0;
+
+ if (ret == 0 && self->parent_cert != NULL)
+ ret = visit(self->parent_cert, arg);
+ return ret;
+}
+
+/*
+ * Decref all contained objects and zero the pointers.
+ *
+ * Arguments: self - The Connection object
+ * Returns: Always 0.
+ */
+static int
+crypto_X509Name_clear(crypto_X509NameObj *self)
+{
+ Py_XDECREF(self->parent_cert);
+ self->parent_cert = NULL;
+ return 0;
+}
+
+/*
+ * Deallocate the memory used by the X509Name object
+ *
+ * Arguments: self - The X509Name object
+ * Returns: None
+ */
+static void
+crypto_X509Name_dealloc(crypto_X509NameObj *self)
+{
+ PyObject_GC_UnTrack(self);
+ /* Sometimes we don't have to dealloc this */
+ if (self->dealloc)
+ X509_NAME_free(self->x509_name);
+
+ crypto_X509Name_clear(self);
+
+ PyObject_GC_Del(self);
+}
+
+PyTypeObject crypto_X509Name_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "X509Name",
+ sizeof(crypto_X509NameObj),
+ 0,
+ (destructor)crypto_X509Name_dealloc,
+ NULL, /* print */
+ (getattrfunc)crypto_X509Name_getattr,
+ (setattrfunc)crypto_X509Name_setattr,
+ (cmpfunc)crypto_X509Name_compare,
+ (reprfunc)crypto_X509Name_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_X509Name_traverse,
+ (inquiry)crypto_X509Name_clear,
+};
+
+
+/*
+ * Initialize the X509Name part of the crypto module
+ *
+ * Arguments: dict - The crypto module dictionary
+ * Returns: None
+ */
+int
+init_crypto_x509name(PyObject *dict)
+{
+ crypto_X509Name_Type.ob_type = &PyType_Type;
+ Py_INCREF(&crypto_X509Name_Type);
+ PyDict_SetItemString(dict, "X509NameType", (PyObject *)&crypto_X509Name_Type);
+ return 1;
+}
diff --git a/src/crypto/x509name.h b/src/crypto/x509name.h
new file mode 100644
index 0000000..362ce35
--- /dev/null
+++ b/src/crypto/x509name.h
@@ -0,0 +1,33 @@
+/*
+ * x509name.h
+ *
+ * Copyright (C) AB Strakt 2001, All rights reserved
+ *
+ * Export X.509 name functions and data structures.
+ * See the file RATIONALE for a short explanation of why this module was written.
+ *
+ * Reviewed 2001-07-23
+ *
+ * @(#) $Id: x509name.h,v 1.8 2002/09/04 22:24:59 iko Exp $
+ */
+#ifndef PyOpenSSL_crypto_X509NAME_H_
+#define PyOpenSSL_crypto_X509NAME_H_
+
+#include <Python.h>
+#include <openssl/ssl.h>
+
+extern int init_crypto_x509name (PyObject *);
+
+extern PyTypeObject crypto_X509Name_Type;
+
+#define crypto_X509Name_Check(v) ((v)->ob_type == &crypto_X509Name_Type)
+
+typedef struct {
+ PyObject_HEAD
+ X509_NAME *x509_name;
+ int dealloc;
+ PyObject *parent_cert;
+} crypto_X509NameObj;
+
+
+#endif
diff --git a/src/crypto/x509req.c b/src/crypto/x509req.c
new file mode 100644
index 0000000..d551de4
--- /dev/null
+++ b/src/crypto/x509req.c
@@ -0,0 +1,324 @@
+/*
+ * x509req.c
+ *
+ * Copyright (C) AB Strakt 2001, All rights reserved
+ *
+ * X.509 Request handling, mostly thin wrapping.
+ * See the file RATIONALE for a short explanation of why this module was written.
+ */
+#include <Python.h>
+#define crypto_MODULE
+#include "crypto.h"
+
+static char *CVSid = "@(#) $Id: x509req.c,v 1.15 2002/09/04 22:24:59 iko Exp $";
+
+
+static char crypto_X509Req_get_subject_doc[] = "\n\
+Create an X509Name object for the subject of the certificate request\n\
+\n\
+Arguments: self - The X509Req object\n\
+ args - The Python argument tuple, should be empty\n\
+Returns: An X509Name object\n\
+";
+
+static PyObject *
+crypto_X509Req_get_subject(crypto_X509ReqObj *self, PyObject *args)
+{
+ crypto_X509NameObj *crypto_X509Name_New(X509_NAME *, int);
+ X509_NAME *name;
+
+ if (!PyArg_ParseTuple(args, ":get_subject"))
+ return NULL;
+
+ if ((name = X509_REQ_get_subject_name(self->x509_req)) == NULL)
+ {
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ return (PyObject *)crypto_X509Name_New(name, 0);
+}
+
+static char crypto_X509Req_get_pubkey_doc[] = "\n\
+Get the public key from the certificate request\n\
+\n\
+Arguments: self - The X509Req object\n\
+ args - The Python argument tuple, should be empty\n\
+Returns: The public key\n\
+";
+
+static PyObject *
+crypto_X509Req_get_pubkey(crypto_X509ReqObj *self, PyObject *args)
+{
+ crypto_PKeyObj *crypto_PKey_New(EVP_PKEY *, int);
+ EVP_PKEY *pkey;
+
+ if (!PyArg_ParseTuple(args, ":get_pubkey"))
+ return NULL;
+
+ if ((pkey = X509_REQ_get_pubkey(self->x509_req)) == NULL)
+ {
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ return (PyObject *)crypto_PKey_New(pkey, 1);
+}
+
+static char crypto_X509Req_set_pubkey_doc[] = "\n\
+Set the public key of the certificate request\n\
+\n\
+Arguments: self - The X509Req object\n\
+ args - The Python argument tuple, should be:\n\
+ pkey - The public key to use\n\
+Returns: None\n\
+";
+
+static PyObject *
+crypto_X509Req_set_pubkey(crypto_X509ReqObj *self, PyObject *args)
+{
+ crypto_PKeyObj *pkey;
+
+ if (!PyArg_ParseTuple(args, "O!:set_pubkey", &crypto_PKey_Type, &pkey))
+ return NULL;
+
+ if (!X509_REQ_set_pubkey(self->x509_req, pkey->pkey))
+ {
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char crypto_X509Req_sign_doc[] = "\n\
+Sign the certificate request using the supplied key and digest\n\
+\n\
+Arguments: self - The X509Req object\n\
+ args - The Python argument tuple, should be:\n\
+ pkey - The key to sign with\n\
+ digest - The message digest to use\n\
+Returns: None\n\
+";
+
+static PyObject *
+crypto_X509Req_sign(crypto_X509ReqObj *self, PyObject *args)
+{
+ crypto_PKeyObj *pkey;
+ char *digest_name;
+ const EVP_MD *digest;
+
+ if (!PyArg_ParseTuple(args, "O!s:sign", &crypto_PKey_Type, &pkey,
+ &digest_name))
+ return NULL;
+
+ if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
+ {
+ PyErr_SetString(PyExc_ValueError, "No such digest method");
+ return NULL;
+ }
+
+ if (!X509_REQ_sign(self->x509_req, pkey->pkey, digest))
+ {
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char crypto_X509Req_verify_doc[] = "\n\
+Verifies a certificate request using the supplied public key\n\
+ \n\
+Arguments: self - X509Req object\n\
+ args - The Python argument tuple, should be:\n\
+ key - a public key\n\
+Returns: True, if the signature is correct, 0 otherwise.\n\
+";
+
+PyObject *
+crypto_X509Req_verify(crypto_X509ReqObj *self, PyObject *args)
+{
+ PyObject *obj;
+ crypto_PKeyObj *key;
+ int answer;
+
+ if (!PyArg_ParseTuple(args, "O!:verify", &crypto_PKey_Type, &obj))
+ return NULL;
+
+ key = (crypto_PKeyObj *)obj;
+
+ if ((answer = X509_REQ_verify(self->x509_req, key->pkey)) < 0)
+ {
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ return PyInt_FromLong(answer);
+}
+
+static char crypto_X509Req_add_extensions_doc[] = "\n\
+Add extensions to the request.\n\
+\n\
+Arguments: self - X509Req object\n\
+ args - The Python argument tuple, should be:\n\
+ extensions - a sequence of X509Extension objects\n\
+Returns: None\n\
+";
+
+static PyObject *
+crypto_X509Req_add_extensions(crypto_X509ReqObj *self, PyObject *args)
+{
+ PyObject *extensions;
+ crypto_X509ExtensionObj *ext;
+ STACK_OF(X509_EXTENSION) *exts;
+ int nr_of_extensions, i;
+
+ if (!PyArg_ParseTuple(args, "O:add_extensions", &extensions))
+ return NULL;
+
+ if (!PySequence_Check(extensions))
+ {
+ PyErr_SetString(PyExc_TypeError, "Expected a sequence");
+ return NULL;
+ }
+
+ /* Make a STACK_OF(X509_EXTENSION) from sequence */
+ if ((exts = sk_X509_EXTENSION_new_null()) == NULL)
+ {
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ /* Put the extensions in a stack */
+ nr_of_extensions = PySequence_Length(extensions);
+
+ for (i = 0; i < nr_of_extensions; i++)
+ {
+ ext = (crypto_X509ExtensionObj *)PySequence_GetItem(extensions, i);
+ if (!(crypto_X509Extension_Check(ext)))
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "One of the elements is not an X509Extension");
+ sk_X509_EXTENSION_free(exts);
+ return NULL;
+ }
+ sk_X509_EXTENSION_push(exts, ext->x509_extension);
+ }
+
+ if (!X509_REQ_add_extensions(self->x509_req, exts))
+ {
+ sk_X509_EXTENSION_free(exts);
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ sk_X509_EXTENSION_free(exts);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+/*
+ * ADD_METHOD(name) expands to a correct PyMethodDef declaration
+ * { 'name', (PyCFunction)crypto_X509Req_name, METH_VARARGS }
+ * for convenience
+ */
+#define ADD_METHOD(name) \
+ { #name, (PyCFunction)crypto_X509Req_##name, METH_VARARGS, crypto_X509Req_##name##_doc }
+static PyMethodDef crypto_X509Req_methods[] =
+{
+ ADD_METHOD(get_subject),
+ ADD_METHOD(get_pubkey),
+ ADD_METHOD(set_pubkey),
+ ADD_METHOD(sign),
+ ADD_METHOD(verify),
+ ADD_METHOD(add_extensions),
+ { NULL, NULL }
+};
+#undef ADD_METHOD
+
+
+/*
+ * Constructor for X509Req, never called by Python code directly
+ *
+ * Arguments: name - A "real" X509_REQ object
+ * dealloc - Boolean value to specify whether the destructor should
+ * free the "real" X509_REQ object
+ * Returns: The newly created X509Req object
+ */
+crypto_X509ReqObj *
+crypto_X509Req_New(X509_REQ *req, int dealloc)
+{
+ crypto_X509ReqObj *self;
+
+ self = PyObject_New(crypto_X509ReqObj, &crypto_X509Req_Type);
+
+ if (self == NULL)
+ return NULL;
+
+ self->x509_req = req;
+ self->dealloc = dealloc;
+
+ return self;
+}
+
+/*
+ * Deallocate the memory used by the X509Req object
+ *
+ * Arguments: self - The X509Req object
+ * Returns: None
+ */
+static void
+crypto_X509Req_dealloc(crypto_X509ReqObj *self)
+{
+ /* Sometimes we don't have to dealloc this */
+ if (self->dealloc)
+ X509_REQ_free(self->x509_req);
+
+ PyObject_Del(self);
+}
+
+
+/*
+ * Find attribute.
+ *
+ * Arguments: self - The X509Req object
+ * name - The attribute name
+ * Returns: A Python object for the attribute, or NULL if something went
+ * wrong
+ */
+static PyObject *
+crypto_X509Req_getattr(crypto_X509ReqObj *self, char *name)
+{
+ return Py_FindMethod(crypto_X509Req_methods, (PyObject *)self, name);
+}
+
+PyTypeObject crypto_X509Req_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "X509Req",
+ sizeof(crypto_X509ReqObj),
+ 0,
+ (destructor)crypto_X509Req_dealloc,
+ NULL, /* print */
+ (getattrfunc)crypto_X509Req_getattr,
+};
+
+
+/*
+ * Initialize the X509Req part of the crypto module
+ *
+ * Arguments: dict - The crypto module dictionary
+ * Returns: None
+ */
+int
+init_crypto_x509req(PyObject *dict)
+{
+ crypto_X509Req_Type.ob_type = &PyType_Type;
+ Py_INCREF(&crypto_X509Req_Type);
+ PyDict_SetItemString(dict, "X509ReqType", (PyObject *)&crypto_X509Req_Type);
+ return 1;
+}
diff --git a/src/crypto/x509req.h b/src/crypto/x509req.h
new file mode 100644
index 0000000..db8043c
--- /dev/null
+++ b/src/crypto/x509req.h
@@ -0,0 +1,30 @@
+/*
+ * x509req.h
+ *
+ * Copyright (C) AB Strakt 2001, All rights reserved
+ *
+ * Export X509 request functions and data structures.
+ * See the file RATIONALE for a short explanation of why this module was written.
+ *
+ * @(#) $Id: x509req.h,v 1.6 2002/09/04 22:24:59 iko Exp $
+ */
+#ifndef PyOpenSSL_SSL_X509REQ_H_
+#define PyOpenSSL_SSL_X509REQ_H_
+
+#include <Python.h>
+#include <openssl/ssl.h>
+
+extern int init_crypto_x509req (PyObject *);
+
+extern PyTypeObject crypto_X509Req_Type;
+
+#define crypto_X509Req_Check(v) ((v)->ob_type == &crypto_X509Req_Type)
+
+typedef struct {
+ PyObject_HEAD
+ X509_REQ *x509_req;
+ int dealloc;
+} crypto_X509ReqObj;
+
+
+#endif
diff --git a/src/crypto/x509store.c b/src/crypto/x509store.c
new file mode 100644
index 0000000..bd81f0a
--- /dev/null
+++ b/src/crypto/x509store.c
@@ -0,0 +1,145 @@
+/*
+ * x509store.c
+ *
+ * Copyright (C) AB Strakt 2001, All rights reserved
+ *
+ * X.509 Store handling, mostly thin wrapping.
+ * See the file RATIONALE for a short explanation of why this module was written.
+ */
+#include <Python.h>
+#define crypto_MODULE
+#include "crypto.h"
+
+static char *CVSid = "@(#) $Id: x509store.c,v 1.9 2002/09/04 22:24:59 iko Exp $";
+
+static char crypto_X509Store_add_cert_doc[] = "\n\
+Add a certificate\n\
+\n\
+Arguments: self - The X509Store object\n\
+ args - The Python argument tuple, should be:\n\
+ cert - The certificate to add\n\
+Returns: None\n\
+";
+
+static PyObject *
+crypto_X509Store_add_cert(crypto_X509StoreObj *self, PyObject *args)
+{
+ crypto_X509Obj *cert;
+
+ if (!PyArg_ParseTuple(args, "O!:add_cert", &crypto_X509_Type, &cert))
+ return NULL;
+
+ if (!X509_STORE_add_cert(self->x509_store, cert->x509))
+ {
+ exception_from_error_queue();
+ return NULL;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+/*
+ * ADD_METHOD(name) expands to a correct PyMethodDef declaration
+ * { 'name', (PyCFunction)crypto_X509Store_name, METH_VARARGS }
+ * for convenience
+ */
+#define ADD_METHOD(name) \
+ { #name, (PyCFunction)crypto_X509Store_##name, METH_VARARGS, crypto_X509Store_##name##_doc }
+static PyMethodDef crypto_X509Store_methods[] =
+{
+ ADD_METHOD(add_cert),
+ { NULL, NULL }
+};
+#undef ADD_METHOD
+
+
+/*
+ * Constructor for X509Store, never called by Python code directly
+ *
+ * Arguments: name - A "real" X509_STORE object
+ * dealloc - Boolean value to specify whether the destructor should
+ * free the "real" X509_STORE object
+ * Returns: The newly created X509Store object
+ */
+crypto_X509StoreObj *
+crypto_X509Store_New(X509_STORE *store, int dealloc)
+{
+ crypto_X509StoreObj *self;
+
+ self = PyObject_New(crypto_X509StoreObj, &crypto_X509Store_Type);
+
+ if (self == NULL)
+ return NULL;
+
+ self->x509_store = store;
+ self->dealloc = dealloc;
+
+ return self;
+}
+
+/*
+ * Deallocate the memory used by the X509Store object
+ *
+ * Arguments: self - The X509Store object
+ * Returns: None
+ */
+static void
+crypto_X509Store_dealloc(crypto_X509StoreObj *self)
+{
+ /* Sometimes we don't have to dealloc this */
+ if (self->dealloc)
+ X509_STORE_free(self->x509_store);
+
+ PyObject_Del(self);
+}
+
+
+/*
+ * Find attribute.
+ *
+ * Arguments: self - The X509Store object
+ * name - The attribute name
+ * Returns: A Python object for the attribute, or NULL if something went
+ * wrong
+ */
+static PyObject *
+crypto_X509Store_getattr(crypto_X509StoreObj *self, char *name)
+{
+ return Py_FindMethod(crypto_X509Store_methods, (PyObject *)self, name);
+}
+
+PyTypeObject crypto_X509Store_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "X509Store",
+ sizeof(crypto_X509StoreObj),
+ 0,
+ (destructor)crypto_X509Store_dealloc,
+ NULL, /* print */
+ (getattrfunc)crypto_X509Store_getattr,
+ NULL, /* setattr */
+ NULL, /* compare */
+ NULL, /* repr */
+ NULL, /* as_number */
+ NULL, /* as_sequence */
+ NULL, /* as_mapping */
+ NULL /* hash */
+};
+
+
+/*
+ * Initialize the X509Store part of the crypto module
+ *
+ * Arguments: dict - The crypto module dictionary
+ * Returns: None
+ */
+int
+init_crypto_x509store(PyObject *dict)
+{
+ crypto_X509Store_Type.ob_type = &PyType_Type;
+ Py_INCREF(&crypto_X509Store_Type);
+ PyDict_SetItemString(dict, "X509StoreType", (PyObject *)&crypto_X509Store_Type);
+ return 1;
+}
diff --git a/src/crypto/x509store.h b/src/crypto/x509store.h
new file mode 100644
index 0000000..9ed5073
--- /dev/null
+++ b/src/crypto/x509store.h
@@ -0,0 +1,30 @@
+/*
+ * x509store.h
+ *
+ * Copyright (C) AB Strakt 2001, All rights reserved
+ *
+ * Export X509 store functions and data structures.
+ * See the file RATIONALE for a short explanation of why this module was written.
+ *
+ * @(#) $Id: x509store.h,v 1.4 2002/09/04 22:24:59 iko Exp $
+ */
+#ifndef PyOpenSSL_SSL_X509STORE_H_
+#define PyOpenSSL_SSL_X509STORE_H_
+
+#include <Python.h>
+#include <openssl/ssl.h>
+
+extern int init_crypto_x509store (PyObject *);
+
+extern PyTypeObject crypto_X509Store_Type;
+
+#define crypto_X509Store_Check(v) ((v)->ob_type == &crypto_X509Store_Type)
+
+typedef struct {
+ PyObject_HEAD
+ X509_STORE *x509_store;
+ int dealloc;
+} crypto_X509StoreObj;
+
+
+#endif