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