blob: b81b9124af658ae4cb5222bf0dda0ea46e2a0cb3 [file] [log] [blame]
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05001/*
2 * x509name.c
3 *
4 * Copyright (C) AB Strakt 2001, All rights reserved
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04005 * Copyright (C) Jean-Paul Calderone 2008, All rights reserved
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05006 *
7 * X.509 Name handling, mostly thin wrapping.
8 * See the file RATIONALE for a short explanation of why this module was written.
9 *
10 * Reviewed 2001-07-23
11 */
12#include <Python.h>
13#define crypto_MODULE
14#include "crypto.h"
15
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050016/*
17 * Constructor for X509Name, never called by Python code directly
18 *
19 * Arguments: name - A "real" X509_NAME object
20 * dealloc - Boolean value to specify whether the destructor should
21 * free the "real" X509_NAME object
22 * Returns: The newly created X509Name object
23 */
24crypto_X509NameObj *
25crypto_X509Name_New(X509_NAME *name, int dealloc)
26{
27 crypto_X509NameObj *self;
28
29 self = PyObject_GC_New(crypto_X509NameObj, &crypto_X509Name_Type);
30
31 if (self == NULL)
32 return NULL;
33
34 self->x509_name = name;
35 self->dealloc = dealloc;
36 self->parent_cert = NULL;
37
38 PyObject_GC_Track(self);
39 return self;
40}
41
42/*
43 * Return a name string given a X509_NAME object and a name identifier. Used
44 * by the getattr function.
45 *
46 * Arguments: name - The X509_NAME object
47 * nid - The name identifier
48 * Returns: The name as a Python string object
49 */
50static int
51get_name_by_nid(X509_NAME *name, int nid, char **utf8string)
52{
53 int entry_idx;
54 X509_NAME_ENTRY *entry;
55 ASN1_STRING *data;
56 int len;
57
58 if ((entry_idx = X509_NAME_get_index_by_NID(name, nid, -1)) == -1)
59 {
60 return 0;
61 }
62 entry = X509_NAME_get_entry(name, entry_idx);
63 data = X509_NAME_ENTRY_get_data(entry);
64 if ((len = ASN1_STRING_to_UTF8((unsigned char **)utf8string, data)) < 0)
65 {
66 exception_from_error_queue();
67 return -1;
68 }
69
70 return len;
71}
72
73/*
74 * Given a X509_NAME object and a name identifier, set the corresponding
75 * attribute to the given string. Used by the setattr function.
76 *
77 * Arguments: name - The X509_NAME object
78 * nid - The name identifier
79 * value - The string to set
80 * Returns: 0 for success, -1 on failure
81 */
82static int
83set_name_by_nid(X509_NAME *name, int nid, char *utf8string)
84{
85 X509_NAME_ENTRY *ne;
86 int i, entry_count, temp_nid;
87
88 /* If there's an old entry for this NID, remove it */
89 entry_count = X509_NAME_entry_count(name);
90 for (i = 0; i < entry_count; i++)
91 {
92 ne = X509_NAME_get_entry(name, i);
93 temp_nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(ne));
94 if (temp_nid == nid)
95 {
96 ne = X509_NAME_delete_entry(name, i);
97 X509_NAME_ENTRY_free(ne);
98 break;
99 }
100 }
101
102 /* Add the new entry */
103 if (!X509_NAME_add_entry_by_NID(name, nid, MBSTRING_UTF8, utf8string,
104 -1, -1, 0))
105 {
106 exception_from_error_queue();
107 return -1;
108 }
109 return 0;
110}
111
112
113/*
114 * Find attribute. An X509Name object has the following attributes:
115 * countryName (alias C), stateOrProvince (alias ST), locality (alias L),
116 * organization (alias O), organizationalUnit (alias OU), commonName (alias
117 * CN) and more...
118 *
119 * Arguments: self - The X509Name object
120 * name - The attribute name
121 * Returns: A Python object for the attribute, or NULL if something went
122 * wrong
123 */
124static PyObject *
125crypto_X509Name_getattr(crypto_X509NameObj *self, char *name)
126{
127 int nid, len;
128 char *utf8string;
129
130 if ((nid = OBJ_txt2nid(name)) == NID_undef)
131 {
132 PyErr_SetString(PyExc_AttributeError, "No such attribute");
133 return NULL;
134 }
135
136 len = get_name_by_nid(self->x509_name, nid, &utf8string);
137 if (len < 0)
138 return NULL;
139 else if (len == 0)
140 {
141 Py_INCREF(Py_None);
142 return Py_None;
143 }
Jean-Paul Calderone5b8c5ee2008-02-19 00:43:02 -0500144 else {
145 PyObject* result = PyUnicode_Decode(utf8string, len, "utf-8", NULL);
146 OPENSSL_free(utf8string);
147 return result;
148 }
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500149}
150
151/*
152 * Set attribute
153 *
154 * Arguments: self - The X509Name object
155 * name - The attribute name
156 * value - The value to set
157 */
158static int
159crypto_X509Name_setattr(crypto_X509NameObj *self, char *name, PyObject *value)
160{
161 int nid;
Jean-Paul Calderone7b0443a2008-02-19 00:25:30 -0500162 int result;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500163 char *buffer;
164
165 if ((nid = OBJ_txt2nid(name)) == NID_undef)
166 {
167 PyErr_SetString(PyExc_AttributeError, "No such attribute");
168 return -1;
169 }
170
171 /* Something of a hack to get nice unicode behaviour */
172 if (!PyArg_Parse(value, "es:setattr", "utf-8", &buffer))
173 return -1;
Jean-Paul Calderone5b8c5ee2008-02-19 00:43:02 -0500174
Jean-Paul Calderone7b0443a2008-02-19 00:25:30 -0500175 result = set_name_by_nid(self->x509_name, nid, buffer);
176 PyMem_Free(buffer);
177 return result;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500178}
179
180/*
181 * Compare two X509Name structures.
182 *
183 * Arguments: n - The first X509Name
184 * m - The second X509Name
185 * Returns: <0 if n < m, 0 if n == m and >0 if n > m
186 */
187static int
188crypto_X509Name_compare(crypto_X509NameObj *n, crypto_X509NameObj *m)
189{
Jean-Paul Calderonee098dc72008-03-06 18:36:19 -0500190 int result = X509_NAME_cmp(n->x509_name, m->x509_name);
191 if (result < 0) {
192 return -1;
193 } else if (result > 0) {
194 return 1;
195 } else if (result == 0) {
196 return 0;
197 }
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500198}
199
200/*
201 * String representation of an X509Name
202 *
203 * Arguments: self - The X509Name object
204 * Returns: A string representation of the object
205 */
206static PyObject *
207crypto_X509Name_repr(crypto_X509NameObj *self)
208{
209 char tmpbuf[512] = "";
210 char realbuf[512+64];
211
212 if (X509_NAME_oneline(self->x509_name, tmpbuf, 512) == NULL)
213 {
214 exception_from_error_queue();
215 return NULL;
216 }
217 else
218 {
219 /* This is safe because tmpbuf is max 512 characters */
220 sprintf(realbuf, "<X509Name object '%s'>", tmpbuf);
221 return PyString_FromString(realbuf);
222 }
223}
224
225/*
226 * Call the visitproc on all contained objects.
227 *
228 * Arguments: self - The Connection object
229 * visit - Function to call
230 * arg - Extra argument to visit
231 * Returns: 0 if all goes well, otherwise the return code from the first
232 * call that gave non-zero result.
233 */
234static int
235crypto_X509Name_traverse(crypto_X509NameObj *self, visitproc visit, void *arg)
236{
237 int ret = 0;
238
239 if (ret == 0 && self->parent_cert != NULL)
240 ret = visit(self->parent_cert, arg);
241 return ret;
242}
243
244/*
245 * Decref all contained objects and zero the pointers.
246 *
247 * Arguments: self - The Connection object
248 * Returns: Always 0.
249 */
250static int
251crypto_X509Name_clear(crypto_X509NameObj *self)
252{
253 Py_XDECREF(self->parent_cert);
254 self->parent_cert = NULL;
255 return 0;
256}
257
258/*
259 * Deallocate the memory used by the X509Name object
260 *
261 * Arguments: self - The X509Name object
262 * Returns: None
263 */
264static void
265crypto_X509Name_dealloc(crypto_X509NameObj *self)
266{
267 PyObject_GC_UnTrack(self);
268 /* Sometimes we don't have to dealloc this */
269 if (self->dealloc)
270 X509_NAME_free(self->x509_name);
271
272 crypto_X509Name_clear(self);
273
274 PyObject_GC_Del(self);
275}
276
277PyTypeObject crypto_X509Name_Type = {
278 PyObject_HEAD_INIT(NULL)
279 0,
280 "X509Name",
281 sizeof(crypto_X509NameObj),
282 0,
283 (destructor)crypto_X509Name_dealloc,
284 NULL, /* print */
285 (getattrfunc)crypto_X509Name_getattr,
286 (setattrfunc)crypto_X509Name_setattr,
287 (cmpfunc)crypto_X509Name_compare,
288 (reprfunc)crypto_X509Name_repr,
289 NULL, /* as_number */
290 NULL, /* as_sequence */
291 NULL, /* as_mapping */
292 NULL, /* hash */
293 NULL, /* call */
294 NULL, /* str */
295 NULL, /* getattro */
296 NULL, /* setattro */
297 NULL, /* as_buffer */
298 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
299 NULL, /* doc */
300 (traverseproc)crypto_X509Name_traverse,
301 (inquiry)crypto_X509Name_clear,
302};
303
304
305/*
306 * Initialize the X509Name part of the crypto module
307 *
308 * Arguments: dict - The crypto module dictionary
309 * Returns: None
310 */
311int
312init_crypto_x509name(PyObject *dict)
313{
314 crypto_X509Name_Type.ob_type = &PyType_Type;
315 Py_INCREF(&crypto_X509Name_Type);
316 PyDict_SetItemString(dict, "X509NameType", (PyObject *)&crypto_X509Name_Type);
317 return 1;
318}