blob: 543708eafc92405e2d91c90f4342fdab8da46699 [file] [log] [blame]
Rick Dean536ba022009-07-24 23:57:27 -05001#include <Python.h>
2#define crypto_MODULE
3#include "crypto.h"
4
5
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -04006static X509_REVOKED * X509_REVOKED_dup(X509_REVOKED *orig) {
Rick Dean536ba022009-07-24 23:57:27 -05007 X509_REVOKED *dupe = NULL;
8
9 dupe = X509_REVOKED_new();
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -040010 if (dupe == NULL) {
Rick Dean536ba022009-07-24 23:57:27 -050011 return NULL;
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -040012 }
13 if (orig->serialNumber) {
Rick Dean536ba022009-07-24 23:57:27 -050014 dupe->serialNumber = M_ASN1_INTEGER_dup(orig->serialNumber);
15 }
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -040016 if (orig->revocationDate) {
Rick Dean536ba022009-07-24 23:57:27 -050017 dupe->revocationDate = M_ASN1_INTEGER_dup(orig->revocationDate);
18 }
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -040019 if (orig->extensions) {
Rick Dean536ba022009-07-24 23:57:27 -050020 STACK_OF(X509_EXTENSION) *sk = NULL;
21 X509_EXTENSION * ext;
22 int j;
23
24 sk = sk_X509_EXTENSION_new_null();
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -040025 for (j = 0; j < sk_X509_EXTENSION_num(orig->extensions); j++) {
26 ext = sk_X509_EXTENSION_value(orig->extensions, j);
27 ext = X509_EXTENSION_dup(ext);
28 sk_X509_EXTENSION_push(sk, ext);
Rick Dean536ba022009-07-24 23:57:27 -050029 }
30 dupe->extensions = sk;
31 }
32 dupe->sequence = orig->sequence;
33 return dupe;
34}
35
36static char crypto_CRL_get_revoked_doc[] = "\n\
37Return revoked portion of the CRL structure (by value\n\
38not reference).\n\
39\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +090040:return: A tuple of Revoked objects.\n\
Rick Dean536ba022009-07-24 23:57:27 -050041";
42static PyObject *
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -040043crypto_CRL_get_revoked(crypto_CRLObj *self, PyObject *args) {
Rick Dean536ba022009-07-24 23:57:27 -050044 int j, num_rev;
45 X509_REVOKED *r = NULL;
46 PyObject *obj = NULL, *rev_obj;
47
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -040048 if (!PyArg_ParseTuple(args, ":get_revoked")) {
Rick Dean536ba022009-07-24 23:57:27 -050049 return NULL;
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -040050 }
Rick Dean536ba022009-07-24 23:57:27 -050051
52 num_rev = sk_X509_REVOKED_num(self->crl->crl->revoked);
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -040053 if (num_rev < 0) {
Rick Dean536ba022009-07-24 23:57:27 -050054 Py_INCREF(Py_None);
55 return Py_None;
56 }
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -040057 if ((obj = PyTuple_New(num_rev)) == NULL) {
Rick Dean536ba022009-07-24 23:57:27 -050058 return NULL;
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -040059 }
Rick Dean536ba022009-07-24 23:57:27 -050060
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -040061 for (j = 0; j < num_rev; j++) {
62 r = sk_X509_REVOKED_value(self->crl->crl->revoked, j);
63 r = X509_REVOKED_dup(r);
64 if (r == NULL ) {
65 goto error;
66 }
67 rev_obj = (PyObject *) crypto_Revoked_New(r);
68 if (rev_obj == NULL) {
69 goto error;
70 }
71 r = NULL; /* it's now owned by rev_obj */
72 PyTuple_SET_ITEM(obj, j, rev_obj);
Rick Dean536ba022009-07-24 23:57:27 -050073 }
74 return obj;
75
76 error:
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -040077 if (r) {
78 X509_REVOKED_free(r);
79 }
Rick Dean536ba022009-07-24 23:57:27 -050080 Py_XDECREF(obj);
81 return NULL;
82}
83
84static char crypto_CRL_add_revoked_doc[] = "\n\
85Add a revoked (by value not reference) to the CRL structure\n\
86\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +090087:param cert: The new revoked.\n\
Jonathan Ballet648875f2011-07-16 14:14:58 +090088:type cert: :class:`X509`\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +090089:return: None\n\
Rick Dean536ba022009-07-24 23:57:27 -050090";
91static PyObject *
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -040092crypto_CRL_add_revoked(crypto_CRLObj *self, PyObject *args, PyObject *keywds) {
Rick Dean536ba022009-07-24 23:57:27 -050093 crypto_RevokedObj * rev_obj = NULL;
94 static char *kwlist[] = {"revoked", NULL};
95 X509_REVOKED * dup;
96
97 if (!PyArg_ParseTupleAndKeywords(args, keywds, "O!:add_revoked",
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -040098 kwlist, &crypto_Revoked_Type, &rev_obj)) {
Rick Dean536ba022009-07-24 23:57:27 -050099 return NULL;
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -0400100 }
Rick Dean536ba022009-07-24 23:57:27 -0500101
102 dup = X509_REVOKED_dup( rev_obj->revoked );
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -0400103 if (dup == NULL) {
Rick Dean536ba022009-07-24 23:57:27 -0500104 return NULL;
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -0400105 }
Rick Dean536ba022009-07-24 23:57:27 -0500106 X509_CRL_add0_revoked(self->crl, dup);
107
108 Py_INCREF(Py_None);
109 return Py_None;
110}
111
112static char crypto_CRL_export_doc[] = "\n\
Jean-Paul Calderone58887472010-01-30 13:12:35 -0500113export(cert, key[, type[, days]]) -> export a CRL as a string\n\
Rick Dean536ba022009-07-24 23:57:27 -0500114\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900115:param cert: Used to sign CRL.\n\
Jonathan Ballet648875f2011-07-16 14:14:58 +0900116:type cert: :class:`X509`\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900117:param key: Used to sign CRL.\n\
Jonathan Ballet648875f2011-07-16 14:14:58 +0900118:type key: :class:`PKey`\n\
119:param type: The export format, either :py:data:`FILETYPE_PEM`, :py:data:`FILETYPE_ASN1`, or :py:data:`FILETYPE_TEXT`.\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900120:param days: The number of days until the next update of this CRL.\n\
Jonathan Ballet648875f2011-07-16 14:14:58 +0900121:type days: :py:data:`int`\n\
122:return: :py:data:`str`\n\
Rick Dean536ba022009-07-24 23:57:27 -0500123";
124static PyObject *
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -0400125crypto_CRL_export(crypto_CRLObj *self, PyObject *args, PyObject *keywds) {
126 int ret, buf_len, type = X509_FILETYPE_PEM, days = 100;
127 char *temp;
128 BIO *bio;
129 PyObject *buffer;
130 crypto_PKeyObj *key;
131 ASN1_TIME *tmptm;
132 crypto_X509Obj *x509;
133 static char *kwlist[] = {"cert", "key", "type", "days", NULL};
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -0400134
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -0400135 if (!PyArg_ParseTupleAndKeywords(args, keywds, "O!O!|ii:dump_crl", kwlist,
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -0400136 &crypto_X509_Type, &x509,
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -0400137 &crypto_PKey_Type, &key, &type, &days)) {
138 return NULL;
139 }
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -0400140
Jean-Paul Calderone3f79cea2012-03-09 14:56:35 -0800141 /* Some versions of OpenSSL check for this, but more recent versions seem
142 * not to.
143 */
144 if (!key->pkey->ameth) {
145 PyErr_SetString(
146 crypto_Error, "Cannot export with an unitialized key");
147 return NULL;
148 }
149
150
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -0400151 bio = BIO_new(BIO_s_mem());
152 tmptm = ASN1_TIME_new();
153 if (!tmptm) {
154 return 0;
155 }
156 X509_gmtime_adj(tmptm,0);
157 X509_CRL_set_lastUpdate(self->crl, tmptm);
158 X509_gmtime_adj(tmptm,days*24*60*60);
159 X509_CRL_set_nextUpdate(self->crl, tmptm);
160 ASN1_TIME_free(tmptm);
161 X509_CRL_set_issuer_name(self->crl, X509_get_subject_name(x509->x509));
Jean-Paul Calderonec7293bc2011-09-13 15:24:38 -0400162
163 if (!X509_CRL_sign(self->crl, key->pkey, EVP_md5())) {
164 exception_from_error_queue(crypto_Error);
165 BIO_free(bio);
166 return NULL;
167 }
168
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -0400169 switch (type) {
170 case X509_FILETYPE_PEM:
171 ret = PEM_write_bio_X509_CRL(bio, self->crl);
172 break;
Rick Dean536ba022009-07-24 23:57:27 -0500173
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -0400174 case X509_FILETYPE_ASN1:
175 ret = (int) i2d_X509_CRL_bio(bio, self->crl);
176 break;
Rick Dean536ba022009-07-24 23:57:27 -0500177
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -0400178 case X509_FILETYPE_TEXT:
179 ret = X509_CRL_print(bio, self->crl);
180 break;
Rick Dean536ba022009-07-24 23:57:27 -0500181
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -0400182 default:
183 PyErr_SetString(
184 PyExc_ValueError,
185 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Rick Dean536ba022009-07-24 23:57:27 -0500186 return NULL;
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -0400187 }
188 if (!ret) {
189 exception_from_error_queue(crypto_Error);
190 BIO_free(bio);
191 return NULL;
192 }
193 buf_len = BIO_get_mem_data(bio, &temp);
Jean-Paul Calderone2f6c66f2010-08-11 19:53:43 -0400194 buffer = PyBytes_FromStringAndSize(temp, buf_len);
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -0400195 BIO_free(bio);
196 return buffer;
Rick Dean536ba022009-07-24 23:57:27 -0500197}
198
199crypto_CRLObj *
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -0400200crypto_CRL_New(X509_CRL *crl) {
Rick Dean536ba022009-07-24 23:57:27 -0500201 crypto_CRLObj *self;
202
203 self = PyObject_New(crypto_CRLObj, &crypto_CRL_Type);
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -0400204 if (self == NULL) {
205 return NULL;
206 }
Rick Dean536ba022009-07-24 23:57:27 -0500207 self->crl = crl;
208 return self;
209}
210
211/*
212 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
213 * { 'name', (PyCFunction)crypto_CRL_name, METH_VARARGS, crypto_CRL_name_doc }
214 * for convenience
215 */
216#define ADD_METHOD(name) \
217 { #name, (PyCFunction)crypto_CRL_##name, METH_VARARGS, crypto_CRL_##name##_doc }
218#define ADD_KW_METHOD(name) \
219 { #name, (PyCFunction)crypto_CRL_##name, METH_VARARGS | METH_KEYWORDS, crypto_CRL_##name##_doc }
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -0400220static PyMethodDef crypto_CRL_methods[] = {
Rick Dean536ba022009-07-24 23:57:27 -0500221 ADD_KW_METHOD(add_revoked),
222 ADD_METHOD(get_revoked),
223 ADD_KW_METHOD(export),
224 { NULL, NULL }
225};
226#undef ADD_METHOD
227
228
Rick Dean536ba022009-07-24 23:57:27 -0500229static void
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -0400230crypto_CRL_dealloc(crypto_CRLObj *self) {
Rick Dean536ba022009-07-24 23:57:27 -0500231 X509_CRL_free(self->crl);
232 self->crl = NULL;
233
234 PyObject_Del(self);
235}
236
237static char crypto_CRL_doc[] = "\n\
238CRL() -> CRL instance\n\
239\n\
240Create a new empty CRL object.\n\
241\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900242:returns: The CRL object\n\
Rick Dean536ba022009-07-24 23:57:27 -0500243";
244
245static PyObject* crypto_CRL_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs) {
Jean-Paul Calderonec5c21602010-05-24 17:52:20 -0400246 if (!PyArg_ParseTuple(args, ":CRL")) {
247 return NULL;
248 }
249
250 return (PyObject *)crypto_CRL_New(X509_CRL_new());
Rick Dean536ba022009-07-24 23:57:27 -0500251}
252
253PyTypeObject crypto_CRL_Type = {
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400254 PyOpenSSL_HEAD_INIT(&PyType_Type, 0)
Rick Dean536ba022009-07-24 23:57:27 -0500255 "CRL",
256 sizeof(crypto_CRLObj),
257 0,
258 (destructor)crypto_CRL_dealloc,
259 NULL, /* print */
Jean-Paul Calderone2f6c66f2010-08-11 19:53:43 -0400260 NULL, /* getattr */
Rick Dean536ba022009-07-24 23:57:27 -0500261 NULL, /* setattr */
262 NULL, /* compare */
263 NULL, /* repr */
264 NULL, /* as_number */
265 NULL, /* as_sequence */
266 NULL, /* as_mapping */
267 NULL, /* hash */
268 NULL, /* call */
269 NULL, /* str */
270 NULL, /* getattro */
271 NULL, /* setattro */
272 NULL, /* as_buffer */
273 Py_TPFLAGS_DEFAULT,
274 crypto_CRL_doc, /* doc */
275 NULL, /* traverse */
276 NULL, /* clear */
277 NULL, /* tp_richcompare */
278 0, /* tp_weaklistoffset */
279 NULL, /* tp_iter */
280 NULL, /* tp_iternext */
281 crypto_CRL_methods, /* tp_methods */
282 NULL, /* tp_members */
283 NULL, /* tp_getset */
284 NULL, /* tp_base */
285 NULL, /* tp_dict */
286 NULL, /* tp_descr_get */
287 NULL, /* tp_descr_set */
288 0, /* tp_dictoffset */
289 NULL, /* tp_init */
290 NULL, /* tp_alloc */
291 crypto_CRL_new, /* tp_new */
292};
293
294int init_crypto_crl(PyObject *module) {
Jean-Paul Calderoneaed23582011-03-12 22:45:02 -0500295 if (PyType_Ready(&crypto_CRL_Type) < 0) {
296 return 0;
297 }
Rick Dean536ba022009-07-24 23:57:27 -0500298
Jean-Paul Calderoneaed23582011-03-12 22:45:02 -0500299 /* PyModule_AddObject steals a reference.
300 */
301 Py_INCREF((PyObject *)&crypto_CRL_Type);
302 if (PyModule_AddObject(module, "CRL", (PyObject *)&crypto_CRL_Type) != 0) {
303 return 0;
304 }
305 return 1;
Rick Dean536ba022009-07-24 23:57:27 -0500306}