diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2016-07-19 15:35:44 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2016-10-31 17:01:14 +0100 |
commit | 5e8009a103a77c22b3877f2b2929ac5b4833d7a2 (patch) | |
tree | ef8364ca5c30afb4462fb918c6432929a7b32958 /lib | |
parent | 1e84b90feed97ee458b7113665300e6bc444798f (diff) | |
download | gnutls-5e8009a103a77c22b3877f2b2929ac5b4833d7a2.tar.gz |
Encode string DNs backwards according to RFC4514
This makes the output string from functions such as gnutls_x509_crt_get*dn()
to comply with RFC4514 requirements in DN element order.
Relates #111
Diffstat (limited to 'lib')
-rw-r--r-- | lib/x509/dn.c | 64 |
1 files changed, 36 insertions, 28 deletions
diff --git a/lib/x509/dn.c b/lib/x509/dn.c index 43c09454a0..7209cdb92f 100644 --- a/lib/x509/dn.c +++ b/lib/x509/dn.c @@ -38,7 +38,7 @@ _gnutls_x509_get_dn(ASN1_TYPE asn1_struct, const char *asn1_rdn_name, gnutls_datum_t * dn) { gnutls_buffer_st out_str; - int k2, k1, result; + int k2, k1, result, max_k2; char tmpbuffer1[ASN1_MAX_NAME_SIZE]; char tmpbuffer2[ASN1_MAX_NAME_SIZE]; char tmpbuffer3[ASN1_MAX_NAME_SIZE]; @@ -51,9 +51,20 @@ _gnutls_x509_get_dn(ASN1_TYPE asn1_struct, _gnutls_buffer_init(&out_str); - k1 = 0; - do { - k1++; + result = asn1_number_of_elements(asn1_struct, asn1_rdn_name, &k1); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + if (k1 == 0) { + gnutls_assert(); + result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + goto cleanup; + } + + while (k1 > 0) { /* create a string like "tbsCertList.issuer.rdnSequence.?1" */ if (asn1_rdn_name[0] != 0) @@ -62,21 +73,13 @@ _gnutls_x509_get_dn(ASN1_TYPE asn1_struct, else snprintf(tmpbuffer1, sizeof(tmpbuffer1), "?%u", k1); + k1--; len = sizeof(value) - 1; result = asn1_read_value(asn1_struct, tmpbuffer1, value, &len); - if (result == ASN1_ELEMENT_NOT_FOUND) { - if (k1 == 1) { - gnutls_assert(); - result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; - goto cleanup; - } - break; - } - - if (result != ASN1_VALUE_NOT_FOUND) { + if (result != ASN1_VALUE_NOT_FOUND && result != ASN1_SUCCESS) { /* expected */ gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; @@ -84,6 +87,13 @@ _gnutls_x509_get_dn(ASN1_TYPE asn1_struct, k2 = 0; + result = asn1_number_of_elements(asn1_struct, tmpbuffer1, &max_k2); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + do { /* Move to the attibute type and values */ k2++; @@ -105,7 +115,7 @@ _gnutls_x509_get_dn(ASN1_TYPE asn1_struct, if (result == ASN1_ELEMENT_NOT_FOUND) break; - if (result != ASN1_VALUE_NOT_FOUND) { + if (result != ASN1_VALUE_NOT_FOUND && result != ASN1_SUCCESS) { /* expected */ gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; @@ -159,18 +169,6 @@ _gnutls_x509_get_dn(ASN1_TYPE asn1_struct, * by a comma character (',' ASCII 44). */ - /* Where there is a multi-valued RDN, the outputs from adjoining - * AttributeTypeAndValues are separated by a plus ('+' ASCII 43) - * character. - */ - if (k1 != 1) { /* the first time do not append a comma */ - if (k2 != 1) { /* adjoining multi-value RDN */ - STR_APPEND("+"); - } else { - STR_APPEND(","); - } - } - ldap_desc = gnutls_x509_dn_oid_name(oid, GNUTLS_X509_DN_OID_RETURN_OID); @@ -197,10 +195,20 @@ _gnutls_x509_get_dn(ASN1_TYPE asn1_struct, DATA_APPEND(td.data, td.size); _gnutls_free_datum(&td); _gnutls_free_datum(&tvd); + + /* Where there is a multi-valued RDN, the outputs from adjoining + * AttributeTypeAndValues are separated by a plus ('+' ASCII 43) + * character. + */ + if (k2 < max_k2) { + STR_APPEND("+"); + } else if (k1 > 0) { + STR_APPEND(","); + } + } while (1); } - while (1); result = _gnutls_buffer_to_datum(&out_str, dn, 1); if (result < 0) |