blob: 3042c4df8676880ab3c2aaf63160f1a4fa88f929 [file] [log] [blame]
Rick Dean536ba022009-07-24 23:57:27 -05001#include <Python.h>
2#define crypto_MODULE
3#include "crypto.h"
4
Jean-Paul Calderone83461592010-01-30 14:19:01 -05005#ifdef _WIN32
6#define strcasecmp(string1, string2) _stricmp(string1, string2)
7#endif
Rick Dean536ba022009-07-24 23:57:27 -05008
Rick Dean6385faf2009-07-26 00:07:47 -05009/* http://www.openssl.org/docs/apps/x509v3_config.html#CRL_distribution_points_ */
10/* which differs from crl_reasons of crypto/x509v3/v3_enum.c that matches */
11/* OCSP_crl_reason_str. We use the latter, just like the command line program. */
12static const char *crl_reasons[] = {
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -040013 "unspecified",
14 "keyCompromise",
15 "CACompromise",
16 "affiliationChanged",
17 "superseded",
18 "cessationOfOperation",
19 "certificateHold",
20 NULL,
21 "removeFromCRL",
Rick Dean6385faf2009-07-26 00:07:47 -050022};
23
24#define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *))
25
26static char crypto_Revoked_all_reasons_doc[] = "\n\
27Return a list of all the supported reason strings.\n\
28\n\
29@return: A list of reason strings.\n\
30";
31static PyObject *
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -040032crypto_Revoked_all_reasons(crypto_RevokedObj *self, PyObject *args) {
Rick Dean6385faf2009-07-26 00:07:47 -050033 PyObject *list, *str;
34 int j;
35
36 list = PyList_New(0);
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -040037 for (j = 0; j < NUM_REASONS; j++) {
38 if(crl_reasons[j]) {
Jean-Paul Calderone289a7b22010-01-30 15:09:43 -050039 str = PyString_FromString(crl_reasons[j]);
Rick Dean6385faf2009-07-26 00:07:47 -050040 PyList_Append(list, str);
41 Py_DECREF(str);
42 }
43 }
44 return list;
45}
46
47static PyObject *
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -040048X509_EXTENSION_value_to_PyString(X509_EXTENSION *ex) {
Rick Dean6385faf2009-07-26 00:07:47 -050049 BIO *bio = NULL;
50 PyObject *str = NULL;
51 int str_len;
52 char *tmp_str;
53
54 /* Create a openssl BIO buffer */
55 bio = BIO_new(BIO_s_mem());
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -040056 if (bio == NULL) {
Rick Dean6385faf2009-07-26 00:07:47 -050057 goto err;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -040058 }
Rick Dean6385faf2009-07-26 00:07:47 -050059
60 /* These are not the droids you are looking for. */
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -040061 if (!X509V3_EXT_print(bio, ex, 0, 0)) {
62 if (M_ASN1_OCTET_STRING_print(bio, ex->value) == 0) {
Rick Dean6385faf2009-07-26 00:07:47 -050063 goto err;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -040064 }
65 }
Rick Dean6385faf2009-07-26 00:07:47 -050066
67 /* Convert to a Python string. */
68 str_len = BIO_get_mem_data(bio, &tmp_str);
69 str = PyString_FromStringAndSize(tmp_str, str_len);
70
71 /* Cleanup */
72 BIO_free(bio);
73 return str;
74
75 err:
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -040076 if (bio) {
Rick Dean6385faf2009-07-26 00:07:47 -050077 BIO_free(bio);
78 }
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -040079 if (str) {
Rick Dean6385faf2009-07-26 00:07:47 -050080 Py_DECREF(str);
81 }
82 return NULL;
83}
84
85static void
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -040086delete_reason(STACK_OF(X509_EXTENSION) *sk) {
Rick Dean6385faf2009-07-26 00:07:47 -050087 X509_EXTENSION * ext;
88 int j;
89
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -040090 for (j = 0; j < sk_X509_EXTENSION_num(sk); j++) {
Rick Dean6385faf2009-07-26 00:07:47 -050091 ext = sk_X509_EXTENSION_value(sk, j);
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -040092 if (OBJ_obj2nid(ext->object) == NID_crl_reason) {
Rick Dean6385faf2009-07-26 00:07:47 -050093 X509_EXTENSION_free(ext);
94 (void) sk_X509_EXTENSION_delete(sk, j);
95 break;
96 }
97 }
98}
99
Jean-Paul Calderone289a7b22010-01-30 15:09:43 -0500100static int
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400101reason_str_to_code(const char * reason_str) {
Rick Dean6385faf2009-07-26 00:07:47 -0500102 int reason_code = -1, j;
103 char *spaceless_reason, * sp;
104
105 /* Remove spaces so that the responses of
106 * get_reason() work in set_reason() */
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400107 if ((spaceless_reason = strdup(reason_str)) == NULL) {
Rick Dean6385faf2009-07-26 00:07:47 -0500108 return -1;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400109 }
110
111 while ((sp = strchr(spaceless_reason, ' '))) {
Rick Dean6385faf2009-07-26 00:07:47 -0500112 memmove(sp, sp+1, strlen(sp));
Jean-Paul Calderone289a7b22010-01-30 15:09:43 -0500113 }
Rick Dean6385faf2009-07-26 00:07:47 -0500114
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400115 for (j = 0; j < NUM_REASONS; j++) {
116 if(crl_reasons[j] && !strcasecmp(spaceless_reason, crl_reasons[j])) {
Rick Dean6385faf2009-07-26 00:07:47 -0500117 reason_code = j;
118 break;
119 }
120 }
121 free(spaceless_reason);
122 return reason_code;
123}
124
125static char crypto_Revoked_set_reason_doc[] = "\n\
126Set the reason of a Revoked object.\n\
127\n\
128@param reason: The reason string.\n\
129@type reason: L{str}\n\
130@return: None\n\
131";
132static PyObject *
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400133crypto_Revoked_set_reason(crypto_RevokedObj *self, PyObject *args, PyObject *keywds) {
Rick Dean6385faf2009-07-26 00:07:47 -0500134 static char *kwlist[] = {"reason", NULL};
135 const char *reason_str = NULL;
136 int reason_code;
137 ASN1_ENUMERATED *rtmp = NULL;
138
Jean-Paul Calderone289a7b22010-01-30 15:09:43 -0500139 if (!PyArg_ParseTupleAndKeywords(args, keywds, "z:set_reason",
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400140 kwlist, &reason_str)) {
Rick Dean6385faf2009-07-26 00:07:47 -0500141 return NULL;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400142 }
Rick Dean6385faf2009-07-26 00:07:47 -0500143
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400144 if(reason_str == NULL) {
Jean-Paul Calderone289a7b22010-01-30 15:09:43 -0500145 delete_reason(self->revoked->extensions);
Rick Dean6385faf2009-07-26 00:07:47 -0500146 goto done;
147 }
148
149 reason_code = reason_str_to_code(reason_str);
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400150 if (reason_code == -1) {
Rick Dean6385faf2009-07-26 00:07:47 -0500151 PyErr_SetString(PyExc_ValueError, "bad reason string");
152 return NULL;
153 }
154
155 rtmp = ASN1_ENUMERATED_new();
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400156 if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code)) {
Rick Dean6385faf2009-07-26 00:07:47 -0500157 goto err;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400158 }
Jean-Paul Calderone289a7b22010-01-30 15:09:43 -0500159 delete_reason(self->revoked->extensions);
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400160 if (!X509_REVOKED_add1_ext_i2d(self->revoked, NID_crl_reason, rtmp, 0, 0)) {
Rick Dean6385faf2009-07-26 00:07:47 -0500161 goto err;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400162 }
Rick Dean6385faf2009-07-26 00:07:47 -0500163
164 done:
165 Py_INCREF(Py_None);
166 return Py_None;
167
168 err:
169 exception_from_error_queue(crypto_Error);
170 return NULL;
171}
172
173
174static char crypto_Revoked_get_reason_doc[] = "\n\
175Return the reason of a Revoked object.\n\
176\n\
177@return: The reason as a string\n\
178";
179static PyObject *
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400180crypto_Revoked_get_reason(crypto_RevokedObj *self, PyObject *args) {
Rick Dean6385faf2009-07-26 00:07:47 -0500181 X509_EXTENSION * ext;
182 int j;
183 STACK_OF(X509_EXTENSION) *sk = NULL;
184
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400185 if (!PyArg_ParseTuple(args, ":get_reason")) {
Rick Dean6385faf2009-07-26 00:07:47 -0500186 return NULL;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400187 }
Rick Dean6385faf2009-07-26 00:07:47 -0500188
189 sk = self->revoked->extensions;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400190 for (j = 0; j < sk_X509_EXTENSION_num(sk); j++) {
Rick Dean6385faf2009-07-26 00:07:47 -0500191 ext = sk_X509_EXTENSION_value(sk, j);
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400192 if (OBJ_obj2nid(ext->object) == NID_crl_reason) {
Rick Dean6385faf2009-07-26 00:07:47 -0500193 return X509_EXTENSION_value_to_PyString(ext);
194 }
195 }
196
197 Py_INCREF(Py_None);
198 return Py_None;
199}
200
201
Rick Dean536ba022009-07-24 23:57:27 -0500202static char crypto_Revoked_get_rev_date_doc[] = "\n\
203Retrieve the revocation date\n\
204\n\
205@return: A string giving the timestamp, in the format:\n\
206\n\
207 YYYYMMDDhhmmssZ\n\
208 YYYYMMDDhhmmss+hhmm\n\
209 YYYYMMDDhhmmss-hhmm\n\
210";
211
212static PyObject*
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400213crypto_Revoked_get_rev_date(crypto_RevokedObj *self, PyObject *args) {
214 /* returns a borrowed reference. */
215 return _get_asn1_time(
216 ":get_rev_date", self->revoked->revocationDate, args);
Rick Dean536ba022009-07-24 23:57:27 -0500217}
218
219static char crypto_Revoked_set_rev_date_doc[] = "\n\
220Set the revocation timestamp\n\
221\n\
222@param when: A string giving the timestamp, in the format:\n\
223\n\
224 YYYYMMDDhhmmssZ\n\
225 YYYYMMDDhhmmss+hhmm\n\
226 YYYYMMDDhhmmss-hhmm\n\
227\n\
228@return: None\n\
229";
230
231static PyObject*
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400232crypto_Revoked_set_rev_date(crypto_RevokedObj *self, PyObject *args) {
233 return _set_asn1_time(
234 "s:set_rev_date", self->revoked->revocationDate, args);
Rick Dean536ba022009-07-24 23:57:27 -0500235}
236
Jean-Paul Calderone289a7b22010-01-30 15:09:43 -0500237/* The integer is converted to an upper-case hex string
Rick Dean6385faf2009-07-26 00:07:47 -0500238 * without a '0x' prefix. */
Rick Dean536ba022009-07-24 23:57:27 -0500239static PyObject *
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400240ASN1_INTEGER_to_PyString(ASN1_INTEGER *asn1_int) {
Rick Dean536ba022009-07-24 23:57:27 -0500241 BIO *bio = NULL;
Rick Dean6385faf2009-07-26 00:07:47 -0500242 PyObject *str = NULL;
243 int str_len;
244 char *tmp_str;
Rick Dean536ba022009-07-24 23:57:27 -0500245
246 /* Create a openssl BIO buffer */
247 bio = BIO_new(BIO_s_mem());
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400248 if (bio == NULL) {
Rick Dean536ba022009-07-24 23:57:27 -0500249 goto err;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400250 }
Rick Dean536ba022009-07-24 23:57:27 -0500251
252 /* Write the integer to the BIO as a hex string. */
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400253 if (i2a_ASN1_INTEGER(bio, asn1_int) < 0) {
Rick Dean536ba022009-07-24 23:57:27 -0500254 goto err;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400255 }
Rick Dean536ba022009-07-24 23:57:27 -0500256
Rick Dean6385faf2009-07-26 00:07:47 -0500257 /* Convert to a Python string. */
258 str_len = BIO_get_mem_data(bio, &tmp_str);
259 str = PyString_FromStringAndSize(tmp_str, str_len);
Rick Dean536ba022009-07-24 23:57:27 -0500260
261 /* Cleanup */
262 BIO_free(bio);
Rick Dean6385faf2009-07-26 00:07:47 -0500263 return str;
Rick Dean536ba022009-07-24 23:57:27 -0500264
265 err:
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400266 if (bio) {
Rick Dean536ba022009-07-24 23:57:27 -0500267 BIO_free(bio);
268 }
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400269 if (str) {
Rick Dean6385faf2009-07-26 00:07:47 -0500270 Py_DECREF(str);
Rick Dean536ba022009-07-24 23:57:27 -0500271 }
272 return NULL;
273}
274
275
276static char crypto_Revoked_get_serial_doc[] = "\n\
277Return the serial number of a Revoked structure\n\
278\n\
279@return: The serial number as a string\n\
280";
281static PyObject *
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400282crypto_Revoked_get_serial(crypto_RevokedObj *self, PyObject *args) {
283 if (!PyArg_ParseTuple(args, ":get_serial")) {
Rick Dean536ba022009-07-24 23:57:27 -0500284 return NULL;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400285 }
Rick Dean536ba022009-07-24 23:57:27 -0500286
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400287 if (self->revoked->serialNumber == NULL) {
Rick Dean536ba022009-07-24 23:57:27 -0500288 /* never happens */
289 Py_INCREF(Py_None);
290 return Py_None;
291 } else {
292 return ASN1_INTEGER_to_PyString(self->revoked->serialNumber);
293 }
294}
295
296static char crypto_Revoked_set_serial_doc[] = "\n\
297Set the serial number of a revoked Revoked structure\n\
298\n\
299@param hex_str: The new serial number.\n\
300@type hex_str: L{str}\n\
301@return: None\n\
302";
303static PyObject *
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400304crypto_Revoked_set_serial(crypto_RevokedObj *self, PyObject *args, PyObject *keywds) {
Rick Dean536ba022009-07-24 23:57:27 -0500305 static char *kwlist[] = {"hex_str", NULL};
306 const char *hex_str = NULL;
307 BIGNUM *serial = NULL;
308 ASN1_INTEGER *tmpser = NULL;
309
Jean-Paul Calderone289a7b22010-01-30 15:09:43 -0500310 if (!PyArg_ParseTupleAndKeywords(args, keywds, "s:set_serial",
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400311 kwlist, &hex_str)) {
Rick Dean536ba022009-07-24 23:57:27 -0500312 return NULL;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400313 }
Rick Dean536ba022009-07-24 23:57:27 -0500314
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400315 if (!BN_hex2bn(&serial, hex_str) ) {
Rick Dean6385faf2009-07-26 00:07:47 -0500316 PyErr_SetString(PyExc_ValueError, "bad hex string");
Rick Dean536ba022009-07-24 23:57:27 -0500317 return NULL;
318 }
319
320 tmpser = BN_to_ASN1_INTEGER(serial, NULL);
321 BN_free(serial);
322 serial = NULL;
323 X509_REVOKED_set_serialNumber(self->revoked, tmpser);
324 ASN1_INTEGER_free(tmpser);
325
326 Py_INCREF(Py_None);
327 return Py_None;
328}
329
330
331crypto_RevokedObj *
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400332crypto_Revoked_New(X509_REVOKED *revoked) {
Rick Dean536ba022009-07-24 23:57:27 -0500333 crypto_RevokedObj *self;
334
335 self = PyObject_New(crypto_RevokedObj, &crypto_Revoked_Type);
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400336 if (self == NULL) {
337 return NULL;
338 }
Rick Dean536ba022009-07-24 23:57:27 -0500339 self->revoked = revoked;
340 return self;
341}
342
343/*
344 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
345 * { 'name', (PyCFunction)crypto_Revoked_name, METH_VARARGS, crypto_Revoked_name_doc }
346 * for convenience
347 */
348#define ADD_METHOD(name) \
349 { #name, (PyCFunction)crypto_Revoked_##name, METH_VARARGS, crypto_Revoked_##name##_doc }
350#define ADD_KW_METHOD(name) \
351 { #name, (PyCFunction)crypto_Revoked_##name, METH_VARARGS | METH_KEYWORDS, crypto_Revoked_##name##_doc }
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400352static PyMethodDef crypto_Revoked_methods[] = {
Rick Dean6385faf2009-07-26 00:07:47 -0500353 ADD_METHOD(all_reasons),
354 ADD_METHOD(get_reason),
355 ADD_KW_METHOD(set_reason),
Rick Dean536ba022009-07-24 23:57:27 -0500356 ADD_METHOD(get_rev_date),
357 ADD_METHOD(set_rev_date),
358 ADD_METHOD(get_serial),
359 ADD_KW_METHOD(set_serial),
360 { NULL, NULL }
361};
362#undef ADD_METHOD
363
364
365static PyObject *
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400366crypto_Revoked_getattr(crypto_RevokedObj *self, char *name) {
Rick Dean536ba022009-07-24 23:57:27 -0500367 return Py_FindMethod(crypto_Revoked_methods, (PyObject *)self, name);
368}
369
370static void
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400371crypto_Revoked_dealloc(crypto_RevokedObj *self) {
Rick Dean536ba022009-07-24 23:57:27 -0500372 X509_REVOKED_free(self->revoked);
373 self->revoked = NULL;
374
375 PyObject_Del(self);
376}
377
378static char crypto_Revoked_doc[] = "\n\
379Revoked() -> Revoked instance\n\
380\n\
381Create a new empty Revoked object.\n\
382\n\
383@returns: The Revoked object\n\
384";
385
386static PyObject* crypto_Revoked_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs) {
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400387 if (!PyArg_ParseTuple(args, ":Revoked")) {
388 return NULL;
389 }
Jean-Paul Calderone289a7b22010-01-30 15:09:43 -0500390
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400391 return (PyObject *)crypto_Revoked_New(X509_REVOKED_new());
Rick Dean536ba022009-07-24 23:57:27 -0500392}
393
394PyTypeObject crypto_Revoked_Type = {
395 PyObject_HEAD_INIT(NULL)
396 0,
397 "Revoked",
398 sizeof(crypto_RevokedObj),
399 0,
400 (destructor)crypto_Revoked_dealloc,
401 NULL, /* print */
402 (getattrfunc)crypto_Revoked_getattr,
403 NULL, /* setattr */
404 NULL, /* compare */
405 NULL, /* repr */
406 NULL, /* as_number */
407 NULL, /* as_sequence */
408 NULL, /* as_mapping */
409 NULL, /* hash */
410 NULL, /* call */
411 NULL, /* str */
412 NULL, /* getattro */
413 NULL, /* setattro */
414 NULL, /* as_buffer */
415 Py_TPFLAGS_DEFAULT,
416 crypto_Revoked_doc, /* doc */
417 NULL, /* traverse */
418 NULL, /* clear */
419 NULL, /* tp_richcompare */
420 0, /* tp_weaklistoffset */
421 NULL, /* tp_iter */
422 NULL, /* tp_iternext */
423 crypto_Revoked_methods, /* tp_methods */
424 NULL, /* tp_members */
425 NULL, /* tp_getset */
426 NULL, /* tp_base */
427 NULL, /* tp_dict */
428 NULL, /* tp_descr_get */
429 NULL, /* tp_descr_set */
430 0, /* tp_dictoffset */
431 NULL, /* tp_init */
432 NULL, /* tp_alloc */
433 crypto_Revoked_new, /* tp_new */
434};
435
436int init_crypto_revoked(PyObject *module) {
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400437 if(PyType_Ready(&crypto_Revoked_Type) < 0) {
438 return 0;
439 }
Jean-Paul Calderone289a7b22010-01-30 15:09:43 -0500440
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400441 if (PyModule_AddObject(module, "Revoked", (PyObject *)&crypto_Revoked_Type) != 0) {
442 return 0;
443 }
444 return 1;
Rick Dean536ba022009-07-24 23:57:27 -0500445}