blob: 273f557c30227e865851a4f837fe09af77a78787 [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) {
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200304 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\
692Arguments: self - X509 object\n\
693Returns: Number of extensions as a Python integer\n\
694";
695
696static PyObject *
697crypto_X509_get_extension_count(crypto_X509Obj *self, PyObject *args)
698{
699 if (!PyArg_ParseTuple(args, ":get_extension_count"))
700 return NULL;
701
702 return PyInt_FromLong((long)X509_get_ext_count(self->x509));
703}
704
705static char crypto_X509_get_extension_doc[] = "\n\
706Get a specific extension of the certificate.\n\
707\n\
708Arguments: self - X509 object\n\
709Returns: An X509 extension object\n\
710";
711
712static PyObject *
713crypto_X509_get_extension(crypto_X509Obj *self, PyObject *args)
714{
715 crypto_X509ExtensionObj *extobj;
716 int loc;
717 X509_EXTENSION *ext;
718
719 if (!PyArg_ParseTuple(args, "i:get_extension", &loc))
720 return NULL;
721
722 /* will return NULL if loc is outside the range of extensions,
723 not registered as an error*/
724 ext = X509_get_ext(self->x509, loc);
725 if (!ext) {
726 return NULL; /* Should be reported as an IndexError ? */
727 /*exception_from_error_queue();*/
728 }
729
730 extobj = PyObject_New(crypto_X509ExtensionObj, &crypto_X509Extension_Type);
731 extobj->x509_extension = X509_EXTENSION_dup(ext);
732
733 return extobj;
734}
735
736/* Copied from openssl/crypto/x509v3/v3_utl.c */
737
738static void str_free(void *str)
739{
740 OPENSSL_free(str);
741}
742static int sk_strcmp(const char * const *a, const char * const *b)
743{
744 return strcmp(*a, *b);
745}
746static int append_ia5(STACK **sk, ASN1_IA5STRING *value)
747{
748 char *tmp;
749 /* First some sanity checks */
750 if(value->type != V_ASN1_IA5STRING) return 1;
751 if(!value->data || !value->length) return 1;
752 if(!*sk) *sk = sk_new(sk_strcmp);
753 if(!*sk) return 0;
754 /* Don't add duplicates */
755 if(sk_find(*sk, (char *)value->data) != -1) return 1;
756 tmp = BUF_strdup((char *)value->data);
757 if(!tmp || !sk_push(*sk, tmp)) {
758 sk_pop_free(*sk, str_free);
759 *sk = NULL;
760 return 0;
761 }
762 return 1;
763}
764
765/* -------------------------------------------------*/
766/* !!! This only works for ASN1_IA5STRING values !!!*/
767/* -------------------------------------------------*/
768static STACK *get_ia5_san_value(GENERAL_NAMES *gens, int type)
769{
770 STACK *ret = NULL;
771 GENERAL_NAME *gen;
772 int i;
773
774 for(i = 0; i < sk_GENERAL_NAME_num(gens); i++)
775 {
776 gen = sk_GENERAL_NAME_value(gens, i);
777 if(gen->type != type) continue;
778 if(!append_ia5(&ret, gen->d.ia5)) return NULL;
779 }
780 return ret;
781}
782
783static char crypto_X509_get_subjectaltname_of_type_doc[] = "\n\
784Get a list of the values of some subjectaltname extensions\n\
785Presently the DNS,EMAIL and URI types are supported.\n\
786\n\
787Arguments: self - X509 object\n\
788 type - one of DNS,EMAIL or URI\n\
789Returns: A list of values\n\
790";
791
792static PyObject *
793crypto_X509_get_subjectaltname_of_type(crypto_X509Obj *self, PyObject *args)
794{
795 GENERAL_NAMES *gens;
796 STACK *ret;
797 char *s;
798 char *type;
799 PyObject *list;
800 int san_type;
801
802 if (!PyArg_ParseTuple(args, "s:get_subjectaltname_of_type", &type))
803 return NULL;
804
805 list = PyList_New(0);
806 gens = X509_get_ext_d2i(self->x509, NID_subject_alt_name, NULL, NULL);
807 if (gens == NULL) {
808 return list;
809 }
810
811 /* These are the ones that are labeled/stored as ASN1_IA5STRINGs */
812 if (strcmp(type,"DNS") == 0) san_type = GEN_DNS;
813 else if(strcmp(type,"EMAIL") == 0) san_type = GEN_EMAIL;
814 else if(strcmp(type,"URI") == 0) san_type = GEN_URI;
815 else {
816 PyErr_SetString(PyExc_AttributeError, type);
817 return NULL;
818 }
819
820 ret = get_ia5_san_value(gens, san_type);
821 if (ret != NULL) {
822 for ( ; s = sk_pop(ret) ; ){
823 PyList_Append(list, PyString_FromString(s));
824 }
825 return list;
826 }
827 else {
828 return list;
829 }
830}
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500831/*
832 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
833 * { 'name', (PyCFunction)crypto_X509_name, METH_VARARGS }
834 * for convenience
835 */
836#define ADD_METHOD(name) \
837 { #name, (PyCFunction)crypto_X509_##name, METH_VARARGS, crypto_X509_##name##_doc }
838static PyMethodDef crypto_X509_methods[] =
839{
840 ADD_METHOD(get_version),
841 ADD_METHOD(set_version),
842 ADD_METHOD(get_serial_number),
843 ADD_METHOD(set_serial_number),
844 ADD_METHOD(get_issuer),
845 ADD_METHOD(set_issuer),
846 ADD_METHOD(get_subject),
847 ADD_METHOD(set_subject),
848 ADD_METHOD(get_pubkey),
849 ADD_METHOD(set_pubkey),
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400850 ADD_METHOD(get_notBefore),
851 ADD_METHOD(set_notBefore),
852 ADD_METHOD(get_notAfter),
853 ADD_METHOD(set_notAfter),
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500854 ADD_METHOD(gmtime_adj_notBefore),
855 ADD_METHOD(gmtime_adj_notAfter),
856 ADD_METHOD(sign),
857 ADD_METHOD(has_expired),
858 ADD_METHOD(subject_name_hash),
859 ADD_METHOD(digest),
860 ADD_METHOD(add_extensions),
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200861 ADD_METHOD(get_extension),
862 ADD_METHOD(get_extension_count),
863 ADD_METHOD(get_subjectaltname_of_type),
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500864 { NULL, NULL }
865};
866#undef ADD_METHOD
867
868
869/*
870 * Constructor for X509 objects, never called by Python code directly
871 *
872 * Arguments: cert - A "real" X509 certificate object
873 * dealloc - Boolean value to specify whether the destructor should
874 * free the "real" X509 object
875 * Returns: The newly created X509 object
876 */
877crypto_X509Obj *
878crypto_X509_New(X509 *cert, int dealloc)
879{
880 crypto_X509Obj *self;
881
882 self = PyObject_New(crypto_X509Obj, &crypto_X509_Type);
883
884 if (self == NULL)
885 return NULL;
886
887 self->x509 = cert;
888 self->dealloc = dealloc;
889
890 return self;
891}
892
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400893
894static char crypto_X509_doc[] = "\n\
895X509() -> X509 instance\n\
896\n\
897Create a new X509 object.\n\
898\n\
899@returns: The X509 object\n\
900";
901
902static PyObject *
903crypto_X509_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
904{
905 if (!PyArg_ParseTuple(args, ":X509")) {
906 return NULL;
907 }
908
909 return (PyObject *)crypto_X509_New(X509_new(), 1);
910}
911
912
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500913/*
914 * Deallocate the memory used by the X509 object
915 *
916 * Arguments: self - The X509 object
917 * Returns: None
918 */
919static void
920crypto_X509_dealloc(crypto_X509Obj *self)
921{
922 /* Sometimes we don't have to dealloc the "real" X509 pointer ourselves */
923 if (self->dealloc)
924 X509_free(self->x509);
925
926 PyObject_Del(self);
927}
928
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500929PyTypeObject crypto_X509_Type = {
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400930 PyOpenSSL_HEAD_INIT(&PyType_Type, 0)
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500931 "X509",
932 sizeof(crypto_X509Obj),
933 0,
934 (destructor)crypto_X509_dealloc,
935 NULL, /* print */
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400936 NULL, /* getattr */
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400937 NULL, /* setattr */
938 NULL, /* compare */
939 NULL, /* repr */
940 NULL, /* as_number */
941 NULL, /* as_sequence */
942 NULL, /* as_mapping */
943 NULL, /* hash */
944 NULL, /* call */
945 NULL, /* str */
946 NULL, /* getattro */
947 NULL, /* setattro */
948 NULL, /* as_buffer */
949 Py_TPFLAGS_DEFAULT,
950 crypto_X509_doc, /* doc */
951 NULL, /* traverse */
952 NULL, /* clear */
953 NULL, /* tp_richcompare */
954 0, /* tp_weaklistoffset */
955 NULL, /* tp_iter */
956 NULL, /* tp_iternext */
957 crypto_X509_methods, /* tp_methods */
958 NULL, /* tp_members */
959 NULL, /* tp_getset */
960 NULL, /* tp_base */
961 NULL, /* tp_dict */
962 NULL, /* tp_descr_get */
963 NULL, /* tp_descr_set */
964 0, /* tp_dictoffset */
965 NULL, /* tp_init */
966 NULL, /* tp_alloc */
967 crypto_X509_new, /* tp_new */
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500968};
969
970/*
971 * Initialize the X509 part of the crypto sub module
972 *
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400973 * Arguments: module - The crypto module
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500974 * Returns: None
975 */
976int
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400977init_crypto_x509(PyObject *module)
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500978{
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400979 if (PyType_Ready(&crypto_X509_Type) < 0) {
980 return 0;
981 }
982
983 if (PyModule_AddObject(module, "X509", (PyObject *)&crypto_X509_Type) != 0) {
984 return 0;
985 }
986
987 if (PyModule_AddObject(module, "X509Type", (PyObject *)&crypto_X509_Type) != 0) {
988 return 0;
989 }
990
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500991 return 1;
992}
993