Initial import to Tizen
[profile/ivi/python-pyOpenSSL.git] / OpenSSL / crypto / x509ext.c
1 /*
2  * x509ext.c
3  *
4  * Copyright (C) Jean-Paul Calderone
5  * See LICENSE for details.
6  *
7  * Export X.509 extension functions and data structures.
8  * See the file RATIONALE for a short explanation of why this module was written.
9  *
10  */
11
12 #include <Python.h>
13 #define crypto_MODULE
14 #include "crypto.h"
15
16 static char crypto_X509Extension_get_critical_doc[] = "\n\
17 Returns the critical field of the X509Extension\n\
18 \n\
19 @return: The critical field.\n\
20 ";
21
22 static PyObject *
23 crypto_X509Extension_get_critical(crypto_X509ExtensionObj *self, PyObject *args)
24 {
25     if (!PyArg_ParseTuple(args, ":get_critical"))
26         return NULL;
27
28     return PyLong_FromLong(X509_EXTENSION_get_critical(self->x509_extension));
29 }
30
31 static char crypto_X509Extension_get_short_name_doc[] = "\n\
32 Returns the short version of the type name of the X509Extension\n\
33 \n\
34 @return: The short type name.\n\
35 ";
36
37 static PyObject *
38 crypto_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 PyBytes_FromString(extname);
51 }
52
53
54 static char crypto_X509Extension_get_data_doc[] = "\n\
55 Returns the data of the X509Extension\n\
56 \n\
57 @return: A C{str} giving the X509Extension's ASN.1 encoded data.\n\
58 ";
59
60 static PyObject *
61 crypto_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
74 /*
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 }
81 static PyMethodDef crypto_X509Extension_methods[] =
82 {
83     ADD_METHOD(get_critical),
84     ADD_METHOD(get_short_name),
85     ADD_METHOD(get_data),
86     { 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     - ???
96  *            subject   - An x509v3 certificate which is the subject for this extension.
97  *            issuer    - An x509v3 certificate which is the issuer for this extension.
98  * Returns:   The newly created X509Extension object
99  */
100 crypto_X509ExtensionObj *
101 crypto_X509Extension_New(char *type_name, int critical, char *value,
102                          crypto_X509Obj *subject, crypto_X509Obj  *issuer) {
103     X509V3_CTX ctx;
104     crypto_X509ExtensionObj *self;
105     char* value_with_critical = NULL;
106
107
108     /*
109      * 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.
112      */
113     X509V3_set_ctx(&ctx, NULL, NULL, NULL, NULL, 0);
114
115     /*
116      * We have no configuration database - but perhaps we should (some
117      * extensions may require it).
118      */
119     X509V3_set_ctx_nodb(&ctx);
120
121     /*
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) {
127             ctx.subject_cert = subject->x509;
128     }
129
130     if (issuer) {
131             ctx.issuer_cert = issuer->x509;
132     }
133
134     self = PyObject_New(crypto_X509ExtensionObj, &crypto_X509Extension_Type);
135
136     if (self == NULL) {
137             goto error;
138     }
139
140     self->dealloc = 0;
141
142     /* 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);
150     if (!value_with_critical) {
151             goto critical_malloc_error;
152     }
153
154     if (critical) {
155             strcpy(value_with_critical, "critical,");
156             strcpy(value_with_critical + strlen("critical,"), value);
157     } else {
158             strcpy(value_with_critical, value);
159     }
160
161     self->x509_extension = X509V3_EXT_nconf(
162             NULL, &ctx, type_name, value_with_critical);
163
164     free(value_with_critical);
165
166     if (!self->x509_extension) {
167             goto nconf_error;
168     }
169
170     self->dealloc = 1;
171     return self;
172
173   nconf_error:
174     exception_from_error_queue(crypto_Error);
175
176   critical_malloc_error:
177     Py_XDECREF(self);
178
179   error:
180     return NULL;
181
182 }
183
184 static char crypto_X509Extension_doc[] = "\n\
185 X509Extension(typename, critical, value[, subject][, issuer]) -> \n\
186                 X509Extension instance\n\
187 \n\
188 @param typename: The name of the extension to create.\n\
189 @type typename: C{str}\n\
190 @param critical: A flag indicating whether this is a critical extension.\n\
191 @param value: The value of the extension.\n\
192 @type value: C{str}\n\
193 @param subject: Optional X509 cert to use as subject.\n\
194 @type subject: C{X509}\n\
195 @param issuer: Optional X509 cert to use as issuer.\n\
196 @type issuer: C{X509}\n\
197 @return: The X509Extension object\n\
198 ";
199
200 static PyObject *
201 crypto_X509Extension_new(PyTypeObject *subtype, PyObject *args,
202                          PyObject *kwargs) {
203     char *type_name, *value;
204     int critical = 0;
205     crypto_X509Obj * subject = NULL;
206     crypto_X509Obj * issuer = NULL;
207     static char *kwlist[] = {"type_name", "critical", "value", "subject",
208                              "issuer", NULL};
209
210     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 )) {
216         return NULL;
217     }
218
219     return (PyObject *)crypto_X509Extension_New(type_name, critical, value,
220                                                 subject, issuer);
221 }
222
223 /*
224  * Deallocate the memory used by the X509Extension object
225  *
226  * Arguments: self - The X509Extension object
227  * Returns:   None
228  */
229 static void
230 crypto_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 /*
240  * Print a nice text representation of the certificate request.
241  */
242 static PyObject *
243 crypto_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);
253         exception_from_error_queue(crypto_Error);
254         return NULL;
255     }
256
257     str_len = BIO_get_mem_data(bio, &tmp_str);
258     str = PyText_FromStringAndSize(tmp_str, str_len);
259
260     BIO_free(bio);
261
262     return str;
263 }
264
265 PyTypeObject crypto_X509Extension_Type = {
266     PyOpenSSL_HEAD_INIT(&PyType_Type, 0)
267     "X509Extension",
268     sizeof(crypto_X509ExtensionObj),
269     0,
270     (destructor)crypto_X509Extension_dealloc, 
271     NULL, /* print */
272     NULL, /* getattr */
273     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 */
281     (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 */
304 };
305
306 /*
307  * Initialize the X509Extension part of the crypto module
308  *
309  * Arguments: dict - The crypto module
310  * Returns:   None
311  */
312 int
313 init_crypto_x509extension(PyObject *module)
314 {
315     if (PyType_Ready(&crypto_X509Extension_Type) < 0) {
316         return 0;
317     }
318
319     if (PyModule_AddObject(module, "X509Extension",
320                            (PyObject *)&crypto_X509Extension_Type) != 0) {
321         return 0;
322     }
323
324     if (PyModule_AddObject(module, "X509ExtensionType",
325                            (PyObject *)&crypto_X509Extension_Type) != 0) {
326         return 0;
327     }
328
329     return 1;
330 }