blob: c8763732632a701fc178e4ab6fc3526ed27ac205 [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 Calderone2f6c66f2010-08-11 19:53:43 -040039 str = PyBytes_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);
Jean-Paul Calderone2f6c66f2010-08-11 19:53:43 -040069 str = PyBytes_FromStringAndSize(tmp_str, str_len);
Rick Dean6385faf2009-07-26 00:07:47 -050070
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
Jean-Paul Calderone281b62b2010-08-28 14:22:29 -0400125
126static int
127crypto_byte_converter(PyObject *input, void* output) {
128 char **message = output;
129 if (input == Py_None) {
130 *message = NULL;
131 } else if (PyBytes_CheckExact(input)) {
132 *message = PyBytes_AsString(input);
133 } else {
134 return 0;
135 }
136 return 1;
137}
138
Rick Dean6385faf2009-07-26 00:07:47 -0500139static char crypto_Revoked_set_reason_doc[] = "\n\
140Set the reason of a Revoked object.\n\
141\n\
142@param reason: The reason string.\n\
143@type reason: L{str}\n\
144@return: None\n\
145";
146static PyObject *
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400147crypto_Revoked_set_reason(crypto_RevokedObj *self, PyObject *args, PyObject *keywds) {
Rick Dean6385faf2009-07-26 00:07:47 -0500148 static char *kwlist[] = {"reason", NULL};
149 const char *reason_str = NULL;
150 int reason_code;
151 ASN1_ENUMERATED *rtmp = NULL;
152
Jean-Paul Calderone281b62b2010-08-28 14:22:29 -0400153 if (!PyArg_ParseTupleAndKeywords(
154 args, keywds, "O&:set_reason", kwlist,
155 crypto_byte_converter, &reason_str)) {
Rick Dean6385faf2009-07-26 00:07:47 -0500156 return NULL;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400157 }
Rick Dean6385faf2009-07-26 00:07:47 -0500158
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400159 if(reason_str == NULL) {
Jean-Paul Calderone289a7b22010-01-30 15:09:43 -0500160 delete_reason(self->revoked->extensions);
Rick Dean6385faf2009-07-26 00:07:47 -0500161 goto done;
162 }
163
164 reason_code = reason_str_to_code(reason_str);
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400165 if (reason_code == -1) {
Rick Dean6385faf2009-07-26 00:07:47 -0500166 PyErr_SetString(PyExc_ValueError, "bad reason string");
167 return NULL;
168 }
169
170 rtmp = ASN1_ENUMERATED_new();
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400171 if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code)) {
Rick Dean6385faf2009-07-26 00:07:47 -0500172 goto err;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400173 }
Jean-Paul Calderone289a7b22010-01-30 15:09:43 -0500174 delete_reason(self->revoked->extensions);
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400175 if (!X509_REVOKED_add1_ext_i2d(self->revoked, NID_crl_reason, rtmp, 0, 0)) {
Rick Dean6385faf2009-07-26 00:07:47 -0500176 goto err;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400177 }
Rick Dean6385faf2009-07-26 00:07:47 -0500178
179 done:
180 Py_INCREF(Py_None);
181 return Py_None;
182
183 err:
184 exception_from_error_queue(crypto_Error);
185 return NULL;
186}
187
188
189static char crypto_Revoked_get_reason_doc[] = "\n\
190Return the reason of a Revoked object.\n\
191\n\
192@return: The reason as a string\n\
193";
194static PyObject *
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400195crypto_Revoked_get_reason(crypto_RevokedObj *self, PyObject *args) {
Rick Dean6385faf2009-07-26 00:07:47 -0500196 X509_EXTENSION * ext;
197 int j;
198 STACK_OF(X509_EXTENSION) *sk = NULL;
199
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400200 if (!PyArg_ParseTuple(args, ":get_reason")) {
Rick Dean6385faf2009-07-26 00:07:47 -0500201 return NULL;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400202 }
Rick Dean6385faf2009-07-26 00:07:47 -0500203
204 sk = self->revoked->extensions;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400205 for (j = 0; j < sk_X509_EXTENSION_num(sk); j++) {
Rick Dean6385faf2009-07-26 00:07:47 -0500206 ext = sk_X509_EXTENSION_value(sk, j);
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400207 if (OBJ_obj2nid(ext->object) == NID_crl_reason) {
Rick Dean6385faf2009-07-26 00:07:47 -0500208 return X509_EXTENSION_value_to_PyString(ext);
209 }
210 }
211
212 Py_INCREF(Py_None);
213 return Py_None;
214}
215
216
Rick Dean536ba022009-07-24 23:57:27 -0500217static char crypto_Revoked_get_rev_date_doc[] = "\n\
218Retrieve the revocation date\n\
219\n\
220@return: A string giving the timestamp, in the format:\n\
221\n\
222 YYYYMMDDhhmmssZ\n\
223 YYYYMMDDhhmmss+hhmm\n\
224 YYYYMMDDhhmmss-hhmm\n\
225";
226
227static PyObject*
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400228crypto_Revoked_get_rev_date(crypto_RevokedObj *self, PyObject *args) {
229 /* returns a borrowed reference. */
230 return _get_asn1_time(
231 ":get_rev_date", self->revoked->revocationDate, args);
Rick Dean536ba022009-07-24 23:57:27 -0500232}
233
234static char crypto_Revoked_set_rev_date_doc[] = "\n\
235Set the revocation timestamp\n\
236\n\
237@param when: A string giving the timestamp, in the format:\n\
238\n\
239 YYYYMMDDhhmmssZ\n\
240 YYYYMMDDhhmmss+hhmm\n\
241 YYYYMMDDhhmmss-hhmm\n\
242\n\
243@return: None\n\
244";
245
246static PyObject*
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400247crypto_Revoked_set_rev_date(crypto_RevokedObj *self, PyObject *args) {
248 return _set_asn1_time(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400249 BYTESTRING_FMT ":set_rev_date", self->revoked->revocationDate, args);
Rick Dean536ba022009-07-24 23:57:27 -0500250}
251
Jean-Paul Calderone289a7b22010-01-30 15:09:43 -0500252/* The integer is converted to an upper-case hex string
Rick Dean6385faf2009-07-26 00:07:47 -0500253 * without a '0x' prefix. */
Rick Dean536ba022009-07-24 23:57:27 -0500254static PyObject *
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400255ASN1_INTEGER_to_PyString(ASN1_INTEGER *asn1_int) {
Rick Dean536ba022009-07-24 23:57:27 -0500256 BIO *bio = NULL;
Rick Dean6385faf2009-07-26 00:07:47 -0500257 PyObject *str = NULL;
258 int str_len;
259 char *tmp_str;
Rick Dean536ba022009-07-24 23:57:27 -0500260
261 /* Create a openssl BIO buffer */
262 bio = BIO_new(BIO_s_mem());
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400263 if (bio == NULL) {
Rick Dean536ba022009-07-24 23:57:27 -0500264 goto err;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400265 }
Rick Dean536ba022009-07-24 23:57:27 -0500266
267 /* Write the integer to the BIO as a hex string. */
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400268 if (i2a_ASN1_INTEGER(bio, asn1_int) < 0) {
Rick Dean536ba022009-07-24 23:57:27 -0500269 goto err;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400270 }
Rick Dean536ba022009-07-24 23:57:27 -0500271
Rick Dean6385faf2009-07-26 00:07:47 -0500272 /* Convert to a Python string. */
273 str_len = BIO_get_mem_data(bio, &tmp_str);
Jean-Paul Calderone2f6c66f2010-08-11 19:53:43 -0400274 str = PyBytes_FromStringAndSize(tmp_str, str_len);
Rick Dean536ba022009-07-24 23:57:27 -0500275
276 /* Cleanup */
277 BIO_free(bio);
Rick Dean6385faf2009-07-26 00:07:47 -0500278 return str;
Rick Dean536ba022009-07-24 23:57:27 -0500279
280 err:
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400281 if (bio) {
Rick Dean536ba022009-07-24 23:57:27 -0500282 BIO_free(bio);
283 }
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400284 if (str) {
Rick Dean6385faf2009-07-26 00:07:47 -0500285 Py_DECREF(str);
Rick Dean536ba022009-07-24 23:57:27 -0500286 }
287 return NULL;
288}
289
290
291static char crypto_Revoked_get_serial_doc[] = "\n\
292Return the serial number of a Revoked structure\n\
293\n\
294@return: The serial number as a string\n\
295";
296static PyObject *
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400297crypto_Revoked_get_serial(crypto_RevokedObj *self, PyObject *args) {
298 if (!PyArg_ParseTuple(args, ":get_serial")) {
Rick Dean536ba022009-07-24 23:57:27 -0500299 return NULL;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400300 }
Rick Dean536ba022009-07-24 23:57:27 -0500301
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400302 if (self->revoked->serialNumber == NULL) {
Rick Dean536ba022009-07-24 23:57:27 -0500303 /* never happens */
304 Py_INCREF(Py_None);
305 return Py_None;
306 } else {
307 return ASN1_INTEGER_to_PyString(self->revoked->serialNumber);
308 }
309}
310
311static char crypto_Revoked_set_serial_doc[] = "\n\
312Set the serial number of a revoked Revoked structure\n\
313\n\
314@param hex_str: The new serial number.\n\
315@type hex_str: L{str}\n\
316@return: None\n\
317";
318static PyObject *
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400319crypto_Revoked_set_serial(crypto_RevokedObj *self, PyObject *args, PyObject *keywds) {
Rick Dean536ba022009-07-24 23:57:27 -0500320 static char *kwlist[] = {"hex_str", NULL};
321 const char *hex_str = NULL;
322 BIGNUM *serial = NULL;
323 ASN1_INTEGER *tmpser = NULL;
324
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400325 if (!PyArg_ParseTupleAndKeywords(args, keywds, BYTESTRING_FMT ":set_serial",
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400326 kwlist, &hex_str)) {
Rick Dean536ba022009-07-24 23:57:27 -0500327 return NULL;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400328 }
Rick Dean536ba022009-07-24 23:57:27 -0500329
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400330 if (!BN_hex2bn(&serial, hex_str) ) {
Rick Dean6385faf2009-07-26 00:07:47 -0500331 PyErr_SetString(PyExc_ValueError, "bad hex string");
Rick Dean536ba022009-07-24 23:57:27 -0500332 return NULL;
333 }
334
335 tmpser = BN_to_ASN1_INTEGER(serial, NULL);
336 BN_free(serial);
337 serial = NULL;
338 X509_REVOKED_set_serialNumber(self->revoked, tmpser);
339 ASN1_INTEGER_free(tmpser);
340
341 Py_INCREF(Py_None);
342 return Py_None;
343}
344
345
346crypto_RevokedObj *
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400347crypto_Revoked_New(X509_REVOKED *revoked) {
Rick Dean536ba022009-07-24 23:57:27 -0500348 crypto_RevokedObj *self;
349
350 self = PyObject_New(crypto_RevokedObj, &crypto_Revoked_Type);
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400351 if (self == NULL) {
352 return NULL;
353 }
Rick Dean536ba022009-07-24 23:57:27 -0500354 self->revoked = revoked;
355 return self;
356}
357
358/*
359 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
360 * { 'name', (PyCFunction)crypto_Revoked_name, METH_VARARGS, crypto_Revoked_name_doc }
361 * for convenience
362 */
363#define ADD_METHOD(name) \
364 { #name, (PyCFunction)crypto_Revoked_##name, METH_VARARGS, crypto_Revoked_##name##_doc }
365#define ADD_KW_METHOD(name) \
366 { #name, (PyCFunction)crypto_Revoked_##name, METH_VARARGS | METH_KEYWORDS, crypto_Revoked_##name##_doc }
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400367static PyMethodDef crypto_Revoked_methods[] = {
Rick Dean6385faf2009-07-26 00:07:47 -0500368 ADD_METHOD(all_reasons),
369 ADD_METHOD(get_reason),
370 ADD_KW_METHOD(set_reason),
Rick Dean536ba022009-07-24 23:57:27 -0500371 ADD_METHOD(get_rev_date),
372 ADD_METHOD(set_rev_date),
373 ADD_METHOD(get_serial),
374 ADD_KW_METHOD(set_serial),
375 { NULL, NULL }
376};
377#undef ADD_METHOD
378
379
Rick Dean536ba022009-07-24 23:57:27 -0500380static void
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400381crypto_Revoked_dealloc(crypto_RevokedObj *self) {
Rick Dean536ba022009-07-24 23:57:27 -0500382 X509_REVOKED_free(self->revoked);
383 self->revoked = NULL;
384
385 PyObject_Del(self);
386}
387
388static char crypto_Revoked_doc[] = "\n\
389Revoked() -> Revoked instance\n\
390\n\
391Create a new empty Revoked object.\n\
392\n\
393@returns: The Revoked object\n\
394";
395
396static PyObject* crypto_Revoked_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs) {
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400397 if (!PyArg_ParseTuple(args, ":Revoked")) {
398 return NULL;
399 }
Jean-Paul Calderone289a7b22010-01-30 15:09:43 -0500400
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400401 return (PyObject *)crypto_Revoked_New(X509_REVOKED_new());
Rick Dean536ba022009-07-24 23:57:27 -0500402}
403
404PyTypeObject crypto_Revoked_Type = {
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400405 PyOpenSSL_HEAD_INIT(&PyType_Type, 0)
Rick Dean536ba022009-07-24 23:57:27 -0500406 "Revoked",
407 sizeof(crypto_RevokedObj),
408 0,
409 (destructor)crypto_Revoked_dealloc,
410 NULL, /* print */
Jean-Paul Calderone2f6c66f2010-08-11 19:53:43 -0400411 NULL, /* getattr */
Rick Dean536ba022009-07-24 23:57:27 -0500412 NULL, /* setattr */
413 NULL, /* compare */
414 NULL, /* repr */
415 NULL, /* as_number */
416 NULL, /* as_sequence */
417 NULL, /* as_mapping */
418 NULL, /* hash */
419 NULL, /* call */
420 NULL, /* str */
421 NULL, /* getattro */
422 NULL, /* setattro */
423 NULL, /* as_buffer */
424 Py_TPFLAGS_DEFAULT,
425 crypto_Revoked_doc, /* doc */
426 NULL, /* traverse */
427 NULL, /* clear */
428 NULL, /* tp_richcompare */
429 0, /* tp_weaklistoffset */
430 NULL, /* tp_iter */
431 NULL, /* tp_iternext */
432 crypto_Revoked_methods, /* tp_methods */
433 NULL, /* tp_members */
434 NULL, /* tp_getset */
435 NULL, /* tp_base */
436 NULL, /* tp_dict */
437 NULL, /* tp_descr_get */
438 NULL, /* tp_descr_set */
439 0, /* tp_dictoffset */
440 NULL, /* tp_init */
441 NULL, /* tp_alloc */
442 crypto_Revoked_new, /* tp_new */
443};
444
445int init_crypto_revoked(PyObject *module) {
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400446 if(PyType_Ready(&crypto_Revoked_Type) < 0) {
447 return 0;
448 }
Jean-Paul Calderone289a7b22010-01-30 15:09:43 -0500449
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400450 if (PyModule_AddObject(module, "Revoked", (PyObject *)&crypto_Revoked_Type) != 0) {
451 return 0;
452 }
453 return 1;
Rick Dean536ba022009-07-24 23:57:27 -0500454}