blob: 08dc567625789c783b6245221838fd729a98b07a [file] [log] [blame]
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05001/*
2 * x509.c
3 *
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05004 * Copyright (C) AB Strakt
5 * Copyright (C) Jean-Paul Calderone
6 * See LICENSE for details.
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05007 *
8 * Certificate (X.509) handling code, mostly thin wrappers around OpenSSL.
9 * See the file RATIONALE for a short explanation of why this module was written.
10 *
11 * Reviewed 2001-07-23
12 */
13#include <Python.h>
14#define crypto_MODULE
15#include "crypto.h"
16
Jean-Paul Calderone525ef802008-03-09 20:39:42 -040017/*
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050018 * X.509 is a standard for digital certificates. See e.g. the OpenSSL homepage
19 * http://www.openssl.org/ for more information
20 */
21
22static char crypto_X509_get_version_doc[] = "\n\
23Return version number of the certificate\n\
24\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040025@return: Version number as a Python integer\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050026";
27
28static PyObject *
29crypto_X509_get_version(crypto_X509Obj *self, PyObject *args)
30{
31 if (!PyArg_ParseTuple(args, ":get_version"))
32 return NULL;
33
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -040034 return PyLong_FromLong((long)X509_get_version(self->x509));
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050035}
36
37static char crypto_X509_set_version_doc[] = "\n\
38Set version number of the certificate\n\
39\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040040@param version: The version number\n\
41@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050042";
43
44static PyObject *
45crypto_X509_set_version(crypto_X509Obj *self, PyObject *args)
46{
47 int version;
48
49 if (!PyArg_ParseTuple(args, "i:set_version", &version))
50 return NULL;
51
52 X509_set_version(self->x509, version);
53
54 Py_INCREF(Py_None);
55 return Py_None;
56}
57
58static char crypto_X509_get_serial_number_doc[] = "\n\
59Return serial number of the certificate\n\
60\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040061@return: Serial number as a Python integer\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050062";
63
64static PyObject *
65crypto_X509_get_serial_number(crypto_X509Obj *self, PyObject *args)
66{
67 ASN1_INTEGER *asn1_i;
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050068 BIGNUM *bignum;
69 char *hex;
70 PyObject *res;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050071
72 if (!PyArg_ParseTuple(args, ":get_serial_number"))
73 return NULL;
74
75 asn1_i = X509_get_serialNumber(self->x509);
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050076 bignum = ASN1_INTEGER_to_BN(asn1_i, NULL);
77 hex = BN_bn2hex(bignum);
78 res = PyLong_FromString(hex, NULL, 16);
79 BN_free(bignum);
80 free(hex);
81 return res;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050082}
83
84static char crypto_X509_set_serial_number_doc[] = "\n\
85Set serial number of the certificate\n\
86\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040087@param serial: The serial number\n\
88@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050089";
90
91static PyObject *
92crypto_X509_set_serial_number(crypto_X509Obj *self, PyObject *args)
93{
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050094 long small_serial;
95 PyObject *serial = NULL;
96 PyObject *hex = NULL;
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050097 ASN1_INTEGER *asn1_i = NULL;
98 BIGNUM *bignum = NULL;
Jean-Paul Calderonedd467fb2010-08-12 20:44:32 -040099 char *hexstr;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500100
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500101 if (!PyArg_ParseTuple(args, "O:set_serial_number", &serial)) {
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500102 return NULL;
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500103 }
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500104
Jean-Paul Calderonec18669e2010-08-12 00:03:05 -0400105 if (!PyOpenSSL_Integer_Check(serial)) {
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500106 PyErr_SetString(
107 PyExc_TypeError, "serial number must be integer");
108 goto err;
109 }
110
Jean-Paul Calderonea5a032f2010-08-12 20:03:32 -0400111 if ((hex = PyOpenSSL_LongToHex(serial)) == NULL) {
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500112 goto err;
113 }
114
Jean-Paul Calderonedd467fb2010-08-12 20:44:32 -0400115#ifdef PY3
116 {
117 PyObject *hexbytes = PyUnicode_AsASCIIString(hex);
118 Py_DECREF(hex);
119 hex = hexbytes;
120 }
121#endif
122
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500123 /**
124 * BN_hex2bn stores the result in &bignum. Unless it doesn't feel like
125 * it. If bignum is still NULL after this call, then the return value
126 * is actually the result. I hope. -exarkun
127 */
Jean-Paul Calderonedd467fb2010-08-12 20:44:32 -0400128 hexstr = PyBytes_AsString(hex);
Jean-Paul Calderone8eb46c72010-08-22 17:05:37 -0400129 if (hexstr[1] == 'x') {
Jean-Paul Calderone728eba92010-08-12 20:17:59 -0400130 /* +2 to skip the "0x" */
Jean-Paul Calderonedd467fb2010-08-12 20:44:32 -0400131 hexstr += 2;
Jean-Paul Calderone728eba92010-08-12 20:17:59 -0400132 }
Jean-Paul Calderonedd467fb2010-08-12 20:44:32 -0400133 small_serial = BN_hex2bn(&bignum, hexstr);
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500134
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500135 Py_DECREF(hex);
136 hex = NULL;
137
138 if (bignum == NULL) {
139 if (ASN1_INTEGER_set(X509_get_serialNumber(self->x509), small_serial)) {
Rick Deand369c932009-07-08 11:48:33 -0500140 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500141 goto err;
142 }
143 } else {
144 asn1_i = BN_to_ASN1_INTEGER(bignum, NULL);
145 BN_free(bignum);
146 bignum = NULL;
147 if (asn1_i == NULL) {
Rick Deand369c932009-07-08 11:48:33 -0500148 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500149 goto err;
150 }
151 if (!X509_set_serialNumber(self->x509, asn1_i)) {
Rick Deand369c932009-07-08 11:48:33 -0500152 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500153 goto err;
154 }
155 ASN1_INTEGER_free(asn1_i);
156 asn1_i = NULL;
157 }
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500158
159 Py_INCREF(Py_None);
160 return Py_None;
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500161
162 err:
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500163 if (hex) {
164 Py_DECREF(hex);
165 }
166 if (bignum) {
167 BN_free(bignum);
168 }
169 if (asn1_i) {
170 ASN1_INTEGER_free(asn1_i);
171 }
172 return NULL;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500173}
174
175static char crypto_X509_get_issuer_doc[] = "\n\
176Create an X509Name object for the issuer of the certificate\n\
177\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400178@return: An X509Name object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500179";
180
181static PyObject *
182crypto_X509_get_issuer(crypto_X509Obj *self, PyObject *args)
183{
184 crypto_X509NameObj *pyname;
185 X509_NAME *name;
186
187 if (!PyArg_ParseTuple(args, ":get_issuer"))
188 return NULL;
189
190 name = X509_get_issuer_name(self->x509);
191 pyname = crypto_X509Name_New(name, 0);
192 if (pyname != NULL)
193 {
194 pyname->parent_cert = (PyObject *)self;
195 Py_INCREF(self);
196 }
197 return (PyObject *)pyname;
198}
199
200static char crypto_X509_set_issuer_doc[] = "\n\
201Set the issuer of the certificate\n\
202\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400203@param issuer: The issuer name\n\
204@type issuer: L{X509Name}\n\
205@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500206";
207
208static PyObject *
209crypto_X509_set_issuer(crypto_X509Obj *self, PyObject *args)
210{
211 crypto_X509NameObj *issuer;
212
213 if (!PyArg_ParseTuple(args, "O!:set_issuer", &crypto_X509Name_Type,
214 &issuer))
215 return NULL;
216
217 if (!X509_set_issuer_name(self->x509, issuer->x509_name))
218 {
Rick Deand369c932009-07-08 11:48:33 -0500219 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500220 return NULL;
221 }
222
223 Py_INCREF(Py_None);
224 return Py_None;
225}
226
227static char crypto_X509_get_subject_doc[] = "\n\
228Create an X509Name object for the subject of the certificate\n\
229\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400230@return: An X509Name object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500231";
232
233static PyObject *
234crypto_X509_get_subject(crypto_X509Obj *self, PyObject *args)
235{
236 crypto_X509NameObj *pyname;
237 X509_NAME *name;
238
239 if (!PyArg_ParseTuple(args, ":get_subject"))
240 return NULL;
241
242 name = X509_get_subject_name(self->x509);
243 pyname = crypto_X509Name_New(name, 0);
244 if (pyname != NULL)
245 {
246 pyname->parent_cert = (PyObject *)self;
247 Py_INCREF(self);
248 }
249 return (PyObject *)pyname;
250}
251
252static char crypto_X509_set_subject_doc[] = "\n\
253Set the subject of the certificate\n\
254\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400255@param subject: The subject name\n\
256@type subject: L{X509Name}\n\
257@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500258";
259
260static PyObject *
261crypto_X509_set_subject(crypto_X509Obj *self, PyObject *args)
262{
263 crypto_X509NameObj *subject;
264
265 if (!PyArg_ParseTuple(args, "O!:set_subject", &crypto_X509Name_Type,
266 &subject))
267 return NULL;
268
269 if (!X509_set_subject_name(self->x509, subject->x509_name))
270 {
Rick Deand369c932009-07-08 11:48:33 -0500271 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500272 return NULL;
273 }
274
275 Py_INCREF(Py_None);
276 return Py_None;
277}
278
279static char crypto_X509_get_pubkey_doc[] = "\n\
280Get the public key of the certificate\n\
281\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400282@return: The public key\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500283";
284
285static PyObject *
286crypto_X509_get_pubkey(crypto_X509Obj *self, PyObject *args)
287{
288 crypto_PKeyObj *crypto_PKey_New(EVP_PKEY *, int);
289 EVP_PKEY *pkey;
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400290 crypto_PKeyObj *py_pkey;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500291
292 if (!PyArg_ParseTuple(args, ":get_pubkey"))
293 return NULL;
294
295 if ((pkey = X509_get_pubkey(self->x509)) == NULL)
296 {
Rick Deand369c932009-07-08 11:48:33 -0500297 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500298 return NULL;
299 }
300
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400301 py_pkey = crypto_PKey_New(pkey, 1);
302 if (py_pkey != NULL) {
303 py_pkey->only_public = 1;
304 }
Jean-Paul Calderonef60beec2008-07-22 21:19:02 -0400305 return (PyObject *)py_pkey;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500306}
307
308static char crypto_X509_set_pubkey_doc[] = "\n\
309Set the public key of the certificate\n\
310\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400311@param pkey: The public key\n\
312@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500313";
314
315static PyObject *
316crypto_X509_set_pubkey(crypto_X509Obj *self, PyObject *args)
317{
318 crypto_PKeyObj *pkey;
319
320 if (!PyArg_ParseTuple(args, "O!:set_pubkey", &crypto_PKey_Type, &pkey))
321 return NULL;
322
323 if (!X509_set_pubkey(self->x509, pkey->pkey))
324 {
Rick Deand369c932009-07-08 11:48:33 -0500325 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500326 return NULL;
327 }
328
329 Py_INCREF(Py_None);
330 return Py_None;
331}
332
Rick Dean536ba022009-07-24 23:57:27 -0500333PyObject*
334_set_asn1_time(char *format, ASN1_TIME* timestamp, PyObject *args)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400335{
336 char *when;
337
338 if (!PyArg_ParseTuple(args, format, &when))
339 return NULL;
340
341 if (ASN1_GENERALIZEDTIME_set_string(timestamp, when) == 0) {
342 ASN1_GENERALIZEDTIME dummy;
343 dummy.type = V_ASN1_GENERALIZEDTIME;
344 dummy.length = strlen(when);
Jean-Paul Calderone28ebb302008-12-29 16:25:30 -0500345 dummy.data = (unsigned char *)when;
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400346 if (!ASN1_GENERALIZEDTIME_check(&dummy)) {
347 PyErr_SetString(PyExc_ValueError, "Invalid string");
348 } else {
349 PyErr_SetString(PyExc_RuntimeError, "Unknown ASN1_GENERALIZEDTIME_set_string failure");
350 }
351 return NULL;
352 }
353 Py_INCREF(Py_None);
354 return Py_None;
355}
356
357static char crypto_X509_set_notBefore_doc[] = "\n\
358Set the time stamp for when the certificate starts being valid\n\
359\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400360@param when: A string giving the timestamp, in the format:\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400361\n\
362 YYYYMMDDhhmmssZ\n\
363 YYYYMMDDhhmmss+hhmm\n\
364 YYYYMMDDhhmmss-hhmm\n\
365\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400366@return: None\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400367";
368
369static PyObject*
370crypto_X509_set_notBefore(crypto_X509Obj *self, PyObject *args)
371{
372 return _set_asn1_time(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400373 BYTESTRING_FMT ":set_notBefore",
374 X509_get_notBefore(self->x509), args);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400375}
376
377static char crypto_X509_set_notAfter_doc[] = "\n\
378Set the time stamp for when the certificate stops being valid\n\
379\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400380@param when: A string giving the timestamp, in the format:\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400381\n\
382 YYYYMMDDhhmmssZ\n\
383 YYYYMMDDhhmmss+hhmm\n\
384 YYYYMMDDhhmmss-hhmm\n\
385\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400386@return: None\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400387";
388
389static PyObject*
390crypto_X509_set_notAfter(crypto_X509Obj *self, PyObject *args)
391{
392 return _set_asn1_time(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400393 BYTESTRING_FMT ":set_notAfter",
394 X509_get_notAfter(self->x509), args);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400395}
396
Rick Dean536ba022009-07-24 23:57:27 -0500397PyObject*
398_get_asn1_time(char *format, ASN1_TIME* timestamp, PyObject *args)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400399{
400 ASN1_GENERALIZEDTIME *gt_timestamp = NULL;
401 PyObject *py_timestamp = NULL;
402
403 if (!PyArg_ParseTuple(args, format)) {
404 return NULL;
405 }
406
407 /*
408 * http://www.columbia.edu/~ariel/ssleay/asn1-time.html
409 */
410 /*
411 * There must be a way to do this without touching timestamp->data
412 * directly. -exarkun
413 */
Jean-Paul Calderonee0615b52008-03-09 21:44:46 -0400414 if (timestamp->length == 0) {
415 Py_INCREF(Py_None);
416 return Py_None;
417 } else if (timestamp->type == V_ASN1_GENERALIZEDTIME) {
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400418 return PyBytes_FromString((char *)timestamp->data);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400419 } else {
420 ASN1_TIME_to_generalizedtime(timestamp, &gt_timestamp);
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -0400421 if (gt_timestamp == NULL) {
Rick Deand369c932009-07-08 11:48:33 -0500422 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400423 return NULL;
424 } else {
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400425 py_timestamp = PyBytes_FromString((char *)gt_timestamp->data);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400426 ASN1_GENERALIZEDTIME_free(gt_timestamp);
427 return py_timestamp;
428 }
429 }
430}
431
432static char crypto_X509_get_notBefore_doc[] = "\n\
433Retrieve the time stamp for when the certificate starts being valid\n\
434\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400435@return: A string giving the timestamp, in the format:\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400436\n\
437 YYYYMMDDhhmmssZ\n\
438 YYYYMMDDhhmmss+hhmm\n\
439 YYYYMMDDhhmmss-hhmm\n\
440 or None if there is no value set.\n\
441";
442
443static PyObject*
444crypto_X509_get_notBefore(crypto_X509Obj *self, PyObject *args)
445{
446 /*
447 * X509_get_notBefore returns a borrowed reference.
448 */
449 return _get_asn1_time(
Rick Dean536ba022009-07-24 23:57:27 -0500450 ":get_notBefore", X509_get_notBefore(self->x509), args);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400451}
452
453
454static char crypto_X509_get_notAfter_doc[] = "\n\
455Retrieve the time stamp for when the certificate stops being valid\n\
456\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400457@return: A string giving the timestamp, in the format:\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400458\n\
459 YYYYMMDDhhmmssZ\n\
460 YYYYMMDDhhmmss+hhmm\n\
461 YYYYMMDDhhmmss-hhmm\n\
462 or None if there is no value set.\n\
463";
464
465static PyObject*
466crypto_X509_get_notAfter(crypto_X509Obj *self, PyObject *args)
467{
468 /*
469 * X509_get_notAfter returns a borrowed reference.
470 */
471 return _get_asn1_time(
Rick Dean536ba022009-07-24 23:57:27 -0500472 ":get_notAfter", X509_get_notAfter(self->x509), args);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400473}
474
475
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500476static char crypto_X509_gmtime_adj_notBefore_doc[] = "\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400477Change the timestamp for when the certificate starts being valid to the current\n\
478time plus an offset.\n \
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500479\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400480@param amount: The number of seconds by which to adjust the starting validity\n\
481 time.\n\
482@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500483";
484
485static PyObject *
486crypto_X509_gmtime_adj_notBefore(crypto_X509Obj *self, PyObject *args)
487{
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400488 long amount;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500489
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400490 if (!PyArg_ParseTuple(args, "l:gmtime_adj_notBefore", &amount))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500491 return NULL;
492
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400493 X509_gmtime_adj(X509_get_notBefore(self->x509), amount);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500494
495 Py_INCREF(Py_None);
496 return Py_None;
497}
498
499static char crypto_X509_gmtime_adj_notAfter_doc[] = "\n\
500Adjust the time stamp for when the certificate stops being valid\n\
501\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400502@param amount: The number of seconds by which to adjust the ending validity\n\
503 time.\n\
504@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500505";
506
507static PyObject *
508crypto_X509_gmtime_adj_notAfter(crypto_X509Obj *self, PyObject *args)
509{
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400510 long amount;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500511
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400512 if (!PyArg_ParseTuple(args, "l:gmtime_adj_notAfter", &amount))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500513 return NULL;
514
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400515 X509_gmtime_adj(X509_get_notAfter(self->x509), amount);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500516
517 Py_INCREF(Py_None);
518 return Py_None;
519}
520
521static char crypto_X509_sign_doc[] = "\n\
522Sign the certificate using the supplied key and digest\n\
523\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400524@param pkey: The key to sign with\n\
525@param digest: The message digest to use\n\
526@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500527";
528
529static PyObject *
530crypto_X509_sign(crypto_X509Obj *self, PyObject *args)
531{
532 crypto_PKeyObj *pkey;
533 char *digest_name;
534 const EVP_MD *digest;
535
536 if (!PyArg_ParseTuple(args, "O!s:sign", &crypto_PKey_Type, &pkey,
537 &digest_name))
538 return NULL;
539
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400540 if (pkey->only_public) {
541 PyErr_SetString(PyExc_ValueError, "Key has only public part");
542 return NULL;
543 }
544
545 if (!pkey->initialized) {
546 PyErr_SetString(PyExc_ValueError, "Key is uninitialized");
547 return NULL;
548 }
549
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500550 if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
551 {
552 PyErr_SetString(PyExc_ValueError, "No such digest method");
553 return NULL;
554 }
555
556 if (!X509_sign(self->x509, pkey->pkey, digest))
557 {
Rick Deand369c932009-07-08 11:48:33 -0500558 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500559 return NULL;
560 }
561
562 Py_INCREF(Py_None);
563 return Py_None;
564}
565
566static char crypto_X509_has_expired_doc[] = "\n\
567Check whether the certificate has expired.\n\
568\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400569@return: True if the certificate has expired, false otherwise\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500570";
571
572static PyObject *
573crypto_X509_has_expired(crypto_X509Obj *self, PyObject *args)
574{
575 time_t tnow;
576
577 if (!PyArg_ParseTuple(args, ":has_expired"))
578 return NULL;
579
580 tnow = time(NULL);
581 if (ASN1_UTCTIME_cmp_time_t(X509_get_notAfter(self->x509), tnow) < 0)
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400582 return PyLong_FromLong(1L);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500583 else
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400584 return PyLong_FromLong(0L);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500585}
586
587static char crypto_X509_subject_name_hash_doc[] = "\n\
588Return the hash of the X509 subject.\n\
589\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400590@return: The hash of the subject\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500591";
592
593static PyObject *
594crypto_X509_subject_name_hash(crypto_X509Obj *self, PyObject *args)
595{
596 if (!PyArg_ParseTuple(args, ":subject_name_hash"))
597 return NULL;
598
Jean-Paul Calderone37306a62010-08-28 15:09:24 -0400599 return PyLong_FromLongLong(X509_subject_name_hash(self->x509));
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500600}
601
602static char crypto_X509_digest_doc[] = "\n\
603Return the digest of the X509 object.\n\
604\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400605@return: The digest of the object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500606";
607
608static PyObject *
609crypto_X509_digest(crypto_X509Obj *self, PyObject *args)
610{
611 unsigned char fp[EVP_MAX_MD_SIZE];
612 char *tmp;
613 char *digest_name;
Jean-Paul Calderone28ebb302008-12-29 16:25:30 -0500614 unsigned int len,i;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500615 PyObject *ret;
616 const EVP_MD *digest;
617
618 if (!PyArg_ParseTuple(args, "s:digest", &digest_name))
619 return NULL;
620
621 if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
622 {
623 PyErr_SetString(PyExc_ValueError, "No such digest method");
624 return NULL;
625 }
626
627 if (!X509_digest(self->x509,digest,fp,&len))
628 {
Rick Deand369c932009-07-08 11:48:33 -0500629 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500630 }
631 tmp = malloc(3*len+1);
632 memset(tmp, 0, 3*len+1);
633 for (i = 0; i < len; i++) {
634 sprintf(tmp+i*3,"%02X:",fp[i]);
635 }
636 tmp[3*len-1] = 0;
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400637 ret = PyBytes_FromStringAndSize(tmp,3*len-1);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500638 free(tmp);
639 return ret;
640}
641
642
643static char crypto_X509_add_extensions_doc[] = "\n\
644Add extensions to the certificate.\n\
645\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400646@param extensions: a sequence of X509Extension objects\n\
647@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500648";
649
650static PyObject *
651crypto_X509_add_extensions(crypto_X509Obj *self, PyObject *args)
652{
653 PyObject *extensions, *seq;
654 crypto_X509ExtensionObj *ext;
655 int nr_of_extensions, i;
656
657 if (!PyArg_ParseTuple(args, "O:add_extensions", &extensions))
658 return NULL;
659
660 seq = PySequence_Fast(extensions, "Expected a sequence");
661 if (seq == NULL)
662 return NULL;
663
664 nr_of_extensions = PySequence_Fast_GET_SIZE(seq);
665
666 for (i = 0; i < nr_of_extensions; i++)
667 {
668 ext = (crypto_X509ExtensionObj *)PySequence_Fast_GET_ITEM(seq, i);
669 if (!crypto_X509Extension_Check(ext))
670 {
671 Py_DECREF(seq);
672 PyErr_SetString(PyExc_ValueError,
673 "One of the elements is not an X509Extension");
674 return NULL;
675 }
676 if (!X509_add_ext(self->x509, ext->x509_extension, -1))
677 {
678 Py_DECREF(seq);
Rick Deand369c932009-07-08 11:48:33 -0500679 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500680 return NULL;
681 }
682 }
683
684 Py_INCREF(Py_None);
685 return Py_None;
686}
687
688/*
689 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
690 * { 'name', (PyCFunction)crypto_X509_name, METH_VARARGS }
691 * for convenience
692 */
693#define ADD_METHOD(name) \
694 { #name, (PyCFunction)crypto_X509_##name, METH_VARARGS, crypto_X509_##name##_doc }
695static PyMethodDef crypto_X509_methods[] =
696{
697 ADD_METHOD(get_version),
698 ADD_METHOD(set_version),
699 ADD_METHOD(get_serial_number),
700 ADD_METHOD(set_serial_number),
701 ADD_METHOD(get_issuer),
702 ADD_METHOD(set_issuer),
703 ADD_METHOD(get_subject),
704 ADD_METHOD(set_subject),
705 ADD_METHOD(get_pubkey),
706 ADD_METHOD(set_pubkey),
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400707 ADD_METHOD(get_notBefore),
708 ADD_METHOD(set_notBefore),
709 ADD_METHOD(get_notAfter),
710 ADD_METHOD(set_notAfter),
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500711 ADD_METHOD(gmtime_adj_notBefore),
712 ADD_METHOD(gmtime_adj_notAfter),
713 ADD_METHOD(sign),
714 ADD_METHOD(has_expired),
715 ADD_METHOD(subject_name_hash),
716 ADD_METHOD(digest),
717 ADD_METHOD(add_extensions),
718 { NULL, NULL }
719};
720#undef ADD_METHOD
721
722
723/*
724 * Constructor for X509 objects, never called by Python code directly
725 *
726 * Arguments: cert - A "real" X509 certificate object
727 * dealloc - Boolean value to specify whether the destructor should
728 * free the "real" X509 object
729 * Returns: The newly created X509 object
730 */
731crypto_X509Obj *
732crypto_X509_New(X509 *cert, int dealloc)
733{
734 crypto_X509Obj *self;
735
736 self = PyObject_New(crypto_X509Obj, &crypto_X509_Type);
737
738 if (self == NULL)
739 return NULL;
740
741 self->x509 = cert;
742 self->dealloc = dealloc;
743
744 return self;
745}
746
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400747
748static char crypto_X509_doc[] = "\n\
749X509() -> X509 instance\n\
750\n\
751Create a new X509 object.\n\
752\n\
753@returns: The X509 object\n\
754";
755
756static PyObject *
757crypto_X509_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
758{
759 if (!PyArg_ParseTuple(args, ":X509")) {
760 return NULL;
761 }
762
763 return (PyObject *)crypto_X509_New(X509_new(), 1);
764}
765
766
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500767/*
768 * Deallocate the memory used by the X509 object
769 *
770 * Arguments: self - The X509 object
771 * Returns: None
772 */
773static void
774crypto_X509_dealloc(crypto_X509Obj *self)
775{
776 /* Sometimes we don't have to dealloc the "real" X509 pointer ourselves */
777 if (self->dealloc)
778 X509_free(self->x509);
779
780 PyObject_Del(self);
781}
782
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500783PyTypeObject crypto_X509_Type = {
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400784 PyOpenSSL_HEAD_INIT(&PyType_Type, 0)
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500785 "X509",
786 sizeof(crypto_X509Obj),
787 0,
788 (destructor)crypto_X509_dealloc,
789 NULL, /* print */
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400790 NULL, /* getattr */
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400791 NULL, /* setattr */
792 NULL, /* compare */
793 NULL, /* repr */
794 NULL, /* as_number */
795 NULL, /* as_sequence */
796 NULL, /* as_mapping */
797 NULL, /* hash */
798 NULL, /* call */
799 NULL, /* str */
800 NULL, /* getattro */
801 NULL, /* setattro */
802 NULL, /* as_buffer */
803 Py_TPFLAGS_DEFAULT,
804 crypto_X509_doc, /* doc */
805 NULL, /* traverse */
806 NULL, /* clear */
807 NULL, /* tp_richcompare */
808 0, /* tp_weaklistoffset */
809 NULL, /* tp_iter */
810 NULL, /* tp_iternext */
811 crypto_X509_methods, /* tp_methods */
812 NULL, /* tp_members */
813 NULL, /* tp_getset */
814 NULL, /* tp_base */
815 NULL, /* tp_dict */
816 NULL, /* tp_descr_get */
817 NULL, /* tp_descr_set */
818 0, /* tp_dictoffset */
819 NULL, /* tp_init */
820 NULL, /* tp_alloc */
821 crypto_X509_new, /* tp_new */
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500822};
823
824/*
825 * Initialize the X509 part of the crypto sub module
826 *
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400827 * Arguments: module - The crypto module
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500828 * Returns: None
829 */
830int
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400831init_crypto_x509(PyObject *module)
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500832{
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400833 if (PyType_Ready(&crypto_X509_Type) < 0) {
834 return 0;
835 }
836
837 if (PyModule_AddObject(module, "X509", (PyObject *)&crypto_X509_Type) != 0) {
838 return 0;
839 }
840
841 if (PyModule_AddObject(module, "X509Type", (PyObject *)&crypto_X509_Type) != 0) {
842 return 0;
843 }
844
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500845 return 1;
846}
847