blob: 13a4c71b6617ef11df3a1f58c52060a536054fa2 [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;
74
75 if (!PyArg_ParseTuple(args, ":get_serial_number"))
76 return NULL;
77
78 asn1_i = X509_get_serialNumber(self->x509);
79 return PyInt_FromLong(ASN1_INTEGER_get(asn1_i));
80}
81
82static char crypto_X509_set_serial_number_doc[] = "\n\
83Set serial number of the certificate\n\
84\n\
85Arguments: self - The X509 object\n\
86 args - The Python argument tuple, should be:\n\
87 serial - The serial number\n\
88Returns: None\n\
89";
90
91static PyObject *
92crypto_X509_set_serial_number(crypto_X509Obj *self, PyObject *args)
93{
94 long serial;
95
96 if (!PyArg_ParseTuple(args, "l:set_serial_number", &serial))
97 return NULL;
98
99 ASN1_INTEGER_set(X509_get_serialNumber(self->x509), serial);
100
101 Py_INCREF(Py_None);
102 return Py_None;
103}
104
105static char crypto_X509_get_issuer_doc[] = "\n\
106Create an X509Name object for the issuer of the certificate\n\
107\n\
108Arguments: self - The X509 object\n\
109 args - The Python argument tuple, should be empty\n\
110Returns: An X509Name object\n\
111";
112
113static PyObject *
114crypto_X509_get_issuer(crypto_X509Obj *self, PyObject *args)
115{
116 crypto_X509NameObj *pyname;
117 X509_NAME *name;
118
119 if (!PyArg_ParseTuple(args, ":get_issuer"))
120 return NULL;
121
122 name = X509_get_issuer_name(self->x509);
123 pyname = crypto_X509Name_New(name, 0);
124 if (pyname != NULL)
125 {
126 pyname->parent_cert = (PyObject *)self;
127 Py_INCREF(self);
128 }
129 return (PyObject *)pyname;
130}
131
132static char crypto_X509_set_issuer_doc[] = "\n\
133Set the issuer of the certificate\n\
134\n\
135Arguments: self - The X509 object\n\
136 args - The Python argument tuple, should be:\n\
137 issuer - The issuer name\n\
138Returns: None\n\
139";
140
141static PyObject *
142crypto_X509_set_issuer(crypto_X509Obj *self, PyObject *args)
143{
144 crypto_X509NameObj *issuer;
145
146 if (!PyArg_ParseTuple(args, "O!:set_issuer", &crypto_X509Name_Type,
147 &issuer))
148 return NULL;
149
150 if (!X509_set_issuer_name(self->x509, issuer->x509_name))
151 {
152 exception_from_error_queue();
153 return NULL;
154 }
155
156 Py_INCREF(Py_None);
157 return Py_None;
158}
159
160static char crypto_X509_get_subject_doc[] = "\n\
161Create an X509Name object for the subject of the certificate\n\
162\n\
163Arguments: self - The X509 object\n\
164 args - The Python argument tuple, should be empty\n\
165Returns: An X509Name object\n\
166";
167
168static PyObject *
169crypto_X509_get_subject(crypto_X509Obj *self, PyObject *args)
170{
171 crypto_X509NameObj *pyname;
172 X509_NAME *name;
173
174 if (!PyArg_ParseTuple(args, ":get_subject"))
175 return NULL;
176
177 name = X509_get_subject_name(self->x509);
178 pyname = crypto_X509Name_New(name, 0);
179 if (pyname != NULL)
180 {
181 pyname->parent_cert = (PyObject *)self;
182 Py_INCREF(self);
183 }
184 return (PyObject *)pyname;
185}
186
187static char crypto_X509_set_subject_doc[] = "\n\
188Set the subject of the certificate\n\
189\n\
190Arguments: self - The X509 object\n\
191 args - The Python argument tuple, should be:\n\
192 subject - The subject name\n\
193Returns: None\n\
194";
195
196static PyObject *
197crypto_X509_set_subject(crypto_X509Obj *self, PyObject *args)
198{
199 crypto_X509NameObj *subject;
200
201 if (!PyArg_ParseTuple(args, "O!:set_subject", &crypto_X509Name_Type,
202 &subject))
203 return NULL;
204
205 if (!X509_set_subject_name(self->x509, subject->x509_name))
206 {
207 exception_from_error_queue();
208 return NULL;
209 }
210
211 Py_INCREF(Py_None);
212 return Py_None;
213}
214
215static char crypto_X509_get_pubkey_doc[] = "\n\
216Get the public key of the certificate\n\
217\n\
218Arguments: self - The X509 object\n\
219 args - The Python argument tuple, should be empty\n\
220Returns: The public key\n\
221";
222
223static PyObject *
224crypto_X509_get_pubkey(crypto_X509Obj *self, PyObject *args)
225{
226 crypto_PKeyObj *crypto_PKey_New(EVP_PKEY *, int);
227 EVP_PKEY *pkey;
228
229 if (!PyArg_ParseTuple(args, ":get_pubkey"))
230 return NULL;
231
232 if ((pkey = X509_get_pubkey(self->x509)) == NULL)
233 {
234 exception_from_error_queue();
235 return NULL;
236 }
237
Jean-Paul Calderone19555b92008-02-19 22:29:57 -0500238 return (PyObject *)crypto_PKey_New(pkey, 1);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500239}
240
241static char crypto_X509_set_pubkey_doc[] = "\n\
242Set the public key of the certificate\n\
243\n\
244Arguments: self - The X509 object\n\
245 args - The Python argument tuple, should be:\n\
246 pkey - The public key\n\
247Returns: None\n\
248";
249
250static PyObject *
251crypto_X509_set_pubkey(crypto_X509Obj *self, PyObject *args)
252{
253 crypto_PKeyObj *pkey;
254
255 if (!PyArg_ParseTuple(args, "O!:set_pubkey", &crypto_PKey_Type, &pkey))
256 return NULL;
257
258 if (!X509_set_pubkey(self->x509, pkey->pkey))
259 {
260 exception_from_error_queue();
261 return NULL;
262 }
263
264 Py_INCREF(Py_None);
265 return Py_None;
266}
267
268static char crypto_X509_gmtime_adj_notBefore_doc[] = "\n\
269Adjust the time stamp for when the certificate starts being valid\n\
270\n\
271Arguments: self - The X509 object\n\
272 args - The Python argument tuple, should be:\n\
273 i - The adjustment\n\
274Returns: None\n\
275";
276
277static PyObject *
278crypto_X509_gmtime_adj_notBefore(crypto_X509Obj *self, PyObject *args)
279{
280 long i;
281
282 if (!PyArg_ParseTuple(args, "l:gmtime_adj_notBefore", &i))
283 return NULL;
284
285 X509_gmtime_adj(X509_get_notBefore(self->x509), i);
286
287 Py_INCREF(Py_None);
288 return Py_None;
289}
290
291static char crypto_X509_gmtime_adj_notAfter_doc[] = "\n\
292Adjust the time stamp for when the certificate stops being valid\n\
293\n\
294Arguments: self - The X509 object\n\
295 args - The Python argument tuple, should be:\n\
296 i - The adjustment\n\
297Returns: None\n\
298";
299
300static PyObject *
301crypto_X509_gmtime_adj_notAfter(crypto_X509Obj *self, PyObject *args)
302{
303 long i;
304
305 if (!PyArg_ParseTuple(args, "l:gmtime_adj_notAfter", &i))
306 return NULL;
307
308 X509_gmtime_adj(X509_get_notAfter(self->x509), i);
309
310 Py_INCREF(Py_None);
311 return Py_None;
312}
313
314static char crypto_X509_sign_doc[] = "\n\
315Sign the certificate using the supplied key and digest\n\
316\n\
317Arguments: self - The X509 object\n\
318 args - The Python argument tuple, should be:\n\
319 pkey - The key to sign with\n\
320 digest - The message digest to use\n\
321Returns: None\n\
322";
323
324static PyObject *
325crypto_X509_sign(crypto_X509Obj *self, PyObject *args)
326{
327 crypto_PKeyObj *pkey;
328 char *digest_name;
329 const EVP_MD *digest;
330
331 if (!PyArg_ParseTuple(args, "O!s:sign", &crypto_PKey_Type, &pkey,
332 &digest_name))
333 return NULL;
334
335 if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
336 {
337 PyErr_SetString(PyExc_ValueError, "No such digest method");
338 return NULL;
339 }
340
341 if (!X509_sign(self->x509, pkey->pkey, digest))
342 {
343 exception_from_error_queue();
344 return NULL;
345 }
346
347 Py_INCREF(Py_None);
348 return Py_None;
349}
350
351static char crypto_X509_has_expired_doc[] = "\n\
352Check whether the certificate has expired.\n\
353\n\
354Arguments: self - The X509 object\n\
355 args - The Python argument tuple, should be empty\n\
356Returns: True if the certificate has expired, false otherwise\n\
357";
358
359static PyObject *
360crypto_X509_has_expired(crypto_X509Obj *self, PyObject *args)
361{
362 time_t tnow;
363
364 if (!PyArg_ParseTuple(args, ":has_expired"))
365 return NULL;
366
367 tnow = time(NULL);
368 if (ASN1_UTCTIME_cmp_time_t(X509_get_notAfter(self->x509), tnow) < 0)
369 return PyInt_FromLong(1L);
370 else
371 return PyInt_FromLong(0L);
372}
373
374static char crypto_X509_subject_name_hash_doc[] = "\n\
375Return the hash of the X509 subject.\n\
376\n\
377Arguments: self - The X509 object\n\
378 args - The Python argument tuple, should be empty\n\
379Returns: The hash of the subject\n\
380";
381
382static PyObject *
383crypto_X509_subject_name_hash(crypto_X509Obj *self, PyObject *args)
384{
385 if (!PyArg_ParseTuple(args, ":subject_name_hash"))
386 return NULL;
387
388 return PyLong_FromLong(X509_subject_name_hash(self->x509));
389}
390
391static char crypto_X509_digest_doc[] = "\n\
392Return the digest of the X509 object.\n\
393\n\
394Arguments: self - The X509 object\n\
395 args - The Python argument tuple, should be empty\n\
396Returns: The digest of the object\n\
397";
398
399static PyObject *
400crypto_X509_digest(crypto_X509Obj *self, PyObject *args)
401{
402 unsigned char fp[EVP_MAX_MD_SIZE];
403 char *tmp;
404 char *digest_name;
405 int len,i;
406 PyObject *ret;
407 const EVP_MD *digest;
408
409 if (!PyArg_ParseTuple(args, "s:digest", &digest_name))
410 return NULL;
411
412 if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
413 {
414 PyErr_SetString(PyExc_ValueError, "No such digest method");
415 return NULL;
416 }
417
418 if (!X509_digest(self->x509,digest,fp,&len))
419 {
420 exception_from_error_queue();
421 }
422 tmp = malloc(3*len+1);
423 memset(tmp, 0, 3*len+1);
424 for (i = 0; i < len; i++) {
425 sprintf(tmp+i*3,"%02X:",fp[i]);
426 }
427 tmp[3*len-1] = 0;
428 ret = PyString_FromStringAndSize(tmp,3*len-1);
429 free(tmp);
430 return ret;
431}
432
433
434static char crypto_X509_add_extensions_doc[] = "\n\
435Add extensions to the certificate.\n\
436\n\
437Arguments: self - X509 object\n\
438 args - The Python argument tuple, should be:\n\
439 extensions - a sequence of X509Extension objects\n\
440Returns: None\n\
441";
442
443static PyObject *
444crypto_X509_add_extensions(crypto_X509Obj *self, PyObject *args)
445{
446 PyObject *extensions, *seq;
447 crypto_X509ExtensionObj *ext;
448 int nr_of_extensions, i;
449
450 if (!PyArg_ParseTuple(args, "O:add_extensions", &extensions))
451 return NULL;
452
453 seq = PySequence_Fast(extensions, "Expected a sequence");
454 if (seq == NULL)
455 return NULL;
456
457 nr_of_extensions = PySequence_Fast_GET_SIZE(seq);
458
459 for (i = 0; i < nr_of_extensions; i++)
460 {
461 ext = (crypto_X509ExtensionObj *)PySequence_Fast_GET_ITEM(seq, i);
462 if (!crypto_X509Extension_Check(ext))
463 {
464 Py_DECREF(seq);
465 PyErr_SetString(PyExc_ValueError,
466 "One of the elements is not an X509Extension");
467 return NULL;
468 }
469 if (!X509_add_ext(self->x509, ext->x509_extension, -1))
470 {
471 Py_DECREF(seq);
472 exception_from_error_queue();
473 return NULL;
474 }
475 }
476
477 Py_INCREF(Py_None);
478 return Py_None;
479}
480
481/*
482 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
483 * { 'name', (PyCFunction)crypto_X509_name, METH_VARARGS }
484 * for convenience
485 */
486#define ADD_METHOD(name) \
487 { #name, (PyCFunction)crypto_X509_##name, METH_VARARGS, crypto_X509_##name##_doc }
488static PyMethodDef crypto_X509_methods[] =
489{
490 ADD_METHOD(get_version),
491 ADD_METHOD(set_version),
492 ADD_METHOD(get_serial_number),
493 ADD_METHOD(set_serial_number),
494 ADD_METHOD(get_issuer),
495 ADD_METHOD(set_issuer),
496 ADD_METHOD(get_subject),
497 ADD_METHOD(set_subject),
498 ADD_METHOD(get_pubkey),
499 ADD_METHOD(set_pubkey),
500 ADD_METHOD(gmtime_adj_notBefore),
501 ADD_METHOD(gmtime_adj_notAfter),
502 ADD_METHOD(sign),
503 ADD_METHOD(has_expired),
504 ADD_METHOD(subject_name_hash),
505 ADD_METHOD(digest),
506 ADD_METHOD(add_extensions),
507 { NULL, NULL }
508};
509#undef ADD_METHOD
510
511
512/*
513 * Constructor for X509 objects, never called by Python code directly
514 *
515 * Arguments: cert - A "real" X509 certificate object
516 * dealloc - Boolean value to specify whether the destructor should
517 * free the "real" X509 object
518 * Returns: The newly created X509 object
519 */
520crypto_X509Obj *
521crypto_X509_New(X509 *cert, int dealloc)
522{
523 crypto_X509Obj *self;
524
525 self = PyObject_New(crypto_X509Obj, &crypto_X509_Type);
526
527 if (self == NULL)
528 return NULL;
529
530 self->x509 = cert;
531 self->dealloc = dealloc;
532
533 return self;
534}
535
536/*
537 * Deallocate the memory used by the X509 object
538 *
539 * Arguments: self - The X509 object
540 * Returns: None
541 */
542static void
543crypto_X509_dealloc(crypto_X509Obj *self)
544{
545 /* Sometimes we don't have to dealloc the "real" X509 pointer ourselves */
546 if (self->dealloc)
547 X509_free(self->x509);
548
549 PyObject_Del(self);
550}
551
552/*
553 * Find attribute
554 *
555 * Arguments: self - The X509 object
556 * name - The attribute name
557 * Returns: A Python object for the attribute, or NULL if something went
558 * wrong
559 */
560static PyObject *
561crypto_X509_getattr(crypto_X509Obj *self, char *name)
562{
563 return Py_FindMethod(crypto_X509_methods, (PyObject *)self, name);
564}
565
566PyTypeObject crypto_X509_Type = {
567 PyObject_HEAD_INIT(NULL)
568 0,
569 "X509",
570 sizeof(crypto_X509Obj),
571 0,
572 (destructor)crypto_X509_dealloc,
573 NULL, /* print */
574 (getattrfunc)crypto_X509_getattr,
575};
576
577/*
578 * Initialize the X509 part of the crypto sub module
579 *
580 * Arguments: dict - The crypto module dictionary
581 * Returns: None
582 */
583int
584init_crypto_x509(PyObject *dict)
585{
586 crypto_X509_Type.ob_type = &PyType_Type;
587 Py_INCREF(&crypto_X509_Type);
588 PyDict_SetItemString(dict, "X509Type", (PyObject *)&crypto_X509_Type);
589 return 1;
590}
591