blob: 53dc48a11bab50c1ffb2dd9814305543ce4a6fc5 [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
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{
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -050058 X509V3_CTX ctx;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050059 crypto_X509ExtensionObj *self;
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -050060 char* value_with_critical = NULL;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050061
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -050062 /* We have no configuration database - but perhaps we should. Anyhow, the
63 * context is necessary for any extension which uses the r2i conversion
64 * method. That is, X509V3_EXT_nconf may segfault if passed a NULL ctx. */
65 X509V3_set_ctx_nodb(&ctx);
66
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050067 self = PyObject_New(crypto_X509ExtensionObj, &crypto_X509Extension_Type);
68
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -050069 if (self == NULL) {
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -050070 goto error;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050071 }
72
Jean-Paul Calderone391585f2008-12-31 14:36:31 -050073 self->dealloc = 0;
74
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -050075 /* There are other OpenSSL APIs which would let us pass in critical
76 * separately, but they're harder to use, and since value is already a pile
77 * of crappy junk smuggling a ton of utterly important structured data,
78 * what's the point of trying to avoid nasty stuff with strings? (However,
79 * X509V3_EXT_i2d in particular seems like it would be a better API to
80 * invoke. I do not know where to get the ext_struc it desires for its
81 * last parameter, though.) */
82 value_with_critical = malloc(strlen("critical,") + strlen(value) + 1);
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -050083 if (!value_with_critical) {
84 goto critical_malloc_error;
85 }
86
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -050087 if (critical) {
88 strcpy(value_with_critical, "critical,");
89 strcpy(value_with_critical + strlen("critical,"), value);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050090 } else {
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -050091 strcpy(value_with_critical, value);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050092 }
93
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -050094 self->x509_extension = X509V3_EXT_nconf(
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -050095 NULL, &ctx, type_name, value_with_critical);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050096
Jean-Paul Calderonee7db4b42008-12-31 13:39:24 -050097 free(value_with_critical);
98
Jean-Paul Calderone391585f2008-12-31 14:36:31 -050099 if (!self->x509_extension) {
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500100 goto nconf_error;
Jean-Paul Calderone391585f2008-12-31 14:36:31 -0500101 }
102
103 self->dealloc = 1;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500104 return self;
Jean-Paul Calderone2ee1e7c2008-12-31 14:58:38 -0500105
106 nconf_error:
107 exception_from_error_queue();
108
109 critical_malloc_error:
110 PyObject_Free(self);
111
112 error:
113 return NULL;
114
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500115}
116
117/*
118 * Deallocate the memory used by the X509Extension object
119 *
120 * Arguments: self - The X509Extension object
121 * Returns: None
122 */
123static void
124crypto_X509Extension_dealloc(crypto_X509ExtensionObj *self)
125{
126 /* Sometimes we don't have to dealloc this */
127 if (self->dealloc)
128 X509_EXTENSION_free(self->x509_extension);
129
130 PyObject_Del(self);
131}
132
133/*
134 * Find attribute
135 *
136 * Arguments: self - The X509Extension object
137 * name - The attribute name
138 * Returns: A Python object for the attribute, or NULL if something
139 * went wrong.
140 */
141static PyObject *
142crypto_X509Extension_getattr(crypto_X509ExtensionObj *self, char *name)
143{
144 return Py_FindMethod(crypto_X509Extension_methods, (PyObject *)self, name);
145}
146
147/*
148 * Print a nice text representation of the certificate request.
149 */
150static PyObject *
151crypto_X509Extension_str(crypto_X509ExtensionObj *self)
152{
153 int str_len;
154 char *tmp_str;
155 PyObject *str;
156 BIO *bio = BIO_new(BIO_s_mem());
157
158 if (!X509V3_EXT_print(bio, self->x509_extension, 0, 0))
159 {
160 BIO_free(bio);
161 exception_from_error_queue();
162 return NULL;
163 }
164
165 str_len = BIO_get_mem_data(bio, &tmp_str);
166 str = PyString_FromStringAndSize(tmp_str, str_len);
167
168 BIO_free(bio);
169
170 return str;
171}
172
173PyTypeObject crypto_X509Extension_Type = {
174 PyObject_HEAD_INIT(NULL)
175 0,
176 "X509Extension",
177 sizeof(crypto_X509ExtensionObj),
178 0,
179 (destructor)crypto_X509Extension_dealloc,
180 NULL, /* print */
181 (getattrfunc)crypto_X509Extension_getattr,
182 NULL, /* setattr (setattrfunc)crypto_X509Name_setattr, */
183 NULL, /* compare */
184 NULL, /* repr */
185 NULL, /* as_number */
186 NULL, /* as_sequence */
187 NULL, /* as_mapping */
188 NULL, /* hash */
189 NULL, /* call */
190 (reprfunc)crypto_X509Extension_str /* str */
191};
192
193/*
194 * Initialize the X509Extension part of the crypto module
195 *
196 * Arguments: dict - The crypto module dictionary
197 * Returns: None
198 */
199int
200init_crypto_x509extension(PyObject *dict)
201{
202 crypto_X509Extension_Type.ob_type = &PyType_Type;
203 Py_INCREF(&crypto_X509Extension_Type);
204 PyDict_SetItemString(dict, "X509ExtensionType",
205 (PyObject *)&crypto_X509Extension_Type);
206 return 1;
207}
208