blob: 68f34b77d577651fd6bae02ab296ce3a953d2abc [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;
312
313 if (!PyArg_ParseTuple(args, ":get_pubkey"))
314 return NULL;
315
316 if ((pkey = X509_get_pubkey(self->x509)) == NULL)
317 {
318 exception_from_error_queue();
319 return NULL;
320 }
321
Jean-Paul Calderone19555b92008-02-19 22:29:57 -0500322 return (PyObject *)crypto_PKey_New(pkey, 1);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500323}
324
325static char crypto_X509_set_pubkey_doc[] = "\n\
326Set the public key of the certificate\n\
327\n\
328Arguments: self - The X509 object\n\
329 args - The Python argument tuple, should be:\n\
330 pkey - The public key\n\
331Returns: None\n\
332";
333
334static PyObject *
335crypto_X509_set_pubkey(crypto_X509Obj *self, PyObject *args)
336{
337 crypto_PKeyObj *pkey;
338
339 if (!PyArg_ParseTuple(args, "O!:set_pubkey", &crypto_PKey_Type, &pkey))
340 return NULL;
341
342 if (!X509_set_pubkey(self->x509, pkey->pkey))
343 {
344 exception_from_error_queue();
345 return NULL;
346 }
347
348 Py_INCREF(Py_None);
349 return Py_None;
350}
351
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400352static PyObject*
353_set_asn1_time(char *format, ASN1_TIME* timestamp, crypto_X509Obj *self, PyObject *args)
354{
355 char *when;
356
357 if (!PyArg_ParseTuple(args, format, &when))
358 return NULL;
359
360 if (ASN1_GENERALIZEDTIME_set_string(timestamp, when) == 0) {
361 ASN1_GENERALIZEDTIME dummy;
362 dummy.type = V_ASN1_GENERALIZEDTIME;
363 dummy.length = strlen(when);
364 dummy.data = when;
365 if (!ASN1_GENERALIZEDTIME_check(&dummy)) {
366 PyErr_SetString(PyExc_ValueError, "Invalid string");
367 } else {
368 PyErr_SetString(PyExc_RuntimeError, "Unknown ASN1_GENERALIZEDTIME_set_string failure");
369 }
370 return NULL;
371 }
372 Py_INCREF(Py_None);
373 return Py_None;
374}
375
376static char crypto_X509_set_notBefore_doc[] = "\n\
377Set the time stamp for when the certificate starts being valid\n\
378\n\
379Arguments: self - The X509 object\n\
380 args - The Python argument tuple, should be:\n\
381 when - A string giving the timestamp, in the format:\n\
382\n\
383 YYYYMMDDhhmmssZ\n\
384 YYYYMMDDhhmmss+hhmm\n\
385 YYYYMMDDhhmmss-hhmm\n\
386\n\
387Returns: None\n\
388";
389
390static PyObject*
391crypto_X509_set_notBefore(crypto_X509Obj *self, PyObject *args)
392{
393 return _set_asn1_time(
394 "s:set_notBefore", X509_get_notBefore(self->x509), self, args);
395}
396
397static char crypto_X509_set_notAfter_doc[] = "\n\
398Set the time stamp for when the certificate stops being valid\n\
399\n\
400Arguments: self - The X509 object\n\
401 args - The Python argument tuple, should be:\n\
402 when - A string giving the timestamp, in the format:\n\
403\n\
404 YYYYMMDDhhmmssZ\n\
405 YYYYMMDDhhmmss+hhmm\n\
406 YYYYMMDDhhmmss-hhmm\n\
407\n\
408Returns: None\n\
409";
410
411static PyObject*
412crypto_X509_set_notAfter(crypto_X509Obj *self, PyObject *args)
413{
414 return _set_asn1_time(
415 "s:set_notAfter", X509_get_notAfter(self->x509), self, args);
416}
417
418static PyObject*
419_get_asn1_time(char *format, ASN1_TIME* timestamp, crypto_X509Obj *self, PyObject *args)
420{
421 ASN1_GENERALIZEDTIME *gt_timestamp = NULL;
422 PyObject *py_timestamp = NULL;
423
424 if (!PyArg_ParseTuple(args, format)) {
425 return NULL;
426 }
427
428 /*
429 * http://www.columbia.edu/~ariel/ssleay/asn1-time.html
430 */
431 /*
432 * There must be a way to do this without touching timestamp->data
433 * directly. -exarkun
434 */
435 if (timestamp->type == V_ASN1_GENERALIZEDTIME) {
436 return PyString_FromString(timestamp->data);
437 } else {
438 ASN1_TIME_to_generalizedtime(timestamp, &gt_timestamp);
439 if (gt_timestamp != NULL) {
440 exception_from_error_queue();
441 return NULL;
442 } else {
443 py_timestamp = PyString_FromString(gt_timestamp->data);
444 ASN1_GENERALIZEDTIME_free(gt_timestamp);
445 return py_timestamp;
446 }
447 }
448}
449
450static char crypto_X509_get_notBefore_doc[] = "\n\
451Retrieve the time stamp for when the certificate starts being valid\n\
452\n\
453Arguments: self - The X509 object\n\
454 args - The Python argument tuple, should be empty.\n\
455\n\
456Returns: A string giving the timestamp, in the format:\n\
457\n\
458 YYYYMMDDhhmmssZ\n\
459 YYYYMMDDhhmmss+hhmm\n\
460 YYYYMMDDhhmmss-hhmm\n\
461 or None if there is no value set.\n\
462";
463
464static PyObject*
465crypto_X509_get_notBefore(crypto_X509Obj *self, PyObject *args)
466{
467 /*
468 * X509_get_notBefore returns a borrowed reference.
469 */
470 return _get_asn1_time(
471 ":get_notBefore", X509_get_notBefore(self->x509), self, args);
472}
473
474
475static char crypto_X509_get_notAfter_doc[] = "\n\
476Retrieve the time stamp for when the certificate stops being valid\n\
477\n\
478Arguments: self - The X509 object\n\
479 args - The Python argument tuple, should be empty.\n\
480\n\
481Returns: A string giving the timestamp, in the format:\n\
482\n\
483 YYYYMMDDhhmmssZ\n\
484 YYYYMMDDhhmmss+hhmm\n\
485 YYYYMMDDhhmmss-hhmm\n\
486 or None if there is no value set.\n\
487";
488
489static PyObject*
490crypto_X509_get_notAfter(crypto_X509Obj *self, PyObject *args)
491{
492 /*
493 * X509_get_notAfter returns a borrowed reference.
494 */
495 return _get_asn1_time(
496 ":get_notAfter", X509_get_notAfter(self->x509), self, args);
497}
498
499
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500500static char crypto_X509_gmtime_adj_notBefore_doc[] = "\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400501Change the timestamp for when the certificate starts being valid to the current\n\
502time plus an offset.\n \
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500503\n\
504Arguments: self - The X509 object\n\
505 args - The Python argument tuple, should be:\n\
506 i - The adjustment\n\
507Returns: None\n\
508";
509
510static PyObject *
511crypto_X509_gmtime_adj_notBefore(crypto_X509Obj *self, PyObject *args)
512{
513 long i;
514
515 if (!PyArg_ParseTuple(args, "l:gmtime_adj_notBefore", &i))
516 return NULL;
517
518 X509_gmtime_adj(X509_get_notBefore(self->x509), i);
519
520 Py_INCREF(Py_None);
521 return Py_None;
522}
523
524static char crypto_X509_gmtime_adj_notAfter_doc[] = "\n\
525Adjust the time stamp for when the certificate stops being valid\n\
526\n\
527Arguments: self - The X509 object\n\
528 args - The Python argument tuple, should be:\n\
529 i - The adjustment\n\
530Returns: None\n\
531";
532
533static PyObject *
534crypto_X509_gmtime_adj_notAfter(crypto_X509Obj *self, PyObject *args)
535{
536 long i;
537
538 if (!PyArg_ParseTuple(args, "l:gmtime_adj_notAfter", &i))
539 return NULL;
540
541 X509_gmtime_adj(X509_get_notAfter(self->x509), i);
542
543 Py_INCREF(Py_None);
544 return Py_None;
545}
546
547static char crypto_X509_sign_doc[] = "\n\
548Sign the certificate using the supplied key and digest\n\
549\n\
550Arguments: self - The X509 object\n\
551 args - The Python argument tuple, should be:\n\
552 pkey - The key to sign with\n\
553 digest - The message digest to use\n\
554Returns: None\n\
555";
556
557static PyObject *
558crypto_X509_sign(crypto_X509Obj *self, PyObject *args)
559{
560 crypto_PKeyObj *pkey;
561 char *digest_name;
562 const EVP_MD *digest;
563
564 if (!PyArg_ParseTuple(args, "O!s:sign", &crypto_PKey_Type, &pkey,
565 &digest_name))
566 return NULL;
567
568 if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
569 {
570 PyErr_SetString(PyExc_ValueError, "No such digest method");
571 return NULL;
572 }
573
574 if (!X509_sign(self->x509, pkey->pkey, digest))
575 {
576 exception_from_error_queue();
577 return NULL;
578 }
579
580 Py_INCREF(Py_None);
581 return Py_None;
582}
583
584static char crypto_X509_has_expired_doc[] = "\n\
585Check whether the certificate has expired.\n\
586\n\
587Arguments: self - The X509 object\n\
588 args - The Python argument tuple, should be empty\n\
589Returns: True if the certificate has expired, false otherwise\n\
590";
591
592static PyObject *
593crypto_X509_has_expired(crypto_X509Obj *self, PyObject *args)
594{
595 time_t tnow;
596
597 if (!PyArg_ParseTuple(args, ":has_expired"))
598 return NULL;
599
600 tnow = time(NULL);
601 if (ASN1_UTCTIME_cmp_time_t(X509_get_notAfter(self->x509), tnow) < 0)
602 return PyInt_FromLong(1L);
603 else
604 return PyInt_FromLong(0L);
605}
606
607static char crypto_X509_subject_name_hash_doc[] = "\n\
608Return the hash of the X509 subject.\n\
609\n\
610Arguments: self - The X509 object\n\
611 args - The Python argument tuple, should be empty\n\
612Returns: The hash of the subject\n\
613";
614
615static PyObject *
616crypto_X509_subject_name_hash(crypto_X509Obj *self, PyObject *args)
617{
618 if (!PyArg_ParseTuple(args, ":subject_name_hash"))
619 return NULL;
620
621 return PyLong_FromLong(X509_subject_name_hash(self->x509));
622}
623
624static char crypto_X509_digest_doc[] = "\n\
625Return the digest of the X509 object.\n\
626\n\
627Arguments: self - The X509 object\n\
628 args - The Python argument tuple, should be empty\n\
629Returns: The digest of the object\n\
630";
631
632static PyObject *
633crypto_X509_digest(crypto_X509Obj *self, PyObject *args)
634{
635 unsigned char fp[EVP_MAX_MD_SIZE];
636 char *tmp;
637 char *digest_name;
638 int len,i;
639 PyObject *ret;
640 const EVP_MD *digest;
641
642 if (!PyArg_ParseTuple(args, "s:digest", &digest_name))
643 return NULL;
644
645 if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
646 {
647 PyErr_SetString(PyExc_ValueError, "No such digest method");
648 return NULL;
649 }
650
651 if (!X509_digest(self->x509,digest,fp,&len))
652 {
653 exception_from_error_queue();
654 }
655 tmp = malloc(3*len+1);
656 memset(tmp, 0, 3*len+1);
657 for (i = 0; i < len; i++) {
658 sprintf(tmp+i*3,"%02X:",fp[i]);
659 }
660 tmp[3*len-1] = 0;
661 ret = PyString_FromStringAndSize(tmp,3*len-1);
662 free(tmp);
663 return ret;
664}
665
666
667static char crypto_X509_add_extensions_doc[] = "\n\
668Add extensions to the certificate.\n\
669\n\
670Arguments: self - X509 object\n\
671 args - The Python argument tuple, should be:\n\
672 extensions - a sequence of X509Extension objects\n\
673Returns: None\n\
674";
675
676static PyObject *
677crypto_X509_add_extensions(crypto_X509Obj *self, PyObject *args)
678{
679 PyObject *extensions, *seq;
680 crypto_X509ExtensionObj *ext;
681 int nr_of_extensions, i;
682
683 if (!PyArg_ParseTuple(args, "O:add_extensions", &extensions))
684 return NULL;
685
686 seq = PySequence_Fast(extensions, "Expected a sequence");
687 if (seq == NULL)
688 return NULL;
689
690 nr_of_extensions = PySequence_Fast_GET_SIZE(seq);
691
692 for (i = 0; i < nr_of_extensions; i++)
693 {
694 ext = (crypto_X509ExtensionObj *)PySequence_Fast_GET_ITEM(seq, i);
695 if (!crypto_X509Extension_Check(ext))
696 {
697 Py_DECREF(seq);
698 PyErr_SetString(PyExc_ValueError,
699 "One of the elements is not an X509Extension");
700 return NULL;
701 }
702 if (!X509_add_ext(self->x509, ext->x509_extension, -1))
703 {
704 Py_DECREF(seq);
705 exception_from_error_queue();
706 return NULL;
707 }
708 }
709
710 Py_INCREF(Py_None);
711 return Py_None;
712}
713
714/*
715 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
716 * { 'name', (PyCFunction)crypto_X509_name, METH_VARARGS }
717 * for convenience
718 */
719#define ADD_METHOD(name) \
720 { #name, (PyCFunction)crypto_X509_##name, METH_VARARGS, crypto_X509_##name##_doc }
721static PyMethodDef crypto_X509_methods[] =
722{
723 ADD_METHOD(get_version),
724 ADD_METHOD(set_version),
725 ADD_METHOD(get_serial_number),
726 ADD_METHOD(set_serial_number),
727 ADD_METHOD(get_issuer),
728 ADD_METHOD(set_issuer),
729 ADD_METHOD(get_subject),
730 ADD_METHOD(set_subject),
731 ADD_METHOD(get_pubkey),
732 ADD_METHOD(set_pubkey),
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400733 ADD_METHOD(get_notBefore),
734 ADD_METHOD(set_notBefore),
735 ADD_METHOD(get_notAfter),
736 ADD_METHOD(set_notAfter),
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500737 ADD_METHOD(gmtime_adj_notBefore),
738 ADD_METHOD(gmtime_adj_notAfter),
739 ADD_METHOD(sign),
740 ADD_METHOD(has_expired),
741 ADD_METHOD(subject_name_hash),
742 ADD_METHOD(digest),
743 ADD_METHOD(add_extensions),
744 { NULL, NULL }
745};
746#undef ADD_METHOD
747
748
749/*
750 * Constructor for X509 objects, never called by Python code directly
751 *
752 * Arguments: cert - A "real" X509 certificate object
753 * dealloc - Boolean value to specify whether the destructor should
754 * free the "real" X509 object
755 * Returns: The newly created X509 object
756 */
757crypto_X509Obj *
758crypto_X509_New(X509 *cert, int dealloc)
759{
760 crypto_X509Obj *self;
761
762 self = PyObject_New(crypto_X509Obj, &crypto_X509_Type);
763
764 if (self == NULL)
765 return NULL;
766
767 self->x509 = cert;
768 self->dealloc = dealloc;
769
770 return self;
771}
772
773/*
774 * Deallocate the memory used by the X509 object
775 *
776 * Arguments: self - The X509 object
777 * Returns: None
778 */
779static void
780crypto_X509_dealloc(crypto_X509Obj *self)
781{
782 /* Sometimes we don't have to dealloc the "real" X509 pointer ourselves */
783 if (self->dealloc)
784 X509_free(self->x509);
785
786 PyObject_Del(self);
787}
788
789/*
790 * Find attribute
791 *
792 * Arguments: self - The X509 object
793 * name - The attribute name
794 * Returns: A Python object for the attribute, or NULL if something went
795 * wrong
796 */
797static PyObject *
798crypto_X509_getattr(crypto_X509Obj *self, char *name)
799{
800 return Py_FindMethod(crypto_X509_methods, (PyObject *)self, name);
801}
802
803PyTypeObject crypto_X509_Type = {
804 PyObject_HEAD_INIT(NULL)
805 0,
806 "X509",
807 sizeof(crypto_X509Obj),
808 0,
809 (destructor)crypto_X509_dealloc,
810 NULL, /* print */
811 (getattrfunc)crypto_X509_getattr,
812};
813
814/*
815 * Initialize the X509 part of the crypto sub module
816 *
817 * Arguments: dict - The crypto module dictionary
818 * Returns: None
819 */
820int
821init_crypto_x509(PyObject *dict)
822{
823 crypto_X509_Type.ob_type = &PyType_Type;
824 Py_INCREF(&crypto_X509_Type);
825 PyDict_SetItemString(dict, "X509Type", (PyObject *)&crypto_X509_Type);
826 return 1;
827}
828