4 * Copyright (C) AB Strakt
5 * Copyright (C) Jean-Paul Calderone
6 * See LICENSE for details.
8 * X.509 Name handling, mostly thin wrapping.
9 * See the file RATIONALE for a short explanation of why this module was written.
17 static PyMethodDef crypto_X509Name_methods[4];
20 * Constructor for X509Name, never called by Python code directly
22 * Arguments: name - A "real" X509_NAME object
23 * dealloc - Boolean value to specify whether the destructor should
24 * free the "real" X509_NAME object
25 * Returns: The newly created X509Name object
28 crypto_X509Name_New(X509_NAME *name, int dealloc)
30 crypto_X509NameObj *self;
32 self = PyObject_GC_New(crypto_X509NameObj, &crypto_X509Name_Type);
37 self->x509_name = name;
38 self->dealloc = dealloc;
39 self->parent_cert = NULL;
41 PyObject_GC_Track(self);
46 static char crypto_X509Name_doc[] = "\n\
47 X509Name(name) -> New X509Name object\n\
49 Create a new X509Name, copying the given X509Name instance.\n\
51 @param name: An X509Name object to copy\n\
52 @return: The X509Name object\n\
56 crypto_X509Name_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
58 crypto_X509NameObj *name;
60 if (!PyArg_ParseTuple(args, "O!:X509Name", &crypto_X509Name_Type, &name)) {
64 return (PyObject *)crypto_X509Name_New(X509_NAME_dup(name->x509_name), 1);
69 * Return a name string given a X509_NAME object and a name identifier. Used
70 * by the getattr function.
72 * Arguments: name - The X509_NAME object
73 * nid - The name identifier
74 * Returns: The name as a Python string object
77 get_name_by_nid(X509_NAME *name, int nid, char **utf8string)
80 X509_NAME_ENTRY *entry;
84 if ((entry_idx = X509_NAME_get_index_by_NID(name, nid, -1)) == -1)
88 entry = X509_NAME_get_entry(name, entry_idx);
89 data = X509_NAME_ENTRY_get_data(entry);
90 if ((len = ASN1_STRING_to_UTF8((unsigned char **)utf8string, data)) < 0)
92 exception_from_error_queue(crypto_Error);
100 * Given a X509_NAME object and a name identifier, set the corresponding
101 * attribute to the given string. Used by the setattr function.
103 * Arguments: name - The X509_NAME object
104 * nid - The name identifier
105 * value - The string to set
106 * Returns: 0 for success, -1 on failure
109 set_name_by_nid(X509_NAME *name, int nid, char *utf8string)
112 int i, entry_count, temp_nid;
114 /* If there's an old entry for this NID, remove it */
115 entry_count = X509_NAME_entry_count(name);
116 for (i = 0; i < entry_count; i++)
118 ne = X509_NAME_get_entry(name, i);
119 temp_nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(ne));
122 ne = X509_NAME_delete_entry(name, i);
123 X509_NAME_ENTRY_free(ne);
128 /* Add the new entry */
129 if (!X509_NAME_add_entry_by_NID(name, nid, MBSTRING_UTF8,
130 (unsigned char *)utf8string,
133 exception_from_error_queue(crypto_Error);
141 * Find attribute. An X509Name object has the following attributes:
142 * countryName (alias C), stateOrProvince (alias ST), locality (alias L),
143 * organization (alias O), organizationalUnit (alias OU), commonName (alias
146 * Arguments: self - The X509Name object
147 * name - The attribute name
148 * Returns: A Python object for the attribute, or NULL if something went
152 crypto_X509Name_getattro(crypto_X509NameObj *self, PyObject *nameobj)
158 name = PyBytes_AsString(PyUnicode_AsASCIIString(nameobj));
160 name = PyBytes_AsString(nameobj);
163 if ((nid = OBJ_txt2nid(name)) == NID_undef) {
165 * This is a bit weird. OBJ_txt2nid indicated failure, but it seems
166 * a lower level function, a2d_ASN1_OBJECT, also feels the need to
167 * push something onto the error queue. If we don't clean that up
168 * now, someone else will bump into it later and be quite confused.
172 return PyObject_GenericGetAttr((PyObject*)self, nameobj);
175 len = get_name_by_nid(self->x509_name, nid, &utf8string);
184 PyObject* result = PyUnicode_Decode(utf8string, len, "utf-8", NULL);
185 OPENSSL_free(utf8string);
193 * Arguments: self - The X509Name object
194 * name - The attribute name
195 * value - The value to set
198 crypto_X509Name_setattr(crypto_X509NameObj *self, char *name, PyObject *value)
204 if ((nid = OBJ_txt2nid(name)) == NID_undef)
206 PyErr_SetString(PyExc_AttributeError, "No such attribute");
210 /* Something of a hack to get nice unicode behaviour */
211 if (!PyArg_Parse(value, "es:setattr", "utf-8", &buffer))
214 result = set_name_by_nid(self->x509_name, nid, buffer);
220 * Compare two X509Name structures.
222 * Arguments: n - The first X509Name
223 * m - The second X509Name
224 * Returns: <0 if n < m, 0 if n == m and >0 if n > m
227 crypto_X509Name_richcompare(PyObject *n, PyObject *m, int op) {
230 if (!crypto_X509Name_Check(n) || !crypto_X509Name_Check(m)) {
231 Py_INCREF(Py_NotImplemented);
232 return Py_NotImplemented;
235 result = X509_NAME_cmp(
236 ((crypto_X509NameObj*)n)->x509_name,
237 ((crypto_X509NameObj*)m)->x509_name);
241 result = (result == 0);
245 result = (result != 0);
249 result = (result < 0);
253 result = (result <= 0);
257 result = (result > 0);
261 result = (result >= 0);
265 /* Should be impossible */
266 Py_INCREF(Py_NotImplemented);
267 return Py_NotImplemented;
280 * String representation of an X509Name
282 * Arguments: self - The X509Name object
283 * Returns: A string representation of the object
286 crypto_X509Name_repr(crypto_X509NameObj *self)
288 char tmpbuf[512] = "";
289 char realbuf[512+64];
291 if (X509_NAME_oneline(self->x509_name, tmpbuf, 512) == NULL)
293 exception_from_error_queue(crypto_Error);
298 /* This is safe because tmpbuf is max 512 characters */
299 sprintf(realbuf, "<X509Name object '%s'>", tmpbuf);
300 return PyText_FromString(realbuf);
304 static char crypto_X509Name_hash_doc[] = "\n\
305 Return the hash value of this name\n\
311 * First four bytes of the MD5 digest of the DER form of an X509Name.
313 * Arguments: self - The X509Name object
314 * Returns: An integer giving the hash.
317 crypto_X509Name_hash(crypto_X509NameObj *self, PyObject* args)
321 if (!PyArg_ParseTuple(args, ":hash")) {
324 hash = X509_NAME_hash(self->x509_name);
325 return PyLong_FromLong(hash);
328 static char crypto_X509Name_der_doc[] = "\n\
329 Return the DER encoding of this name\n\
335 * Arguments: self - The X509Name object
336 * Returns: The DER form of an X509Name.
339 crypto_X509Name_der(crypto_X509NameObj *self, PyObject *args)
341 if (!PyArg_ParseTuple(args, ":der")) {
345 i2d_X509_NAME(self->x509_name, 0);
346 return PyBytes_FromStringAndSize(self->x509_name->bytes->data,
347 self->x509_name->bytes->length);
351 static char crypto_X509Name_get_components_doc[] = "\n\
352 Returns the split-up components of this name.\n\
354 @return: List of tuples (name, value).\n\
358 crypto_X509Name_get_components(crypto_X509NameObj *self, PyObject *args)
361 X509_NAME *name = self->x509_name;
364 if (!PyArg_ParseTuple(args, ":get_components"))
367 n = X509_NAME_entry_count(name);
368 list = PyList_New(n);
369 for (i = 0; i < n; i++)
371 X509_NAME_ENTRY *ent;
379 ent = X509_NAME_get_entry(name, i);
381 fname = X509_NAME_ENTRY_get_object(ent);
382 fval = X509_NAME_ENTRY_get_data(ent);
384 l = ASN1_STRING_length(fval);
385 str = ASN1_STRING_data(fval);
387 nid = OBJ_obj2nid(fname);
389 /* printf("fname is %s len=%d str=%s\n", OBJ_nid2sn(nid), l, str); */
391 tuple = PyTuple_New(2);
392 PyTuple_SetItem(tuple, 0, PyBytes_FromString(OBJ_nid2sn(nid)));
393 PyTuple_SetItem(tuple, 1, PyBytes_FromStringAndSize((char *)str, l));
395 PyList_SetItem(list, i, tuple);
403 * Call the visitproc on all contained objects.
405 * Arguments: self - The Connection object
406 * visit - Function to call
407 * arg - Extra argument to visit
408 * Returns: 0 if all goes well, otherwise the return code from the first
409 * call that gave non-zero result.
412 crypto_X509Name_traverse(crypto_X509NameObj *self, visitproc visit, void *arg)
416 if (ret == 0 && self->parent_cert != NULL)
417 ret = visit(self->parent_cert, arg);
422 * Decref all contained objects and zero the pointers.
424 * Arguments: self - The Connection object
428 crypto_X509Name_clear(crypto_X509NameObj *self)
430 Py_XDECREF(self->parent_cert);
431 self->parent_cert = NULL;
436 * Deallocate the memory used by the X509Name object
438 * Arguments: self - The X509Name object
442 crypto_X509Name_dealloc(crypto_X509NameObj *self)
444 PyObject_GC_UnTrack(self);
445 /* Sometimes we don't have to dealloc this */
447 X509_NAME_free(self->x509_name);
449 crypto_X509Name_clear(self);
451 PyObject_GC_Del(self);
455 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
456 * { 'name', (PyCFunction)crypto_X509_name, METH_VARARGS }
459 #define ADD_METHOD(name) \
460 { #name, (PyCFunction)crypto_X509Name_##name, METH_VARARGS, crypto_X509Name_##name##_doc }
461 static PyMethodDef crypto_X509Name_methods[] =
465 ADD_METHOD(get_components),
470 PyTypeObject crypto_X509Name_Type = {
471 PyOpenSSL_HEAD_INIT(&PyType_Type, 0)
473 sizeof(crypto_X509NameObj),
475 (destructor)crypto_X509Name_dealloc,
478 (setattrfunc)crypto_X509Name_setattr,
480 (reprfunc)crypto_X509Name_repr,
481 NULL, /* as_number */
482 NULL, /* as_sequence */
483 NULL, /* as_mapping */
487 (getattrofunc)crypto_X509Name_getattro, /* getattro */
489 NULL, /* as_buffer */
490 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
491 crypto_X509Name_doc, /* tp_doc */
492 (traverseproc)crypto_X509Name_traverse, /* tp_traverse */
493 (inquiry)crypto_X509Name_clear, /* tp_clear */
494 crypto_X509Name_richcompare, /* tp_richcompare */
495 0, /* tp_weaklistoffset */
497 NULL, /* tp_iternext */
498 crypto_X509Name_methods, /* tp_methods */
499 NULL, /* tp_members */
500 NULL, /* tp_getset */
503 NULL, /* tp_descr_get */
504 NULL, /* tp_descr_set */
505 0, /* tp_dictoffset */
508 crypto_X509Name_new, /* tp_new */
512 * Initialize the X509Name part of the crypto module
514 * Arguments: module - The crypto module
518 init_crypto_x509name(PyObject *module)
520 if (PyType_Ready(&crypto_X509Name_Type) < 0) {
524 if (PyModule_AddObject(module, "X509Name", (PyObject *)&crypto_X509Name_Type) != 0) {
528 if (PyModule_AddObject(module, "X509NameType", (PyObject *)&crypto_X509Name_Type) != 0) {