From 2aa91df406a8c907b53d01773b1b860117542c48 Mon Sep 17 00:00:00 2001 From: "Dr. David von Oheimb" Date: Wed, 2 Sep 2020 14:18:34 +0200 Subject: [PATCH] X509_NAME_oneline(): Fix output of multi-valued RDNs, escaping '/' and '+' in values Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/12769) --- crypto/x509/x509_obj.c | 26 ++++++++++++++++---------- doc/man3/X509_NAME_print_ex.pod | 23 ++++++++++++----------- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/crypto/x509/x509_obj.c b/crypto/x509/x509_obj.c index c1e893bf136..7bed79a2d52 100644 --- a/crypto/x509/x509_obj.c +++ b/crypto/x509/x509_obj.c @@ -13,6 +13,7 @@ #include #include #include "crypto/x509.h" +#include "crypto/ctype.h" DEFINE_STACK_OF(X509_NAME_ENTRY) @@ -28,6 +29,7 @@ char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len) const X509_NAME_ENTRY *ne; int i; int n, lold, l, l1, l2, num, j, type; + int prev_set = -1; const char *s; char *p; unsigned char *q; @@ -109,14 +111,11 @@ char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len) if (!gs_doit[j & 3]) continue; l2++; -#ifndef CHARSET_EBCDIC - if ((q[j] < ' ') || (q[j] > '~')) - l2 += 3; -#else - if ((os_toascii[q[j]] < os_toascii[' ']) || - (os_toascii[q[j]] > os_toascii['~'])) + if (q[j] == '/' || q[j] == '+') + l2++; /* char needs to be escaped */ + else if ((ossl_toascii(q[j]) < ossl_toascii(' ')) || + (ossl_toascii(q[j]) > ossl_toascii('~'))) l2 += 3; -#endif } lold = l; @@ -133,7 +132,7 @@ char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len) break; } else p = &(buf[lold]); - *(p++) = '/'; + *(p++) = prev_set == ne->set ? '+' : '/'; memcpy(p, s, (unsigned int)l1); p += l1; *(p++) = '='; @@ -152,8 +151,11 @@ char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len) *(p++) = 'x'; *(p++) = hex[(n >> 4) & 0x0f]; *(p++) = hex[n & 0x0f]; - } else + } else { + if (n == '/' || n == '+') + *(p++) = '\\'; *(p++) = n; + } #else n = os_toascii[q[j]]; if ((n < os_toascii[' ']) || (n > os_toascii['~'])) { @@ -161,11 +163,15 @@ char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len) *(p++) = 'x'; *(p++) = hex[(n >> 4) & 0x0f]; *(p++) = hex[n & 0x0f]; - } else + } else { + if (n == os_toascii['/'] || n == os_toascii['+']) + *(p++) = '\\'; *(p++) = q[j]; + } #endif } *p = '\0'; + prev_set = ne->set; } if (b != NULL) { p = b->data; diff --git a/doc/man3/X509_NAME_print_ex.pod b/doc/man3/X509_NAME_print_ex.pod index e5bdf1d5823..ccb4b5629ab 100644 --- a/doc/man3/X509_NAME_print_ex.pod +++ b/doc/man3/X509_NAME_print_ex.pod @@ -18,27 +18,28 @@ X509_NAME_oneline - X509_NAME printing routines =head1 DESCRIPTION -X509_NAME_print_ex() prints a human readable version of B to BIO B. -Each line (for multiline formats) is indented by B spaces. The -output format can be extensively customised by use of the B parameter. +X509_NAME_print_ex() prints a human readable version of I to BIO I. +Each line (for multiline formats) is indented by I spaces. The +output format can be extensively customised by use of the I parameter. X509_NAME_print_ex_fp() is identical to X509_NAME_print_ex() -except the output is written to FILE pointer B. +except the output is written to FILE pointer I. -X509_NAME_oneline() prints an ASCII version of B to B. -If B is B then a buffer is dynamically allocated and returned, and -B is ignored. -Otherwise, at most B bytes will be written, including the ending '\0', -and B is returned. +X509_NAME_oneline() prints an ASCII version of I to I. +This supports multi-valued RDNs and escapes B and B<+> characters in values. +If I is B then a buffer is dynamically allocated and returned, and +I is ignored. +Otherwise, at most I bytes will be written, including the ending '\0', +and I is returned. -X509_NAME_print() prints out B to B indenting each line by B +X509_NAME_print() prints out I to I indenting each line by I characters. Multiple lines are used if the output (including indent) exceeds 80 characters. =head1 NOTES The functions X509_NAME_oneline() and X509_NAME_print() -produce a non standard output form, they don't handle multi character fields and +produce a non standard output form, they don't handle multi-character fields and have various quirks and inconsistencies. Their use is strongly discouraged in new applications and they could be deprecated in a future release. -- 2.47.2