blob: a10c53a4a18a431764b160057127f7fc7b11c7f1 [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
5 *
6 * Certificate (X.509) handling code, mostly thin wrappers around OpenSSL.
7 * See the file RATIONALE for a short explanation of why this module was written.
8 *
9 * Reviewed 2001-07-23
10 */
11#include <Python.h>
12#define crypto_MODULE
13#include "crypto.h"
14
15static char *CVSid = "@(#) $Id: x509.c,v 1.20 2004/08/10 10:37:31 martin Exp $";
16
Jean-Paul Calderone525ef802008-03-09 20:39:42 -040017/*
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050018 * X.509 is a standard for digital certificates. See e.g. the OpenSSL homepage
19 * http://www.openssl.org/ for more information
20 */
21
22static char crypto_X509_get_version_doc[] = "\n\
23Return version number of the certificate\n\
24\n\
25Arguments: self - The X509 object\n\
26 args - The Python argument tuple, should be empty\n\
27Returns: Version number as a Python integer\n\
28";
29
30static PyObject *
31crypto_X509_get_version(crypto_X509Obj *self, PyObject *args)
32{
33 if (!PyArg_ParseTuple(args, ":get_version"))
34 return NULL;
35
36 return PyInt_FromLong((long)X509_get_version(self->x509));
37}
38
39static char crypto_X509_set_version_doc[] = "\n\
40Set version number of the certificate\n\
41\n\
42Arguments: self - The X509 object\n\
43 args - The Python argument tuple, should be:\n\
44 version - The version number\n\
45Returns: None\n\
46";
47
48static PyObject *
49crypto_X509_set_version(crypto_X509Obj *self, PyObject *args)
50{
51 int version;
52
53 if (!PyArg_ParseTuple(args, "i:set_version", &version))
54 return NULL;
55
56 X509_set_version(self->x509, version);
57
58 Py_INCREF(Py_None);
59 return Py_None;
60}
61
62static char crypto_X509_get_serial_number_doc[] = "\n\
63Return serial number of the certificate\n\
64\n\
65Arguments: self - The X509 object\n\
66 args - The Python argument tuple, should be empty\n\
67Returns: Serial number as a Python integer\n\
68";
69
70static PyObject *
71crypto_X509_get_serial_number(crypto_X509Obj *self, PyObject *args)
72{
73 ASN1_INTEGER *asn1_i;
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050074 BIGNUM *bignum;
75 char *hex;
76 PyObject *res;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050077
78 if (!PyArg_ParseTuple(args, ":get_serial_number"))
79 return NULL;
80
81 asn1_i = X509_get_serialNumber(self->x509);
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050082 bignum = ASN1_INTEGER_to_BN(asn1_i, NULL);
83 hex = BN_bn2hex(bignum);
84 res = PyLong_FromString(hex, NULL, 16);
85 BN_free(bignum);
86 free(hex);
87 return res;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050088}
89
90static char crypto_X509_set_serial_number_doc[] = "\n\
91Set serial number of the certificate\n\
92\n\
93Arguments: self - The X509 object\n\
94 args - The Python argument tuple, should be:\n\
95 serial - The serial number\n\
96Returns: None\n\
97";
98
99static PyObject *
100crypto_X509_set_serial_number(crypto_X509Obj *self, PyObject *args)
101{
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500102 long small_serial;
103 PyObject *serial = NULL;
104 PyObject *hex = NULL;
105 PyObject *format = NULL;
106 PyObject *format_args = NULL;
107 ASN1_INTEGER *asn1_i = NULL;
108 BIGNUM *bignum = NULL;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500109
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500110 if (!PyArg_ParseTuple(args, "O:set_serial_number", &serial)) {
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500111 return NULL;
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500112 }
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500113
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500114 if (!PyInt_Check(serial) && !PyLong_Check(serial)) {
115 PyErr_SetString(
116 PyExc_TypeError, "serial number must be integer");
117 goto err;
118 }
119
120 if ((format_args = Py_BuildValue("(O)", serial)) == NULL) {
121 goto err;
122 }
123
124 if ((format = PyString_FromString("%x")) == NULL) {
125 goto err;
126 }
127
128 if ((hex = PyString_Format(format, format_args)) == NULL) {
129 goto err;
130 }
131
132 /**
133 * BN_hex2bn stores the result in &bignum. Unless it doesn't feel like
134 * it. If bignum is still NULL after this call, then the return value
135 * is actually the result. I hope. -exarkun
136 */
137 small_serial = BN_hex2bn(&bignum, PyString_AsString(hex));
138
139 Py_DECREF(format_args);
140 format_args = NULL;
141 Py_DECREF(format);
142 format = NULL;
143 Py_DECREF(hex);
144 hex = NULL;
145
146 if (bignum == NULL) {
147 if (ASN1_INTEGER_set(X509_get_serialNumber(self->x509), small_serial)) {
148 exception_from_error_queue();
149 goto err;
150 }
151 } else {
152 asn1_i = BN_to_ASN1_INTEGER(bignum, NULL);
153 BN_free(bignum);
154 bignum = NULL;
155 if (asn1_i == NULL) {
156 exception_from_error_queue();
157 goto err;
158 }
159 if (!X509_set_serialNumber(self->x509, asn1_i)) {
160 exception_from_error_queue();
161 goto err;
162 }
163 ASN1_INTEGER_free(asn1_i);
164 asn1_i = NULL;
165 }
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500166
167 Py_INCREF(Py_None);
168 return Py_None;
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500169
170 err:
171 if (format_args) {
172 Py_DECREF(format_args);
173 }
174 if (format) {
175 Py_DECREF(format);
176 }
177 if (hex) {
178 Py_DECREF(hex);
179 }
180 if (bignum) {
181 BN_free(bignum);
182 }
183 if (asn1_i) {
184 ASN1_INTEGER_free(asn1_i);
185 }
186 return NULL;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500187}
188
189static char crypto_X509_get_issuer_doc[] = "\n\
190Create an X509Name object for the issuer of the certificate\n\
191\n\
192Arguments: self - The X509 object\n\
193 args - The Python argument tuple, should be empty\n\
194Returns: An X509Name object\n\
195";
196
197static PyObject *
198crypto_X509_get_issuer(crypto_X509Obj *self, PyObject *args)
199{
200 crypto_X509NameObj *pyname;
201 X509_NAME *name;
202
203 if (!PyArg_ParseTuple(args, ":get_issuer"))
204 return NULL;
205
206 name = X509_get_issuer_name(self->x509);
207 pyname = crypto_X509Name_New(name, 0);
208 if (pyname != NULL)
209 {
210 pyname->parent_cert = (PyObject *)self;
211 Py_INCREF(self);
212 }
213 return (PyObject *)pyname;
214}
215
216static char crypto_X509_set_issuer_doc[] = "\n\
217Set the issuer of the certificate\n\
218\n\
219Arguments: self - The X509 object\n\
220 args - The Python argument tuple, should be:\n\
221 issuer - The issuer name\n\
222Returns: None\n\
223";
224
225static PyObject *
226crypto_X509_set_issuer(crypto_X509Obj *self, PyObject *args)
227{
228 crypto_X509NameObj *issuer;
229
230 if (!PyArg_ParseTuple(args, "O!:set_issuer", &crypto_X509Name_Type,
231 &issuer))
232 return NULL;
233
234 if (!X509_set_issuer_name(self->x509, issuer->x509_name))
235 {
236 exception_from_error_queue();
237 return NULL;
238 }
239
240 Py_INCREF(Py_None);
241 return Py_None;
242}
243
244static char crypto_X509_get_subject_doc[] = "\n\
245Create an X509Name object for the subject of the certificate\n\
246\n\
247Arguments: self - The X509 object\n\
248 args - The Python argument tuple, should be empty\n\
249Returns: An X509Name object\n\
250";
251
252static PyObject *
253crypto_X509_get_subject(crypto_X509Obj *self, PyObject *args)
254{
255 crypto_X509NameObj *pyname;
256 X509_NAME *name;
257
258 if (!PyArg_ParseTuple(args, ":get_subject"))
259 return NULL;
260
261 name = X509_get_subject_name(self->x509);
262 pyname = crypto_X509Name_New(name, 0);
263 if (pyname != NULL)
264 {
265 pyname->parent_cert = (PyObject *)self;
266 Py_INCREF(self);
267 }
268 return (PyObject *)pyname;
269}
270
271static char crypto_X509_set_subject_doc[] = "\n\
272Set the subject of the certificate\n\
273\n\
274Arguments: self - The X509 object\n\
275 args - The Python argument tuple, should be:\n\
276 subject - The subject name\n\
277Returns: None\n\
278";
279
280static PyObject *
281crypto_X509_set_subject(crypto_X509Obj *self, PyObject *args)
282{
283 crypto_X509NameObj *subject;
284
285 if (!PyArg_ParseTuple(args, "O!:set_subject", &crypto_X509Name_Type,
286 &subject))
287 return NULL;
288
289 if (!X509_set_subject_name(self->x509, subject->x509_name))
290 {
291 exception_from_error_queue();
292 return NULL;
293 }
294
295 Py_INCREF(Py_None);
296 return Py_None;
297}
298
299static char crypto_X509_get_pubkey_doc[] = "\n\
300Get the public key of the certificate\n\
301\n\
302Arguments: self - The X509 object\n\
303 args - The Python argument tuple, should be empty\n\
304Returns: The public key\n\
305";
306
307static PyObject *
308crypto_X509_get_pubkey(crypto_X509Obj *self, PyObject *args)
309{
310 crypto_PKeyObj *crypto_PKey_New(EVP_PKEY *, int);
311 EVP_PKEY *pkey;
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400312 crypto_PKeyObj *py_pkey;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500313
314 if (!PyArg_ParseTuple(args, ":get_pubkey"))
315 return NULL;
316
317 if ((pkey = X509_get_pubkey(self->x509)) == NULL)
318 {
319 exception_from_error_queue();
320 return NULL;
321 }
322
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400323 py_pkey = crypto_PKey_New(pkey, 1);
324 if (py_pkey != NULL) {
325 py_pkey->only_public = 1;
326 }
327 return py_pkey;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500328}
329
330static char crypto_X509_set_pubkey_doc[] = "\n\
331Set the public key of the certificate\n\
332\n\
333Arguments: self - The X509 object\n\
334 args - The Python argument tuple, should be:\n\
335 pkey - The public key\n\
336Returns: None\n\
337";
338
339static PyObject *
340crypto_X509_set_pubkey(crypto_X509Obj *self, PyObject *args)
341{
342 crypto_PKeyObj *pkey;
343
344 if (!PyArg_ParseTuple(args, "O!:set_pubkey", &crypto_PKey_Type, &pkey))
345 return NULL;
346
347 if (!X509_set_pubkey(self->x509, pkey->pkey))
348 {
349 exception_from_error_queue();
350 return NULL;
351 }
352
353 Py_INCREF(Py_None);
354 return Py_None;
355}
356
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400357static PyObject*
358_set_asn1_time(char *format, ASN1_TIME* timestamp, crypto_X509Obj *self, PyObject *args)
359{
360 char *when;
361
362 if (!PyArg_ParseTuple(args, format, &when))
363 return NULL;
364
365 if (ASN1_GENERALIZEDTIME_set_string(timestamp, when) == 0) {
366 ASN1_GENERALIZEDTIME dummy;
367 dummy.type = V_ASN1_GENERALIZEDTIME;
368 dummy.length = strlen(when);
369 dummy.data = when;
370 if (!ASN1_GENERALIZEDTIME_check(&dummy)) {
371 PyErr_SetString(PyExc_ValueError, "Invalid string");
372 } else {
373 PyErr_SetString(PyExc_RuntimeError, "Unknown ASN1_GENERALIZEDTIME_set_string failure");
374 }
375 return NULL;
376 }
377 Py_INCREF(Py_None);
378 return Py_None;
379}
380
381static char crypto_X509_set_notBefore_doc[] = "\n\
382Set the time stamp for when the certificate starts being valid\n\
383\n\
384Arguments: self - The X509 object\n\
385 args - The Python argument tuple, should be:\n\
386 when - A string giving the timestamp, in the format:\n\
387\n\
388 YYYYMMDDhhmmssZ\n\
389 YYYYMMDDhhmmss+hhmm\n\
390 YYYYMMDDhhmmss-hhmm\n\
391\n\
392Returns: None\n\
393";
394
395static PyObject*
396crypto_X509_set_notBefore(crypto_X509Obj *self, PyObject *args)
397{
398 return _set_asn1_time(
399 "s:set_notBefore", X509_get_notBefore(self->x509), self, args);
400}
401
402static char crypto_X509_set_notAfter_doc[] = "\n\
403Set the time stamp for when the certificate stops being valid\n\
404\n\
405Arguments: self - The X509 object\n\
406 args - The Python argument tuple, should be:\n\
407 when - A string giving the timestamp, in the format:\n\
408\n\
409 YYYYMMDDhhmmssZ\n\
410 YYYYMMDDhhmmss+hhmm\n\
411 YYYYMMDDhhmmss-hhmm\n\
412\n\
413Returns: None\n\
414";
415
416static PyObject*
417crypto_X509_set_notAfter(crypto_X509Obj *self, PyObject *args)
418{
419 return _set_asn1_time(
420 "s:set_notAfter", X509_get_notAfter(self->x509), self, args);
421}
422
423static PyObject*
424_get_asn1_time(char *format, ASN1_TIME* timestamp, crypto_X509Obj *self, PyObject *args)
425{
426 ASN1_GENERALIZEDTIME *gt_timestamp = NULL;
427 PyObject *py_timestamp = NULL;
428
429 if (!PyArg_ParseTuple(args, format)) {
430 return NULL;
431 }
432
433 /*
434 * http://www.columbia.edu/~ariel/ssleay/asn1-time.html
435 */
436 /*
437 * There must be a way to do this without touching timestamp->data
438 * directly. -exarkun
439 */
Jean-Paul Calderonee0615b52008-03-09 21:44:46 -0400440 if (timestamp->length == 0) {
441 Py_INCREF(Py_None);
442 return Py_None;
443 } else if (timestamp->type == V_ASN1_GENERALIZEDTIME) {
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400444 return PyString_FromString(timestamp->data);
445 } else {
446 ASN1_TIME_to_generalizedtime(timestamp, &gt_timestamp);
447 if (gt_timestamp != NULL) {
448 exception_from_error_queue();
449 return NULL;
450 } else {
451 py_timestamp = PyString_FromString(gt_timestamp->data);
452 ASN1_GENERALIZEDTIME_free(gt_timestamp);
453 return py_timestamp;
454 }
455 }
456}
457
458static char crypto_X509_get_notBefore_doc[] = "\n\
459Retrieve the time stamp for when the certificate starts being valid\n\
460\n\
461Arguments: self - The X509 object\n\
462 args - The Python argument tuple, should be empty.\n\
463\n\
464Returns: A string giving the timestamp, in the format:\n\
465\n\
466 YYYYMMDDhhmmssZ\n\
467 YYYYMMDDhhmmss+hhmm\n\
468 YYYYMMDDhhmmss-hhmm\n\
469 or None if there is no value set.\n\
470";
471
472static PyObject*
473crypto_X509_get_notBefore(crypto_X509Obj *self, PyObject *args)
474{
475 /*
476 * X509_get_notBefore returns a borrowed reference.
477 */
478 return _get_asn1_time(
479 ":get_notBefore", X509_get_notBefore(self->x509), self, args);
480}
481
482
483static char crypto_X509_get_notAfter_doc[] = "\n\
484Retrieve the time stamp for when the certificate stops being valid\n\
485\n\
486Arguments: self - The X509 object\n\
487 args - The Python argument tuple, should be empty.\n\
488\n\
489Returns: A string giving the timestamp, in the format:\n\
490\n\
491 YYYYMMDDhhmmssZ\n\
492 YYYYMMDDhhmmss+hhmm\n\
493 YYYYMMDDhhmmss-hhmm\n\
494 or None if there is no value set.\n\
495";
496
497static PyObject*
498crypto_X509_get_notAfter(crypto_X509Obj *self, PyObject *args)
499{
500 /*
501 * X509_get_notAfter returns a borrowed reference.
502 */
503 return _get_asn1_time(
504 ":get_notAfter", X509_get_notAfter(self->x509), self, args);
505}
506
507
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500508static char crypto_X509_gmtime_adj_notBefore_doc[] = "\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400509Change the timestamp for when the certificate starts being valid to the current\n\
510time plus an offset.\n \
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500511\n\
512Arguments: self - The X509 object\n\
513 args - The Python argument tuple, should be:\n\
514 i - The adjustment\n\
515Returns: None\n\
516";
517
518static PyObject *
519crypto_X509_gmtime_adj_notBefore(crypto_X509Obj *self, PyObject *args)
520{
521 long i;
522
523 if (!PyArg_ParseTuple(args, "l:gmtime_adj_notBefore", &i))
524 return NULL;
525
526 X509_gmtime_adj(X509_get_notBefore(self->x509), i);
527
528 Py_INCREF(Py_None);
529 return Py_None;
530}
531
532static char crypto_X509_gmtime_adj_notAfter_doc[] = "\n\
533Adjust the time stamp for when the certificate stops being valid\n\
534\n\
535Arguments: self - The X509 object\n\
536 args - The Python argument tuple, should be:\n\
537 i - The adjustment\n\
538Returns: None\n\
539";
540
541static PyObject *
542crypto_X509_gmtime_adj_notAfter(crypto_X509Obj *self, PyObject *args)
543{
544 long i;
545
546 if (!PyArg_ParseTuple(args, "l:gmtime_adj_notAfter", &i))
547 return NULL;
548
549 X509_gmtime_adj(X509_get_notAfter(self->x509), i);
550
551 Py_INCREF(Py_None);
552 return Py_None;
553}
554
555static char crypto_X509_sign_doc[] = "\n\
556Sign the certificate using the supplied key and digest\n\
557\n\
558Arguments: self - The X509 object\n\
559 args - The Python argument tuple, should be:\n\
560 pkey - The key to sign with\n\
561 digest - The message digest to use\n\
562Returns: None\n\
563";
564
565static PyObject *
566crypto_X509_sign(crypto_X509Obj *self, PyObject *args)
567{
568 crypto_PKeyObj *pkey;
569 char *digest_name;
570 const EVP_MD *digest;
571
572 if (!PyArg_ParseTuple(args, "O!s:sign", &crypto_PKey_Type, &pkey,
573 &digest_name))
574 return NULL;
575
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400576 if (pkey->only_public) {
577 PyErr_SetString(PyExc_ValueError, "Key has only public part");
578 return NULL;
579 }
580
581 if (!pkey->initialized) {
582 PyErr_SetString(PyExc_ValueError, "Key is uninitialized");
583 return NULL;
584 }
585
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500586 if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
587 {
588 PyErr_SetString(PyExc_ValueError, "No such digest method");
589 return NULL;
590 }
591
592 if (!X509_sign(self->x509, pkey->pkey, digest))
593 {
594 exception_from_error_queue();
595 return NULL;
596 }
597
598 Py_INCREF(Py_None);
599 return Py_None;
600}
601
602static char crypto_X509_has_expired_doc[] = "\n\
603Check whether the certificate has expired.\n\
604\n\
605Arguments: self - The X509 object\n\
606 args - The Python argument tuple, should be empty\n\
607Returns: True if the certificate has expired, false otherwise\n\
608";
609
610static PyObject *
611crypto_X509_has_expired(crypto_X509Obj *self, PyObject *args)
612{
613 time_t tnow;
614
615 if (!PyArg_ParseTuple(args, ":has_expired"))
616 return NULL;
617
618 tnow = time(NULL);
619 if (ASN1_UTCTIME_cmp_time_t(X509_get_notAfter(self->x509), tnow) < 0)
620 return PyInt_FromLong(1L);
621 else
622 return PyInt_FromLong(0L);
623}
624
625static char crypto_X509_subject_name_hash_doc[] = "\n\
626Return the hash of the X509 subject.\n\
627\n\
628Arguments: self - The X509 object\n\
629 args - The Python argument tuple, should be empty\n\
630Returns: The hash of the subject\n\
631";
632
633static PyObject *
634crypto_X509_subject_name_hash(crypto_X509Obj *self, PyObject *args)
635{
636 if (!PyArg_ParseTuple(args, ":subject_name_hash"))
637 return NULL;
638
639 return PyLong_FromLong(X509_subject_name_hash(self->x509));
640}
641
642static char crypto_X509_digest_doc[] = "\n\
643Return the digest of the X509 object.\n\
644\n\
645Arguments: self - The X509 object\n\
646 args - The Python argument tuple, should be empty\n\
647Returns: The digest of the object\n\
648";
649
650static PyObject *
651crypto_X509_digest(crypto_X509Obj *self, PyObject *args)
652{
653 unsigned char fp[EVP_MAX_MD_SIZE];
654 char *tmp;
655 char *digest_name;
656 int len,i;
657 PyObject *ret;
658 const EVP_MD *digest;
659
660 if (!PyArg_ParseTuple(args, "s:digest", &digest_name))
661 return NULL;
662
663 if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
664 {
665 PyErr_SetString(PyExc_ValueError, "No such digest method");
666 return NULL;
667 }
668
669 if (!X509_digest(self->x509,digest,fp,&len))
670 {
671 exception_from_error_queue();
672 }
673 tmp = malloc(3*len+1);
674 memset(tmp, 0, 3*len+1);
675 for (i = 0; i < len; i++) {
676 sprintf(tmp+i*3,"%02X:",fp[i]);
677 }
678 tmp[3*len-1] = 0;
679 ret = PyString_FromStringAndSize(tmp,3*len-1);
680 free(tmp);
681 return ret;
682}
683
684
685static char crypto_X509_add_extensions_doc[] = "\n\
686Add extensions to the certificate.\n\
687\n\
688Arguments: self - X509 object\n\
689 args - The Python argument tuple, should be:\n\
690 extensions - a sequence of X509Extension objects\n\
691Returns: None\n\
692";
693
694static PyObject *
695crypto_X509_add_extensions(crypto_X509Obj *self, PyObject *args)
696{
697 PyObject *extensions, *seq;
698 crypto_X509ExtensionObj *ext;
699 int nr_of_extensions, i;
700
701 if (!PyArg_ParseTuple(args, "O:add_extensions", &extensions))
702 return NULL;
703
704 seq = PySequence_Fast(extensions, "Expected a sequence");
705 if (seq == NULL)
706 return NULL;
707
708 nr_of_extensions = PySequence_Fast_GET_SIZE(seq);
709
710 for (i = 0; i < nr_of_extensions; i++)
711 {
712 ext = (crypto_X509ExtensionObj *)PySequence_Fast_GET_ITEM(seq, i);
713 if (!crypto_X509Extension_Check(ext))
714 {
715 Py_DECREF(seq);
716 PyErr_SetString(PyExc_ValueError,
717 "One of the elements is not an X509Extension");
718 return NULL;
719 }
720 if (!X509_add_ext(self->x509, ext->x509_extension, -1))
721 {
722 Py_DECREF(seq);
723 exception_from_error_queue();
724 return NULL;
725 }
726 }
727
728 Py_INCREF(Py_None);
729 return Py_None;
730}
731
732/*
733 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
734 * { 'name', (PyCFunction)crypto_X509_name, METH_VARARGS }
735 * for convenience
736 */
737#define ADD_METHOD(name) \
738 { #name, (PyCFunction)crypto_X509_##name, METH_VARARGS, crypto_X509_##name##_doc }
739static PyMethodDef crypto_X509_methods[] =
740{
741 ADD_METHOD(get_version),
742 ADD_METHOD(set_version),
743 ADD_METHOD(get_serial_number),
744 ADD_METHOD(set_serial_number),
745 ADD_METHOD(get_issuer),
746 ADD_METHOD(set_issuer),
747 ADD_METHOD(get_subject),
748 ADD_METHOD(set_subject),
749 ADD_METHOD(get_pubkey),
750 ADD_METHOD(set_pubkey),
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400751 ADD_METHOD(get_notBefore),
752 ADD_METHOD(set_notBefore),
753 ADD_METHOD(get_notAfter),
754 ADD_METHOD(set_notAfter),
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500755 ADD_METHOD(gmtime_adj_notBefore),
756 ADD_METHOD(gmtime_adj_notAfter),
757 ADD_METHOD(sign),
758 ADD_METHOD(has_expired),
759 ADD_METHOD(subject_name_hash),
760 ADD_METHOD(digest),
761 ADD_METHOD(add_extensions),
762 { NULL, NULL }
763};
764#undef ADD_METHOD
765
766
767/*
768 * Constructor for X509 objects, never called by Python code directly
769 *
770 * Arguments: cert - A "real" X509 certificate object
771 * dealloc - Boolean value to specify whether the destructor should
772 * free the "real" X509 object
773 * Returns: The newly created X509 object
774 */
775crypto_X509Obj *
776crypto_X509_New(X509 *cert, int dealloc)
777{
778 crypto_X509Obj *self;
779
780 self = PyObject_New(crypto_X509Obj, &crypto_X509_Type);
781
782 if (self == NULL)
783 return NULL;
784
785 self->x509 = cert;
786 self->dealloc = dealloc;
787
788 return self;
789}
790
791/*
792 * Deallocate the memory used by the X509 object
793 *
794 * Arguments: self - The X509 object
795 * Returns: None
796 */
797static void
798crypto_X509_dealloc(crypto_X509Obj *self)
799{
800 /* Sometimes we don't have to dealloc the "real" X509 pointer ourselves */
801 if (self->dealloc)
802 X509_free(self->x509);
803
804 PyObject_Del(self);
805}
806
807/*
808 * Find attribute
809 *
810 * Arguments: self - The X509 object
811 * name - The attribute name
812 * Returns: A Python object for the attribute, or NULL if something went
813 * wrong
814 */
815static PyObject *
816crypto_X509_getattr(crypto_X509Obj *self, char *name)
817{
818 return Py_FindMethod(crypto_X509_methods, (PyObject *)self, name);
819}
820
821PyTypeObject crypto_X509_Type = {
822 PyObject_HEAD_INIT(NULL)
823 0,
824 "X509",
825 sizeof(crypto_X509Obj),
826 0,
827 (destructor)crypto_X509_dealloc,
828 NULL, /* print */
829 (getattrfunc)crypto_X509_getattr,
830};
831
832/*
833 * Initialize the X509 part of the crypto sub module
834 *
835 * Arguments: dict - The crypto module dictionary
836 * Returns: None
837 */
838int
839init_crypto_x509(PyObject *dict)
840{
841 crypto_X509_Type.ob_type = &PyType_Type;
842 Py_INCREF(&crypto_X509_Type);
843 PyDict_SetItemString(dict, "X509Type", (PyObject *)&crypto_X509_Type);
844 return 1;
845}
846