[tin-dev] [PATCH] USE_OPENSSL and cert (subject/issuer) with umlauts

Dennis Preiser dennis at d--p.de
Wed Dec 6 16:43:34 CET 2023


Hi there,

at least with OpenSSL the current code doesn't handle umlauts in
certificates (subject/issuer) very well in case of
defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE) (startup messages and
ConnectionInfo 'J'). Umlauts are displayed somehow raw.

Here is how it currently looks like (news.individual.de):

| Subject: /C=DE/ST=Berlin/O=Freie Universit\xC3\xA4t Berlin/CN=news.individual.de
                                            ^^^^^^^^
| Issuer : /C=GB/ST=Greater Manchester/L=Salford/O=Sectigo Limited/CN=Sectigo RSA Organization

I'm not sure whether it's worth the effort in this respect, but the
attached patch changes the behaviour so that at least with
defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE) umlauts are displayed
correctly. The whole output also looks a little more elegant.

Here is the defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE) case:

| Subject: C=DE, ST=Berlin, O=Freie Universität Berlin, CN=news.individual.de
| Issuer : C=GB, ST=Greater Manchester, L=Salford, O=Sectigo Limited, CN=Sectigo RSA Organization

and here the !(defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)) case:

| Subject: C=DE, ST=Berlin, O=Freie Universit\C3\A4t Berlin, CN=news.individual.de
| Issuer : C=GB, ST=Greater Manchester, L=Salford, O=Sectigo Limited, CN=Sectigo RSA Organization

As I only have OpenSSL available, I cannot say whether this is the case
with the other variants. The patch only affects the OpenSSL case.

Dennis
-------------- next part --------------
--- a/src/nntps.c
+++ b/src/nntps.c
@@ -47,6 +47,7 @@ static void log_func(int level, const char *msg);
 #	endif /* DEBUG */
 #else
 #	ifdef USE_OPENSSL
+static char **get_cert_info(const X509 *cert);
 #		ifdef DEBUG
 static void info_callback(const SSL *s, int where, int ret);
 #		endif /* DEBUG */
@@ -533,7 +534,6 @@ err_cert:
 	BIO *client = session_ctx;
 	SSL *ssl;
 	X509 *peer;
-	char name[128];
 
 	ERR_clear_error();
 
@@ -561,8 +561,15 @@ err_cert:
 	peer = SSL_get_peer_certificate(ssl);
 	if (peer) {
 		if (!batch_mode || verbose) {
-			wait_message(0, _(txt_conninfo_subject), X509_NAME_oneline(X509_get_subject_name(peer), name, sizeof(name)));
-			wait_message(0, _(txt_conninfo_issuer), X509_NAME_oneline(X509_get_issuer_name(peer), name, sizeof(name)));
+			char **cert_info;
+
+			if ((cert_info = get_cert_info(peer))) {
+				wait_message(0, _(txt_conninfo_subject), BlankIfNull(cert_info[0]));
+				wait_message(0, _(txt_conninfo_issuer), BlankIfNull(cert_info[1]));
+				FreeIfNeeded(cert_info[0]);
+				FreeIfNeeded(cert_info[1]);
+				free(cert_info);
+			}
 		}
 		X509_free(peer);
 	}
@@ -899,6 +906,7 @@ err_cert:
 
 	if (chain) {
 		char name[128];
+		char **cert_info;
 		const ASN1_TIME *asn1;
 		int i;
 		struct tm tm;
@@ -909,8 +917,14 @@ err_cert:
 			if (i > 0)
 				fputs("\n", fp);
 			fprintf(fp, _(txt_conninfo_cert), i);
-			fprintf(fp, _(txt_conninfo_subject), X509_NAME_oneline(X509_get_subject_name(cert), name, sizeof(name)));
-			fprintf(fp, _(txt_conninfo_issuer), X509_NAME_oneline(X509_get_issuer_name(cert), name, sizeof(name)));
+
+			if ((cert_info = get_cert_info(cert))) {
+				fprintf(fp, _(txt_conninfo_subject), BlankIfNull(cert_info[0]));
+				fprintf(fp, _(txt_conninfo_issuer), BlankIfNull(cert_info[1]));
+				FreeIfNeeded(cert_info[0]);
+				FreeIfNeeded(cert_info[1]);
+				free(cert_info);
+			}
 
 			asn1 = X509_get0_notBefore(cert);
 			result = ASN1_TIME_to_tm(asn1, &tm);
@@ -937,6 +951,46 @@ err_cert:
 
 
 #ifdef USE_OPENSSL
+static char **
+get_cert_info(
+	const X509 *cert)
+{
+	BIO *io_buf;
+	char **res = NULL;
+	char *tmp, *subject = NULL, *issuer = NULL;
+	long len;
+#if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
+	unsigned long flags = XN_FLAG_ONELINE & ~ASN1_STRFLGS_ESC_MSB & ~XN_FLAG_SPC_EQ;
+#else
+	unsigned long flags = XN_FLAG_ONELINE & ~XN_FLAG_SPC_EQ;
+#endif /* MULTIBYTE_ABLE && !NO_LOCALE */
+
+	if (cert && (io_buf = BIO_new(BIO_s_mem()))) {
+		res = my_malloc(sizeof(char *) * 2);
+		if (X509_NAME_print_ex(io_buf, X509_get_subject_name(cert), 0, flags) != -1) {
+			len = BIO_get_mem_data(io_buf, &tmp);
+			if (len > 0) {
+				subject = my_malloc((size_t) len + 1);
+				memcpy(subject, tmp, len);
+				subject[len] = '\0';
+			}
+		}
+		if (BIO_reset(io_buf) != -1 && X509_NAME_print_ex(io_buf, X509_get_issuer_name(cert), 0, flags) != -1) {
+			len = BIO_get_mem_data(io_buf, &tmp);
+			if (len > 0) {
+				issuer = my_malloc((size_t) len + 1);
+				memcpy(issuer, tmp, len);
+				issuer[len] = '\0';
+			}
+		}
+		res[0] = subject;
+		res[1] = issuer;
+		BIO_free(io_buf);
+	}
+	return res;
+}
+
+
 static void
 show_errors(
 	const char *msg_fmt)


More information about the tin-dev mailing list