summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2016-07-19 15:35:44 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2016-10-31 17:01:14 +0100
commit5e8009a103a77c22b3877f2b2929ac5b4833d7a2 (patch)
treeef8364ca5c30afb4462fb918c6432929a7b32958 /lib
parent1e84b90feed97ee458b7113665300e6bc444798f (diff)
downloadgnutls-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.c64
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)