blob: 9a628c3ab5b7f90c712667b4931ab82db46d10a3 [file] [log] [blame]
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05001/*
2 * x509ext.c
3 *
4 * Export X.509 extension functions and data structures.
5 * See the file RATIONALE for a short explanation of why this module was written.
6 *
7 * @(#) $Id: x509ext.c,v 1.1 2002/07/09 13:34:46 martin Exp $
8 */
9
10#include <Python.h>
11#define crypto_MODULE
12#include "crypto.h"
13
14static char *CVSid = "@(#) $Id: x509ext.c,v 1.1 2002/07/09 13:34:46 martin Exp $";
15
16static 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
33/*
34 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
35 * { 'name', (PyCFunction)crypto_X509Extension_name, METH_VARARGS }
36 * for convenience
37 */
38#define ADD_METHOD(name) \
39{ #name, (PyCFunction)crypto_X509Extension_##name, METH_VARARGS, crypto_X509Extension_##name##_doc }
40static PyMethodDef crypto_X509Extension_methods[] =
41{
42 ADD_METHOD(get_critical),
43 { NULL, NULL }
44};
45#undef ADD_METHOD
46
47/*
48 * Constructor for X509Extension, never called by Python code directly
49 *
50 * Arguments: type_name - ???
51 * critical - ???
52 * value - ???
53 * Returns: The newly created X509Extension object
54 */
55crypto_X509ExtensionObj *
56crypto_X509Extension_New(char *type_name, int critical, char *value)
57{
58 crypto_X509ExtensionObj *self;
59 int ext_len, ext_nid;
60 unsigned char *ext_der;
61 X509V3_EXT_METHOD *ext_method = NULL;
62 ASN1_OCTET_STRING *ext_oct;
63 STACK_OF(CONF_VALUE) *nval;
64 void * ext_struct;
65 X509_EXTENSION *extension = NULL;
66
67 self = PyObject_New(crypto_X509ExtensionObj, &crypto_X509Extension_Type);
68
69 if (self == NULL)
70 return NULL;
71
72 /* Try to get a NID for the name */
73 if ((ext_nid = OBJ_sn2nid(type_name)) == NID_undef)
74 {
75 PyErr_SetString(PyExc_ValueError, "Unknown extension name");
76 return NULL;
77 }
78
79 /* Lookup the extension method structure */
80 if (!(ext_method = X509V3_EXT_get_nid(ext_nid)))
81 {
82 PyErr_SetString(PyExc_ValueError, "Unknown extension");
83 return NULL;
84 }
85
86 /* Look if it has a function to convert value to an
87 * internal structure.
88 */
89 if (!ext_method->v2i)
90 {
91 PyErr_SetString(PyExc_ValueError, "Can't initialize exception");
92 return NULL;
93 }
94
95 /* Parse the value */
96 nval = X509V3_parse_list(value);
97 if (!nval)
98 {
99 PyErr_SetString(PyExc_ValueError, "Invalid extension string");
100 return NULL;
101 }
102
103 /* And use it to get the internal structure */
104 if(!(ext_struct = ext_method->v2i(ext_method, NULL, nval))) {
105 exception_from_error_queue();
106 return NULL;
107 }
108
109 /* Deallocate the configuration value stack */
110 sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
111
112 /* Find out how much memory we need */
113
114
115 /* Convert internal representation to DER */
116 /* and Allocate */
117 if (ext_method->it) {
118 ext_der = NULL;
119 ext_len = ASN1_item_i2d(ext_struct, &ext_der, ASN1_ITEM_ptr(ext_method->it));
120 if (ext_len < 0) {
121 PyErr_SetString(PyExc_MemoryError, "Could not allocate memory");
122 return NULL;
123 }
124 } else {
125 unsigned char *p;
126 ext_len = ext_method->i2d(ext_struct, NULL);
127 if(!(ext_der = malloc(ext_len))) {
128 PyErr_SetString(PyExc_MemoryError, "Could not allocate memory");
129 return NULL;
130 }
131 p = ext_der;
132 ext_method->i2d(ext_struct, &p);
133 }
134
135 /* And create the ASN1_OCTET_STRING */
136 if(!(ext_oct = M_ASN1_OCTET_STRING_new())) {
137 exception_from_error_queue();
138 return NULL;
139 }
140
141 ext_oct->data = ext_der;
142 ext_oct->length = ext_len;
143
144 /* Now that we got all ingredients, make the extension */
145 extension = X509_EXTENSION_create_by_NID(NULL, ext_nid, critical, ext_oct);
146 if (extension == NULL)
147 {
148 exception_from_error_queue();
149 M_ASN1_OCTET_STRING_free(ext_oct);
150 ext_method->ext_free(ext_struct);
151 return NULL;
152 }
153
154 M_ASN1_OCTET_STRING_free(ext_oct);
155 //ext_method->ext_free(ext_struct);
156
157 self->x509_extension = extension;
158 self->dealloc = 1;
159
160 return self;
161}
162
163/*
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 */
236 (reprfunc)crypto_X509Extension_str /* str */
237};
238
239/*
240 * Initialize the X509Extension part of the crypto module
241 *
242 * Arguments: dict - The crypto module dictionary
243 * Returns: None
244 */
245int
246init_crypto_x509extension(PyObject *dict)
247{
248 crypto_X509Extension_Type.ob_type = &PyType_Type;
249 Py_INCREF(&crypto_X509Extension_Type);
250 PyDict_SetItemString(dict, "X509ExtensionType",
251 (PyObject *)&crypto_X509Extension_Type);
252 return 1;
253}
254