blob: 5d03d2e92ce67a413e0187b6c8e1984aeedc6186 [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"
Roland Hedberg7e4930e2008-04-22 22:58:50 +020016#include "x509ext.h"
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050017
Jean-Paul Calderone525ef802008-03-09 20:39:42 -040018/*
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050019 * X.509 is a standard for digital certificates. See e.g. the OpenSSL homepage
20 * http://www.openssl.org/ for more information
21 */
22
23static char crypto_X509_get_version_doc[] = "\n\
24Return version number of the certificate\n\
25\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040026@return: Version number as a Python integer\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050027";
28
29static PyObject *
30crypto_X509_get_version(crypto_X509Obj *self, PyObject *args)
31{
32 if (!PyArg_ParseTuple(args, ":get_version"))
33 return NULL;
34
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -040035 return PyLong_FromLong((long)X509_get_version(self->x509));
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050036}
37
38static char crypto_X509_set_version_doc[] = "\n\
39Set version number of the certificate\n\
40\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040041@param version: The version number\n\
42@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050043";
44
45static PyObject *
46crypto_X509_set_version(crypto_X509Obj *self, PyObject *args)
47{
48 int version;
49
50 if (!PyArg_ParseTuple(args, "i:set_version", &version))
51 return NULL;
52
53 X509_set_version(self->x509, version);
54
55 Py_INCREF(Py_None);
56 return Py_None;
57}
58
59static char crypto_X509_get_serial_number_doc[] = "\n\
60Return serial number of the certificate\n\
61\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040062@return: Serial number as a Python integer\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050063";
64
65static PyObject *
66crypto_X509_get_serial_number(crypto_X509Obj *self, PyObject *args)
67{
68 ASN1_INTEGER *asn1_i;
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050069 BIGNUM *bignum;
70 char *hex;
71 PyObject *res;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050072
73 if (!PyArg_ParseTuple(args, ":get_serial_number"))
74 return NULL;
75
76 asn1_i = X509_get_serialNumber(self->x509);
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050077 bignum = ASN1_INTEGER_to_BN(asn1_i, NULL);
78 hex = BN_bn2hex(bignum);
79 res = PyLong_FromString(hex, NULL, 16);
80 BN_free(bignum);
81 free(hex);
82 return res;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050083}
84
85static char crypto_X509_set_serial_number_doc[] = "\n\
86Set serial number of the certificate\n\
87\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040088@param serial: The serial number\n\
89@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050090";
91
92static PyObject *
93crypto_X509_set_serial_number(crypto_X509Obj *self, PyObject *args)
94{
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050095 long small_serial;
96 PyObject *serial = NULL;
97 PyObject *hex = NULL;
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050098 ASN1_INTEGER *asn1_i = NULL;
99 BIGNUM *bignum = NULL;
Jean-Paul Calderonedd467fb2010-08-12 20:44:32 -0400100 char *hexstr;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500101
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500102 if (!PyArg_ParseTuple(args, "O:set_serial_number", &serial)) {
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500103 return NULL;
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500104 }
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500105
Jean-Paul Calderonec18669e2010-08-12 00:03:05 -0400106 if (!PyOpenSSL_Integer_Check(serial)) {
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500107 PyErr_SetString(
108 PyExc_TypeError, "serial number must be integer");
109 goto err;
110 }
111
Jean-Paul Calderonea5a032f2010-08-12 20:03:32 -0400112 if ((hex = PyOpenSSL_LongToHex(serial)) == NULL) {
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500113 goto err;
114 }
115
Jean-Paul Calderonedd467fb2010-08-12 20:44:32 -0400116#ifdef PY3
117 {
118 PyObject *hexbytes = PyUnicode_AsASCIIString(hex);
119 Py_DECREF(hex);
120 hex = hexbytes;
121 }
122#endif
123
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500124 /**
125 * BN_hex2bn stores the result in &bignum. Unless it doesn't feel like
126 * it. If bignum is still NULL after this call, then the return value
127 * is actually the result. I hope. -exarkun
128 */
Jean-Paul Calderonedd467fb2010-08-12 20:44:32 -0400129 hexstr = PyBytes_AsString(hex);
Jean-Paul Calderone8eb46c72010-08-22 17:05:37 -0400130 if (hexstr[1] == 'x') {
Jean-Paul Calderone728eba92010-08-12 20:17:59 -0400131 /* +2 to skip the "0x" */
Jean-Paul Calderonedd467fb2010-08-12 20:44:32 -0400132 hexstr += 2;
Jean-Paul Calderone728eba92010-08-12 20:17:59 -0400133 }
Jean-Paul Calderonedd467fb2010-08-12 20:44:32 -0400134 small_serial = BN_hex2bn(&bignum, hexstr);
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500135
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500136 Py_DECREF(hex);
137 hex = NULL;
138
139 if (bignum == NULL) {
140 if (ASN1_INTEGER_set(X509_get_serialNumber(self->x509), small_serial)) {
Rick Deand369c932009-07-08 11:48:33 -0500141 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500142 goto err;
143 }
144 } else {
145 asn1_i = BN_to_ASN1_INTEGER(bignum, NULL);
146 BN_free(bignum);
147 bignum = NULL;
148 if (asn1_i == NULL) {
Rick Deand369c932009-07-08 11:48:33 -0500149 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500150 goto err;
151 }
152 if (!X509_set_serialNumber(self->x509, asn1_i)) {
Rick Deand369c932009-07-08 11:48:33 -0500153 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500154 goto err;
155 }
156 ASN1_INTEGER_free(asn1_i);
157 asn1_i = NULL;
158 }
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500159
160 Py_INCREF(Py_None);
161 return Py_None;
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500162
163 err:
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500164 if (hex) {
165 Py_DECREF(hex);
166 }
167 if (bignum) {
168 BN_free(bignum);
169 }
170 if (asn1_i) {
171 ASN1_INTEGER_free(asn1_i);
172 }
173 return NULL;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500174}
175
176static char crypto_X509_get_issuer_doc[] = "\n\
177Create an X509Name object for the issuer of the certificate\n\
178\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400179@return: An X509Name object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500180";
181
182static PyObject *
183crypto_X509_get_issuer(crypto_X509Obj *self, PyObject *args)
184{
185 crypto_X509NameObj *pyname;
186 X509_NAME *name;
187
188 if (!PyArg_ParseTuple(args, ":get_issuer"))
189 return NULL;
190
191 name = X509_get_issuer_name(self->x509);
192 pyname = crypto_X509Name_New(name, 0);
193 if (pyname != NULL)
194 {
195 pyname->parent_cert = (PyObject *)self;
196 Py_INCREF(self);
197 }
198 return (PyObject *)pyname;
199}
200
201static char crypto_X509_set_issuer_doc[] = "\n\
202Set the issuer of the certificate\n\
203\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400204@param issuer: The issuer name\n\
205@type issuer: L{X509Name}\n\
206@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500207";
208
209static PyObject *
210crypto_X509_set_issuer(crypto_X509Obj *self, PyObject *args)
211{
212 crypto_X509NameObj *issuer;
213
214 if (!PyArg_ParseTuple(args, "O!:set_issuer", &crypto_X509Name_Type,
215 &issuer))
216 return NULL;
217
218 if (!X509_set_issuer_name(self->x509, issuer->x509_name))
219 {
Rick Deand369c932009-07-08 11:48:33 -0500220 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500221 return NULL;
222 }
223
224 Py_INCREF(Py_None);
225 return Py_None;
226}
227
228static char crypto_X509_get_subject_doc[] = "\n\
229Create an X509Name object for the subject of the certificate\n\
230\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400231@return: An X509Name object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500232";
233
234static PyObject *
235crypto_X509_get_subject(crypto_X509Obj *self, PyObject *args)
236{
237 crypto_X509NameObj *pyname;
238 X509_NAME *name;
239
240 if (!PyArg_ParseTuple(args, ":get_subject"))
241 return NULL;
242
243 name = X509_get_subject_name(self->x509);
244 pyname = crypto_X509Name_New(name, 0);
245 if (pyname != NULL)
246 {
247 pyname->parent_cert = (PyObject *)self;
248 Py_INCREF(self);
249 }
250 return (PyObject *)pyname;
251}
252
253static char crypto_X509_set_subject_doc[] = "\n\
254Set the subject of the certificate\n\
255\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400256@param subject: The subject name\n\
257@type subject: L{X509Name}\n\
258@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500259";
260
261static PyObject *
262crypto_X509_set_subject(crypto_X509Obj *self, PyObject *args)
263{
264 crypto_X509NameObj *subject;
265
266 if (!PyArg_ParseTuple(args, "O!:set_subject", &crypto_X509Name_Type,
267 &subject))
268 return NULL;
269
270 if (!X509_set_subject_name(self->x509, subject->x509_name))
271 {
Rick Deand369c932009-07-08 11:48:33 -0500272 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500273 return NULL;
274 }
275
276 Py_INCREF(Py_None);
277 return Py_None;
278}
279
280static char crypto_X509_get_pubkey_doc[] = "\n\
281Get the public key of the certificate\n\
282\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400283@return: The public key\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500284";
285
286static PyObject *
287crypto_X509_get_pubkey(crypto_X509Obj *self, PyObject *args)
288{
289 crypto_PKeyObj *crypto_PKey_New(EVP_PKEY *, int);
290 EVP_PKEY *pkey;
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400291 crypto_PKeyObj *py_pkey;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500292
293 if (!PyArg_ParseTuple(args, ":get_pubkey"))
294 return NULL;
295
296 if ((pkey = X509_get_pubkey(self->x509)) == NULL)
297 {
Rick Deand369c932009-07-08 11:48:33 -0500298 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500299 return NULL;
300 }
301
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400302 py_pkey = crypto_PKey_New(pkey, 1);
303 if (py_pkey != NULL) {
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400304 py_pkey->only_public = 1;
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400305 }
Jean-Paul Calderonef60beec2008-07-22 21:19:02 -0400306 return (PyObject *)py_pkey;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500307}
308
309static char crypto_X509_set_pubkey_doc[] = "\n\
310Set the public key of the certificate\n\
311\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400312@param pkey: The public key\n\
313@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500314";
315
316static PyObject *
317crypto_X509_set_pubkey(crypto_X509Obj *self, PyObject *args)
318{
319 crypto_PKeyObj *pkey;
320
321 if (!PyArg_ParseTuple(args, "O!:set_pubkey", &crypto_PKey_Type, &pkey))
322 return NULL;
323
324 if (!X509_set_pubkey(self->x509, pkey->pkey))
325 {
Rick Deand369c932009-07-08 11:48:33 -0500326 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500327 return NULL;
328 }
329
330 Py_INCREF(Py_None);
331 return Py_None;
332}
333
Rick Dean536ba022009-07-24 23:57:27 -0500334PyObject*
335_set_asn1_time(char *format, ASN1_TIME* timestamp, PyObject *args)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400336{
337 char *when;
338
339 if (!PyArg_ParseTuple(args, format, &when))
340 return NULL;
341
342 if (ASN1_GENERALIZEDTIME_set_string(timestamp, when) == 0) {
343 ASN1_GENERALIZEDTIME dummy;
344 dummy.type = V_ASN1_GENERALIZEDTIME;
345 dummy.length = strlen(when);
Jean-Paul Calderone28ebb302008-12-29 16:25:30 -0500346 dummy.data = (unsigned char *)when;
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400347 if (!ASN1_GENERALIZEDTIME_check(&dummy)) {
348 PyErr_SetString(PyExc_ValueError, "Invalid string");
349 } else {
350 PyErr_SetString(PyExc_RuntimeError, "Unknown ASN1_GENERALIZEDTIME_set_string failure");
351 }
352 return NULL;
353 }
354 Py_INCREF(Py_None);
355 return Py_None;
356}
357
358static char crypto_X509_set_notBefore_doc[] = "\n\
359Set the time stamp for when the certificate starts being valid\n\
360\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400361@param when: A string giving the timestamp, in the format:\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400362\n\
363 YYYYMMDDhhmmssZ\n\
364 YYYYMMDDhhmmss+hhmm\n\
365 YYYYMMDDhhmmss-hhmm\n\
366\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400367@return: None\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400368";
369
370static PyObject*
371crypto_X509_set_notBefore(crypto_X509Obj *self, PyObject *args)
372{
373 return _set_asn1_time(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400374 BYTESTRING_FMT ":set_notBefore",
375 X509_get_notBefore(self->x509), args);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400376}
377
378static char crypto_X509_set_notAfter_doc[] = "\n\
379Set the time stamp for when the certificate stops being valid\n\
380\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400381@param when: A string giving the timestamp, in the format:\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400382\n\
383 YYYYMMDDhhmmssZ\n\
384 YYYYMMDDhhmmss+hhmm\n\
385 YYYYMMDDhhmmss-hhmm\n\
386\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400387@return: None\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400388";
389
390static PyObject*
391crypto_X509_set_notAfter(crypto_X509Obj *self, PyObject *args)
392{
393 return _set_asn1_time(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400394 BYTESTRING_FMT ":set_notAfter",
395 X509_get_notAfter(self->x509), args);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400396}
397
Rick Dean536ba022009-07-24 23:57:27 -0500398PyObject*
399_get_asn1_time(char *format, ASN1_TIME* timestamp, PyObject *args)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400400{
401 ASN1_GENERALIZEDTIME *gt_timestamp = NULL;
402 PyObject *py_timestamp = NULL;
403
404 if (!PyArg_ParseTuple(args, format)) {
405 return NULL;
406 }
407
408 /*
409 * http://www.columbia.edu/~ariel/ssleay/asn1-time.html
410 */
411 /*
412 * There must be a way to do this without touching timestamp->data
413 * directly. -exarkun
414 */
Jean-Paul Calderonee0615b52008-03-09 21:44:46 -0400415 if (timestamp->length == 0) {
416 Py_INCREF(Py_None);
417 return Py_None;
418 } else if (timestamp->type == V_ASN1_GENERALIZEDTIME) {
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400419 return PyBytes_FromString((char *)timestamp->data);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400420 } else {
421 ASN1_TIME_to_generalizedtime(timestamp, &gt_timestamp);
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -0400422 if (gt_timestamp == NULL) {
Rick Deand369c932009-07-08 11:48:33 -0500423 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400424 return NULL;
425 } else {
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400426 py_timestamp = PyBytes_FromString((char *)gt_timestamp->data);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400427 ASN1_GENERALIZEDTIME_free(gt_timestamp);
428 return py_timestamp;
429 }
430 }
431}
432
433static char crypto_X509_get_notBefore_doc[] = "\n\
434Retrieve the time stamp for when the certificate starts being valid\n\
435\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400436@return: A string giving the timestamp, in the format:\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400437\n\
438 YYYYMMDDhhmmssZ\n\
439 YYYYMMDDhhmmss+hhmm\n\
440 YYYYMMDDhhmmss-hhmm\n\
441 or None if there is no value set.\n\
442";
443
444static PyObject*
445crypto_X509_get_notBefore(crypto_X509Obj *self, PyObject *args)
446{
447 /*
448 * X509_get_notBefore returns a borrowed reference.
449 */
450 return _get_asn1_time(
Rick Dean536ba022009-07-24 23:57:27 -0500451 ":get_notBefore", X509_get_notBefore(self->x509), args);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400452}
453
454
455static char crypto_X509_get_notAfter_doc[] = "\n\
456Retrieve the time stamp for when the certificate stops being valid\n\
457\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400458@return: A string giving the timestamp, in the format:\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400459\n\
460 YYYYMMDDhhmmssZ\n\
461 YYYYMMDDhhmmss+hhmm\n\
462 YYYYMMDDhhmmss-hhmm\n\
463 or None if there is no value set.\n\
464";
465
466static PyObject*
467crypto_X509_get_notAfter(crypto_X509Obj *self, PyObject *args)
468{
469 /*
470 * X509_get_notAfter returns a borrowed reference.
471 */
472 return _get_asn1_time(
Rick Dean536ba022009-07-24 23:57:27 -0500473 ":get_notAfter", X509_get_notAfter(self->x509), args);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400474}
475
476
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500477static char crypto_X509_gmtime_adj_notBefore_doc[] = "\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400478Change the timestamp for when the certificate starts being valid to the current\n\
479time plus an offset.\n \
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500480\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400481@param amount: The number of seconds by which to adjust the starting validity\n\
482 time.\n\
483@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500484";
485
486static PyObject *
487crypto_X509_gmtime_adj_notBefore(crypto_X509Obj *self, PyObject *args)
488{
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400489 long amount;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500490
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400491 if (!PyArg_ParseTuple(args, "l:gmtime_adj_notBefore", &amount))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500492 return NULL;
493
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400494 X509_gmtime_adj(X509_get_notBefore(self->x509), amount);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500495
496 Py_INCREF(Py_None);
497 return Py_None;
498}
499
500static char crypto_X509_gmtime_adj_notAfter_doc[] = "\n\
501Adjust the time stamp for when the certificate stops being valid\n\
502\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400503@param amount: The number of seconds by which to adjust the ending validity\n\
504 time.\n\
505@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500506";
507
508static PyObject *
509crypto_X509_gmtime_adj_notAfter(crypto_X509Obj *self, PyObject *args)
510{
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400511 long amount;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500512
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400513 if (!PyArg_ParseTuple(args, "l:gmtime_adj_notAfter", &amount))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500514 return NULL;
515
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400516 X509_gmtime_adj(X509_get_notAfter(self->x509), amount);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500517
518 Py_INCREF(Py_None);
519 return Py_None;
520}
521
522static char crypto_X509_sign_doc[] = "\n\
523Sign the certificate using the supplied key and digest\n\
524\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400525@param pkey: The key to sign with\n\
526@param digest: The message digest to use\n\
527@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500528";
529
530static PyObject *
531crypto_X509_sign(crypto_X509Obj *self, PyObject *args)
532{
533 crypto_PKeyObj *pkey;
534 char *digest_name;
535 const EVP_MD *digest;
536
537 if (!PyArg_ParseTuple(args, "O!s:sign", &crypto_PKey_Type, &pkey,
538 &digest_name))
539 return NULL;
540
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400541 if (pkey->only_public) {
542 PyErr_SetString(PyExc_ValueError, "Key has only public part");
543 return NULL;
544 }
545
546 if (!pkey->initialized) {
547 PyErr_SetString(PyExc_ValueError, "Key is uninitialized");
548 return NULL;
549 }
550
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500551 if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
552 {
553 PyErr_SetString(PyExc_ValueError, "No such digest method");
554 return NULL;
555 }
556
557 if (!X509_sign(self->x509, pkey->pkey, digest))
558 {
Rick Deand369c932009-07-08 11:48:33 -0500559 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500560 return NULL;
561 }
562
563 Py_INCREF(Py_None);
564 return Py_None;
565}
566
567static char crypto_X509_has_expired_doc[] = "\n\
568Check whether the certificate has expired.\n\
569\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400570@return: True if the certificate has expired, false otherwise\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500571";
572
573static PyObject *
574crypto_X509_has_expired(crypto_X509Obj *self, PyObject *args)
575{
576 time_t tnow;
577
578 if (!PyArg_ParseTuple(args, ":has_expired"))
579 return NULL;
580
581 tnow = time(NULL);
582 if (ASN1_UTCTIME_cmp_time_t(X509_get_notAfter(self->x509), tnow) < 0)
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400583 return PyLong_FromLong(1L);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500584 else
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400585 return PyLong_FromLong(0L);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500586}
587
588static char crypto_X509_subject_name_hash_doc[] = "\n\
589Return the hash of the X509 subject.\n\
590\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400591@return: The hash of the subject\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500592";
593
594static PyObject *
595crypto_X509_subject_name_hash(crypto_X509Obj *self, PyObject *args)
596{
597 if (!PyArg_ParseTuple(args, ":subject_name_hash"))
598 return NULL;
599
Jean-Paul Calderone37306a62010-08-28 15:09:24 -0400600 return PyLong_FromLongLong(X509_subject_name_hash(self->x509));
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500601}
602
603static char crypto_X509_digest_doc[] = "\n\
604Return the digest of the X509 object.\n\
605\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400606@return: The digest of the object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500607";
608
609static PyObject *
610crypto_X509_digest(crypto_X509Obj *self, PyObject *args)
611{
612 unsigned char fp[EVP_MAX_MD_SIZE];
613 char *tmp;
614 char *digest_name;
Jean-Paul Calderone28ebb302008-12-29 16:25:30 -0500615 unsigned int len,i;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500616 PyObject *ret;
617 const EVP_MD *digest;
618
619 if (!PyArg_ParseTuple(args, "s:digest", &digest_name))
620 return NULL;
621
622 if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
623 {
624 PyErr_SetString(PyExc_ValueError, "No such digest method");
625 return NULL;
626 }
627
628 if (!X509_digest(self->x509,digest,fp,&len))
629 {
Rick Deand369c932009-07-08 11:48:33 -0500630 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500631 }
632 tmp = malloc(3*len+1);
633 memset(tmp, 0, 3*len+1);
634 for (i = 0; i < len; i++) {
635 sprintf(tmp+i*3,"%02X:",fp[i]);
636 }
637 tmp[3*len-1] = 0;
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400638 ret = PyBytes_FromStringAndSize(tmp,3*len-1);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500639 free(tmp);
640 return ret;
641}
642
643
644static char crypto_X509_add_extensions_doc[] = "\n\
645Add extensions to the certificate.\n\
646\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400647@param extensions: a sequence of X509Extension objects\n\
648@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500649";
650
651static PyObject *
652crypto_X509_add_extensions(crypto_X509Obj *self, PyObject *args)
653{
654 PyObject *extensions, *seq;
655 crypto_X509ExtensionObj *ext;
656 int nr_of_extensions, i;
657
658 if (!PyArg_ParseTuple(args, "O:add_extensions", &extensions))
659 return NULL;
660
661 seq = PySequence_Fast(extensions, "Expected a sequence");
662 if (seq == NULL)
663 return NULL;
664
665 nr_of_extensions = PySequence_Fast_GET_SIZE(seq);
666
667 for (i = 0; i < nr_of_extensions; i++)
668 {
669 ext = (crypto_X509ExtensionObj *)PySequence_Fast_GET_ITEM(seq, i);
670 if (!crypto_X509Extension_Check(ext))
671 {
672 Py_DECREF(seq);
673 PyErr_SetString(PyExc_ValueError,
674 "One of the elements is not an X509Extension");
675 return NULL;
676 }
677 if (!X509_add_ext(self->x509, ext->x509_extension, -1))
678 {
679 Py_DECREF(seq);
Rick Deand369c932009-07-08 11:48:33 -0500680 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500681 return NULL;
682 }
683 }
684
685 Py_INCREF(Py_None);
686 return Py_None;
687}
688
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200689static char crypto_X509_get_extension_count_doc[] = "\n\
690Get the number of extensions on the certificate.\n\
691\n\
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400692@return: Number of extensions as a Python integer\n\
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200693";
694
695static PyObject *
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400696crypto_X509_get_extension_count(crypto_X509Obj *self, PyObject *args) {
697 if (!PyArg_ParseTuple(args, ":get_extension_count")) {
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200698 return NULL;
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400699 }
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200700
Jean-Paul Calderone48659612011-04-06 17:22:15 -0400701 return PyLong_FromLong((long)X509_get_ext_count(self->x509));
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200702}
703
704static char crypto_X509_get_extension_doc[] = "\n\
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400705Get a specific extension of the certificate by index.\n\
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200706\n\
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -0400707@param index: The index of the extension to retrieve.\n\
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400708@return: The X509Extension object at the specified index.\n\
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200709";
710
711static PyObject *
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400712crypto_X509_get_extension(crypto_X509Obj *self, PyObject *args) {
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200713 crypto_X509ExtensionObj *extobj;
714 int loc;
715 X509_EXTENSION *ext;
716
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400717 if (!PyArg_ParseTuple(args, "i:get_extension", &loc)) {
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200718 return NULL;
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400719 }
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200720
721 /* will return NULL if loc is outside the range of extensions,
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400722 not registered as an error*/
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200723 ext = X509_get_ext(self->x509, loc);
724 if (!ext) {
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -0400725 PyErr_SetString(PyExc_IndexError, "extension index out of bounds");
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200726 return NULL; /* Should be reported as an IndexError ? */
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200727 }
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400728
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200729 extobj = PyObject_New(crypto_X509ExtensionObj, &crypto_X509Extension_Type);
730 extobj->x509_extension = X509_EXTENSION_dup(ext);
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400731
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -0400732 return (PyObject*)extobj;
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200733}
734
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500735/*
736 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
737 * { 'name', (PyCFunction)crypto_X509_name, METH_VARARGS }
738 * for convenience
739 */
740#define ADD_METHOD(name) \
741 { #name, (PyCFunction)crypto_X509_##name, METH_VARARGS, crypto_X509_##name##_doc }
742static PyMethodDef crypto_X509_methods[] =
743{
744 ADD_METHOD(get_version),
745 ADD_METHOD(set_version),
746 ADD_METHOD(get_serial_number),
747 ADD_METHOD(set_serial_number),
748 ADD_METHOD(get_issuer),
749 ADD_METHOD(set_issuer),
750 ADD_METHOD(get_subject),
751 ADD_METHOD(set_subject),
752 ADD_METHOD(get_pubkey),
753 ADD_METHOD(set_pubkey),
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400754 ADD_METHOD(get_notBefore),
755 ADD_METHOD(set_notBefore),
756 ADD_METHOD(get_notAfter),
757 ADD_METHOD(set_notAfter),
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500758 ADD_METHOD(gmtime_adj_notBefore),
759 ADD_METHOD(gmtime_adj_notAfter),
760 ADD_METHOD(sign),
761 ADD_METHOD(has_expired),
762 ADD_METHOD(subject_name_hash),
763 ADD_METHOD(digest),
764 ADD_METHOD(add_extensions),
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200765 ADD_METHOD(get_extension),
766 ADD_METHOD(get_extension_count),
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500767 { NULL, NULL }
768};
769#undef ADD_METHOD
770
771
772/*
773 * Constructor for X509 objects, never called by Python code directly
774 *
775 * Arguments: cert - A "real" X509 certificate object
776 * dealloc - Boolean value to specify whether the destructor should
777 * free the "real" X509 object
778 * Returns: The newly created X509 object
779 */
780crypto_X509Obj *
781crypto_X509_New(X509 *cert, int dealloc)
782{
783 crypto_X509Obj *self;
784
785 self = PyObject_New(crypto_X509Obj, &crypto_X509_Type);
786
787 if (self == NULL)
788 return NULL;
789
790 self->x509 = cert;
791 self->dealloc = dealloc;
792
793 return self;
794}
795
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400796
797static char crypto_X509_doc[] = "\n\
798X509() -> X509 instance\n\
799\n\
800Create a new X509 object.\n\
801\n\
802@returns: The X509 object\n\
803";
804
805static PyObject *
806crypto_X509_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
807{
808 if (!PyArg_ParseTuple(args, ":X509")) {
809 return NULL;
810 }
811
812 return (PyObject *)crypto_X509_New(X509_new(), 1);
813}
814
815
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500816/*
817 * Deallocate the memory used by the X509 object
818 *
819 * Arguments: self - The X509 object
820 * Returns: None
821 */
822static void
823crypto_X509_dealloc(crypto_X509Obj *self)
824{
825 /* Sometimes we don't have to dealloc the "real" X509 pointer ourselves */
826 if (self->dealloc)
827 X509_free(self->x509);
828
829 PyObject_Del(self);
830}
831
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500832PyTypeObject crypto_X509_Type = {
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400833 PyOpenSSL_HEAD_INIT(&PyType_Type, 0)
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500834 "X509",
835 sizeof(crypto_X509Obj),
836 0,
837 (destructor)crypto_X509_dealloc,
838 NULL, /* print */
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400839 NULL, /* getattr */
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400840 NULL, /* setattr */
841 NULL, /* compare */
842 NULL, /* repr */
843 NULL, /* as_number */
844 NULL, /* as_sequence */
845 NULL, /* as_mapping */
846 NULL, /* hash */
847 NULL, /* call */
848 NULL, /* str */
849 NULL, /* getattro */
850 NULL, /* setattro */
851 NULL, /* as_buffer */
852 Py_TPFLAGS_DEFAULT,
853 crypto_X509_doc, /* doc */
854 NULL, /* traverse */
855 NULL, /* clear */
856 NULL, /* tp_richcompare */
857 0, /* tp_weaklistoffset */
858 NULL, /* tp_iter */
859 NULL, /* tp_iternext */
860 crypto_X509_methods, /* tp_methods */
861 NULL, /* tp_members */
862 NULL, /* tp_getset */
863 NULL, /* tp_base */
864 NULL, /* tp_dict */
865 NULL, /* tp_descr_get */
866 NULL, /* tp_descr_set */
867 0, /* tp_dictoffset */
868 NULL, /* tp_init */
869 NULL, /* tp_alloc */
870 crypto_X509_new, /* tp_new */
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500871};
872
873/*
874 * Initialize the X509 part of the crypto sub module
875 *
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400876 * Arguments: module - The crypto module
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500877 * Returns: None
878 */
879int
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400880init_crypto_x509(PyObject *module)
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500881{
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400882 if (PyType_Ready(&crypto_X509_Type) < 0) {
883 return 0;
884 }
885
886 if (PyModule_AddObject(module, "X509", (PyObject *)&crypto_X509_Type) != 0) {
887 return 0;
888 }
889
890 if (PyModule_AddObject(module, "X509Type", (PyObject *)&crypto_X509_Type) != 0) {
891 return 0;
892 }
893
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500894 return 1;
895}
896