initial source import
diff --git a/src/crypto/x509name.c b/src/crypto/x509name.c
new file mode 100644
index 0000000..b9c0233
--- /dev/null
+++ b/src/crypto/x509name.c
@@ -0,0 +1,307 @@
+/*
+ * x509name.c
+ *
+ * Copyright (C) AB Strakt 2001, All rights reserved
+ *
+ * X.509 Name handling, mostly thin wrapping.
+ * See the file RATIONALE for a short explanation of why this module was written.
+ *
+ * Reviewed 2001-07-23
+ */
+#include <Python.h>
+#define crypto_MODULE
+#include "crypto.h"
+
+static char *CVSid = "@(#) $Id: x509name.c,v 1.16 2003/01/09 17:08:32 martin Exp $";
+
+
+/*
+ * Constructor for X509Name, never called by Python code directly
+ *
+ * Arguments: name - A "real" X509_NAME object
+ * dealloc - Boolean value to specify whether the destructor should
+ * free the "real" X509_NAME object
+ * Returns: The newly created X509Name object
+ */
+crypto_X509NameObj *
+crypto_X509Name_New(X509_NAME *name, int dealloc)
+{
+ crypto_X509NameObj *self;
+
+ self = PyObject_GC_New(crypto_X509NameObj, &crypto_X509Name_Type);
+
+ if (self == NULL)
+ return NULL;
+
+ self->x509_name = name;
+ self->dealloc = dealloc;
+ self->parent_cert = NULL;
+
+ PyObject_GC_Track(self);
+ return self;
+}
+
+/*
+ * Return a name string given a X509_NAME object and a name identifier. Used
+ * by the getattr function.
+ *
+ * Arguments: name - The X509_NAME object
+ * nid - The name identifier
+ * Returns: The name as a Python string object
+ */
+static int
+get_name_by_nid(X509_NAME *name, int nid, char **utf8string)
+{
+ int entry_idx;
+ X509_NAME_ENTRY *entry;
+ ASN1_STRING *data;
+ int len;
+
+ if ((entry_idx = X509_NAME_get_index_by_NID(name, nid, -1)) == -1)
+ {
+ return 0;
+ }
+ entry = X509_NAME_get_entry(name, entry_idx);
+ data = X509_NAME_ENTRY_get_data(entry);
+ if ((len = ASN1_STRING_to_UTF8((unsigned char **)utf8string, data)) < 0)
+ {
+ exception_from_error_queue();
+ return -1;
+ }
+
+ return len;
+}
+
+/*
+ * Given a X509_NAME object and a name identifier, set the corresponding
+ * attribute to the given string. Used by the setattr function.
+ *
+ * Arguments: name - The X509_NAME object
+ * nid - The name identifier
+ * value - The string to set
+ * Returns: 0 for success, -1 on failure
+ */
+static int
+set_name_by_nid(X509_NAME *name, int nid, char *utf8string)
+{
+ X509_NAME_ENTRY *ne;
+ int i, entry_count, temp_nid;
+
+ /* If there's an old entry for this NID, remove it */
+ entry_count = X509_NAME_entry_count(name);
+ for (i = 0; i < entry_count; i++)
+ {
+ ne = X509_NAME_get_entry(name, i);
+ temp_nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(ne));
+ if (temp_nid == nid)
+ {
+ ne = X509_NAME_delete_entry(name, i);
+ X509_NAME_ENTRY_free(ne);
+ break;
+ }
+ }
+
+ /* Add the new entry */
+ if (!X509_NAME_add_entry_by_NID(name, nid, MBSTRING_UTF8, utf8string,
+ -1, -1, 0))
+ {
+ exception_from_error_queue();
+ return -1;
+ }
+ return 0;
+}
+
+
+/*
+ * Find attribute. An X509Name object has the following attributes:
+ * countryName (alias C), stateOrProvince (alias ST), locality (alias L),
+ * organization (alias O), organizationalUnit (alias OU), commonName (alias
+ * CN) and more...
+ *
+ * Arguments: self - The X509Name object
+ * name - The attribute name
+ * Returns: A Python object for the attribute, or NULL if something went
+ * wrong
+ */
+static PyObject *
+crypto_X509Name_getattr(crypto_X509NameObj *self, char *name)
+{
+ int nid, len;
+ char *utf8string;
+
+ if ((nid = OBJ_txt2nid(name)) == NID_undef)
+ {
+ PyErr_SetString(PyExc_AttributeError, "No such attribute");
+ return NULL;
+ }
+
+ len = get_name_by_nid(self->x509_name, nid, &utf8string);
+ if (len < 0)
+ return NULL;
+ else if (len == 0)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ else
+ return PyUnicode_Decode(utf8string, len, "utf-8", NULL);
+}
+
+/*
+ * Set attribute
+ *
+ * Arguments: self - The X509Name object
+ * name - The attribute name
+ * value - The value to set
+ */
+static int
+crypto_X509Name_setattr(crypto_X509NameObj *self, char *name, PyObject *value)
+{
+ int nid;
+ char *buffer;
+
+ if ((nid = OBJ_txt2nid(name)) == NID_undef)
+ {
+ PyErr_SetString(PyExc_AttributeError, "No such attribute");
+ return -1;
+ }
+
+ /* Something of a hack to get nice unicode behaviour */
+ if (!PyArg_Parse(value, "es:setattr", "utf-8", &buffer))
+ return -1;
+
+ return set_name_by_nid(self->x509_name, nid, buffer);
+}
+
+/*
+ * Compare two X509Name structures.
+ *
+ * Arguments: n - The first X509Name
+ * m - The second X509Name
+ * Returns: <0 if n < m, 0 if n == m and >0 if n > m
+ */
+static int
+crypto_X509Name_compare(crypto_X509NameObj *n, crypto_X509NameObj *m)
+{
+ return X509_NAME_cmp(n->x509_name, m->x509_name);
+}
+
+/*
+ * String representation of an X509Name
+ *
+ * Arguments: self - The X509Name object
+ * Returns: A string representation of the object
+ */
+static PyObject *
+crypto_X509Name_repr(crypto_X509NameObj *self)
+{
+ char tmpbuf[512] = "";
+ char realbuf[512+64];
+
+ if (X509_NAME_oneline(self->x509_name, tmpbuf, 512) == NULL)
+ {
+ exception_from_error_queue();
+ return NULL;
+ }
+ else
+ {
+ /* This is safe because tmpbuf is max 512 characters */
+ sprintf(realbuf, "<X509Name object '%s'>", tmpbuf);
+ return PyString_FromString(realbuf);
+ }
+}
+
+/*
+ * Call the visitproc on all contained objects.
+ *
+ * Arguments: self - The Connection object
+ * visit - Function to call
+ * arg - Extra argument to visit
+ * Returns: 0 if all goes well, otherwise the return code from the first
+ * call that gave non-zero result.
+ */
+static int
+crypto_X509Name_traverse(crypto_X509NameObj *self, visitproc visit, void *arg)
+{
+ int ret = 0;
+
+ if (ret == 0 && self->parent_cert != NULL)
+ ret = visit(self->parent_cert, arg);
+ return ret;
+}
+
+/*
+ * Decref all contained objects and zero the pointers.
+ *
+ * Arguments: self - The Connection object
+ * Returns: Always 0.
+ */
+static int
+crypto_X509Name_clear(crypto_X509NameObj *self)
+{
+ Py_XDECREF(self->parent_cert);
+ self->parent_cert = NULL;
+ return 0;
+}
+
+/*
+ * Deallocate the memory used by the X509Name object
+ *
+ * Arguments: self - The X509Name object
+ * Returns: None
+ */
+static void
+crypto_X509Name_dealloc(crypto_X509NameObj *self)
+{
+ PyObject_GC_UnTrack(self);
+ /* Sometimes we don't have to dealloc this */
+ if (self->dealloc)
+ X509_NAME_free(self->x509_name);
+
+ crypto_X509Name_clear(self);
+
+ PyObject_GC_Del(self);
+}
+
+PyTypeObject crypto_X509Name_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "X509Name",
+ sizeof(crypto_X509NameObj),
+ 0,
+ (destructor)crypto_X509Name_dealloc,
+ NULL, /* print */
+ (getattrfunc)crypto_X509Name_getattr,
+ (setattrfunc)crypto_X509Name_setattr,
+ (cmpfunc)crypto_X509Name_compare,
+ (reprfunc)crypto_X509Name_repr,
+ NULL, /* as_number */
+ NULL, /* as_sequence */
+ NULL, /* as_mapping */
+ NULL, /* hash */
+ NULL, /* call */
+ NULL, /* str */
+ NULL, /* getattro */
+ NULL, /* setattro */
+ NULL, /* as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
+ NULL, /* doc */
+ (traverseproc)crypto_X509Name_traverse,
+ (inquiry)crypto_X509Name_clear,
+};
+
+
+/*
+ * Initialize the X509Name part of the crypto module
+ *
+ * Arguments: dict - The crypto module dictionary
+ * Returns: None
+ */
+int
+init_crypto_x509name(PyObject *dict)
+{
+ crypto_X509Name_Type.ob_type = &PyType_Type;
+ Py_INCREF(&crypto_X509Name_Type);
+ PyDict_SetItemString(dict, "X509NameType", (PyObject *)&crypto_X509Name_Type);
+ return 1;
+}