#include #define crypto_MODULE #include "crypto.h" static X509_REVOKED * X509_REVOKED_dup(X509_REVOKED *orig) { X509_REVOKED *dupe = NULL; dupe = X509_REVOKED_new(); if (dupe == NULL) { return NULL; } if (orig->serialNumber) { dupe->serialNumber = M_ASN1_INTEGER_dup(orig->serialNumber); } if (orig->revocationDate) { dupe->revocationDate = M_ASN1_INTEGER_dup(orig->revocationDate); } if (orig->extensions) { STACK_OF(X509_EXTENSION) *sk = NULL; X509_EXTENSION * ext; int j; sk = sk_X509_EXTENSION_new_null(); for (j = 0; j < sk_X509_EXTENSION_num(orig->extensions); j++) { ext = sk_X509_EXTENSION_value(orig->extensions, j); ext = X509_EXTENSION_dup(ext); sk_X509_EXTENSION_push(sk, ext); } dupe->extensions = sk; } dupe->sequence = orig->sequence; return dupe; } static char crypto_CRL_get_revoked_doc[] = "\n\ Return revoked portion of the CRL structure (by value\n\ not reference).\n\ \n\ :return: A tuple of Revoked objects.\n\ "; static PyObject * crypto_CRL_get_revoked(crypto_CRLObj *self, PyObject *args) { int j, num_rev; X509_REVOKED *r = NULL; PyObject *obj = NULL, *rev_obj; if (!PyArg_ParseTuple(args, ":get_revoked")) { return NULL; } num_rev = sk_X509_REVOKED_num(self->crl->crl->revoked); if (num_rev < 0) { Py_INCREF(Py_None); return Py_None; } if ((obj = PyTuple_New(num_rev)) == NULL) { return NULL; } for (j = 0; j < num_rev; j++) { r = sk_X509_REVOKED_value(self->crl->crl->revoked, j); r = X509_REVOKED_dup(r); if (r == NULL ) { goto error; } rev_obj = (PyObject *) crypto_Revoked_New(r); if (rev_obj == NULL) { goto error; } r = NULL; /* it's now owned by rev_obj */ PyTuple_SET_ITEM(obj, j, rev_obj); } return obj; error: if (r) { X509_REVOKED_free(r); } Py_XDECREF(obj); return NULL; } static char crypto_CRL_add_revoked_doc[] = "\n\ Add a revoked (by value not reference) to the CRL structure\n\ \n\ :param cert: The new revoked.\n\ :type cert: :class:`X509`\n\ :return: None\n\ "; static PyObject * crypto_CRL_add_revoked(crypto_CRLObj *self, PyObject *args, PyObject *keywds) { crypto_RevokedObj * rev_obj = NULL; static char *kwlist[] = {"revoked", NULL}; X509_REVOKED * dup; if (!PyArg_ParseTupleAndKeywords(args, keywds, "O!:add_revoked", kwlist, &crypto_Revoked_Type, &rev_obj)) { return NULL; } dup = X509_REVOKED_dup( rev_obj->revoked ); if (dup == NULL) { return NULL; } X509_CRL_add0_revoked(self->crl, dup); Py_INCREF(Py_None); return Py_None; } static char crypto_CRL_export_doc[] = "\n\ export(cert, key[, type[, days]]) -> export a CRL as a string\n\ \n\ :param cert: Used to sign CRL.\n\ :type cert: :class:`X509`\n\ :param key: Used to sign CRL.\n\ :type key: :class:`PKey`\n\ :param type: The export format, either :py:data:`FILETYPE_PEM`, :py:data:`FILETYPE_ASN1`, or :py:data:`FILETYPE_TEXT`.\n\ :param days: The number of days until the next update of this CRL.\n\ :type days: :py:data:`int`\n\ :return: :py:data:`str`\n\ "; static PyObject * crypto_CRL_export(crypto_CRLObj *self, PyObject *args, PyObject *keywds) { int ret, buf_len, type = X509_FILETYPE_PEM, days = 100; char *temp; BIO *bio; PyObject *buffer; crypto_PKeyObj *key; ASN1_TIME *tmptm; crypto_X509Obj *x509; static char *kwlist[] = {"cert", "key", "type", "days", NULL}; if (!PyArg_ParseTupleAndKeywords(args, keywds, "O!O!|ii:dump_crl", kwlist, &crypto_X509_Type, &x509, &crypto_PKey_Type, &key, &type, &days)) { return NULL; } #if OPENSSL_VERSION_NUMBER >= 0x01000000L /* Older versions of OpenSSL had no problem with trying to export using an * uninitialized key. Newer versions segfault, instead. We can only check * on the new versions, though, because the old versions don't even have the * field that the segfault is triggered by. */ if (!key->pkey->ameth) { PyErr_SetString( crypto_Error, "Cannot export with an unitialized key"); return NULL; } #endif bio = BIO_new(BIO_s_mem()); tmptm = ASN1_TIME_new(); if (!tmptm) { return 0; } X509_gmtime_adj(tmptm,0); X509_CRL_set_lastUpdate(self->crl, tmptm); X509_gmtime_adj(tmptm,days*24*60*60); X509_CRL_set_nextUpdate(self->crl, tmptm); ASN1_TIME_free(tmptm); X509_CRL_set_issuer_name(self->crl, X509_get_subject_name(x509->x509)); if (!X509_CRL_sign(self->crl, key->pkey, EVP_md5())) { exception_from_error_queue(crypto_Error); BIO_free(bio); return NULL; } switch (type) { case X509_FILETYPE_PEM: ret = PEM_write_bio_X509_CRL(bio, self->crl); break; case X509_FILETYPE_ASN1: ret = (int) i2d_X509_CRL_bio(bio, self->crl); break; case X509_FILETYPE_TEXT: ret = X509_CRL_print(bio, self->crl); break; default: PyErr_SetString( PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT"); return NULL; } if (!ret) { exception_from_error_queue(crypto_Error); BIO_free(bio); return NULL; } buf_len = BIO_get_mem_data(bio, &temp); buffer = PyBytes_FromStringAndSize(temp, buf_len); BIO_free(bio); return buffer; } crypto_CRLObj * crypto_CRL_New(X509_CRL *crl) { crypto_CRLObj *self; self = PyObject_New(crypto_CRLObj, &crypto_CRL_Type); if (self == NULL) { return NULL; } self->crl = crl; return self; } /* * ADD_METHOD(name) expands to a correct PyMethodDef declaration * { 'name', (PyCFunction)crypto_CRL_name, METH_VARARGS, crypto_CRL_name_doc } * for convenience */ #define ADD_METHOD(name) \ { #name, (PyCFunction)crypto_CRL_##name, METH_VARARGS, crypto_CRL_##name##_doc } #define ADD_KW_METHOD(name) \ { #name, (PyCFunction)crypto_CRL_##name, METH_VARARGS | METH_KEYWORDS, crypto_CRL_##name##_doc } static PyMethodDef crypto_CRL_methods[] = { ADD_KW_METHOD(add_revoked), ADD_METHOD(get_revoked), ADD_KW_METHOD(export), { NULL, NULL } }; #undef ADD_METHOD static void crypto_CRL_dealloc(crypto_CRLObj *self) { X509_CRL_free(self->crl); self->crl = NULL; PyObject_Del(self); } static char crypto_CRL_doc[] = "\n\ CRL() -> CRL instance\n\ \n\ Create a new empty CRL object.\n\ \n\ :returns: The CRL object\n\ "; static PyObject* crypto_CRL_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs) { if (!PyArg_ParseTuple(args, ":CRL")) { return NULL; } return (PyObject *)crypto_CRL_New(X509_CRL_new()); } PyTypeObject crypto_CRL_Type = { PyOpenSSL_HEAD_INIT(&PyType_Type, 0) "CRL", sizeof(crypto_CRLObj), 0, (destructor)crypto_CRL_dealloc, NULL, /* print */ NULL, /* 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, crypto_CRL_doc, /* doc */ NULL, /* traverse */ NULL, /* clear */ NULL, /* tp_richcompare */ 0, /* tp_weaklistoffset */ NULL, /* tp_iter */ NULL, /* tp_iternext */ crypto_CRL_methods, /* tp_methods */ NULL, /* tp_members */ NULL, /* tp_getset */ NULL, /* tp_base */ NULL, /* tp_dict */ NULL, /* tp_descr_get */ NULL, /* tp_descr_set */ 0, /* tp_dictoffset */ NULL, /* tp_init */ NULL, /* tp_alloc */ crypto_CRL_new, /* tp_new */ }; int init_crypto_crl(PyObject *module) { if (PyType_Ready(&crypto_CRL_Type) < 0) { return 0; } /* PyModule_AddObject steals a reference. */ Py_INCREF((PyObject *)&crypto_CRL_Type); if (PyModule_AddObject(module, "CRL", (PyObject *)&crypto_CRL_Type) != 0) { return 0; } return 1; }