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