blob: e9b1297c4dffa6b40aa72989eebe3af21ce1ad50 [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
Rick Dean6385faf2009-07-26 00:07:47 -0500126static char crypto_Revoked_set_reason_doc[] = "\n\
127Set the reason of a Revoked object.\n\
128\n\
129@param reason: The reason string.\n\
130@type reason: L{str}\n\
131@return: None\n\
132";
133static PyObject *
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400134crypto_Revoked_set_reason(crypto_RevokedObj *self, PyObject *args, PyObject *keywds) {
Rick Dean6385faf2009-07-26 00:07:47 -0500135 static char *kwlist[] = {"reason", NULL};
136 const char *reason_str = NULL;
137 int reason_code;
138 ASN1_ENUMERATED *rtmp = NULL;
139
Jean-Paul Calderone281b62b2010-08-28 14:22:29 -0400140 if (!PyArg_ParseTupleAndKeywords(
141 args, keywds, "O&:set_reason", kwlist,
142 crypto_byte_converter, &reason_str)) {
Rick Dean6385faf2009-07-26 00:07:47 -0500143 return NULL;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400144 }
Rick Dean6385faf2009-07-26 00:07:47 -0500145
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400146 if(reason_str == NULL) {
Jean-Paul Calderone289a7b22010-01-30 15:09:43 -0500147 delete_reason(self->revoked->extensions);
Rick Dean6385faf2009-07-26 00:07:47 -0500148 goto done;
149 }
150
151 reason_code = reason_str_to_code(reason_str);
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400152 if (reason_code == -1) {
Rick Dean6385faf2009-07-26 00:07:47 -0500153 PyErr_SetString(PyExc_ValueError, "bad reason string");
154 return NULL;
155 }
156
157 rtmp = ASN1_ENUMERATED_new();
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400158 if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code)) {
Rick Dean6385faf2009-07-26 00:07:47 -0500159 goto err;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400160 }
Jean-Paul Calderone289a7b22010-01-30 15:09:43 -0500161 delete_reason(self->revoked->extensions);
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400162 if (!X509_REVOKED_add1_ext_i2d(self->revoked, NID_crl_reason, rtmp, 0, 0)) {
Rick Dean6385faf2009-07-26 00:07:47 -0500163 goto err;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400164 }
Rick Dean6385faf2009-07-26 00:07:47 -0500165
166 done:
167 Py_INCREF(Py_None);
168 return Py_None;
169
170 err:
171 exception_from_error_queue(crypto_Error);
172 return NULL;
173}
174
175
176static char crypto_Revoked_get_reason_doc[] = "\n\
177Return the reason of a Revoked object.\n\
178\n\
179@return: The reason as a string\n\
180";
181static PyObject *
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400182crypto_Revoked_get_reason(crypto_RevokedObj *self, PyObject *args) {
Rick Dean6385faf2009-07-26 00:07:47 -0500183 X509_EXTENSION * ext;
184 int j;
185 STACK_OF(X509_EXTENSION) *sk = NULL;
186
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400187 if (!PyArg_ParseTuple(args, ":get_reason")) {
Rick Dean6385faf2009-07-26 00:07:47 -0500188 return NULL;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400189 }
Rick Dean6385faf2009-07-26 00:07:47 -0500190
191 sk = self->revoked->extensions;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400192 for (j = 0; j < sk_X509_EXTENSION_num(sk); j++) {
Rick Dean6385faf2009-07-26 00:07:47 -0500193 ext = sk_X509_EXTENSION_value(sk, j);
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400194 if (OBJ_obj2nid(ext->object) == NID_crl_reason) {
Rick Dean6385faf2009-07-26 00:07:47 -0500195 return X509_EXTENSION_value_to_PyString(ext);
196 }
197 }
198
199 Py_INCREF(Py_None);
200 return Py_None;
201}
202
203
Rick Dean536ba022009-07-24 23:57:27 -0500204static char crypto_Revoked_get_rev_date_doc[] = "\n\
205Retrieve the revocation date\n\
206\n\
207@return: A string giving the timestamp, in the format:\n\
208\n\
209 YYYYMMDDhhmmssZ\n\
210 YYYYMMDDhhmmss+hhmm\n\
211 YYYYMMDDhhmmss-hhmm\n\
212";
213
214static PyObject*
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400215crypto_Revoked_get_rev_date(crypto_RevokedObj *self, PyObject *args) {
216 /* returns a borrowed reference. */
217 return _get_asn1_time(
218 ":get_rev_date", self->revoked->revocationDate, args);
Rick Dean536ba022009-07-24 23:57:27 -0500219}
220
221static char crypto_Revoked_set_rev_date_doc[] = "\n\
222Set the revocation timestamp\n\
223\n\
224@param when: A string giving the timestamp, in the format:\n\
225\n\
226 YYYYMMDDhhmmssZ\n\
227 YYYYMMDDhhmmss+hhmm\n\
228 YYYYMMDDhhmmss-hhmm\n\
229\n\
230@return: None\n\
231";
232
233static PyObject*
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400234crypto_Revoked_set_rev_date(crypto_RevokedObj *self, PyObject *args) {
235 return _set_asn1_time(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400236 BYTESTRING_FMT ":set_rev_date", self->revoked->revocationDate, args);
Rick Dean536ba022009-07-24 23:57:27 -0500237}
238
Jean-Paul Calderone289a7b22010-01-30 15:09:43 -0500239/* The integer is converted to an upper-case hex string
Rick Dean6385faf2009-07-26 00:07:47 -0500240 * without a '0x' prefix. */
Rick Dean536ba022009-07-24 23:57:27 -0500241static PyObject *
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400242ASN1_INTEGER_to_PyString(ASN1_INTEGER *asn1_int) {
Rick Dean536ba022009-07-24 23:57:27 -0500243 BIO *bio = NULL;
Rick Dean6385faf2009-07-26 00:07:47 -0500244 PyObject *str = NULL;
245 int str_len;
246 char *tmp_str;
Rick Dean536ba022009-07-24 23:57:27 -0500247
248 /* Create a openssl BIO buffer */
249 bio = BIO_new(BIO_s_mem());
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400250 if (bio == NULL) {
Rick Dean536ba022009-07-24 23:57:27 -0500251 goto err;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400252 }
Rick Dean536ba022009-07-24 23:57:27 -0500253
254 /* Write the integer to the BIO as a hex string. */
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400255 if (i2a_ASN1_INTEGER(bio, asn1_int) < 0) {
Rick Dean536ba022009-07-24 23:57:27 -0500256 goto err;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400257 }
Rick Dean536ba022009-07-24 23:57:27 -0500258
Rick Dean6385faf2009-07-26 00:07:47 -0500259 /* Convert to a Python string. */
260 str_len = BIO_get_mem_data(bio, &tmp_str);
Jean-Paul Calderone2f6c66f2010-08-11 19:53:43 -0400261 str = PyBytes_FromStringAndSize(tmp_str, str_len);
Rick Dean536ba022009-07-24 23:57:27 -0500262
263 /* Cleanup */
264 BIO_free(bio);
Rick Dean6385faf2009-07-26 00:07:47 -0500265 return str;
Rick Dean536ba022009-07-24 23:57:27 -0500266
267 err:
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400268 if (bio) {
Rick Dean536ba022009-07-24 23:57:27 -0500269 BIO_free(bio);
270 }
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400271 if (str) {
Rick Dean6385faf2009-07-26 00:07:47 -0500272 Py_DECREF(str);
Rick Dean536ba022009-07-24 23:57:27 -0500273 }
274 return NULL;
275}
276
277
278static char crypto_Revoked_get_serial_doc[] = "\n\
279Return the serial number of a Revoked structure\n\
280\n\
281@return: The serial number as a string\n\
282";
283static PyObject *
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400284crypto_Revoked_get_serial(crypto_RevokedObj *self, PyObject *args) {
285 if (!PyArg_ParseTuple(args, ":get_serial")) {
Rick Dean536ba022009-07-24 23:57:27 -0500286 return NULL;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400287 }
Rick Dean536ba022009-07-24 23:57:27 -0500288
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400289 if (self->revoked->serialNumber == NULL) {
Rick Dean536ba022009-07-24 23:57:27 -0500290 /* never happens */
291 Py_INCREF(Py_None);
292 return Py_None;
293 } else {
294 return ASN1_INTEGER_to_PyString(self->revoked->serialNumber);
295 }
296}
297
298static char crypto_Revoked_set_serial_doc[] = "\n\
299Set the serial number of a revoked Revoked structure\n\
300\n\
301@param hex_str: The new serial number.\n\
302@type hex_str: L{str}\n\
303@return: None\n\
304";
305static PyObject *
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400306crypto_Revoked_set_serial(crypto_RevokedObj *self, PyObject *args, PyObject *keywds) {
Rick Dean536ba022009-07-24 23:57:27 -0500307 static char *kwlist[] = {"hex_str", NULL};
308 const char *hex_str = NULL;
309 BIGNUM *serial = NULL;
310 ASN1_INTEGER *tmpser = NULL;
311
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400312 if (!PyArg_ParseTupleAndKeywords(args, keywds, BYTESTRING_FMT ":set_serial",
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400313 kwlist, &hex_str)) {
Rick Dean536ba022009-07-24 23:57:27 -0500314 return NULL;
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400315 }
Rick Dean536ba022009-07-24 23:57:27 -0500316
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400317 if (!BN_hex2bn(&serial, hex_str) ) {
Rick Dean6385faf2009-07-26 00:07:47 -0500318 PyErr_SetString(PyExc_ValueError, "bad hex string");
Rick Dean536ba022009-07-24 23:57:27 -0500319 return NULL;
320 }
321
322 tmpser = BN_to_ASN1_INTEGER(serial, NULL);
323 BN_free(serial);
324 serial = NULL;
325 X509_REVOKED_set_serialNumber(self->revoked, tmpser);
326 ASN1_INTEGER_free(tmpser);
327
328 Py_INCREF(Py_None);
329 return Py_None;
330}
331
332
333crypto_RevokedObj *
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400334crypto_Revoked_New(X509_REVOKED *revoked) {
Rick Dean536ba022009-07-24 23:57:27 -0500335 crypto_RevokedObj *self;
336
337 self = PyObject_New(crypto_RevokedObj, &crypto_Revoked_Type);
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400338 if (self == NULL) {
339 return NULL;
340 }
Rick Dean536ba022009-07-24 23:57:27 -0500341 self->revoked = revoked;
342 return self;
343}
344
345/*
346 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
347 * { 'name', (PyCFunction)crypto_Revoked_name, METH_VARARGS, crypto_Revoked_name_doc }
348 * for convenience
349 */
350#define ADD_METHOD(name) \
351 { #name, (PyCFunction)crypto_Revoked_##name, METH_VARARGS, crypto_Revoked_##name##_doc }
352#define ADD_KW_METHOD(name) \
353 { #name, (PyCFunction)crypto_Revoked_##name, METH_VARARGS | METH_KEYWORDS, crypto_Revoked_##name##_doc }
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400354static PyMethodDef crypto_Revoked_methods[] = {
Rick Dean6385faf2009-07-26 00:07:47 -0500355 ADD_METHOD(all_reasons),
356 ADD_METHOD(get_reason),
357 ADD_KW_METHOD(set_reason),
Rick Dean536ba022009-07-24 23:57:27 -0500358 ADD_METHOD(get_rev_date),
359 ADD_METHOD(set_rev_date),
360 ADD_METHOD(get_serial),
361 ADD_KW_METHOD(set_serial),
362 { NULL, NULL }
363};
364#undef ADD_METHOD
365
366
Rick Dean536ba022009-07-24 23:57:27 -0500367static void
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400368crypto_Revoked_dealloc(crypto_RevokedObj *self) {
Rick Dean536ba022009-07-24 23:57:27 -0500369 X509_REVOKED_free(self->revoked);
370 self->revoked = NULL;
371
372 PyObject_Del(self);
373}
374
375static char crypto_Revoked_doc[] = "\n\
376Revoked() -> Revoked instance\n\
377\n\
378Create a new empty Revoked object.\n\
379\n\
380@returns: The Revoked object\n\
381";
382
383static PyObject* crypto_Revoked_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs) {
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400384 if (!PyArg_ParseTuple(args, ":Revoked")) {
385 return NULL;
386 }
Jean-Paul Calderone289a7b22010-01-30 15:09:43 -0500387
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400388 return (PyObject *)crypto_Revoked_New(X509_REVOKED_new());
Rick Dean536ba022009-07-24 23:57:27 -0500389}
390
391PyTypeObject crypto_Revoked_Type = {
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400392 PyOpenSSL_HEAD_INIT(&PyType_Type, 0)
Rick Dean536ba022009-07-24 23:57:27 -0500393 "Revoked",
394 sizeof(crypto_RevokedObj),
395 0,
396 (destructor)crypto_Revoked_dealloc,
397 NULL, /* print */
Jean-Paul Calderone2f6c66f2010-08-11 19:53:43 -0400398 NULL, /* getattr */
Rick Dean536ba022009-07-24 23:57:27 -0500399 NULL, /* setattr */
400 NULL, /* compare */
401 NULL, /* repr */
402 NULL, /* as_number */
403 NULL, /* as_sequence */
404 NULL, /* as_mapping */
405 NULL, /* hash */
406 NULL, /* call */
407 NULL, /* str */
408 NULL, /* getattro */
409 NULL, /* setattro */
410 NULL, /* as_buffer */
411 Py_TPFLAGS_DEFAULT,
412 crypto_Revoked_doc, /* doc */
413 NULL, /* traverse */
414 NULL, /* clear */
415 NULL, /* tp_richcompare */
416 0, /* tp_weaklistoffset */
417 NULL, /* tp_iter */
418 NULL, /* tp_iternext */
419 crypto_Revoked_methods, /* tp_methods */
420 NULL, /* tp_members */
421 NULL, /* tp_getset */
422 NULL, /* tp_base */
423 NULL, /* tp_dict */
424 NULL, /* tp_descr_get */
425 NULL, /* tp_descr_set */
426 0, /* tp_dictoffset */
427 NULL, /* tp_init */
428 NULL, /* tp_alloc */
429 crypto_Revoked_new, /* tp_new */
430};
431
432int init_crypto_revoked(PyObject *module) {
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400433 if(PyType_Ready(&crypto_Revoked_Type) < 0) {
434 return 0;
435 }
Jean-Paul Calderone289a7b22010-01-30 15:09:43 -0500436
Jean-Paul Calderonebd9f2472010-05-24 18:03:36 -0400437 if (PyModule_AddObject(module, "Revoked", (PyObject *)&crypto_Revoked_Type) != 0) {
438 return 0;
439 }
440 return 1;
Rick Dean536ba022009-07-24 23:57:27 -0500441}