summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2016-10-31 13:00:14 +0100
committerNikos Mavrogiannopoulos <nmav@redhat.com>2016-10-31 17:01:22 +0100
commit3e153d4f2564cd0b62c0c5be9c92ce7de8ca1a59 (patch)
treea876852afbeaf9ff73f59b61ce070c551c55eb1b
parent5e8009a103a77c22b3877f2b2929ac5b4833d7a2 (diff)
downloadgnutls-3e153d4f2564cd0b62c0c5be9c92ce7de8ca1a59.tar.gz
gnutls_x509_crt_set_*dn, gnutls_x509_dn_set_str: honor the reverse property of RFC4514
When converting an RFC4514 string to a DN ensure that the elements are encoded in reverse order, as required by the RFC. Resolves #111
-rw-r--r--lib/x509/x509_dn.c76
1 files changed, 64 insertions, 12 deletions
diff --git a/lib/x509/x509_dn.c b/lib/x509/x509_dn.c
index c3737dd307..4fa90e5d4b 100644
--- a/lib/x509/x509_dn.c
+++ b/lib/x509/x509_dn.c
@@ -109,7 +109,8 @@ int dn_attr_crt_set(set_dn_func f, void *crt, const gnutls_datum_t * name,
}
static int read_attr_and_val(const char **ptr,
- gnutls_datum_t * name, gnutls_datum_t * val, unsigned *is_raw)
+ gnutls_datum_t *name, gnutls_datum_t *val,
+ unsigned *is_raw)
{
const unsigned char *p = (void *) *ptr;
@@ -164,6 +165,30 @@ static int read_attr_and_val(const char **ptr,
return 0;
}
+typedef struct elem_list_st {
+ gnutls_datum_t name;
+ gnutls_datum_t val;
+ const char *pos;
+ unsigned is_raw;
+ struct elem_list_st *next;
+} elem_list_st;
+
+static int add_new_elem(elem_list_st **head, const gnutls_datum_t *name, const gnutls_datum_t *val, const char *pos, unsigned is_raw)
+{
+ elem_list_st *elem = gnutls_malloc(sizeof(*elem));
+ if (elem == NULL)
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+ memcpy(&elem->name, name, sizeof(*name));
+ memcpy(&elem->val, val, sizeof(*val));
+ elem->pos = pos;
+ elem->is_raw = is_raw;
+ elem->next = *head;
+ *head = elem;
+
+ return 0;
+}
+
static int
crt_set_dn(set_dn_func f, void *crt, const char *dn, const char **err)
{
@@ -171,10 +196,15 @@ crt_set_dn(set_dn_func f, void *crt, const char *dn, const char **err)
int ret;
gnutls_datum_t name, val;
unsigned is_raw;
+ elem_list_st *list = NULL, *plist, *next;
if (crt == NULL || dn == NULL)
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ /* We parse the string and set all elements to a linked list in
+ * reverse order. That way we can encode in reverse order,
+ * the way RFC4514 requires. */
+
/* For each element */
while (*p != 0 && *p != '\n') {
if (err)
@@ -182,27 +212,49 @@ crt_set_dn(set_dn_func f, void *crt, const char *dn, const char **err)
is_raw = 0;
ret = read_attr_and_val(&p, &name, &val, &is_raw);
- if (ret < 0)
- return gnutls_assert_val(ret);
+ if (ret < 0) {
+ gnutls_assert();
+ goto fail;
+ }
/* skip spaces and look for comma */
while (c_isspace(*p))
p++;
- ret = dn_attr_crt_set(f, crt, &name, &val, is_raw);
- if (ret < 0)
- return gnutls_assert_val(ret);
-
- if (err)
- *err = p;
+ ret = add_new_elem(&list, &name, &val, p, is_raw);
+ if (ret < 0) {
+ gnutls_assert();
+ goto fail;
+ }
- if (*p != ',' && *p != 0 && *p != '\n')
- return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+ if (*p != ',' && *p != 0 && *p != '\n') {
+ ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+ goto fail;
+ }
if (*p == ',')
p++;
}
- return 0;
+ plist = list;
+ while(plist) {
+ if (err)
+ *err = plist->pos;
+ ret = dn_attr_crt_set(f, crt, &plist->name, &plist->val, plist->is_raw);
+ if (ret < 0)
+ goto fail;
+
+ plist = plist->next;
+ }
+
+ ret = 0;
+fail:
+ plist = list;
+ while(plist) {
+ next = plist->next;
+ gnutls_free(plist);
+ plist = next;
+ }
+ return ret;
}