blob: 84df441ea37e95d2dc3023b76986848e95c239ae [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\
19Arguments: self - The X509Extension object\n\
20 args - The argument tuple, should be empty\n\
21Returns: The critical field.\n\
22";
23
24static PyObject *
25crypto_X509Extension_get_critical(crypto_X509ExtensionObj *self, PyObject *args)
26{
27 if (!PyArg_ParseTuple(args, ":get_critical"))
28 return NULL;
29
30 return PyInt_FromLong(X509_EXTENSION_get_critical(self->x509_extension));
31}
32
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -050033static char crypto_X509Extension_get_short_name_doc[] = "\n\
34Returns the short version of the type name of the X509Extension\n\
35\n\
36Arguments: self - The X509Extension object\n\
37 args - The argument tuple, should be empty\n\
38Returns: The short type name.\n\
39";
40
41static PyObject *
42crypto_X509Extension_get_short_name(crypto_X509ExtensionObj *self, PyObject *args) {
43 ASN1_OBJECT *obj;
44 const char *extname;
45
46 if (!PyArg_ParseTuple(args, ":get_short_name")) {
47 return NULL;
48 }
49
50 /* Returns an internal pointer to x509_extension, not a copy */
51 obj = X509_EXTENSION_get_object(self->x509_extension);
52
53 extname = OBJ_nid2sn(OBJ_obj2nid(obj));
54 return PyString_FromString(extname);
55}
56
57
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050058/*
59 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
60 * { 'name', (PyCFunction)crypto_X509Extension_name, METH_VARARGS }
61 * for convenience
62 */
63#define ADD_METHOD(name) \
64{ #name, (PyCFunction)crypto_X509Extension_##name, METH_VARARGS, crypto_X509Extension_##name##_doc }
65static PyMethodDef crypto_X509Extension_methods[] =
66{
67 ADD_METHOD(get_critical),
Jean-Paul Calderonef8c5fab2008-12-31 15:53:48 -050068 ADD_METHOD(get_short_name),
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050069 { NULL, NULL }
70};
71#undef ADD_METHOD
72
73/*
74 * Constructor for X509Extension, never called by Python code directly
75 *
76 * Arguments: type_name - ???
77 * critical - ???
78 * value - ???
79 * Returns: The newly created X509Extension object
80 */
81crypto_X509ExtensionObj *
82crypto_X509Extension_New(char *type_name, int critical, char *value)
83{
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -050084 X509V3_CTX ctx;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050085 crypto_X509ExtensionObj *self;
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -050086 char* value_with_critical = NULL;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050087
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -050088 /* We have no configuration database - but perhaps we should. Anyhow, the
89 * context is necessary for any extension which uses the r2i conversion
90 * method. That is, X509V3_EXT_nconf may segfault if passed a NULL ctx. */
91 X509V3_set_ctx_nodb(&ctx);
92
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050093 self = PyObject_New(crypto_X509ExtensionObj, &crypto_X509Extension_Type);
94
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -050095 if (self == NULL) {
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -050096 goto error;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050097 }
98
Jean-Paul Calderone391585f2008-12-31 14:36:31 -050099 self->dealloc = 0;
100
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500101 /* There are other OpenSSL APIs which would let us pass in critical
102 * separately, but they're harder to use, and since value is already a pile
103 * of crappy junk smuggling a ton of utterly important structured data,
104 * what's the point of trying to avoid nasty stuff with strings? (However,
105 * X509V3_EXT_i2d in particular seems like it would be a better API to
106 * invoke. I do not know where to get the ext_struc it desires for its
107 * last parameter, though.) */
108 value_with_critical = malloc(strlen("critical,") + strlen(value) + 1);
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500109 if (!value_with_critical) {
110 goto critical_malloc_error;
111 }
112
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500113 if (critical) {
114 strcpy(value_with_critical, "critical,");
115 strcpy(value_with_critical + strlen("critical,"), value);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500116 } else {
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500117 strcpy(value_with_critical, value);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500118 }
119
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500120 self->x509_extension = X509V3_EXT_nconf(
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500121 NULL, &ctx, type_name, value_with_critical);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500122
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -0500123 free(value_with_critical);
124
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500125 if (!self->x509_extension) {
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500126 goto nconf_error;
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500127 }
128
129 self->dealloc = 1;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500130 return self;
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500131
132 nconf_error:
133 exception_from_error_queue();
134
135 critical_malloc_error:
Jean-Paul Calderonea96bfed2009-05-27 08:47:34 -0400136 Py_XDECREF(self);
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500137
138 error:
139 return NULL;
140
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500141}
142
143/*
144 * Deallocate the memory used by the X509Extension object
145 *
146 * Arguments: self - The X509Extension object
147 * Returns: None
148 */
149static void
150crypto_X509Extension_dealloc(crypto_X509ExtensionObj *self)
151{
152 /* Sometimes we don't have to dealloc this */
153 if (self->dealloc)
154 X509_EXTENSION_free(self->x509_extension);
155
156 PyObject_Del(self);
157}
158
159/*
160 * Find attribute
161 *
162 * Arguments: self - The X509Extension object
163 * name - The attribute name
164 * Returns: A Python object for the attribute, or NULL if something
165 * went wrong.
166 */
167static PyObject *
168crypto_X509Extension_getattr(crypto_X509ExtensionObj *self, char *name)
169{
170 return Py_FindMethod(crypto_X509Extension_methods, (PyObject *)self, name);
171}
172
173/*
174 * Print a nice text representation of the certificate request.
175 */
176static PyObject *
177crypto_X509Extension_str(crypto_X509ExtensionObj *self)
178{
179 int str_len;
180 char *tmp_str;
181 PyObject *str;
182 BIO *bio = BIO_new(BIO_s_mem());
183
184 if (!X509V3_EXT_print(bio, self->x509_extension, 0, 0))
185 {
186 BIO_free(bio);
187 exception_from_error_queue();
188 return NULL;
189 }
190
191 str_len = BIO_get_mem_data(bio, &tmp_str);
192 str = PyString_FromStringAndSize(tmp_str, str_len);
193
194 BIO_free(bio);
195
196 return str;
197}
198
199PyTypeObject crypto_X509Extension_Type = {
200 PyObject_HEAD_INIT(NULL)
201 0,
202 "X509Extension",
203 sizeof(crypto_X509ExtensionObj),
204 0,
205 (destructor)crypto_X509Extension_dealloc,
206 NULL, /* print */
207 (getattrfunc)crypto_X509Extension_getattr,
208 NULL, /* setattr (setattrfunc)crypto_X509Name_setattr, */
209 NULL, /* compare */
210 NULL, /* repr */
211 NULL, /* as_number */
212 NULL, /* as_sequence */
213 NULL, /* as_mapping */
214 NULL, /* hash */
215 NULL, /* call */
216 (reprfunc)crypto_X509Extension_str /* str */
217};
218
219/*
220 * Initialize the X509Extension part of the crypto module
221 *
222 * Arguments: dict - The crypto module dictionary
223 * Returns: None
224 */
225int
226init_crypto_x509extension(PyObject *dict)
227{
228 crypto_X509Extension_Type.ob_type = &PyType_Type;
229 Py_INCREF(&crypto_X509Extension_Type);
230 PyDict_SetItemString(dict, "X509ExtensionType",
231 (PyObject *)&crypto_X509Extension_Type);
232 return 1;
233}
234