blob: 1552a627a9f4f62d72706a891062edcf44f19eee [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
701 return PyInt_FromLong((long)X509_get_ext_count(self->x509));
702}
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
735/* Copied from openssl/crypto/x509v3/v3_utl.c */
736
737static void str_free(void *str)
738{
739 OPENSSL_free(str);
740}
741static int sk_strcmp(const char * const *a, const char * const *b)
742{
743 return strcmp(*a, *b);
744}
745static int append_ia5(STACK **sk, ASN1_IA5STRING *value)
746{
747 char *tmp;
748 /* First some sanity checks */
749 if(value->type != V_ASN1_IA5STRING) return 1;
750 if(!value->data || !value->length) return 1;
751 if(!*sk) *sk = sk_new(sk_strcmp);
752 if(!*sk) return 0;
753 /* Don't add duplicates */
754 if(sk_find(*sk, (char *)value->data) != -1) return 1;
755 tmp = BUF_strdup((char *)value->data);
756 if(!tmp || !sk_push(*sk, tmp)) {
757 sk_pop_free(*sk, str_free);
758 *sk = NULL;
759 return 0;
760 }
761 return 1;
762}
763
764/* -------------------------------------------------*/
765/* !!! This only works for ASN1_IA5STRING values !!!*/
766/* -------------------------------------------------*/
767static STACK *get_ia5_san_value(GENERAL_NAMES *gens, int type)
768{
769 STACK *ret = NULL;
770 GENERAL_NAME *gen;
771 int i;
772
773 for(i = 0; i < sk_GENERAL_NAME_num(gens); i++)
774 {
775 gen = sk_GENERAL_NAME_value(gens, i);
776 if(gen->type != type) continue;
777 if(!append_ia5(&ret, gen->d.ia5)) return NULL;
778 }
779 return ret;
780}
781
782static char crypto_X509_get_subjectaltname_of_type_doc[] = "\n\
783Get a list of the values of some subjectaltname extensions\n\
784Presently the DNS,EMAIL and URI types are supported.\n\
785\n\
786Arguments: self - X509 object\n\
787 type - one of DNS,EMAIL or URI\n\
788Returns: A list of values\n\
789";
790
791static PyObject *
792crypto_X509_get_subjectaltname_of_type(crypto_X509Obj *self, PyObject *args)
793{
794 GENERAL_NAMES *gens;
795 STACK *ret;
796 char *s;
797 char *type;
798 PyObject *list;
799 int san_type;
800
801 if (!PyArg_ParseTuple(args, "s:get_subjectaltname_of_type", &type))
802 return NULL;
803
804 list = PyList_New(0);
805 gens = X509_get_ext_d2i(self->x509, NID_subject_alt_name, NULL, NULL);
806 if (gens == NULL) {
807 return list;
808 }
809
810 /* These are the ones that are labeled/stored as ASN1_IA5STRINGs */
811 if (strcmp(type,"DNS") == 0) san_type = GEN_DNS;
812 else if(strcmp(type,"EMAIL") == 0) san_type = GEN_EMAIL;
813 else if(strcmp(type,"URI") == 0) san_type = GEN_URI;
814 else {
815 PyErr_SetString(PyExc_AttributeError, type);
816 return NULL;
817 }
818
819 ret = get_ia5_san_value(gens, san_type);
820 if (ret != NULL) {
821 for ( ; s = sk_pop(ret) ; ){
822 PyList_Append(list, PyString_FromString(s));
823 }
824 return list;
825 }
826 else {
827 return list;
828 }
829}
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500830/*
831 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
832 * { 'name', (PyCFunction)crypto_X509_name, METH_VARARGS }
833 * for convenience
834 */
835#define ADD_METHOD(name) \
836 { #name, (PyCFunction)crypto_X509_##name, METH_VARARGS, crypto_X509_##name##_doc }
837static PyMethodDef crypto_X509_methods[] =
838{
839 ADD_METHOD(get_version),
840 ADD_METHOD(set_version),
841 ADD_METHOD(get_serial_number),
842 ADD_METHOD(set_serial_number),
843 ADD_METHOD(get_issuer),
844 ADD_METHOD(set_issuer),
845 ADD_METHOD(get_subject),
846 ADD_METHOD(set_subject),
847 ADD_METHOD(get_pubkey),
848 ADD_METHOD(set_pubkey),
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400849 ADD_METHOD(get_notBefore),
850 ADD_METHOD(set_notBefore),
851 ADD_METHOD(get_notAfter),
852 ADD_METHOD(set_notAfter),
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500853 ADD_METHOD(gmtime_adj_notBefore),
854 ADD_METHOD(gmtime_adj_notAfter),
855 ADD_METHOD(sign),
856 ADD_METHOD(has_expired),
857 ADD_METHOD(subject_name_hash),
858 ADD_METHOD(digest),
859 ADD_METHOD(add_extensions),
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200860 ADD_METHOD(get_extension),
861 ADD_METHOD(get_extension_count),
862 ADD_METHOD(get_subjectaltname_of_type),
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500863 { NULL, NULL }
864};
865#undef ADD_METHOD
866
867
868/*
869 * Constructor for X509 objects, never called by Python code directly
870 *
871 * Arguments: cert - A "real" X509 certificate object
872 * dealloc - Boolean value to specify whether the destructor should
873 * free the "real" X509 object
874 * Returns: The newly created X509 object
875 */
876crypto_X509Obj *
877crypto_X509_New(X509 *cert, int dealloc)
878{
879 crypto_X509Obj *self;
880
881 self = PyObject_New(crypto_X509Obj, &crypto_X509_Type);
882
883 if (self == NULL)
884 return NULL;
885
886 self->x509 = cert;
887 self->dealloc = dealloc;
888
889 return self;
890}
891
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400892
893static char crypto_X509_doc[] = "\n\
894X509() -> X509 instance\n\
895\n\
896Create a new X509 object.\n\
897\n\
898@returns: The X509 object\n\
899";
900
901static PyObject *
902crypto_X509_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
903{
904 if (!PyArg_ParseTuple(args, ":X509")) {
905 return NULL;
906 }
907
908 return (PyObject *)crypto_X509_New(X509_new(), 1);
909}
910
911
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500912/*
913 * Deallocate the memory used by the X509 object
914 *
915 * Arguments: self - The X509 object
916 * Returns: None
917 */
918static void
919crypto_X509_dealloc(crypto_X509Obj *self)
920{
921 /* Sometimes we don't have to dealloc the "real" X509 pointer ourselves */
922 if (self->dealloc)
923 X509_free(self->x509);
924
925 PyObject_Del(self);
926}
927
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500928PyTypeObject crypto_X509_Type = {
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400929 PyOpenSSL_HEAD_INIT(&PyType_Type, 0)
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500930 "X509",
931 sizeof(crypto_X509Obj),
932 0,
933 (destructor)crypto_X509_dealloc,
934 NULL, /* print */
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400935 NULL, /* getattr */
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400936 NULL, /* setattr */
937 NULL, /* compare */
938 NULL, /* repr */
939 NULL, /* as_number */
940 NULL, /* as_sequence */
941 NULL, /* as_mapping */
942 NULL, /* hash */
943 NULL, /* call */
944 NULL, /* str */
945 NULL, /* getattro */
946 NULL, /* setattro */
947 NULL, /* as_buffer */
948 Py_TPFLAGS_DEFAULT,
949 crypto_X509_doc, /* doc */
950 NULL, /* traverse */
951 NULL, /* clear */
952 NULL, /* tp_richcompare */
953 0, /* tp_weaklistoffset */
954 NULL, /* tp_iter */
955 NULL, /* tp_iternext */
956 crypto_X509_methods, /* tp_methods */
957 NULL, /* tp_members */
958 NULL, /* tp_getset */
959 NULL, /* tp_base */
960 NULL, /* tp_dict */
961 NULL, /* tp_descr_get */
962 NULL, /* tp_descr_set */
963 0, /* tp_dictoffset */
964 NULL, /* tp_init */
965 NULL, /* tp_alloc */
966 crypto_X509_new, /* tp_new */
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500967};
968
969/*
970 * Initialize the X509 part of the crypto sub module
971 *
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400972 * Arguments: module - The crypto module
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500973 * Returns: None
974 */
975int
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400976init_crypto_x509(PyObject *module)
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500977{
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400978 if (PyType_Ready(&crypto_X509_Type) < 0) {
979 return 0;
980 }
981
982 if (PyModule_AddObject(module, "X509", (PyObject *)&crypto_X509_Type) != 0) {
983 return 0;
984 }
985
986 if (PyModule_AddObject(module, "X509Type", (PyObject *)&crypto_X509_Type) != 0) {
987 return 0;
988 }
989
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500990 return 1;
991}
992