blob: 2149d280bad1490b749ad013d5d08d80afbd991c [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
17/*
18 * 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
352static char crypto_X509_gmtime_adj_notBefore_doc[] = "\n\
353Adjust the time stamp for when the certificate starts being valid\n\
354\n\
355Arguments: self - The X509 object\n\
356 args - The Python argument tuple, should be:\n\
357 i - The adjustment\n\
358Returns: None\n\
359";
360
361static PyObject *
362crypto_X509_gmtime_adj_notBefore(crypto_X509Obj *self, PyObject *args)
363{
364 long i;
365
366 if (!PyArg_ParseTuple(args, "l:gmtime_adj_notBefore", &i))
367 return NULL;
368
369 X509_gmtime_adj(X509_get_notBefore(self->x509), i);
370
371 Py_INCREF(Py_None);
372 return Py_None;
373}
374
375static char crypto_X509_gmtime_adj_notAfter_doc[] = "\n\
376Adjust the time stamp for when the certificate stops being valid\n\
377\n\
378Arguments: self - The X509 object\n\
379 args - The Python argument tuple, should be:\n\
380 i - The adjustment\n\
381Returns: None\n\
382";
383
384static PyObject *
385crypto_X509_gmtime_adj_notAfter(crypto_X509Obj *self, PyObject *args)
386{
387 long i;
388
389 if (!PyArg_ParseTuple(args, "l:gmtime_adj_notAfter", &i))
390 return NULL;
391
392 X509_gmtime_adj(X509_get_notAfter(self->x509), i);
393
394 Py_INCREF(Py_None);
395 return Py_None;
396}
397
398static char crypto_X509_sign_doc[] = "\n\
399Sign the certificate using the supplied key and digest\n\
400\n\
401Arguments: self - The X509 object\n\
402 args - The Python argument tuple, should be:\n\
403 pkey - The key to sign with\n\
404 digest - The message digest to use\n\
405Returns: None\n\
406";
407
408static PyObject *
409crypto_X509_sign(crypto_X509Obj *self, PyObject *args)
410{
411 crypto_PKeyObj *pkey;
412 char *digest_name;
413 const EVP_MD *digest;
414
415 if (!PyArg_ParseTuple(args, "O!s:sign", &crypto_PKey_Type, &pkey,
416 &digest_name))
417 return NULL;
418
419 if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
420 {
421 PyErr_SetString(PyExc_ValueError, "No such digest method");
422 return NULL;
423 }
424
425 if (!X509_sign(self->x509, pkey->pkey, digest))
426 {
427 exception_from_error_queue();
428 return NULL;
429 }
430
431 Py_INCREF(Py_None);
432 return Py_None;
433}
434
435static char crypto_X509_has_expired_doc[] = "\n\
436Check whether the certificate has expired.\n\
437\n\
438Arguments: self - The X509 object\n\
439 args - The Python argument tuple, should be empty\n\
440Returns: True if the certificate has expired, false otherwise\n\
441";
442
443static PyObject *
444crypto_X509_has_expired(crypto_X509Obj *self, PyObject *args)
445{
446 time_t tnow;
447
448 if (!PyArg_ParseTuple(args, ":has_expired"))
449 return NULL;
450
451 tnow = time(NULL);
452 if (ASN1_UTCTIME_cmp_time_t(X509_get_notAfter(self->x509), tnow) < 0)
453 return PyInt_FromLong(1L);
454 else
455 return PyInt_FromLong(0L);
456}
457
458static char crypto_X509_subject_name_hash_doc[] = "\n\
459Return the hash of the X509 subject.\n\
460\n\
461Arguments: self - The X509 object\n\
462 args - The Python argument tuple, should be empty\n\
463Returns: The hash of the subject\n\
464";
465
466static PyObject *
467crypto_X509_subject_name_hash(crypto_X509Obj *self, PyObject *args)
468{
469 if (!PyArg_ParseTuple(args, ":subject_name_hash"))
470 return NULL;
471
472 return PyLong_FromLong(X509_subject_name_hash(self->x509));
473}
474
475static char crypto_X509_digest_doc[] = "\n\
476Return the digest of the X509 object.\n\
477\n\
478Arguments: self - The X509 object\n\
479 args - The Python argument tuple, should be empty\n\
480Returns: The digest of the object\n\
481";
482
483static PyObject *
484crypto_X509_digest(crypto_X509Obj *self, PyObject *args)
485{
486 unsigned char fp[EVP_MAX_MD_SIZE];
487 char *tmp;
488 char *digest_name;
489 int len,i;
490 PyObject *ret;
491 const EVP_MD *digest;
492
493 if (!PyArg_ParseTuple(args, "s:digest", &digest_name))
494 return NULL;
495
496 if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
497 {
498 PyErr_SetString(PyExc_ValueError, "No such digest method");
499 return NULL;
500 }
501
502 if (!X509_digest(self->x509,digest,fp,&len))
503 {
504 exception_from_error_queue();
505 }
506 tmp = malloc(3*len+1);
507 memset(tmp, 0, 3*len+1);
508 for (i = 0; i < len; i++) {
509 sprintf(tmp+i*3,"%02X:",fp[i]);
510 }
511 tmp[3*len-1] = 0;
512 ret = PyString_FromStringAndSize(tmp,3*len-1);
513 free(tmp);
514 return ret;
515}
516
517
518static char crypto_X509_add_extensions_doc[] = "\n\
519Add extensions to the certificate.\n\
520\n\
521Arguments: self - X509 object\n\
522 args - The Python argument tuple, should be:\n\
523 extensions - a sequence of X509Extension objects\n\
524Returns: None\n\
525";
526
527static PyObject *
528crypto_X509_add_extensions(crypto_X509Obj *self, PyObject *args)
529{
530 PyObject *extensions, *seq;
531 crypto_X509ExtensionObj *ext;
532 int nr_of_extensions, i;
533
534 if (!PyArg_ParseTuple(args, "O:add_extensions", &extensions))
535 return NULL;
536
537 seq = PySequence_Fast(extensions, "Expected a sequence");
538 if (seq == NULL)
539 return NULL;
540
541 nr_of_extensions = PySequence_Fast_GET_SIZE(seq);
542
543 for (i = 0; i < nr_of_extensions; i++)
544 {
545 ext = (crypto_X509ExtensionObj *)PySequence_Fast_GET_ITEM(seq, i);
546 if (!crypto_X509Extension_Check(ext))
547 {
548 Py_DECREF(seq);
549 PyErr_SetString(PyExc_ValueError,
550 "One of the elements is not an X509Extension");
551 return NULL;
552 }
553 if (!X509_add_ext(self->x509, ext->x509_extension, -1))
554 {
555 Py_DECREF(seq);
556 exception_from_error_queue();
557 return NULL;
558 }
559 }
560
561 Py_INCREF(Py_None);
562 return Py_None;
563}
564
565/*
566 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
567 * { 'name', (PyCFunction)crypto_X509_name, METH_VARARGS }
568 * for convenience
569 */
570#define ADD_METHOD(name) \
571 { #name, (PyCFunction)crypto_X509_##name, METH_VARARGS, crypto_X509_##name##_doc }
572static PyMethodDef crypto_X509_methods[] =
573{
574 ADD_METHOD(get_version),
575 ADD_METHOD(set_version),
576 ADD_METHOD(get_serial_number),
577 ADD_METHOD(set_serial_number),
578 ADD_METHOD(get_issuer),
579 ADD_METHOD(set_issuer),
580 ADD_METHOD(get_subject),
581 ADD_METHOD(set_subject),
582 ADD_METHOD(get_pubkey),
583 ADD_METHOD(set_pubkey),
584 ADD_METHOD(gmtime_adj_notBefore),
585 ADD_METHOD(gmtime_adj_notAfter),
586 ADD_METHOD(sign),
587 ADD_METHOD(has_expired),
588 ADD_METHOD(subject_name_hash),
589 ADD_METHOD(digest),
590 ADD_METHOD(add_extensions),
591 { NULL, NULL }
592};
593#undef ADD_METHOD
594
595
596/*
597 * Constructor for X509 objects, never called by Python code directly
598 *
599 * Arguments: cert - A "real" X509 certificate object
600 * dealloc - Boolean value to specify whether the destructor should
601 * free the "real" X509 object
602 * Returns: The newly created X509 object
603 */
604crypto_X509Obj *
605crypto_X509_New(X509 *cert, int dealloc)
606{
607 crypto_X509Obj *self;
608
609 self = PyObject_New(crypto_X509Obj, &crypto_X509_Type);
610
611 if (self == NULL)
612 return NULL;
613
614 self->x509 = cert;
615 self->dealloc = dealloc;
616
617 return self;
618}
619
620/*
621 * Deallocate the memory used by the X509 object
622 *
623 * Arguments: self - The X509 object
624 * Returns: None
625 */
626static void
627crypto_X509_dealloc(crypto_X509Obj *self)
628{
629 /* Sometimes we don't have to dealloc the "real" X509 pointer ourselves */
630 if (self->dealloc)
631 X509_free(self->x509);
632
633 PyObject_Del(self);
634}
635
636/*
637 * Find attribute
638 *
639 * Arguments: self - The X509 object
640 * name - The attribute name
641 * Returns: A Python object for the attribute, or NULL if something went
642 * wrong
643 */
644static PyObject *
645crypto_X509_getattr(crypto_X509Obj *self, char *name)
646{
647 return Py_FindMethod(crypto_X509_methods, (PyObject *)self, name);
648}
649
650PyTypeObject crypto_X509_Type = {
651 PyObject_HEAD_INIT(NULL)
652 0,
653 "X509",
654 sizeof(crypto_X509Obj),
655 0,
656 (destructor)crypto_X509_dealloc,
657 NULL, /* print */
658 (getattrfunc)crypto_X509_getattr,
659};
660
661/*
662 * Initialize the X509 part of the crypto sub module
663 *
664 * Arguments: dict - The crypto module dictionary
665 * Returns: None
666 */
667int
668init_crypto_x509(PyObject *dict)
669{
670 crypto_X509_Type.ob_type = &PyType_Type;
671 Py_INCREF(&crypto_X509_Type);
672 PyDict_SetItemString(dict, "X509Type", (PyObject *)&crypto_X509_Type);
673 return 1;
674}
675