blob: fd9a54555fdf8272839ef43e8ced8fd16a978eeb [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
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
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -0400231#ifdef PY3
232#define FMT(name) ("y" name)
233#else
234#define FMT(name) ("s" name)
235#endif
236
Rick Dean536ba022009-07-24 23:57:27 -0500237static PyObject*
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400238crypto_Revoked_set_rev_date(crypto_RevokedObj *self, PyObject *args) {
239 return _set_asn1_time(
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -0400240 FMT(":set_rev_date"), self->revoked->revocationDate, args);
Rick Dean536ba022009-07-24 23:57:27 -0500241}
242
Jean-Paul Calderone289a7b22010-01-30 15:09:43 -0500243/* The integer is converted to an upper-case hex string
Rick Dean6385faf2009-07-26 00:07:47 -0500244 * without a '0x' prefix. */
Rick Dean536ba022009-07-24 23:57:27 -0500245static PyObject *
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400246ASN1_INTEGER_to_PyString(ASN1_INTEGER *asn1_int) {
Rick Dean536ba022009-07-24 23:57:27 -0500247 BIO *bio = NULL;
Rick Dean6385faf2009-07-26 00:07:47 -0500248 PyObject *str = NULL;
249 int str_len;
250 char *tmp_str;
Rick Dean536ba022009-07-24 23:57:27 -0500251
252 /* Create a openssl BIO buffer */
253 bio = BIO_new(BIO_s_mem());
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400254 if (bio == NULL) {
Rick Dean536ba022009-07-24 23:57:27 -0500255 goto err;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400256 }
Rick Dean536ba022009-07-24 23:57:27 -0500257
258 /* Write the integer to the BIO as a hex string. */
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400259 if (i2a_ASN1_INTEGER(bio, asn1_int) < 0) {
Rick Dean536ba022009-07-24 23:57:27 -0500260 goto err;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400261 }
Rick Dean536ba022009-07-24 23:57:27 -0500262
Rick Dean6385faf2009-07-26 00:07:47 -0500263 /* Convert to a Python string. */
264 str_len = BIO_get_mem_data(bio, &tmp_str);
Jean-Paul Calderone2f6c66f2010-08-11 19:53:43 -0400265 str = PyBytes_FromStringAndSize(tmp_str, str_len);
Rick Dean536ba022009-07-24 23:57:27 -0500266
267 /* Cleanup */
268 BIO_free(bio);
Rick Dean6385faf2009-07-26 00:07:47 -0500269 return str;
Rick Dean536ba022009-07-24 23:57:27 -0500270
271 err:
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400272 if (bio) {
Rick Dean536ba022009-07-24 23:57:27 -0500273 BIO_free(bio);
274 }
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400275 if (str) {
Rick Dean6385faf2009-07-26 00:07:47 -0500276 Py_DECREF(str);
Rick Dean536ba022009-07-24 23:57:27 -0500277 }
278 return NULL;
279}
280
281
282static char crypto_Revoked_get_serial_doc[] = "\n\
283Return the serial number of a Revoked structure\n\
284\n\
285@return: The serial number as a string\n\
286";
287static PyObject *
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400288crypto_Revoked_get_serial(crypto_RevokedObj *self, PyObject *args) {
289 if (!PyArg_ParseTuple(args, ":get_serial")) {
Rick Dean536ba022009-07-24 23:57:27 -0500290 return NULL;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400291 }
Rick Dean536ba022009-07-24 23:57:27 -0500292
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400293 if (self->revoked->serialNumber == NULL) {
Rick Dean536ba022009-07-24 23:57:27 -0500294 /* never happens */
295 Py_INCREF(Py_None);
296 return Py_None;
297 } else {
298 return ASN1_INTEGER_to_PyString(self->revoked->serialNumber);
299 }
300}
301
302static char crypto_Revoked_set_serial_doc[] = "\n\
303Set the serial number of a revoked Revoked structure\n\
304\n\
305@param hex_str: The new serial number.\n\
306@type hex_str: L{str}\n\
307@return: None\n\
308";
309static PyObject *
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400310crypto_Revoked_set_serial(crypto_RevokedObj *self, PyObject *args, PyObject *keywds) {
Rick Dean536ba022009-07-24 23:57:27 -0500311 static char *kwlist[] = {"hex_str", NULL};
312 const char *hex_str = NULL;
313 BIGNUM *serial = NULL;
314 ASN1_INTEGER *tmpser = NULL;
315
Jean-Paul Calderoneeacad4a2010-08-22 17:12:55 -0400316 if (!PyArg_ParseTupleAndKeywords(args, keywds, FMT(":set_serial"),
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400317 kwlist, &hex_str)) {
Rick Dean536ba022009-07-24 23:57:27 -0500318 return NULL;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400319 }
Rick Dean536ba022009-07-24 23:57:27 -0500320
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400321 if (!BN_hex2bn(&serial, hex_str) ) {
Rick Dean6385faf2009-07-26 00:07:47 -0500322 PyErr_SetString(PyExc_ValueError, "bad hex string");
Rick Dean536ba022009-07-24 23:57:27 -0500323 return NULL;
324 }
325
326 tmpser = BN_to_ASN1_INTEGER(serial, NULL);
327 BN_free(serial);
328 serial = NULL;
329 X509_REVOKED_set_serialNumber(self->revoked, tmpser);
330 ASN1_INTEGER_free(tmpser);
331
332 Py_INCREF(Py_None);
333 return Py_None;
334}
335
336
337crypto_RevokedObj *
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400338crypto_Revoked_New(X509_REVOKED *revoked) {
Rick Dean536ba022009-07-24 23:57:27 -0500339 crypto_RevokedObj *self;
340
341 self = PyObject_New(crypto_RevokedObj, &crypto_Revoked_Type);
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400342 if (self == NULL) {
343 return NULL;
344 }
Rick Dean536ba022009-07-24 23:57:27 -0500345 self->revoked = revoked;
346 return self;
347}
348
349/*
350 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
351 * { 'name', (PyCFunction)crypto_Revoked_name, METH_VARARGS, crypto_Revoked_name_doc }
352 * for convenience
353 */
354#define ADD_METHOD(name) \
355 { #name, (PyCFunction)crypto_Revoked_##name, METH_VARARGS, crypto_Revoked_##name##_doc }
356#define ADD_KW_METHOD(name) \
357 { #name, (PyCFunction)crypto_Revoked_##name, METH_VARARGS | METH_KEYWORDS, crypto_Revoked_##name##_doc }
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400358static PyMethodDef crypto_Revoked_methods[] = {
Rick Dean6385faf2009-07-26 00:07:47 -0500359 ADD_METHOD(all_reasons),
360 ADD_METHOD(get_reason),
361 ADD_KW_METHOD(set_reason),
Rick Dean536ba022009-07-24 23:57:27 -0500362 ADD_METHOD(get_rev_date),
363 ADD_METHOD(set_rev_date),
364 ADD_METHOD(get_serial),
365 ADD_KW_METHOD(set_serial),
366 { NULL, NULL }
367};
368#undef ADD_METHOD
369
370
Rick Dean536ba022009-07-24 23:57:27 -0500371static void
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400372crypto_Revoked_dealloc(crypto_RevokedObj *self) {
Rick Dean536ba022009-07-24 23:57:27 -0500373 X509_REVOKED_free(self->revoked);
374 self->revoked = NULL;
375
376 PyObject_Del(self);
377}
378
379static char crypto_Revoked_doc[] = "\n\
380Revoked() -> Revoked instance\n\
381\n\
382Create a new empty Revoked object.\n\
383\n\
384@returns: The Revoked object\n\
385";
386
387static PyObject* crypto_Revoked_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs) {
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400388 if (!PyArg_ParseTuple(args, ":Revoked")) {
389 return NULL;
390 }
Jean-Paul Calderone289a7b22010-01-30 15:09:43 -0500391
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400392 return (PyObject *)crypto_Revoked_New(X509_REVOKED_new());
Rick Dean536ba022009-07-24 23:57:27 -0500393}
394
395PyTypeObject crypto_Revoked_Type = {
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400396 PyOpenSSL_HEAD_INIT(&PyType_Type, 0)
Rick Dean536ba022009-07-24 23:57:27 -0500397 "Revoked",
398 sizeof(crypto_RevokedObj),
399 0,
400 (destructor)crypto_Revoked_dealloc,
401 NULL, /* print */
Jean-Paul Calderone2f6c66f2010-08-11 19:53:43 -0400402 NULL, /* getattr */
Rick Dean536ba022009-07-24 23:57:27 -0500403 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}