summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2017-08-01 11:29:26 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2017-08-07 09:40:47 +0200
commitc427e872e7543a0cad398869522e6328fb631b6c (patch)
treeafa31c30acef2ff9b075620abfe26769926e0b12
parentfd0fc5060b4d0fda6d86b234cdd13ac038bb20b3 (diff)
downloadgnutls-c427e872e7543a0cad398869522e6328fb631b6c.tar.gz
x509: separated PKIX1 attributes parsing code for cert request handling
This allows other code to utilize it. Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
-rw-r--r--lib/x509/Makefile.am2
-rw-r--r--lib/x509/attributes.c299
-rw-r--r--lib/x509/attributes.h30
-rw-r--r--lib/x509/crq.c270
4 files changed, 335 insertions, 266 deletions
diff --git a/lib/x509/Makefile.am b/lib/x509/Makefile.am
index 8bf2e04b8b..2a775eacc7 100644
--- a/lib/x509/Makefile.am
+++ b/lib/x509/Makefile.am
@@ -42,6 +42,8 @@ libgnutls_x509_la_SOURCES = \
crl_write.c \
crq.c \
dn.c \
+ attributes.c \
+ attributes.h \
extensions.c \
mpi.c \
output.c \
diff --git a/lib/x509/attributes.c b/lib/x509/attributes.c
new file mode 100644
index 0000000000..4d116be4ec
--- /dev/null
+++ b/lib/x509/attributes.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2003-2016 Free Software Foundation, Inc.
+ * Copyright (C) 2012-2016 Nikos Mavrogiannopoulos
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "gnutls_int.h"
+
+#include <datum.h>
+#include "errors.h"
+#include <common.h>
+#include <x509.h>
+#include "x509_int.h"
+#include "attributes.h"
+
+/* Functions to parse and set the PKIX1 Attributes structure.
+ */
+
+/* Overwrite the given attribute (using the index)
+ * index here starts from one.
+ */
+static int
+overwrite_attribute(ASN1_TYPE asn, const char *root, unsigned indx,
+ const gnutls_datum_t * ext_data)
+{
+ char name[MAX_NAME_SIZE], name2[MAX_NAME_SIZE];
+ int result;
+
+ snprintf(name, sizeof(name), "%s.?%u", root, indx);
+
+ _gnutls_str_cpy(name2, sizeof(name2), name);
+ _gnutls_str_cat(name2, sizeof(name2), ".values.?LAST");
+
+ result = _gnutls_x509_write_value(asn, name2, ext_data);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+
+ return 0;
+}
+
+/* Parses an Attribute list in the asn1_struct, and searches for the
+ * given OID. The index indicates the attribute value to be returned.
+ *
+ * If raw==0 only printable data are returned, or
+ * GNUTLS_E_X509_UNSUPPORTED_ATTRIBUTE.
+ *
+ * asn1_attr_name must be a string in the form
+ * "certificationRequestInfo.attributes"
+ *
+ */
+int
+_x509_parse_attribute(ASN1_TYPE asn1_struct,
+ const char *attr_name, const char *given_oid, unsigned indx,
+ int raw, gnutls_datum_t * out)
+{
+ int k1, result;
+ char tmpbuffer1[MAX_NAME_SIZE];
+ char tmpbuffer3[MAX_NAME_SIZE];
+ char value[200];
+ gnutls_datum_t td;
+ char oid[MAX_OID_SIZE];
+ int len;
+
+ k1 = 0;
+ do {
+
+ k1++;
+ /* create a string like "attribute.?1"
+ */
+ if (attr_name[0] != 0)
+ snprintf(tmpbuffer1, sizeof(tmpbuffer1), "%s.?%u",
+ attr_name, k1);
+ else
+ snprintf(tmpbuffer1, sizeof(tmpbuffer1), "?%u",
+ k1);
+
+ len = sizeof(value) - 1;
+ result =
+ asn1_read_value(asn1_struct, tmpbuffer1, value, &len);
+
+ if (result == ASN1_ELEMENT_NOT_FOUND) {
+ gnutls_assert();
+ break;
+ }
+
+ if (result != ASN1_VALUE_NOT_FOUND) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ /* Move to the attibute type and values
+ */
+ /* Read the OID
+ */
+ _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3),
+ tmpbuffer1);
+ _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3), ".type");
+
+ len = sizeof(oid) - 1;
+ result =
+ asn1_read_value(asn1_struct, tmpbuffer3, oid, &len);
+
+ if (result == ASN1_ELEMENT_NOT_FOUND)
+ break;
+ else if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ if (strcmp(oid, given_oid) == 0) { /* Found the OID */
+
+ /* Read the Value
+ */
+ snprintf(tmpbuffer3, sizeof(tmpbuffer3),
+ "%s.values.?%u", tmpbuffer1, indx + 1);
+
+ len = sizeof(value) - 1;
+ result =
+ _gnutls_x509_read_value(asn1_struct,
+ tmpbuffer3, &td);
+
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ if (raw == 0) {
+ result =
+ _gnutls_x509_dn_to_string
+ (oid, td.data, td.size, out);
+
+ _gnutls_free_datum(&td);
+
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+ return 0;
+ } else { /* raw!=0 */
+ out->data = td.data;
+ out->size = td.size;
+
+ return 0;
+ }
+ }
+
+ }
+ while (1);
+
+ gnutls_assert();
+
+ result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+
+ cleanup:
+ return result;
+}
+
+/* This function will attempt to set the requested attribute in
+ * the given X509v3 certificate.
+ *
+ * Critical will be either 0 or 1.
+ */
+static int
+add_attribute(ASN1_TYPE asn, const char *root, const char *attribute_id,
+ const gnutls_datum_t * ext_data)
+{
+ int result;
+ char name[MAX_NAME_SIZE];
+
+ snprintf(name, sizeof(name), "%s", root);
+
+ /* Add a new attribute in the list.
+ */
+ result = asn1_write_value(asn, name, "NEW", 1);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ snprintf(name, sizeof(name), "%s.?LAST.type", root);
+
+ result = asn1_write_value(asn, name, attribute_id, 1);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ snprintf(name, sizeof(name), "%s.?LAST.values", root);
+
+ result = asn1_write_value(asn, name, "NEW", 1);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ snprintf(name, sizeof(name), "%s.?LAST.values.?LAST", root);
+
+ result = _gnutls_x509_write_value(asn, name, ext_data);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ return 0;
+}
+
+
+int
+_x509_set_attribute(ASN1_TYPE asn, const char *root,
+ const char *ext_id, const gnutls_datum_t * ext_data)
+{
+ int result;
+ int k, len;
+ char name[MAX_NAME_SIZE], name2[MAX_NAME_SIZE];
+ char extnID[MAX_OID_SIZE];
+
+ /* Find the index of the given attribute.
+ */
+ k = 0;
+ do {
+ k++;
+
+ snprintf(name, sizeof(name), "%s.?%u", root, k);
+
+ len = sizeof(extnID) - 1;
+ result = asn1_read_value(asn, name, extnID, &len);
+
+ /* move to next
+ */
+
+ if (result == ASN1_ELEMENT_NOT_FOUND) {
+ break;
+ }
+
+ do {
+
+ _gnutls_str_cpy(name2, sizeof(name2), name);
+ _gnutls_str_cat(name2, sizeof(name2), ".type");
+
+ len = sizeof(extnID) - 1;
+ result = asn1_read_value(asn, name2, extnID, &len);
+
+ if (result == ASN1_ELEMENT_NOT_FOUND) {
+ gnutls_assert();
+ break;
+ } else if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ /* Handle Extension
+ */
+ if (strcmp(extnID, ext_id) == 0) {
+ /* attribute was found
+ */
+ return overwrite_attribute(asn, root, k,
+ ext_data);
+ }
+
+
+ }
+ while (0);
+ }
+ while (1);
+
+ if (result == ASN1_ELEMENT_NOT_FOUND) {
+ return add_attribute(asn, root, ext_id, ext_data);
+ } else {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+
+ return 0;
+}
diff --git a/lib/x509/attributes.h b/lib/x509/attributes.h
new file mode 100644
index 0000000000..3d2591b6c7
--- /dev/null
+++ b/lib/x509/attributes.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+int
+_x509_parse_attribute(ASN1_TYPE asn1_struct,
+ const char *attr_name, const char *given_oid, unsigned indx,
+ int raw, gnutls_datum_t * out);
+
+int
+_x509_set_attribute(ASN1_TYPE asn, const char *root,
+ const char *ext_id, const gnutls_datum_t * ext_data);
diff --git a/lib/x509/crq.c b/lib/x509/crq.c
index a4150649d7..b73096a307 100644
--- a/lib/x509/crq.c
+++ b/lib/x509/crq.c
@@ -38,6 +38,7 @@
#include "x509_int.h"
#include <libtasn1.h>
#include <pk.h>
+#include "attributes.h"
/**
* gnutls_x509_crq_init:
@@ -418,126 +419,6 @@ gnutls_x509_crq_get_dn_oid(gnutls_x509_crq_t crq,
indx, oid, sizeof_oid);
}
-/* Parses an Attribute list in the asn1_struct, and searches for the
- * given OID. The index indicates the attribute value to be returned.
- *
- * If raw==0 only printable data are returned, or
- * GNUTLS_E_X509_UNSUPPORTED_ATTRIBUTE.
- *
- * asn1_attr_name must be a string in the form
- * "certificationRequestInfo.attributes"
- *
- */
-static int
-parse_attribute(ASN1_TYPE asn1_struct,
- const char *attr_name, const char *given_oid, unsigned indx,
- int raw, gnutls_datum_t * out)
-{
- int k1, result;
- char tmpbuffer1[MAX_NAME_SIZE];
- char tmpbuffer3[MAX_NAME_SIZE];
- char value[200];
- gnutls_datum_t td;
- char oid[MAX_OID_SIZE];
- int len;
-
- k1 = 0;
- do {
-
- k1++;
- /* create a string like "attribute.?1"
- */
- if (attr_name[0] != 0)
- snprintf(tmpbuffer1, sizeof(tmpbuffer1), "%s.?%u",
- attr_name, k1);
- else
- snprintf(tmpbuffer1, sizeof(tmpbuffer1), "?%u",
- k1);
-
- len = sizeof(value) - 1;
- result =
- asn1_read_value(asn1_struct, tmpbuffer1, value, &len);
-
- if (result == ASN1_ELEMENT_NOT_FOUND) {
- gnutls_assert();
- break;
- }
-
- if (result != ASN1_VALUE_NOT_FOUND) {
- gnutls_assert();
- result = _gnutls_asn2err(result);
- goto cleanup;
- }
-
- /* Move to the attibute type and values
- */
- /* Read the OID
- */
- _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3),
- tmpbuffer1);
- _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3), ".type");
-
- len = sizeof(oid) - 1;
- result =
- asn1_read_value(asn1_struct, tmpbuffer3, oid, &len);
-
- if (result == ASN1_ELEMENT_NOT_FOUND)
- break;
- else if (result != ASN1_SUCCESS) {
- gnutls_assert();
- result = _gnutls_asn2err(result);
- goto cleanup;
- }
-
- if (strcmp(oid, given_oid) == 0) { /* Found the OID */
-
- /* Read the Value
- */
- snprintf(tmpbuffer3, sizeof(tmpbuffer3),
- "%s.values.?%u", tmpbuffer1, indx + 1);
-
- len = sizeof(value) - 1;
- result =
- _gnutls_x509_read_value(asn1_struct,
- tmpbuffer3, &td);
-
- if (result != ASN1_SUCCESS) {
- gnutls_assert();
- result = _gnutls_asn2err(result);
- goto cleanup;
- }
-
- if (raw == 0) {
- result =
- _gnutls_x509_dn_to_string
- (oid, td.data, td.size, out);
-
- _gnutls_free_datum(&td);
-
- if (result < 0) {
- gnutls_assert();
- goto cleanup;
- }
- return 0;
- } else { /* raw!=0 */
- out->data = td.data;
- out->size = td.size;
-
- return 0;
- }
- }
-
- }
- while (1);
-
- gnutls_assert();
-
- result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
-
- cleanup:
- return result;
-}
-
/**
* gnutls_x509_crq_get_challenge_password:
* @crq: should contain a #gnutls_x509_crq_t type
@@ -564,7 +445,7 @@ gnutls_x509_crq_get_challenge_password(gnutls_x509_crq_t crq,
}
ret =
- parse_attribute(crq->crq,
+ _x509_parse_attribute(crq->crq,
"certificationRequestInfo.attributes",
"1.2.840.113549.1.9.7", 0, 0, &td);
if (ret < 0)
@@ -573,149 +454,6 @@ gnutls_x509_crq_get_challenge_password(gnutls_x509_crq_t crq,
return _gnutls_strdatum_to_buf(&td, pass, pass_size);
}
-/* This function will attempt to set the requested attribute in
- * the given X509v3 certificate.
- *
- * Critical will be either 0 or 1.
- */
-static int
-add_attribute(ASN1_TYPE asn, const char *root, const char *attribute_id,
- const gnutls_datum_t * ext_data)
-{
- int result;
- char name[MAX_NAME_SIZE];
-
- snprintf(name, sizeof(name), "%s", root);
-
- /* Add a new attribute in the list.
- */
- result = asn1_write_value(asn, name, "NEW", 1);
- if (result != ASN1_SUCCESS) {
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
-
- snprintf(name, sizeof(name), "%s.?LAST.type", root);
-
- result = asn1_write_value(asn, name, attribute_id, 1);
- if (result != ASN1_SUCCESS) {
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
-
- snprintf(name, sizeof(name), "%s.?LAST.values", root);
-
- result = asn1_write_value(asn, name, "NEW", 1);
- if (result != ASN1_SUCCESS) {
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
-
- snprintf(name, sizeof(name), "%s.?LAST.values.?LAST", root);
-
- result = _gnutls_x509_write_value(asn, name, ext_data);
- if (result < 0) {
- gnutls_assert();
- return result;
- }
-
- return 0;
-}
-
-/* Overwrite the given attribute (using the index)
- * index here starts from one.
- */
-static int
-overwrite_attribute(ASN1_TYPE asn, const char *root, unsigned indx,
- const gnutls_datum_t * ext_data)
-{
- char name[MAX_NAME_SIZE], name2[MAX_NAME_SIZE];
- int result;
-
- snprintf(name, sizeof(name), "%s.?%u", root, indx);
-
- _gnutls_str_cpy(name2, sizeof(name2), name);
- _gnutls_str_cat(name2, sizeof(name2), ".values.?LAST");
-
- result = _gnutls_x509_write_value(asn, name2, ext_data);
- if (result < 0) {
- gnutls_assert();
- return result;
- }
-
-
- return 0;
-}
-
-static int
-set_attribute(ASN1_TYPE asn, const char *root,
- const char *ext_id, const gnutls_datum_t * ext_data)
-{
- int result;
- int k, len;
- char name[MAX_NAME_SIZE], name2[MAX_NAME_SIZE];
- char extnID[MAX_OID_SIZE];
-
- /* Find the index of the given attribute.
- */
- k = 0;
- do {
- k++;
-
- snprintf(name, sizeof(name), "%s.?%u", root, k);
-
- len = sizeof(extnID) - 1;
- result = asn1_read_value(asn, name, extnID, &len);
-
- /* move to next
- */
-
- if (result == ASN1_ELEMENT_NOT_FOUND) {
- break;
- }
-
- do {
-
- _gnutls_str_cpy(name2, sizeof(name2), name);
- _gnutls_str_cat(name2, sizeof(name2), ".type");
-
- len = sizeof(extnID) - 1;
- result = asn1_read_value(asn, name2, extnID, &len);
-
- if (result == ASN1_ELEMENT_NOT_FOUND) {
- gnutls_assert();
- break;
- } else if (result != ASN1_SUCCESS) {
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
-
- /* Handle Extension
- */
- if (strcmp(extnID, ext_id) == 0) {
- /* attribute was found
- */
- return overwrite_attribute(asn, root, k,
- ext_data);
- }
-
-
- }
- while (0);
- }
- while (1);
-
- if (result == ASN1_ELEMENT_NOT_FOUND) {
- return add_attribute(asn, root, ext_id, ext_data);
- } else {
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
-
-
- return 0;
-}
-
/**
* gnutls_x509_crq_set_attribute_by_oid:
* @crq: should contain a #gnutls_x509_crq_t type
@@ -748,7 +486,7 @@ gnutls_x509_crq_set_attribute_by_oid(gnutls_x509_crq_t crq,
return GNUTLS_E_INVALID_REQUEST;
}
- return set_attribute(crq->crq,
+ return _x509_set_attribute(crq->crq,
"certificationRequestInfo.attributes", oid,
&data);
}
@@ -786,7 +524,7 @@ gnutls_x509_crq_get_attribute_by_oid(gnutls_x509_crq_t crq,
}
ret =
- parse_attribute(crq->crq,
+ _x509_parse_attribute(crq->crq,
"certificationRequestInfo.attributes", oid,
indx, 1, &td);
if (ret < 0)