blob: 5c5fafb5763c4d6be0451b718c377e60e37d64e3 [file] [log] [blame]
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05001/*
2 * x509.c
3 *
4 * Copyright (C) AB Strakt 2001, All rights reserved
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04005 * Copyright (C) Jean-Paul Calderone 2008, All rights reserved
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05006 *
7 * Certificate (X.509) handling code, mostly thin wrappers around OpenSSL.
8 * See the file RATIONALE for a short explanation of why this module was written.
9 *
10 * Reviewed 2001-07-23
11 */
12#include <Python.h>
13#define crypto_MODULE
14#include "crypto.h"
15
Jean-Paul Calderone525ef802008-03-09 20:39:42 -040016/*
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050017 * X.509 is a standard for digital certificates. See e.g. the OpenSSL homepage
18 * http://www.openssl.org/ for more information
19 */
20
21static char crypto_X509_get_version_doc[] = "\n\
22Return version number of the certificate\n\
23\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040024@return: Version number as a Python integer\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050025";
26
27static PyObject *
28crypto_X509_get_version(crypto_X509Obj *self, PyObject *args)
29{
30 if (!PyArg_ParseTuple(args, ":get_version"))
31 return NULL;
32
33 return PyInt_FromLong((long)X509_get_version(self->x509));
34}
35
36static char crypto_X509_set_version_doc[] = "\n\
37Set version number of the certificate\n\
38\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040039@param version: The version number\n\
40@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050041";
42
43static PyObject *
44crypto_X509_set_version(crypto_X509Obj *self, PyObject *args)
45{
46 int version;
47
48 if (!PyArg_ParseTuple(args, "i:set_version", &version))
49 return NULL;
50
51 X509_set_version(self->x509, version);
52
53 Py_INCREF(Py_None);
54 return Py_None;
55}
56
57static char crypto_X509_get_serial_number_doc[] = "\n\
58Return serial number of the certificate\n\
59\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040060@return: Serial number as a Python integer\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050061";
62
63static PyObject *
64crypto_X509_get_serial_number(crypto_X509Obj *self, PyObject *args)
65{
66 ASN1_INTEGER *asn1_i;
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050067 BIGNUM *bignum;
68 char *hex;
69 PyObject *res;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050070
71 if (!PyArg_ParseTuple(args, ":get_serial_number"))
72 return NULL;
73
74 asn1_i = X509_get_serialNumber(self->x509);
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050075 bignum = ASN1_INTEGER_to_BN(asn1_i, NULL);
76 hex = BN_bn2hex(bignum);
77 res = PyLong_FromString(hex, NULL, 16);
78 BN_free(bignum);
79 free(hex);
80 return res;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050081}
82
83static char crypto_X509_set_serial_number_doc[] = "\n\
84Set serial number of the certificate\n\
85\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040086@param serial: The serial number\n\
87@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050088";
89
90static PyObject *
91crypto_X509_set_serial_number(crypto_X509Obj *self, PyObject *args)
92{
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050093 long small_serial;
94 PyObject *serial = NULL;
95 PyObject *hex = NULL;
96 PyObject *format = NULL;
97 PyObject *format_args = NULL;
98 ASN1_INTEGER *asn1_i = NULL;
99 BIGNUM *bignum = NULL;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500100
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500101 if (!PyArg_ParseTuple(args, "O:set_serial_number", &serial)) {
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500102 return NULL;
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500103 }
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500104
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500105 if (!PyInt_Check(serial) && !PyLong_Check(serial)) {
106 PyErr_SetString(
107 PyExc_TypeError, "serial number must be integer");
108 goto err;
109 }
110
111 if ((format_args = Py_BuildValue("(O)", serial)) == NULL) {
112 goto err;
113 }
114
115 if ((format = PyString_FromString("%x")) == NULL) {
116 goto err;
117 }
118
119 if ((hex = PyString_Format(format, format_args)) == NULL) {
120 goto err;
121 }
122
123 /**
124 * BN_hex2bn stores the result in &bignum. Unless it doesn't feel like
125 * it. If bignum is still NULL after this call, then the return value
126 * is actually the result. I hope. -exarkun
127 */
128 small_serial = BN_hex2bn(&bignum, PyString_AsString(hex));
129
130 Py_DECREF(format_args);
131 format_args = NULL;
132 Py_DECREF(format);
133 format = NULL;
134 Py_DECREF(hex);
135 hex = NULL;
136
137 if (bignum == NULL) {
138 if (ASN1_INTEGER_set(X509_get_serialNumber(self->x509), small_serial)) {
139 exception_from_error_queue();
140 goto err;
141 }
142 } else {
143 asn1_i = BN_to_ASN1_INTEGER(bignum, NULL);
144 BN_free(bignum);
145 bignum = NULL;
146 if (asn1_i == NULL) {
147 exception_from_error_queue();
148 goto err;
149 }
150 if (!X509_set_serialNumber(self->x509, asn1_i)) {
151 exception_from_error_queue();
152 goto err;
153 }
154 ASN1_INTEGER_free(asn1_i);
155 asn1_i = NULL;
156 }
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500157
158 Py_INCREF(Py_None);
159 return Py_None;
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500160
161 err:
162 if (format_args) {
163 Py_DECREF(format_args);
164 }
165 if (format) {
166 Py_DECREF(format);
167 }
168 if (hex) {
169 Py_DECREF(hex);
170 }
171 if (bignum) {
172 BN_free(bignum);
173 }
174 if (asn1_i) {
175 ASN1_INTEGER_free(asn1_i);
176 }
177 return NULL;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500178}
179
180static char crypto_X509_get_issuer_doc[] = "\n\
181Create an X509Name object for the issuer of the certificate\n\
182\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400183@return: An X509Name object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500184";
185
186static PyObject *
187crypto_X509_get_issuer(crypto_X509Obj *self, PyObject *args)
188{
189 crypto_X509NameObj *pyname;
190 X509_NAME *name;
191
192 if (!PyArg_ParseTuple(args, ":get_issuer"))
193 return NULL;
194
195 name = X509_get_issuer_name(self->x509);
196 pyname = crypto_X509Name_New(name, 0);
197 if (pyname != NULL)
198 {
199 pyname->parent_cert = (PyObject *)self;
200 Py_INCREF(self);
201 }
202 return (PyObject *)pyname;
203}
204
205static char crypto_X509_set_issuer_doc[] = "\n\
206Set the issuer of the certificate\n\
207\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400208@param issuer: The issuer name\n\
209@type issuer: L{X509Name}\n\
210@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500211";
212
213static PyObject *
214crypto_X509_set_issuer(crypto_X509Obj *self, PyObject *args)
215{
216 crypto_X509NameObj *issuer;
217
218 if (!PyArg_ParseTuple(args, "O!:set_issuer", &crypto_X509Name_Type,
219 &issuer))
220 return NULL;
221
222 if (!X509_set_issuer_name(self->x509, issuer->x509_name))
223 {
224 exception_from_error_queue();
225 return NULL;
226 }
227
228 Py_INCREF(Py_None);
229 return Py_None;
230}
231
232static char crypto_X509_get_subject_doc[] = "\n\
233Create an X509Name object for the subject of the certificate\n\
234\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400235@return: An X509Name object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500236";
237
238static PyObject *
239crypto_X509_get_subject(crypto_X509Obj *self, PyObject *args)
240{
241 crypto_X509NameObj *pyname;
242 X509_NAME *name;
243
244 if (!PyArg_ParseTuple(args, ":get_subject"))
245 return NULL;
246
247 name = X509_get_subject_name(self->x509);
248 pyname = crypto_X509Name_New(name, 0);
249 if (pyname != NULL)
250 {
251 pyname->parent_cert = (PyObject *)self;
252 Py_INCREF(self);
253 }
254 return (PyObject *)pyname;
255}
256
257static char crypto_X509_set_subject_doc[] = "\n\
258Set the subject of the certificate\n\
259\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400260@param subject: The subject name\n\
261@type subject: L{X509Name}\n\
262@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500263";
264
265static PyObject *
266crypto_X509_set_subject(crypto_X509Obj *self, PyObject *args)
267{
268 crypto_X509NameObj *subject;
269
270 if (!PyArg_ParseTuple(args, "O!:set_subject", &crypto_X509Name_Type,
271 &subject))
272 return NULL;
273
274 if (!X509_set_subject_name(self->x509, subject->x509_name))
275 {
276 exception_from_error_queue();
277 return NULL;
278 }
279
280 Py_INCREF(Py_None);
281 return Py_None;
282}
283
284static char crypto_X509_get_pubkey_doc[] = "\n\
285Get the public key of the certificate\n\
286\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400287@return: The public key\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500288";
289
290static PyObject *
291crypto_X509_get_pubkey(crypto_X509Obj *self, PyObject *args)
292{
293 crypto_PKeyObj *crypto_PKey_New(EVP_PKEY *, int);
294 EVP_PKEY *pkey;
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400295 crypto_PKeyObj *py_pkey;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500296
297 if (!PyArg_ParseTuple(args, ":get_pubkey"))
298 return NULL;
299
300 if ((pkey = X509_get_pubkey(self->x509)) == NULL)
301 {
302 exception_from_error_queue();
303 return NULL;
304 }
305
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400306 py_pkey = crypto_PKey_New(pkey, 1);
307 if (py_pkey != NULL) {
308 py_pkey->only_public = 1;
309 }
Jean-Paul Calderonef60beec2008-07-22 21:19:02 -0400310 return (PyObject *)py_pkey;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500311}
312
313static char crypto_X509_set_pubkey_doc[] = "\n\
314Set the public key of the certificate\n\
315\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400316@param pkey: The public key\n\
317@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500318";
319
320static PyObject *
321crypto_X509_set_pubkey(crypto_X509Obj *self, PyObject *args)
322{
323 crypto_PKeyObj *pkey;
324
325 if (!PyArg_ParseTuple(args, "O!:set_pubkey", &crypto_PKey_Type, &pkey))
326 return NULL;
327
328 if (!X509_set_pubkey(self->x509, pkey->pkey))
329 {
330 exception_from_error_queue();
331 return NULL;
332 }
333
334 Py_INCREF(Py_None);
335 return Py_None;
336}
337
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400338static PyObject*
339_set_asn1_time(char *format, ASN1_TIME* timestamp, crypto_X509Obj *self, PyObject *args)
340{
341 char *when;
342
343 if (!PyArg_ParseTuple(args, format, &when))
344 return NULL;
345
346 if (ASN1_GENERALIZEDTIME_set_string(timestamp, when) == 0) {
347 ASN1_GENERALIZEDTIME dummy;
348 dummy.type = V_ASN1_GENERALIZEDTIME;
349 dummy.length = strlen(when);
Jean-Paul Calderone28ebb302008-12-29 16:25:30 -0500350 dummy.data = (unsigned char *)when;
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400351 if (!ASN1_GENERALIZEDTIME_check(&dummy)) {
352 PyErr_SetString(PyExc_ValueError, "Invalid string");
353 } else {
354 PyErr_SetString(PyExc_RuntimeError, "Unknown ASN1_GENERALIZEDTIME_set_string failure");
355 }
356 return NULL;
357 }
358 Py_INCREF(Py_None);
359 return Py_None;
360}
361
362static char crypto_X509_set_notBefore_doc[] = "\n\
363Set the time stamp for when the certificate starts being valid\n\
364\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400365@param when: A string giving the timestamp, in the format:\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400366\n\
367 YYYYMMDDhhmmssZ\n\
368 YYYYMMDDhhmmss+hhmm\n\
369 YYYYMMDDhhmmss-hhmm\n\
370\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400371@return: None\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400372";
373
374static PyObject*
375crypto_X509_set_notBefore(crypto_X509Obj *self, PyObject *args)
376{
377 return _set_asn1_time(
378 "s:set_notBefore", X509_get_notBefore(self->x509), self, args);
379}
380
381static char crypto_X509_set_notAfter_doc[] = "\n\
382Set the time stamp for when the certificate stops being valid\n\
383\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400384@param when: A string giving the timestamp, in the format:\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400385\n\
386 YYYYMMDDhhmmssZ\n\
387 YYYYMMDDhhmmss+hhmm\n\
388 YYYYMMDDhhmmss-hhmm\n\
389\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400390@return: None\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400391";
392
393static PyObject*
394crypto_X509_set_notAfter(crypto_X509Obj *self, PyObject *args)
395{
396 return _set_asn1_time(
397 "s:set_notAfter", X509_get_notAfter(self->x509), self, args);
398}
399
400static PyObject*
401_get_asn1_time(char *format, ASN1_TIME* timestamp, crypto_X509Obj *self, PyObject *args)
402{
403 ASN1_GENERALIZEDTIME *gt_timestamp = NULL;
404 PyObject *py_timestamp = NULL;
405
406 if (!PyArg_ParseTuple(args, format)) {
407 return NULL;
408 }
409
410 /*
411 * http://www.columbia.edu/~ariel/ssleay/asn1-time.html
412 */
413 /*
414 * There must be a way to do this without touching timestamp->data
415 * directly. -exarkun
416 */
Jean-Paul Calderonee0615b52008-03-09 21:44:46 -0400417 if (timestamp->length == 0) {
418 Py_INCREF(Py_None);
419 return Py_None;
420 } else if (timestamp->type == V_ASN1_GENERALIZEDTIME) {
Jean-Paul Calderone7ef4ee22008-12-29 16:45:27 -0500421 return PyString_FromString((char *)timestamp->data);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400422 } else {
423 ASN1_TIME_to_generalizedtime(timestamp, &gt_timestamp);
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -0400424 if (gt_timestamp == NULL) {
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400425 exception_from_error_queue();
426 return NULL;
427 } else {
Jean-Paul Calderone7ef4ee22008-12-29 16:45:27 -0500428 py_timestamp = PyString_FromString((char *)gt_timestamp->data);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400429 ASN1_GENERALIZEDTIME_free(gt_timestamp);
430 return py_timestamp;
431 }
432 }
433}
434
435static char crypto_X509_get_notBefore_doc[] = "\n\
436Retrieve the time stamp for when the certificate starts being valid\n\
437\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400438@return: A string giving the timestamp, in the format:\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400439\n\
440 YYYYMMDDhhmmssZ\n\
441 YYYYMMDDhhmmss+hhmm\n\
442 YYYYMMDDhhmmss-hhmm\n\
443 or None if there is no value set.\n\
444";
445
446static PyObject*
447crypto_X509_get_notBefore(crypto_X509Obj *self, PyObject *args)
448{
449 /*
450 * X509_get_notBefore returns a borrowed reference.
451 */
452 return _get_asn1_time(
453 ":get_notBefore", X509_get_notBefore(self->x509), self, args);
454}
455
456
457static char crypto_X509_get_notAfter_doc[] = "\n\
458Retrieve the time stamp for when the certificate stops being valid\n\
459\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400460@return: A string giving the timestamp, in the format:\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400461\n\
462 YYYYMMDDhhmmssZ\n\
463 YYYYMMDDhhmmss+hhmm\n\
464 YYYYMMDDhhmmss-hhmm\n\
465 or None if there is no value set.\n\
466";
467
468static PyObject*
469crypto_X509_get_notAfter(crypto_X509Obj *self, PyObject *args)
470{
471 /*
472 * X509_get_notAfter returns a borrowed reference.
473 */
474 return _get_asn1_time(
475 ":get_notAfter", X509_get_notAfter(self->x509), self, args);
476}
477
478
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500479static char crypto_X509_gmtime_adj_notBefore_doc[] = "\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400480Change the timestamp for when the certificate starts being valid to the current\n\
481time plus an offset.\n \
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500482\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400483@param amount: The number of seconds by which to adjust the starting validity\n\
484 time.\n\
485@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500486";
487
488static PyObject *
489crypto_X509_gmtime_adj_notBefore(crypto_X509Obj *self, PyObject *args)
490{
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400491 long amount;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500492
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400493 if (!PyArg_ParseTuple(args, "l:gmtime_adj_notBefore", &amount))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500494 return NULL;
495
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400496 X509_gmtime_adj(X509_get_notBefore(self->x509), amount);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500497
498 Py_INCREF(Py_None);
499 return Py_None;
500}
501
502static char crypto_X509_gmtime_adj_notAfter_doc[] = "\n\
503Adjust the time stamp for when the certificate stops being valid\n\
504\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400505@param amount: The number of seconds by which to adjust the ending validity\n\
506 time.\n\
507@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500508";
509
510static PyObject *
511crypto_X509_gmtime_adj_notAfter(crypto_X509Obj *self, PyObject *args)
512{
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400513 long amount;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500514
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400515 if (!PyArg_ParseTuple(args, "l:gmtime_adj_notAfter", &amount))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500516 return NULL;
517
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400518 X509_gmtime_adj(X509_get_notAfter(self->x509), amount);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500519
520 Py_INCREF(Py_None);
521 return Py_None;
522}
523
524static char crypto_X509_sign_doc[] = "\n\
525Sign the certificate using the supplied key and digest\n\
526\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400527@param pkey: The key to sign with\n\
528@param digest: The message digest to use\n\
529@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500530";
531
532static PyObject *
533crypto_X509_sign(crypto_X509Obj *self, PyObject *args)
534{
535 crypto_PKeyObj *pkey;
536 char *digest_name;
537 const EVP_MD *digest;
538
539 if (!PyArg_ParseTuple(args, "O!s:sign", &crypto_PKey_Type, &pkey,
540 &digest_name))
541 return NULL;
542
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400543 if (pkey->only_public) {
544 PyErr_SetString(PyExc_ValueError, "Key has only public part");
545 return NULL;
546 }
547
548 if (!pkey->initialized) {
549 PyErr_SetString(PyExc_ValueError, "Key is uninitialized");
550 return NULL;
551 }
552
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500553 if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
554 {
555 PyErr_SetString(PyExc_ValueError, "No such digest method");
556 return NULL;
557 }
558
559 if (!X509_sign(self->x509, pkey->pkey, digest))
560 {
561 exception_from_error_queue();
562 return NULL;
563 }
564
565 Py_INCREF(Py_None);
566 return Py_None;
567}
568
569static char crypto_X509_has_expired_doc[] = "\n\
570Check whether the certificate has expired.\n\
571\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400572@return: True if the certificate has expired, false otherwise\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500573";
574
575static PyObject *
576crypto_X509_has_expired(crypto_X509Obj *self, PyObject *args)
577{
578 time_t tnow;
579
580 if (!PyArg_ParseTuple(args, ":has_expired"))
581 return NULL;
582
583 tnow = time(NULL);
584 if (ASN1_UTCTIME_cmp_time_t(X509_get_notAfter(self->x509), tnow) < 0)
585 return PyInt_FromLong(1L);
586 else
587 return PyInt_FromLong(0L);
588}
589
590static char crypto_X509_subject_name_hash_doc[] = "\n\
591Return the hash of the X509 subject.\n\
592\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400593@return: The hash of the subject\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500594";
595
596static PyObject *
597crypto_X509_subject_name_hash(crypto_X509Obj *self, PyObject *args)
598{
599 if (!PyArg_ParseTuple(args, ":subject_name_hash"))
600 return NULL;
601
602 return PyLong_FromLong(X509_subject_name_hash(self->x509));
603}
604
605static char crypto_X509_digest_doc[] = "\n\
606Return the digest of the X509 object.\n\
607\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400608@return: The digest of the object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500609";
610
611static PyObject *
612crypto_X509_digest(crypto_X509Obj *self, PyObject *args)
613{
614 unsigned char fp[EVP_MAX_MD_SIZE];
615 char *tmp;
616 char *digest_name;
Jean-Paul Calderone28ebb302008-12-29 16:25:30 -0500617 unsigned int len,i;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500618 PyObject *ret;
619 const EVP_MD *digest;
620
621 if (!PyArg_ParseTuple(args, "s:digest", &digest_name))
622 return NULL;
623
624 if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
625 {
626 PyErr_SetString(PyExc_ValueError, "No such digest method");
627 return NULL;
628 }
629
630 if (!X509_digest(self->x509,digest,fp,&len))
631 {
632 exception_from_error_queue();
633 }
634 tmp = malloc(3*len+1);
635 memset(tmp, 0, 3*len+1);
636 for (i = 0; i < len; i++) {
637 sprintf(tmp+i*3,"%02X:",fp[i]);
638 }
639 tmp[3*len-1] = 0;
640 ret = PyString_FromStringAndSize(tmp,3*len-1);
641 free(tmp);
642 return ret;
643}
644
645
646static char crypto_X509_add_extensions_doc[] = "\n\
647Add extensions to the certificate.\n\
648\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400649@param extensions: a sequence of X509Extension objects\n\
650@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500651";
652
653static PyObject *
654crypto_X509_add_extensions(crypto_X509Obj *self, PyObject *args)
655{
656 PyObject *extensions, *seq;
657 crypto_X509ExtensionObj *ext;
658 int nr_of_extensions, i;
659
660 if (!PyArg_ParseTuple(args, "O:add_extensions", &extensions))
661 return NULL;
662
663 seq = PySequence_Fast(extensions, "Expected a sequence");
664 if (seq == NULL)
665 return NULL;
666
667 nr_of_extensions = PySequence_Fast_GET_SIZE(seq);
668
669 for (i = 0; i < nr_of_extensions; i++)
670 {
671 ext = (crypto_X509ExtensionObj *)PySequence_Fast_GET_ITEM(seq, i);
672 if (!crypto_X509Extension_Check(ext))
673 {
674 Py_DECREF(seq);
675 PyErr_SetString(PyExc_ValueError,
676 "One of the elements is not an X509Extension");
677 return NULL;
678 }
679 if (!X509_add_ext(self->x509, ext->x509_extension, -1))
680 {
681 Py_DECREF(seq);
682 exception_from_error_queue();
683 return NULL;
684 }
685 }
686
687 Py_INCREF(Py_None);
688 return Py_None;
689}
690
691/*
692 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
693 * { 'name', (PyCFunction)crypto_X509_name, METH_VARARGS }
694 * for convenience
695 */
696#define ADD_METHOD(name) \
697 { #name, (PyCFunction)crypto_X509_##name, METH_VARARGS, crypto_X509_##name##_doc }
698static PyMethodDef crypto_X509_methods[] =
699{
700 ADD_METHOD(get_version),
701 ADD_METHOD(set_version),
702 ADD_METHOD(get_serial_number),
703 ADD_METHOD(set_serial_number),
704 ADD_METHOD(get_issuer),
705 ADD_METHOD(set_issuer),
706 ADD_METHOD(get_subject),
707 ADD_METHOD(set_subject),
708 ADD_METHOD(get_pubkey),
709 ADD_METHOD(set_pubkey),
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400710 ADD_METHOD(get_notBefore),
711 ADD_METHOD(set_notBefore),
712 ADD_METHOD(get_notAfter),
713 ADD_METHOD(set_notAfter),
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500714 ADD_METHOD(gmtime_adj_notBefore),
715 ADD_METHOD(gmtime_adj_notAfter),
716 ADD_METHOD(sign),
717 ADD_METHOD(has_expired),
718 ADD_METHOD(subject_name_hash),
719 ADD_METHOD(digest),
720 ADD_METHOD(add_extensions),
721 { NULL, NULL }
722};
723#undef ADD_METHOD
724
725
726/*
727 * Constructor for X509 objects, never called by Python code directly
728 *
729 * Arguments: cert - A "real" X509 certificate object
730 * dealloc - Boolean value to specify whether the destructor should
731 * free the "real" X509 object
732 * Returns: The newly created X509 object
733 */
734crypto_X509Obj *
735crypto_X509_New(X509 *cert, int dealloc)
736{
737 crypto_X509Obj *self;
738
739 self = PyObject_New(crypto_X509Obj, &crypto_X509_Type);
740
741 if (self == NULL)
742 return NULL;
743
744 self->x509 = cert;
745 self->dealloc = dealloc;
746
747 return self;
748}
749
750/*
751 * Deallocate the memory used by the X509 object
752 *
753 * Arguments: self - The X509 object
754 * Returns: None
755 */
756static void
757crypto_X509_dealloc(crypto_X509Obj *self)
758{
759 /* Sometimes we don't have to dealloc the "real" X509 pointer ourselves */
760 if (self->dealloc)
761 X509_free(self->x509);
762
763 PyObject_Del(self);
764}
765
766/*
767 * Find attribute
768 *
769 * Arguments: self - The X509 object
770 * name - The attribute name
771 * Returns: A Python object for the attribute, or NULL if something went
772 * wrong
773 */
774static PyObject *
775crypto_X509_getattr(crypto_X509Obj *self, char *name)
776{
777 return Py_FindMethod(crypto_X509_methods, (PyObject *)self, name);
778}
779
780PyTypeObject crypto_X509_Type = {
781 PyObject_HEAD_INIT(NULL)
782 0,
783 "X509",
784 sizeof(crypto_X509Obj),
785 0,
786 (destructor)crypto_X509_dealloc,
787 NULL, /* print */
788 (getattrfunc)crypto_X509_getattr,
789};
790
791/*
792 * Initialize the X509 part of the crypto sub module
793 *
794 * Arguments: dict - The crypto module dictionary
795 * Returns: None
796 */
797int
798init_crypto_x509(PyObject *dict)
799{
800 crypto_X509_Type.ob_type = &PyType_Type;
801 Py_INCREF(&crypto_X509_Type);
802 PyDict_SetItemString(dict, "X509Type", (PyObject *)&crypto_X509_Type);
803 return 1;
804}
805