Initial import to Tizen
[profile/ivi/python-pyOpenSSL.git] / OpenSSL / crypto / x509.c
1 /*
2  * x509.c
3  *
4  * Copyright (C) AB Strakt
5  * Copyright (C) Jean-Paul Calderone
6  * See LICENSE for details.
7  *
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"
16 #include "x509ext.h"
17
18 /*
19  * X.509 is a standard for digital certificates.  See e.g. the OpenSSL homepage
20  * http://www.openssl.org/ for more information
21  */
22
23 static char crypto_X509_get_version_doc[] = "\n\
24 Return version number of the certificate\n\
25 \n\
26 @return: Version number as a Python integer\n\
27 ";
28
29 static PyObject *
30 crypto_X509_get_version(crypto_X509Obj *self, PyObject *args)
31 {
32     if (!PyArg_ParseTuple(args, ":get_version"))
33         return NULL;
34
35     return PyLong_FromLong((long)X509_get_version(self->x509));
36 }
37
38 static char crypto_X509_set_version_doc[] = "\n\
39 Set version number of the certificate\n\
40 \n\
41 @param version: The version number\n\
42 @return: None\n\
43 ";
44
45 static PyObject *
46 crypto_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
59 static char crypto_X509_get_serial_number_doc[] = "\n\
60 Return serial number of the certificate\n\
61 \n\
62 @return: Serial number as a Python integer\n\
63 ";
64
65 static PyObject *
66 crypto_X509_get_serial_number(crypto_X509Obj *self, PyObject *args)
67 {
68     ASN1_INTEGER *asn1_i;
69     BIGNUM *bignum;
70     char *hex;
71     PyObject *res;
72
73     if (!PyArg_ParseTuple(args, ":get_serial_number"))
74         return NULL;
75
76     asn1_i = X509_get_serialNumber(self->x509);
77     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;
83 }
84
85 static char crypto_X509_set_serial_number_doc[] = "\n\
86 Set serial number of the certificate\n\
87 \n\
88 @param serial: The serial number\n\
89 @return: None\n\
90 ";
91
92 static PyObject *
93 crypto_X509_set_serial_number(crypto_X509Obj *self, PyObject *args)
94 {
95     long small_serial;
96     PyObject *serial = NULL;
97     PyObject *hex = NULL;
98     ASN1_INTEGER *asn1_i = NULL;
99     BIGNUM *bignum = NULL;
100     char *hexstr;
101
102     if (!PyArg_ParseTuple(args, "O:set_serial_number", &serial)) {
103         return NULL;
104     }
105
106     if (!PyOpenSSL_Integer_Check(serial)) {
107         PyErr_SetString(
108             PyExc_TypeError, "serial number must be integer");
109         goto err;
110     }
111
112     if ((hex = PyOpenSSL_LongToHex(serial)) == NULL) {
113         goto err;
114     }
115
116 #ifdef PY3
117     {
118         PyObject *hexbytes = PyUnicode_AsASCIIString(hex);
119         Py_DECREF(hex);
120         hex = hexbytes;
121     }
122 #endif
123
124     /**
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      */
129     hexstr = PyBytes_AsString(hex);
130     if (hexstr[1] == 'x') {
131         /* +2 to skip the "0x" */
132         hexstr += 2;
133     }
134     small_serial = BN_hex2bn(&bignum, hexstr);
135
136     Py_DECREF(hex);
137     hex = NULL;
138
139     if (bignum == NULL) {
140         if (ASN1_INTEGER_set(X509_get_serialNumber(self->x509), small_serial)) {
141             exception_from_error_queue(crypto_Error);
142             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) {
149             exception_from_error_queue(crypto_Error);
150             goto err;
151         }
152         if (!X509_set_serialNumber(self->x509, asn1_i)) {
153             exception_from_error_queue(crypto_Error);
154             goto err;
155         }
156         ASN1_INTEGER_free(asn1_i);
157         asn1_i = NULL;
158     }
159
160     Py_INCREF(Py_None);
161     return Py_None;
162
163   err:
164     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;
174 }
175
176 static char crypto_X509_get_issuer_doc[] = "\n\
177 Create an X509Name object for the issuer of the certificate\n\
178 \n\
179 @return: An X509Name object\n\
180 ";
181
182 static PyObject *
183 crypto_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
201 static char crypto_X509_set_issuer_doc[] = "\n\
202 Set the issuer of the certificate\n\
203 \n\
204 @param issuer: The issuer name\n\
205 @type issuer: L{X509Name}\n\
206 @return: None\n\
207 ";
208
209 static PyObject *
210 crypto_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     {
220         exception_from_error_queue(crypto_Error);
221         return NULL;
222     }
223
224     Py_INCREF(Py_None);
225     return Py_None;
226 }
227
228 static char crypto_X509_get_subject_doc[] = "\n\
229 Create an X509Name object for the subject of the certificate\n\
230 \n\
231 @return: An X509Name object\n\
232 ";
233
234 static PyObject *
235 crypto_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
253 static char crypto_X509_set_subject_doc[] = "\n\
254 Set the subject of the certificate\n\
255 \n\
256 @param subject: The subject name\n\
257 @type subject: L{X509Name}\n\
258 @return: None\n\
259 ";
260
261 static PyObject *
262 crypto_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     {
272         exception_from_error_queue(crypto_Error);
273         return NULL;
274     }
275
276     Py_INCREF(Py_None);
277     return Py_None;
278 }
279
280 static char crypto_X509_get_pubkey_doc[] = "\n\
281 Get the public key of the certificate\n\
282 \n\
283 @return: The public key\n\
284 ";
285
286 static PyObject *
287 crypto_X509_get_pubkey(crypto_X509Obj *self, PyObject *args)
288 {
289     crypto_PKeyObj *crypto_PKey_New(EVP_PKEY *, int);
290     EVP_PKEY *pkey;
291     crypto_PKeyObj *py_pkey;
292
293     if (!PyArg_ParseTuple(args, ":get_pubkey"))
294         return NULL;
295
296     if ((pkey = X509_get_pubkey(self->x509)) == NULL)
297     {
298         exception_from_error_queue(crypto_Error);
299         return NULL;
300     }
301
302     py_pkey = crypto_PKey_New(pkey, 1);
303     if (py_pkey != NULL) {
304         py_pkey->only_public = 1;
305     }
306     return (PyObject *)py_pkey;
307 }
308
309 static char crypto_X509_set_pubkey_doc[] = "\n\
310 Set the public key of the certificate\n\
311 \n\
312 @param pkey: The public key\n\
313 @return: None\n\
314 ";
315
316 static PyObject *
317 crypto_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     {
326         exception_from_error_queue(crypto_Error);
327         return NULL;
328     }
329
330     Py_INCREF(Py_None);
331     return Py_None;
332 }
333
334 PyObject*
335 _set_asn1_time(char *format, ASN1_TIME* timestamp, PyObject *args)
336 {
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);
346                 dummy.data = (unsigned char *)when;
347                 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
358 static char crypto_X509_set_notBefore_doc[] = "\n\
359 Set the time stamp for when the certificate starts being valid\n\
360 \n\
361 @param when: A string giving the timestamp, in the format:\n\
362 \n\
363                  YYYYMMDDhhmmssZ\n\
364                  YYYYMMDDhhmmss+hhmm\n\
365                  YYYYMMDDhhmmss-hhmm\n\
366 \n\
367 @return: None\n\
368 ";
369
370 static PyObject*
371 crypto_X509_set_notBefore(crypto_X509Obj *self, PyObject *args)
372 {
373         return _set_asn1_time(
374             BYTESTRING_FMT ":set_notBefore",
375             X509_get_notBefore(self->x509), args);
376 }
377
378 static char crypto_X509_set_notAfter_doc[] = "\n\
379 Set the time stamp for when the certificate stops being valid\n\
380 \n\
381 @param 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\
387 @return: None\n\
388 ";
389
390 static PyObject*
391 crypto_X509_set_notAfter(crypto_X509Obj *self, PyObject *args)
392 {
393         return _set_asn1_time(
394             BYTESTRING_FMT ":set_notAfter",
395             X509_get_notAfter(self->x509), args);
396 }
397
398 PyObject*
399 _get_asn1_time(char *format, ASN1_TIME* timestamp, PyObject *args)
400 {
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          */
415         if (timestamp->length == 0) {
416             Py_INCREF(Py_None);
417             return Py_None;
418         } else if (timestamp->type == V_ASN1_GENERALIZEDTIME) {
419                 return PyBytes_FromString((char *)timestamp->data);
420         } else {
421                 ASN1_TIME_to_generalizedtime(timestamp, &gt_timestamp);
422                 if (gt_timestamp == NULL) {
423                         exception_from_error_queue(crypto_Error);
424                         return NULL;
425                 } else {
426                         py_timestamp = PyBytes_FromString((char *)gt_timestamp->data);
427                         ASN1_GENERALIZEDTIME_free(gt_timestamp);
428                         return py_timestamp;
429                 }
430         }
431 }
432
433 static char crypto_X509_get_notBefore_doc[] = "\n\
434 Retrieve the time stamp for when the certificate starts being valid\n\
435 \n\
436 @return: A string giving the timestamp, in the format:\n\
437 \n\
438                  YYYYMMDDhhmmssZ\n\
439                  YYYYMMDDhhmmss+hhmm\n\
440                  YYYYMMDDhhmmss-hhmm\n\
441            or None if there is no value set.\n\
442 ";
443
444 static PyObject*
445 crypto_X509_get_notBefore(crypto_X509Obj *self, PyObject *args)
446 {
447         /*
448          * X509_get_notBefore returns a borrowed reference.
449          */
450         return _get_asn1_time(
451                 ":get_notBefore", X509_get_notBefore(self->x509), args);
452 }
453
454
455 static char crypto_X509_get_notAfter_doc[] = "\n\
456 Retrieve the time stamp for when the certificate stops being valid\n\
457 \n\
458 @return: A string giving the timestamp, in the format:\n\
459 \n\
460                  YYYYMMDDhhmmssZ\n\
461                  YYYYMMDDhhmmss+hhmm\n\
462                  YYYYMMDDhhmmss-hhmm\n\
463            or None if there is no value set.\n\
464 ";
465
466 static PyObject*
467 crypto_X509_get_notAfter(crypto_X509Obj *self, PyObject *args)
468 {
469         /*
470          * X509_get_notAfter returns a borrowed reference.
471          */
472         return _get_asn1_time(
473                 ":get_notAfter", X509_get_notAfter(self->x509), args);
474 }
475
476
477 static char crypto_X509_gmtime_adj_notBefore_doc[] = "\n\
478 Change the timestamp for when the certificate starts being valid to the current\n\
479 time plus an offset.\n \
480 \n\
481 @param amount: The number of seconds by which to adjust the starting validity\n\
482                time.\n\
483 @return: None\n\
484 ";
485
486 static PyObject *
487 crypto_X509_gmtime_adj_notBefore(crypto_X509Obj *self, PyObject *args)
488 {
489     long amount;
490
491     if (!PyArg_ParseTuple(args, "l:gmtime_adj_notBefore", &amount))
492         return NULL;
493
494     X509_gmtime_adj(X509_get_notBefore(self->x509), amount);
495
496     Py_INCREF(Py_None);
497     return Py_None;
498 }
499
500 static char crypto_X509_gmtime_adj_notAfter_doc[] = "\n\
501 Adjust the time stamp for when the certificate stops being valid\n\
502 \n\
503 @param amount: The number of seconds by which to adjust the ending validity\n\
504                time.\n\
505 @return: None\n\
506 ";
507
508 static PyObject *
509 crypto_X509_gmtime_adj_notAfter(crypto_X509Obj *self, PyObject *args)
510 {
511     long amount;
512
513     if (!PyArg_ParseTuple(args, "l:gmtime_adj_notAfter", &amount))
514         return NULL;
515
516     X509_gmtime_adj(X509_get_notAfter(self->x509), amount);
517
518     Py_INCREF(Py_None);
519     return Py_None;
520 }
521
522 static char crypto_X509_sign_doc[] = "\n\
523 Sign the certificate using the supplied key and digest\n\
524 \n\
525 @param pkey: The key to sign with\n\
526 @param digest: The message digest to use\n\
527 @return: None\n\
528 ";
529
530 static PyObject *
531 crypto_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
541     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
551     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     {
559         exception_from_error_queue(crypto_Error);
560         return NULL;
561     }
562
563     Py_INCREF(Py_None);
564     return Py_None;
565 }
566
567 static char crypto_X509_has_expired_doc[] = "\n\
568 Check whether the certificate has expired.\n\
569 \n\
570 @return: True if the certificate has expired, false otherwise\n\
571 ";
572
573 static PyObject *
574 crypto_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)
583         return PyLong_FromLong(1L);
584     else
585         return PyLong_FromLong(0L);
586 }
587
588 static char crypto_X509_subject_name_hash_doc[] = "\n\
589 Return the hash of the X509 subject.\n\
590 \n\
591 @return: The hash of the subject\n\
592 ";
593
594 static PyObject *
595 crypto_X509_subject_name_hash(crypto_X509Obj *self, PyObject *args)
596 {
597     if (!PyArg_ParseTuple(args, ":subject_name_hash"))
598         return NULL;
599
600     return PyLong_FromLongLong(X509_subject_name_hash(self->x509));
601 }
602
603 static char crypto_X509_digest_doc[] = "\n\
604 Return the digest of the X509 object.\n\
605 \n\
606 @return: The digest of the object\n\
607 ";
608
609 static PyObject *
610 crypto_X509_digest(crypto_X509Obj *self, PyObject *args)
611 {
612     unsigned char fp[EVP_MAX_MD_SIZE];
613     char *tmp;
614     char *digest_name;
615     unsigned int len,i;
616     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     {
630         exception_from_error_queue(crypto_Error);
631     }
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;
638     ret = PyBytes_FromStringAndSize(tmp,3*len-1);
639     free(tmp);
640     return ret;
641 }
642
643
644 static char crypto_X509_add_extensions_doc[] = "\n\
645 Add extensions to the certificate.\n\
646 \n\
647 @param extensions: a sequence of X509Extension objects\n\
648 @return: None\n\
649 ";
650
651 static PyObject *
652 crypto_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);
680             exception_from_error_queue(crypto_Error);
681             return NULL;
682         }
683     }
684
685     Py_INCREF(Py_None);
686     return Py_None;
687 }
688
689 static char crypto_X509_get_extension_count_doc[] = "\n\
690 Get the number of extensions on the certificate.\n\
691 \n\
692 @return: Number of extensions as a Python integer\n\
693 ";
694
695 static PyObject *
696 crypto_X509_get_extension_count(crypto_X509Obj *self, PyObject *args) {
697     if (!PyArg_ParseTuple(args, ":get_extension_count")) {
698         return NULL;
699     }
700
701     return PyLong_FromLong((long)X509_get_ext_count(self->x509));
702 }
703
704 static char crypto_X509_get_extension_doc[] = "\n\
705 Get a specific extension of the certificate by index.\n\
706 \n\
707 @param index: The index of the extension to retrieve.\n\
708 @return: The X509Extension object at the specified index.\n\
709 ";
710
711 static PyObject *
712 crypto_X509_get_extension(crypto_X509Obj *self, PyObject *args) {
713     crypto_X509ExtensionObj *extobj;
714     int loc;
715     X509_EXTENSION *ext;
716
717     if (!PyArg_ParseTuple(args, "i:get_extension", &loc)) {
718         return NULL;
719     }
720
721     /* will return NULL if loc is outside the range of extensions,
722        not registered as an error*/
723     ext = X509_get_ext(self->x509, loc);
724     if (!ext) {
725         PyErr_SetString(PyExc_IndexError, "extension index out of bounds");
726         return NULL; /* Should be reported as an IndexError ? */
727     }
728
729     extobj = PyObject_New(crypto_X509ExtensionObj, &crypto_X509Extension_Type);
730     extobj->x509_extension = X509_EXTENSION_dup(ext);
731
732     return (PyObject*)extobj;
733 }
734
735 /*
736  * ADD_METHOD(name) expands to a correct PyMethodDef declaration
737  *   {  'name', (PyCFunction)crypto_X509_name, METH_VARARGS }
738  * for convenience
739  */
740 #define ADD_METHOD(name)        \
741     { #name, (PyCFunction)crypto_X509_##name, METH_VARARGS, crypto_X509_##name##_doc }
742 static PyMethodDef crypto_X509_methods[] =
743 {
744     ADD_METHOD(get_version),
745     ADD_METHOD(set_version),
746     ADD_METHOD(get_serial_number),
747     ADD_METHOD(set_serial_number),
748     ADD_METHOD(get_issuer),
749     ADD_METHOD(set_issuer),
750     ADD_METHOD(get_subject),
751     ADD_METHOD(set_subject),
752     ADD_METHOD(get_pubkey),
753     ADD_METHOD(set_pubkey),
754     ADD_METHOD(get_notBefore),
755     ADD_METHOD(set_notBefore),
756     ADD_METHOD(get_notAfter),
757     ADD_METHOD(set_notAfter),
758     ADD_METHOD(gmtime_adj_notBefore),
759     ADD_METHOD(gmtime_adj_notAfter),
760     ADD_METHOD(sign),
761     ADD_METHOD(has_expired),
762     ADD_METHOD(subject_name_hash),
763     ADD_METHOD(digest),
764     ADD_METHOD(add_extensions),
765     ADD_METHOD(get_extension),
766     ADD_METHOD(get_extension_count),
767     { NULL, NULL }
768 };
769 #undef ADD_METHOD
770
771
772 /*
773  * Constructor for X509 objects, never called by Python code directly
774  *
775  * Arguments: cert    - A "real" X509 certificate object
776  *            dealloc - Boolean value to specify whether the destructor should
777  *                      free the "real" X509 object
778  * Returns:   The newly created X509 object
779  */
780 crypto_X509Obj *
781 crypto_X509_New(X509 *cert, int dealloc)
782 {
783     crypto_X509Obj *self;
784
785     self = PyObject_New(crypto_X509Obj, &crypto_X509_Type);
786
787     if (self == NULL)
788         return NULL;
789
790     self->x509 = cert;
791     self->dealloc = dealloc;
792
793     return self;
794 }
795
796
797 static char crypto_X509_doc[] = "\n\
798 X509() -> X509 instance\n\
799 \n\
800 Create a new X509 object.\n\
801 \n\
802 @returns: The X509 object\n\
803 ";
804
805 static PyObject *
806 crypto_X509_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
807 {
808     if (!PyArg_ParseTuple(args, ":X509")) {
809         return NULL;
810     }
811
812     return (PyObject *)crypto_X509_New(X509_new(), 1);
813 }
814
815
816 /*
817  * Deallocate the memory used by the X509 object
818  *
819  * Arguments: self - The X509 object
820  * Returns:   None
821  */
822 static void
823 crypto_X509_dealloc(crypto_X509Obj *self)
824 {
825     /* Sometimes we don't have to dealloc the "real" X509 pointer ourselves */
826     if (self->dealloc)
827         X509_free(self->x509);
828
829     PyObject_Del(self);
830 }
831
832 PyTypeObject crypto_X509_Type = {
833     PyOpenSSL_HEAD_INIT(&PyType_Type, 0)
834     "X509",
835     sizeof(crypto_X509Obj),
836     0,
837     (destructor)crypto_X509_dealloc,
838     NULL, /* print */
839     NULL, /* getattr */
840     NULL, /* setattr */
841     NULL, /* compare */
842     NULL, /* repr */
843     NULL, /* as_number */
844     NULL, /* as_sequence */
845     NULL, /* as_mapping */
846     NULL, /* hash */
847     NULL, /* call */
848     NULL, /* str */
849     NULL, /* getattro */
850     NULL, /* setattro */
851     NULL, /* as_buffer */
852     Py_TPFLAGS_DEFAULT,
853     crypto_X509_doc, /* doc */
854     NULL, /* traverse */
855     NULL, /* clear */
856     NULL, /* tp_richcompare */
857     0, /* tp_weaklistoffset */
858     NULL, /* tp_iter */
859     NULL, /* tp_iternext */
860     crypto_X509_methods, /* tp_methods */
861     NULL, /* tp_members */
862     NULL, /* tp_getset */
863     NULL, /* tp_base */
864     NULL, /* tp_dict */
865     NULL, /* tp_descr_get */
866     NULL, /* tp_descr_set */
867     0, /* tp_dictoffset */
868     NULL, /* tp_init */
869     NULL, /* tp_alloc */
870     crypto_X509_new, /* tp_new */
871 };
872
873 /*
874  * Initialize the X509 part of the crypto sub module
875  *
876  * Arguments: module - The crypto module
877  * Returns:   None
878  */
879 int
880 init_crypto_x509(PyObject *module)
881 {
882     if (PyType_Ready(&crypto_X509_Type) < 0) {
883         return 0;
884     }
885
886     if (PyModule_AddObject(module, "X509", (PyObject *)&crypto_X509_Type) != 0) {
887         return 0;
888     }
889
890     if (PyModule_AddObject(module, "X509Type", (PyObject *)&crypto_X509_Type) != 0) {
891         return 0;
892     }
893
894     return 1;
895 }
896