blob: ab7562de9807d07a0f437c6418ed97076116bc37 [file] [log] [blame]
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05001/*
2 * pkcs12.c
3 *
4 * Copyright (C) AB Strakt 2001, All rights reserved
5 *
6 * Certificate transport (PKCS12) handling code,
7 * mostly thin wrappers around OpenSSL.
8 * See the file RATIONALE for a short explanation of why
9 * this module was written.
10 *
11 * Reviewed 2001-07-23
12 */
13#include <Python.h>
14#define crypto_MODULE
15#include "crypto.h"
16
17static char *CVSid = "@(#) $Id: pkcs12.c,v 1.3 2003/01/09 17:08:32 martin Exp $";
18
19/*
20 * PKCS12 is a standard exchange format for digital certificates.
21 * See e.g. the OpenSSL homepage http://www.openssl.org/ for more information
22 */
23
24static void crypto_PKCS12_dealloc(crypto_PKCS12Obj *self);
25
26static char crypto_PKCS12_get_certificate_doc[] = "\n\
27Return certificate portion of the PKCS12 structure\n\
28\n\
29Arguments: self - The PKCS12 object\n\
30 args - The Python argument tuple, should be empty\n\
31Returns: X509 object containing the certificate\n\
32";
33static PyObject *
34crypto_PKCS12_get_certificate(crypto_PKCS12Obj *self, PyObject *args)
35{
36 if (!PyArg_ParseTuple(args, ":get_certificate"))
37 return NULL;
38
39 Py_INCREF(self->cert);
40 return self->cert;
41}
42
43static char crypto_PKCS12_get_privatekey_doc[] = "\n\
44Return private key portion of the PKCS12 structure\n\
45\n\
46Arguments: self - The PKCS12 object\n\
47 args - The Python argument tuple, should be empty\n\
48Returns: PKey object containing the private key\n\
49";
50static PyObject *
51crypto_PKCS12_get_privatekey(crypto_PKCS12Obj *self, PyObject *args)
52{
53 if (!PyArg_ParseTuple(args, ":get_privatekey"))
54 return NULL;
55
56 Py_INCREF(self->key);
57 return self->key;
58}
59
60static char crypto_PKCS12_get_ca_certificates_doc[] = "\n\
61Return CA certificates within of the PKCS12 object\n\
62\n\
63Arguments: self - The PKCS12 object\n\
64 args - The Python argument tuple, should be empty\n\
65Returns: A newly created tuple containing the CA certificates in the chain,\n\
66 if any are present, or None if no CA certificates are present.\n\
67";
68static PyObject *
69crypto_PKCS12_get_ca_certificates(crypto_PKCS12Obj *self, PyObject *args)
70{
71 if (!PyArg_ParseTuple(args, ":get_ca_certificates"))
72 return NULL;
73
74 Py_INCREF(self->cacerts);
75 return self->cacerts;
76}
77
78/*
79 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
80 * { 'name', (PyCFunction)crypto_PKCS12_name, METH_VARARGS, crypto_PKCS12_name_doc }
81 * for convenience
82 */
83#define ADD_METHOD(name) \
84 { #name, (PyCFunction)crypto_PKCS12_##name, METH_VARARGS, crypto_PKCS12_##name##_doc }
85static PyMethodDef crypto_PKCS12_methods[] =
86{
87 ADD_METHOD(get_certificate),
88 ADD_METHOD(get_privatekey),
89 ADD_METHOD(get_ca_certificates),
90 { NULL, NULL }
91};
92#undef ADD_METHOD
93
94/*
95 * Constructor for PKCS12 objects, never called by Python code directly.
96 * The strategy for this object is to create all the Python objects
97 * corresponding to the cert/key/CA certs right away
98 *
99 * Arguments: p12 - A "real" PKCS12 object
100 * passphrase - Passphrase to use when decrypting the PKCS12 object
101 * Returns: The newly created PKCS12 object
102 */
103crypto_PKCS12Obj *
104crypto_PKCS12_New(PKCS12 *p12, char *passphrase)
105{
106 crypto_PKCS12Obj *self;
107 PyObject *cacertobj = NULL;
108
109 X509 *cert = NULL;
110 EVP_PKEY *pkey = NULL;
111 STACK_OF(X509) *cacerts = NULL;
112
113 int i, cacert_count = 0;
114
115 /* allocate space for the CA cert stack */
116 cacerts = sk_X509_new_null();
117
118 /* parse the PKCS12 lump */
119 if (!(cacerts && PKCS12_parse(p12, passphrase, &pkey, &cert, &cacerts)))
120 {
121 exception_from_error_queue();
122 return NULL;
123 }
124
125 if (!(self = PyObject_GC_New(crypto_PKCS12Obj, &crypto_PKCS12_Type)))
126 return NULL;
127
128 self->cert = NULL;
129 self->key = NULL;
130 Py_INCREF(Py_None);
131 self->cacerts = Py_None;
132
133 if ((self->cert = (PyObject *)crypto_X509_New(cert, 1)) == NULL)
134 goto error;
135
136 if ((self->key = (PyObject *)crypto_PKey_New(pkey, 1)) == NULL)
137 goto error;
138
139 /* Make a tuple for the CA certs */
140 cacert_count = sk_X509_num(cacerts);
141 if (cacert_count > 0)
142 {
143 Py_DECREF(self->cacerts);
144 if ((self->cacerts = PyTuple_New(cacert_count)) == NULL)
145 goto error;
146
147 for (i = 0; i < cacert_count; i++)
148 {
149 cert = sk_X509_value(cacerts, i);
150 if ((cacertobj = (PyObject *)crypto_X509_New(cert, 1)) == NULL)
151 goto error;
152 PyTuple_SET_ITEM(self->cacerts, i, cacertobj);
153 }
154 }
155
156 sk_X509_free(cacerts); /* don't free the certs, just the stack */
157 PyObject_GC_Track(self);
158
159 return self;
160error:
161 crypto_PKCS12_dealloc(self);
162 return NULL;
163}
164
165/*
166 * Find attribute
167 *
168 * Arguments: self - The PKCS12 object
169 * name - The attribute name
170 * Returns: A Python object for the attribute, or NULL if something went
171 * wrong
172 */
173static PyObject *
174crypto_PKCS12_getattr(crypto_PKCS12Obj *self, char *name)
175{
176 return Py_FindMethod(crypto_PKCS12_methods, (PyObject *)self, name);
177}
178
179/*
180 * Call the visitproc on all contained objects.
181 *
182 * Arguments: self - The PKCS12 object
183 * visit - Function to call
184 * arg - Extra argument to visit
185 * Returns: 0 if all goes well, otherwise the return code from the first
186 * call that gave non-zero result.
187 */
188static int
189crypto_PKCS12_traverse(crypto_PKCS12Obj *self, visitproc visit, void *arg)
190{
191 int ret = 0;
192
193 if (ret == 0 && self->cert != NULL)
194 ret = visit(self->cert, arg);
195 if (ret == 0 && self->key != NULL)
196 ret = visit(self->key, arg);
197 if (ret == 0 && self->cacerts != NULL)
198 ret = visit(self->cacerts, arg);
199 return ret;
200}
201
202/*
203 * Decref all contained objects and zero the pointers.
204 *
205 * Arguments: self - The PKCS12 object
206 * Returns: Always 0.
207 */
208static int
209crypto_PKCS12_clear(crypto_PKCS12Obj *self)
210{
211 Py_XDECREF(self->cert);
212 self->cert = NULL;
213 Py_XDECREF(self->key);
214 self->key = NULL;
215 Py_XDECREF(self->cacerts);
216 self->cacerts = NULL;
217 return 0;
218}
219
220/*
221 * Deallocate the memory used by the PKCS12 object
222 *
223 * Arguments: self - The PKCS12 object
224 * Returns: None
225 */
226static void
227crypto_PKCS12_dealloc(crypto_PKCS12Obj *self)
228{
229 PyObject_GC_UnTrack(self);
230 crypto_PKCS12_clear(self);
231 PyObject_GC_Del(self);
232}
233
234PyTypeObject crypto_PKCS12_Type = {
235 PyObject_HEAD_INIT(NULL)
236 0,
237 "PKCS12",
238 sizeof(crypto_PKCS12Obj),
239 0,
240 (destructor)crypto_PKCS12_dealloc,
241 NULL, /* print */
242 (getattrfunc)crypto_PKCS12_getattr,
243 NULL, /* setattr */
244 NULL, /* compare */
245 NULL, /* repr */
246 NULL, /* as_number */
247 NULL, /* as_sequence */
248 NULL, /* as_mapping */
249 NULL, /* hash */
250 NULL, /* call */
251 NULL, /* str */
252 NULL, /* getattro */
253 NULL, /* setattro */
254 NULL, /* as_buffer */
255 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
256 NULL, /* doc */
257 (traverseproc)crypto_PKCS12_traverse,
258 (inquiry)crypto_PKCS12_clear,
259};
260
261/*
262 * Initialize the PKCS12 part of the crypto sub module
263 *
264 * Arguments: dict - The crypto module dictionary
265 * Returns: None
266 */
267int
268init_crypto_pkcs12(PyObject *dict)
269{
270 crypto_PKCS12_Type.ob_type = &PyType_Type;
271 Py_INCREF(&crypto_PKCS12_Type);
272 PyDict_SetItemString(dict, "PKCS12Type", (PyObject *)&crypto_PKCS12_Type);
273 return 1;
274}
275