blob: 995a079916014d44e4b33e442b1570cd07b442ef [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
Jean-Paul Calderone2f6c66f2010-08-11 19:53:43 -040028 return PyLong_FromLong(X509_EXTENSION_get_critical(self->x509_extension));
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050029}
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));
Jean-Paul Calderone2f6c66f2010-08-11 19:53:43 -040050 return PyBytes_FromString(extname);
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -050051}
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 - ???
Jean-Paul Calderonee04be5f2009-07-17 15:09:48 -040075 * subject - An x509v3 certificate which is the subject for this extension.
76 * issuer - An x509v3 certificate which is the issuer for this extension.
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050077 * Returns: The newly created X509Extension object
78 */
79crypto_X509ExtensionObj *
Jean-Paul Calderone5ae32fb2009-07-17 15:03:31 -040080crypto_X509Extension_New(char *type_name, int critical, char *value,
Jean-Paul Calderonee04be5f2009-07-17 15:09:48 -040081 crypto_X509Obj *subject, crypto_X509Obj *issuer) {
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -050082 X509V3_CTX ctx;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050083 crypto_X509ExtensionObj *self;
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -050084 char* value_with_critical = NULL;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050085
Jean-Paul Calderonee04be5f2009-07-17 15:09:48 -040086
Jean-Paul Calderone5ae32fb2009-07-17 15:03:31 -040087 /*
Jean-Paul Calderonee04be5f2009-07-17 15:09:48 -040088 * A context is necessary for any extension which uses the r2i conversion
89 * method. That is, X509V3_EXT_nconf may segfault if passed a NULL ctx.
90 * Start off by initializing most of the fields to NULL.
Jean-Paul Calderone5ae32fb2009-07-17 15:03:31 -040091 */
92 X509V3_set_ctx(&ctx, NULL, NULL, NULL, NULL, 0);
93
Jean-Paul Calderonee04be5f2009-07-17 15:09:48 -040094 /*
95 * We have no configuration database - but perhaps we should (some
96 * extensions may require it).
Jean-Paul Calderone5ae32fb2009-07-17 15:03:31 -040097 */
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -050098 X509V3_set_ctx_nodb(&ctx);
99
Jean-Paul Calderone5ae32fb2009-07-17 15:03:31 -0400100 /*
101 * Initialize the subject and issuer, if appropriate. ctx is a local, and
102 * as far as I can tell none of the X509V3_* APIs invoked here steal any
103 * references, so no need to incref subject or issuer.
104 */
105 if (subject) {
Rick Dean47262da2009-07-08 16:17:17 -0500106 ctx.subject_cert = subject->x509;
Jean-Paul Calderone5ae32fb2009-07-17 15:03:31 -0400107 }
108
109 if (issuer) {
Rick Dean47262da2009-07-08 16:17:17 -0500110 ctx.issuer_cert = issuer->x509;
Jean-Paul Calderone5ae32fb2009-07-17 15:03:31 -0400111 }
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500112
113 self = PyObject_New(crypto_X509ExtensionObj, &crypto_X509Extension_Type);
114
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500115 if (self == NULL) {
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500116 goto error;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500117 }
118
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500119 self->dealloc = 0;
120
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500121 /* There are other OpenSSL APIs which would let us pass in critical
122 * separately, but they're harder to use, and since value is already a pile
123 * of crappy junk smuggling a ton of utterly important structured data,
124 * what's the point of trying to avoid nasty stuff with strings? (However,
125 * X509V3_EXT_i2d in particular seems like it would be a better API to
126 * invoke. I do not know where to get the ext_struc it desires for its
127 * last parameter, though.) */
128 value_with_critical = malloc(strlen("critical,") + strlen(value) + 1);
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500129 if (!value_with_critical) {
130 goto critical_malloc_error;
131 }
132
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500133 if (critical) {
134 strcpy(value_with_critical, "critical,");
135 strcpy(value_with_critical + strlen("critical,"), value);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500136 } else {
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500137 strcpy(value_with_critical, value);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500138 }
139
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500140 self->x509_extension = X509V3_EXT_nconf(
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500141 NULL, &ctx, type_name, value_with_critical);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500142
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500143 free(value_with_critical);
144
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500145 if (!self->x509_extension) {
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500146 goto nconf_error;
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500147 }
148
149 self->dealloc = 1;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500150 return self;
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500151
152 nconf_error:
Rick Deand369c932009-07-08 11:48:33 -0500153 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500154
155 critical_malloc_error:
Jean-Paul Calderonea96bfed2009-05-27 08:47:34 -0400156 Py_XDECREF(self);
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500157
158 error:
159 return NULL;
160
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500161}
162
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400163static char crypto_X509Extension_doc[] = "\n\
Rick Dean47262da2009-07-08 16:17:17 -0500164X509Extension(typename, critical, value[, subject][, issuer]) -> \n\
165 X509Extension instance\n\
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400166\n\
167@param typename: The name of the extension to create.\n\
168@type typename: C{str}\n\
169@param critical: A flag indicating whether this is a critical extension.\n\
170@param value: The value of the extension.\n\
171@type value: C{str}\n\
Rick Dean47262da2009-07-08 16:17:17 -0500172@param subject: Optional X509 cert to use as subject.\n\
173@type subject: C{X509}\n\
174@param issuer: Optional X509 cert to use as issuer.\n\
175@type issuer: C{X509}\n\
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400176@return: The X509Extension object\n\
177";
178
179static PyObject *
Jean-Paul Calderonee04be5f2009-07-17 15:09:48 -0400180crypto_X509Extension_new(PyTypeObject *subtype, PyObject *args,
Rick Dean47262da2009-07-08 16:17:17 -0500181 PyObject *kwargs) {
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400182 char *type_name, *value;
Rick Dean47262da2009-07-08 16:17:17 -0500183 int critical = 0;
184 crypto_X509Obj * subject = NULL;
185 crypto_X509Obj * issuer = NULL;
Jean-Paul Calderonee04be5f2009-07-17 15:09:48 -0400186 static char *kwlist[] = {"type_name", "critical", "value", "subject",
Rick Dean47262da2009-07-08 16:17:17 -0500187 "issuer", NULL};
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400188
Jean-Paul Calderonee04be5f2009-07-17 15:09:48 -0400189 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sis|O!O!:X509Extension",
190 kwlist, &type_name, &critical, &value,
191 &crypto_X509_Type, &subject,
192 &crypto_X509_Type, &issuer )) {
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400193 return NULL;
194 }
195
Rick Dean47262da2009-07-08 16:17:17 -0500196 return (PyObject *)crypto_X509Extension_New(type_name, critical, value,
197 subject, issuer);
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400198}
199
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500200/*
201 * Deallocate the memory used by the X509Extension object
202 *
203 * Arguments: self - The X509Extension object
204 * Returns: None
205 */
206static void
207crypto_X509Extension_dealloc(crypto_X509ExtensionObj *self)
208{
209 /* Sometimes we don't have to dealloc this */
210 if (self->dealloc)
211 X509_EXTENSION_free(self->x509_extension);
212
213 PyObject_Del(self);
214}
215
216/*
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500217 * Print a nice text representation of the certificate request.
218 */
219static PyObject *
220crypto_X509Extension_str(crypto_X509ExtensionObj *self)
221{
222 int str_len;
223 char *tmp_str;
224 PyObject *str;
225 BIO *bio = BIO_new(BIO_s_mem());
226
227 if (!X509V3_EXT_print(bio, self->x509_extension, 0, 0))
228 {
229 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500230 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500231 return NULL;
232 }
233
234 str_len = BIO_get_mem_data(bio, &tmp_str);
Jean-Paul Calderone2f6c66f2010-08-11 19:53:43 -0400235 str = PyText_FromStringAndSize(tmp_str, str_len);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500236
237 BIO_free(bio);
238
239 return str;
240}
241
242PyTypeObject crypto_X509Extension_Type = {
Jean-Paul Calderone2f6c66f2010-08-11 19:53:43 -0400243 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500244 "X509Extension",
245 sizeof(crypto_X509ExtensionObj),
246 0,
247 (destructor)crypto_X509Extension_dealloc,
248 NULL, /* print */
Jean-Paul Calderone2f6c66f2010-08-11 19:53:43 -0400249 NULL, /* getattr */
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500250 NULL, /* setattr (setattrfunc)crypto_X509Name_setattr, */
251 NULL, /* compare */
252 NULL, /* repr */
253 NULL, /* as_number */
254 NULL, /* as_sequence */
255 NULL, /* as_mapping */
256 NULL, /* hash */
257 NULL, /* call */
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400258 (reprfunc)crypto_X509Extension_str, /* str */
259 NULL, /* getattro */
260 NULL, /* setattro */
261 NULL, /* as_buffer */
262 Py_TPFLAGS_DEFAULT,
263 crypto_X509Extension_doc, /* doc */
264 NULL, /* traverse */
265 NULL, /* clear */
266 NULL, /* tp_richcompare */
267 0, /* tp_weaklistoffset */
268 NULL, /* tp_iter */
269 NULL, /* tp_iternext */
270 crypto_X509Extension_methods, /* tp_methods */
271 NULL, /* tp_members */
272 NULL, /* tp_getset */
273 NULL, /* tp_base */
274 NULL, /* tp_dict */
275 NULL, /* tp_descr_get */
276 NULL, /* tp_descr_set */
277 0, /* tp_dictoffset */
278 NULL, /* tp_init */
279 NULL, /* tp_alloc */
280 crypto_X509Extension_new, /* tp_new */
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500281};
282
283/*
284 * Initialize the X509Extension part of the crypto module
285 *
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400286 * Arguments: dict - The crypto module
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500287 * Returns: None
288 */
289int
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400290init_crypto_x509extension(PyObject *module)
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500291{
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400292 if (PyType_Ready(&crypto_X509Extension_Type) < 0) {
293 return 0;
294 }
295
296 if (PyModule_AddObject(module, "X509Extension",
297 (PyObject *)&crypto_X509Extension_Type) != 0) {
298 return 0;
299 }
300
301 if (PyModule_AddObject(module, "X509ExtensionType",
302 (PyObject *)&crypto_X509Extension_Type) != 0) {
303 return 0;
304 }
305
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500306 return 1;
307}