blob: f65fd0f8e38dc7586538e9569c8cdd08095461fc [file] [log] [blame]
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05001/*
2 * x509ext.c
3 *
Jean-Paul Calderone97d1fd92011-03-02 19:28:52 -05004 * Copyright (C) Jean-Paul Calderone
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05005 * See LICENSE for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04006 *
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05007 * Export X.509 extension functions and data structures.
8 * See the file RATIONALE for a short explanation of why this module was written.
9 *
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050010 */
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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +090019: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +090034: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 Calderone5a9e4612011-04-01 18:27:45 -040054static char crypto_X509Extension_get_data_doc[] = "\n\
55Returns the data of the X509Extension\n\
56\n\
Jonathan Ballet648875f2011-07-16 14:14:58 +090057:return: A :py:data:`str` giving the X509Extension's ASN.1 encoded data.\n\
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -040058";
59
60static PyObject *
61crypto_X509Extension_get_data(crypto_X509ExtensionObj *self, PyObject *args) {
62 ASN1_OCTET_STRING *data;
63 PyObject *result;
64
65 if (!PyArg_ParseTuple(args, ":get_data")) {
66 return NULL;
67 }
68
69 data = X509_EXTENSION_get_data(self->x509_extension);
70 result = PyBytes_FromStringAndSize((const char*)data->data, data->length);
71 return result;
72}
73
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050074/*
75 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
76 * { 'name', (PyCFunction)crypto_X509Extension_name, METH_VARARGS }
77 * for convenience
78 */
79#define ADD_METHOD(name) \
80{ #name, (PyCFunction)crypto_X509Extension_##name, METH_VARARGS, crypto_X509Extension_##name##_doc }
81static PyMethodDef crypto_X509Extension_methods[] =
82{
83 ADD_METHOD(get_critical),
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -050084 ADD_METHOD(get_short_name),
Jean-Paul Calderone5a9e4612011-04-01 18:27:45 -040085 ADD_METHOD(get_data),
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050086 { NULL, NULL }
87};
88#undef ADD_METHOD
89
90/*
91 * Constructor for X509Extension, never called by Python code directly
92 *
93 * Arguments: type_name - ???
94 * critical - ???
95 * value - ???
Jean-Paul Calderonee04be5f2009-07-17 15:09:48 -040096 * subject - An x509v3 certificate which is the subject for this extension.
97 * issuer - An x509v3 certificate which is the issuer for this extension.
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050098 * Returns: The newly created X509Extension object
99 */
100crypto_X509ExtensionObj *
Jean-Paul Calderone5ae32fb2009-07-17 15:03:31 -0400101crypto_X509Extension_New(char *type_name, int critical, char *value,
Jean-Paul Calderonee04be5f2009-07-17 15:09:48 -0400102 crypto_X509Obj *subject, crypto_X509Obj *issuer) {
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500103 X509V3_CTX ctx;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500104 crypto_X509ExtensionObj *self;
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500105 char* value_with_critical = NULL;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500106
Jean-Paul Calderonee04be5f2009-07-17 15:09:48 -0400107
Jean-Paul Calderone5ae32fb2009-07-17 15:03:31 -0400108 /*
Jean-Paul Calderonee04be5f2009-07-17 15:09:48 -0400109 * A context is necessary for any extension which uses the r2i conversion
110 * method. That is, X509V3_EXT_nconf may segfault if passed a NULL ctx.
111 * Start off by initializing most of the fields to NULL.
Jean-Paul Calderone5ae32fb2009-07-17 15:03:31 -0400112 */
113 X509V3_set_ctx(&ctx, NULL, NULL, NULL, NULL, 0);
114
Jean-Paul Calderonee04be5f2009-07-17 15:09:48 -0400115 /*
116 * We have no configuration database - but perhaps we should (some
117 * extensions may require it).
Jean-Paul Calderone5ae32fb2009-07-17 15:03:31 -0400118 */
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500119 X509V3_set_ctx_nodb(&ctx);
120
Jean-Paul Calderone5ae32fb2009-07-17 15:03:31 -0400121 /*
122 * Initialize the subject and issuer, if appropriate. ctx is a local, and
123 * as far as I can tell none of the X509V3_* APIs invoked here steal any
124 * references, so no need to incref subject or issuer.
125 */
126 if (subject) {
Rick Dean47262da2009-07-08 16:17:17 -0500127 ctx.subject_cert = subject->x509;
Jean-Paul Calderone5ae32fb2009-07-17 15:03:31 -0400128 }
129
130 if (issuer) {
Rick Dean47262da2009-07-08 16:17:17 -0500131 ctx.issuer_cert = issuer->x509;
Jean-Paul Calderone5ae32fb2009-07-17 15:03:31 -0400132 }
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500133
134 self = PyObject_New(crypto_X509ExtensionObj, &crypto_X509Extension_Type);
135
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500136 if (self == NULL) {
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500137 goto error;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500138 }
139
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500140 self->dealloc = 0;
141
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500142 /* There are other OpenSSL APIs which would let us pass in critical
143 * separately, but they're harder to use, and since value is already a pile
144 * of crappy junk smuggling a ton of utterly important structured data,
145 * what's the point of trying to avoid nasty stuff with strings? (However,
146 * X509V3_EXT_i2d in particular seems like it would be a better API to
147 * invoke. I do not know where to get the ext_struc it desires for its
148 * last parameter, though.) */
149 value_with_critical = malloc(strlen("critical,") + strlen(value) + 1);
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500150 if (!value_with_critical) {
151 goto critical_malloc_error;
152 }
153
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500154 if (critical) {
155 strcpy(value_with_critical, "critical,");
156 strcpy(value_with_critical + strlen("critical,"), value);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500157 } else {
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500158 strcpy(value_with_critical, value);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500159 }
160
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500161 self->x509_extension = X509V3_EXT_nconf(
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500162 NULL, &ctx, type_name, value_with_critical);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500163
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500164 free(value_with_critical);
165
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500166 if (!self->x509_extension) {
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500167 goto nconf_error;
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500168 }
169
170 self->dealloc = 1;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500171 return self;
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500172
173 nconf_error:
Rick Deand369c932009-07-08 11:48:33 -0500174 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500175
176 critical_malloc_error:
Jean-Paul Calderonea96bfed2009-05-27 08:47:34 -0400177 Py_XDECREF(self);
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500178
179 error:
180 return NULL;
181
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500182}
183
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400184static char crypto_X509Extension_doc[] = "\n\
Rick Dean47262da2009-07-08 16:17:17 -0500185X509Extension(typename, critical, value[, subject][, issuer]) -> \n\
186 X509Extension instance\n\
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400187\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900188:param typename: The name of the extension to create.\n\
Jonathan Ballet648875f2011-07-16 14:14:58 +0900189:type typename: :py:data:`str`\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900190:param critical: A flag indicating whether this is a critical extension.\n\
191:param value: The value of the extension.\n\
Jonathan Ballet648875f2011-07-16 14:14:58 +0900192:type value: :py:data:`str`\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900193:param subject: Optional X509 cert to use as subject.\n\
Jonathan Ballet648875f2011-07-16 14:14:58 +0900194:type subject: :py:class:`X509`\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900195:param issuer: Optional X509 cert to use as issuer.\n\
Jonathan Ballet648875f2011-07-16 14:14:58 +0900196:type issuer: :py:class:`X509`\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900197:return: The X509Extension object\n\
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400198";
199
200static PyObject *
Jean-Paul Calderonee04be5f2009-07-17 15:09:48 -0400201crypto_X509Extension_new(PyTypeObject *subtype, PyObject *args,
Rick Dean47262da2009-07-08 16:17:17 -0500202 PyObject *kwargs) {
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400203 char *type_name, *value;
Rick Dean47262da2009-07-08 16:17:17 -0500204 int critical = 0;
205 crypto_X509Obj * subject = NULL;
206 crypto_X509Obj * issuer = NULL;
Jean-Paul Calderonee04be5f2009-07-17 15:09:48 -0400207 static char *kwlist[] = {"type_name", "critical", "value", "subject",
Rick Dean47262da2009-07-08 16:17:17 -0500208 "issuer", NULL};
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400209
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400210 if (!PyArg_ParseTupleAndKeywords(
211 args, kwargs,
212 BYTESTRING_FMT "i" BYTESTRING_FMT "|O!O!:X509Extension",
213 kwlist, &type_name, &critical, &value,
214 &crypto_X509_Type, &subject,
215 &crypto_X509_Type, &issuer )) {
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400216 return NULL;
217 }
218
Rick Dean47262da2009-07-08 16:17:17 -0500219 return (PyObject *)crypto_X509Extension_New(type_name, critical, value,
220 subject, issuer);
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400221}
222
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500223/*
224 * Deallocate the memory used by the X509Extension object
225 *
226 * Arguments: self - The X509Extension object
227 * Returns: None
228 */
229static void
230crypto_X509Extension_dealloc(crypto_X509ExtensionObj *self)
231{
232 /* Sometimes we don't have to dealloc this */
233 if (self->dealloc)
234 X509_EXTENSION_free(self->x509_extension);
235
236 PyObject_Del(self);
237}
238
239/*
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500240 * Print a nice text representation of the certificate request.
241 */
242static PyObject *
243crypto_X509Extension_str(crypto_X509ExtensionObj *self)
244{
245 int str_len;
246 char *tmp_str;
247 PyObject *str;
248 BIO *bio = BIO_new(BIO_s_mem());
249
250 if (!X509V3_EXT_print(bio, self->x509_extension, 0, 0))
251 {
252 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500253 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500254 return NULL;
255 }
256
257 str_len = BIO_get_mem_data(bio, &tmp_str);
Jean-Paul Calderone2f6c66f2010-08-11 19:53:43 -0400258 str = PyText_FromStringAndSize(tmp_str, str_len);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500259
260 BIO_free(bio);
261
262 return str;
263}
264
265PyTypeObject crypto_X509Extension_Type = {
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400266 PyOpenSSL_HEAD_INIT(&PyType_Type, 0)
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500267 "X509Extension",
268 sizeof(crypto_X509ExtensionObj),
269 0,
270 (destructor)crypto_X509Extension_dealloc,
271 NULL, /* print */
Jean-Paul Calderone2f6c66f2010-08-11 19:53:43 -0400272 NULL, /* getattr */
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500273 NULL, /* setattr (setattrfunc)crypto_X509Name_setattr, */
274 NULL, /* compare */
275 NULL, /* repr */
276 NULL, /* as_number */
277 NULL, /* as_sequence */
278 NULL, /* as_mapping */
279 NULL, /* hash */
280 NULL, /* call */
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400281 (reprfunc)crypto_X509Extension_str, /* str */
282 NULL, /* getattro */
283 NULL, /* setattro */
284 NULL, /* as_buffer */
285 Py_TPFLAGS_DEFAULT,
286 crypto_X509Extension_doc, /* doc */
287 NULL, /* traverse */
288 NULL, /* clear */
289 NULL, /* tp_richcompare */
290 0, /* tp_weaklistoffset */
291 NULL, /* tp_iter */
292 NULL, /* tp_iternext */
293 crypto_X509Extension_methods, /* tp_methods */
294 NULL, /* tp_members */
295 NULL, /* tp_getset */
296 NULL, /* tp_base */
297 NULL, /* tp_dict */
298 NULL, /* tp_descr_get */
299 NULL, /* tp_descr_set */
300 0, /* tp_dictoffset */
301 NULL, /* tp_init */
302 NULL, /* tp_alloc */
303 crypto_X509Extension_new, /* tp_new */
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500304};
305
306/*
307 * Initialize the X509Extension part of the crypto module
308 *
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400309 * Arguments: dict - The crypto module
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500310 * Returns: None
311 */
312int
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400313init_crypto_x509extension(PyObject *module)
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500314{
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400315 if (PyType_Ready(&crypto_X509Extension_Type) < 0) {
316 return 0;
317 }
318
Jean-Paul Calderone86ad7112010-05-11 16:08:45 -0400319 /* PyModule_AddObject steals a reference.
320 */
321 Py_INCREF((PyObject *)&crypto_X509Extension_Type);
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400322 if (PyModule_AddObject(module, "X509Extension",
323 (PyObject *)&crypto_X509Extension_Type) != 0) {
324 return 0;
325 }
326
Jean-Paul Calderoneaed23582011-03-12 22:45:02 -0500327 /* PyModule_AddObject steals a reference.
328 */
329 Py_INCREF((PyObject *)&crypto_X509Extension_Type);
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400330 if (PyModule_AddObject(module, "X509ExtensionType",
331 (PyObject *)&crypto_X509Extension_Type) != 0) {
332 return 0;
333 }
334
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500335 return 1;
336}