diff options
-rw-r--r-- | lib/x509/Makefile.am | 2 | ||||
-rw-r--r-- | lib/x509/attributes.c | 299 | ||||
-rw-r--r-- | lib/x509/attributes.h | 30 | ||||
-rw-r--r-- | lib/x509/crq.c | 270 |
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) |