blob: cd169d2d628b7477f395cb83db1dd4202ddc3743 [file] [log] [blame]
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05001/*
2 * x509ext.c
3 *
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04004 * Copyright (C) Jean-Paul Calderone 2008, All rights reserved
5 *
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05006 * Export X.509 extension functions and data structures.
7 * See the file RATIONALE for a short explanation of why this module was written.
8 *
9 * @(#) $Id: x509ext.c,v 1.1 2002/07/09 13:34:46 martin Exp $
10 */
11
12#include <Python.h>
13#define crypto_MODULE
14#include "crypto.h"
15
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050016static char crypto_X509Extension_get_critical_doc[] = "\n\
17Returns the critical field of the X509Extension\n\
18\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040019@return: The critical field.\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050020";
21
22static PyObject *
23crypto_X509Extension_get_critical(crypto_X509ExtensionObj *self, PyObject *args)
24{
25 if (!PyArg_ParseTuple(args, ":get_critical"))
26 return NULL;
27
28 return PyInt_FromLong(X509_EXTENSION_get_critical(self->x509_extension));
29}
30
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -050031static char crypto_X509Extension_get_short_name_doc[] = "\n\
32Returns the short version of the type name of the X509Extension\n\
33\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040034@return: The short type name.\n\
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -050035";
36
37static PyObject *
38crypto_X509Extension_get_short_name(crypto_X509ExtensionObj *self, PyObject *args) {
39 ASN1_OBJECT *obj;
40 const char *extname;
41
42 if (!PyArg_ParseTuple(args, ":get_short_name")) {
43 return NULL;
44 }
45
46 /* Returns an internal pointer to x509_extension, not a copy */
47 obj = X509_EXTENSION_get_object(self->x509_extension);
48
49 extname = OBJ_nid2sn(OBJ_obj2nid(obj));
50 return PyString_FromString(extname);
51}
52
53
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050054/*
55 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
56 * { 'name', (PyCFunction)crypto_X509Extension_name, METH_VARARGS }
57 * for convenience
58 */
59#define ADD_METHOD(name) \
60{ #name, (PyCFunction)crypto_X509Extension_##name, METH_VARARGS, crypto_X509Extension_##name##_doc }
61static PyMethodDef crypto_X509Extension_methods[] =
62{
63 ADD_METHOD(get_critical),
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -050064 ADD_METHOD(get_short_name),
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050065 { NULL, NULL }
66};
67#undef ADD_METHOD
68
69/*
70 * Constructor for X509Extension, never called by Python code directly
71 *
72 * Arguments: type_name - ???
73 * critical - ???
74 * value - ???
75 * Returns: The newly created X509Extension object
76 */
77crypto_X509ExtensionObj *
78crypto_X509Extension_New(char *type_name, int critical, char *value)
79{
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -050080 X509V3_CTX ctx;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050081 crypto_X509ExtensionObj *self;
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -050082 char* value_with_critical = NULL;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050083
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -050084 /* We have no configuration database - but perhaps we should. Anyhow, the
85 * context is necessary for any extension which uses the r2i conversion
86 * method. That is, X509V3_EXT_nconf may segfault if passed a NULL ctx. */
87 X509V3_set_ctx_nodb(&ctx);
88
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050089 self = PyObject_New(crypto_X509ExtensionObj, &crypto_X509Extension_Type);
90
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -050091 if (self == NULL) {
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -050092 goto error;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050093 }
94
Jean-Paul Calderone391585f2008-12-31 14:36:31 -050095 self->dealloc = 0;
96
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -050097 /* There are other OpenSSL APIs which would let us pass in critical
98 * separately, but they're harder to use, and since value is already a pile
99 * of crappy junk smuggling a ton of utterly important structured data,
100 * what's the point of trying to avoid nasty stuff with strings? (However,
101 * X509V3_EXT_i2d in particular seems like it would be a better API to
102 * invoke. I do not know where to get the ext_struc it desires for its
103 * last parameter, though.) */
104 value_with_critical = malloc(strlen("critical,") + strlen(value) + 1);
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500105 if (!value_with_critical) {
106 goto critical_malloc_error;
107 }
108
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500109 if (critical) {
110 strcpy(value_with_critical, "critical,");
111 strcpy(value_with_critical + strlen("critical,"), value);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500112 } else {
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500113 strcpy(value_with_critical, value);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500114 }
115
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500116 self->x509_extension = X509V3_EXT_nconf(
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500117 NULL, &ctx, type_name, value_with_critical);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500118
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500119 free(value_with_critical);
120
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500121 if (!self->x509_extension) {
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500122 goto nconf_error;
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500123 }
124
125 self->dealloc = 1;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500126 return self;
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500127
128 nconf_error:
129 exception_from_error_queue();
130
131 critical_malloc_error:
Jean-Paul Calderonea96bfed2009-05-27 08:47:34 -0400132 Py_XDECREF(self);
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500133
134 error:
135 return NULL;
136
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500137}
138
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400139static char crypto_X509Extension_doc[] = "\n\
140X509Extension(typename, critical, value) -> X509Extension instance\n\
141\n\
142@param typename: The name of the extension to create.\n\
143@type typename: C{str}\n\
144@param critical: A flag indicating whether this is a critical extension.\n\
145@param value: The value of the extension.\n\
146@type value: C{str}\n\
147@return: The X509Extension object\n\
148";
149
150static PyObject *
151crypto_X509Extension_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs) {
152 char *type_name, *value;
153 int critical;
154
155 if (!PyArg_ParseTuple(args, "sis:X509Extension", &type_name, &critical,
156 &value)) {
157 return NULL;
158 }
159
160 return (PyObject *)crypto_X509Extension_New(type_name, critical, value);
161}
162
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500163/*
164 * Deallocate the memory used by the X509Extension object
165 *
166 * Arguments: self - The X509Extension object
167 * Returns: None
168 */
169static void
170crypto_X509Extension_dealloc(crypto_X509ExtensionObj *self)
171{
172 /* Sometimes we don't have to dealloc this */
173 if (self->dealloc)
174 X509_EXTENSION_free(self->x509_extension);
175
176 PyObject_Del(self);
177}
178
179/*
180 * Find attribute
181 *
182 * Arguments: self - The X509Extension object
183 * name - The attribute name
184 * Returns: A Python object for the attribute, or NULL if something
185 * went wrong.
186 */
187static PyObject *
188crypto_X509Extension_getattr(crypto_X509ExtensionObj *self, char *name)
189{
190 return Py_FindMethod(crypto_X509Extension_methods, (PyObject *)self, name);
191}
192
193/*
194 * Print a nice text representation of the certificate request.
195 */
196static PyObject *
197crypto_X509Extension_str(crypto_X509ExtensionObj *self)
198{
199 int str_len;
200 char *tmp_str;
201 PyObject *str;
202 BIO *bio = BIO_new(BIO_s_mem());
203
204 if (!X509V3_EXT_print(bio, self->x509_extension, 0, 0))
205 {
206 BIO_free(bio);
207 exception_from_error_queue();
208 return NULL;
209 }
210
211 str_len = BIO_get_mem_data(bio, &tmp_str);
212 str = PyString_FromStringAndSize(tmp_str, str_len);
213
214 BIO_free(bio);
215
216 return str;
217}
218
219PyTypeObject crypto_X509Extension_Type = {
220 PyObject_HEAD_INIT(NULL)
221 0,
222 "X509Extension",
223 sizeof(crypto_X509ExtensionObj),
224 0,
225 (destructor)crypto_X509Extension_dealloc,
226 NULL, /* print */
227 (getattrfunc)crypto_X509Extension_getattr,
228 NULL, /* setattr (setattrfunc)crypto_X509Name_setattr, */
229 NULL, /* compare */
230 NULL, /* repr */
231 NULL, /* as_number */
232 NULL, /* as_sequence */
233 NULL, /* as_mapping */
234 NULL, /* hash */
235 NULL, /* call */
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400236 (reprfunc)crypto_X509Extension_str, /* str */
237 NULL, /* getattro */
238 NULL, /* setattro */
239 NULL, /* as_buffer */
240 Py_TPFLAGS_DEFAULT,
241 crypto_X509Extension_doc, /* doc */
242 NULL, /* traverse */
243 NULL, /* clear */
244 NULL, /* tp_richcompare */
245 0, /* tp_weaklistoffset */
246 NULL, /* tp_iter */
247 NULL, /* tp_iternext */
248 crypto_X509Extension_methods, /* tp_methods */
249 NULL, /* tp_members */
250 NULL, /* tp_getset */
251 NULL, /* tp_base */
252 NULL, /* tp_dict */
253 NULL, /* tp_descr_get */
254 NULL, /* tp_descr_set */
255 0, /* tp_dictoffset */
256 NULL, /* tp_init */
257 NULL, /* tp_alloc */
258 crypto_X509Extension_new, /* tp_new */
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500259};
260
261/*
262 * Initialize the X509Extension part of the crypto module
263 *
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400264 * Arguments: dict - The crypto module
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500265 * Returns: None
266 */
267int
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400268init_crypto_x509extension(PyObject *module)
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500269{
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400270 if (PyType_Ready(&crypto_X509Extension_Type) < 0) {
271 return 0;
272 }
273
274 if (PyModule_AddObject(module, "X509Extension",
275 (PyObject *)&crypto_X509Extension_Type) != 0) {
276 return 0;
277 }
278
279 if (PyModule_AddObject(module, "X509ExtensionType",
280 (PyObject *)&crypto_X509Extension_Type) != 0) {
281 return 0;
282 }
283
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500284 return 1;
285}