Index | Thread | Search

From:
Damien Miller <djm@mindrot.org>
Subject:
ssh: allow UTF-8 characters in log messages
To:
tech@openbsd.org
Cc:
openssh@openssh.com
Date:
Thu, 13 Aug 2026 11:42:33 +1000

Download raw body.

Thread
Hi,

This allows UTF-8 characters in log messages, either destined to the
TTY or to syslog IFF ssh/sshd is started in a UTF-8 locale. It will
fall back to strnvis() sanitisation of output strings in other cases.

ok?

diff --git a/Makefile.inc b/Makefile.inc
index a642017..3f15128 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -53,6 +53,7 @@ SRCS_BASE+=	sshbuf-getput-basic.c
 SRCS_BASE+=	sshbuf-misc.c
 SRCS_BASE+=	ssherr.c
 SRCS_BASE+=	log.c
+SRCS_BASE+=	utf8.c
 SRCS_BASE+=	xmalloc.c
 SRCS_BASE+=	misc.c
 SRCS_BASE+=	addr.c
diff --git a/log.c b/log.c
index 74ecd5b..2fad5e2 100644
--- a/log.c
+++ b/log.c
@@ -45,10 +45,10 @@
 #include <string.h>
 #include <syslog.h>
 #include <unistd.h>
-#include <vis.h>
 
 #include "log.h"
 #include "match.h"
+#include "utf8.h"
 
 static LogLevel log_level = SYSLOG_LEVEL_INFO;
 static int log_on_stderr = 1;
@@ -361,12 +361,12 @@ do_log(LogLevel level, int force, const char *suffix, const char *fmt,
 		snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", msgbuf, suffix);
 		strlcpy(msgbuf, fmtbuf, sizeof(msgbuf));
 	}
-	strnvis(fmtbuf, msgbuf, sizeof(fmtbuf), VIS_SAFE|VIS_OCTAL);
+	snmprintf(fmtbuf, sizeof(fmtbuf), NULL, "%s", msgbuf);
 	if (log_handler != NULL) {
 		/* Avoid recursion */
 		tmp_handler = log_handler;
 		log_handler = NULL;
-		/* Note: this sends the raw (i.e. no strnvis) log message */
+		/* Note: this sends a raw (i.e. no sanitisation) log message */
 		tmp_handler(level, force, msgbuf, log_handler_ctx);
 		log_handler = tmp_handler;
 	} else if (log_on_stderr) {
diff --git a/scp/Makefile b/scp/Makefile
index 14fa6ac..5809882 100644
--- a/scp/Makefile
+++ b/scp/Makefile
@@ -3,7 +3,7 @@
 .PATH:		${.CURDIR}/..
 
 SRCS=	scp.c
-SRCS+=	fatal.c atomicio.c progressmeter.c utf8.c
+SRCS+=	fatal.c atomicio.c progressmeter.c
 SRCS+=	sftp-common.c sftp-client.c sftp-glob.c
 SRCS+=	ssherr-nolibcrypto.c
 SRCS+=	${SRCS_BASE}
diff --git a/sftp/Makefile b/sftp/Makefile
index 129d054..8369f99 100644
--- a/sftp/Makefile
+++ b/sftp/Makefile
@@ -3,7 +3,7 @@
 .PATH:		${.CURDIR}/..
 
 SRCS=	sftp.c sftp-client.c sftp-common.c sftp-glob.c sftp-usergroup.c
-SRCS+=	atomicio.c cleanup.c fatal.c progressmeter.c utf8.c
+SRCS+=	atomicio.c cleanup.c fatal.c progressmeter.c
 SRCS+=	ssherr-nolibcrypto.c
 SRCS+=	${SRCS_BASE}
 
diff --git a/ssh-add/Makefile b/ssh-add/Makefile
index 05dc0b2..367b360 100644
--- a/ssh-add/Makefile
+++ b/ssh-add/Makefile
@@ -3,7 +3,7 @@
 .PATH:		${.CURDIR}/..
 
 SRCS=	ssh-add.c
-SRCS+=	authfd.c cleanup.c fatal.c readpass.c utf8.c hostfile.c hmac.c
+SRCS+=	authfd.c cleanup.c fatal.c readpass.c hostfile.c hmac.c
 SRCS+=	${SRCS_BASE} ${SRCS_KEY} ${SRCS_KEYP} ${SRCS_KRL} ${SRCS_UTL}
 SRCS+=	${SRCS_SK_CLIENT} ${SRCS_PKCS11_CLIENT}
 
diff --git a/ssh-agent/Makefile b/ssh-agent/Makefile
index 0fbf493..35e00fd 100644
--- a/ssh-agent/Makefile
+++ b/ssh-agent/Makefile
@@ -3,7 +3,7 @@
 .PATH:		${.CURDIR}/..
 
 SRCS=	ssh-agent.c ${SRCS_PKCS11_CLIENT}
-SRCS+=	compat.c fatal.c readpass.c utf8.c misc-agent.c
+SRCS+=	compat.c fatal.c readpass.c misc-agent.c
 SRCS+=	${SRCS_BASE} ${SRCS_KEY} ${SRCS_KEYP} ${SRCS_KRL} ${SRCS_UTL}
 SRCS+=	${SRCS_SK_CLIENT}
 
diff --git a/ssh-keygen/Makefile b/ssh-keygen/Makefile
index 8c9c924..70e7577 100644
--- a/ssh-keygen/Makefile
+++ b/ssh-keygen/Makefile
@@ -4,7 +4,7 @@
 
 SRCS=	ssh-keygen.c ${SRCS_MODULI}
 SRCS+=	authfd.c cleanup.c dns.c fatal.c hmac.c hostfile.c \
-	readpass.c utf8.c sshsig.c
+	readpass.c sshsig.c
 SRCS+=	${SRCS_BASE} ${SRCS_KEY} ${SRCS_KEYP} ${SRCS_KRL} ${SRCS_UTL} \
 	${SRCS_PKCS11} ${SRCS_SK_CLIENT}
 
diff --git a/ssh-keysign/Makefile b/ssh-keysign/Makefile
index 8093090..8b8bb62 100644
--- a/ssh-keysign/Makefile
+++ b/ssh-keysign/Makefile
@@ -4,7 +4,7 @@
 
 SRCS=	ssh-keysign.c readconf.c compat.c
 SRCS+=	cleanup.c fatal.c
-SRCS+=	uidswap.c utf8.c
+SRCS+=	uidswap.c
 SRCS+=	${SRCS_BASE} ${SRCS_KEY} ${SRCS_KEYP} ${SRCS_KRL} ${SRCS_PKT} \
 	${SRCS_UTL} ${SRCS_SK_CLIENT} ${SRCS_PKCS11_CLIENT}
 PROG=	ssh-keysign
diff --git a/ssh/Makefile b/ssh/Makefile
index 8fc7e9d..94c3704 100644
--- a/ssh/Makefile
+++ b/ssh/Makefile
@@ -3,7 +3,7 @@
 .PATH:		${.CURDIR}/..
 
 SRCS=	ssh.c readconf.c clientloop.c sshtty.c sshconnect.c sshconnect2.c mux.c
-SRCS+=	authfd.c compat.c dns.c fatal.c hostfile.c readpass.c utf8.c
+SRCS+=	authfd.c compat.c dns.c fatal.c hostfile.c readpass.c
 SRCS+=	${SRCS_BASE} ${SRCS_KEX} ${SRCS_KEXC} ${SRCS_KEY} ${SRCS_KEYP} \
 	${SRCS_KRL} ${SRCS_PROT} ${SRCS_PKT} ${SRCS_UTL} ${SRCS_PKCS11} \
 	${SRCS_SK_CLIENT}
diff --git a/sshd-auth/Makefile b/sshd-auth/Makefile
index 4c2381d..34852c8 100644
--- a/sshd-auth/Makefile
+++ b/sshd-auth/Makefile
@@ -9,7 +9,7 @@ SRCS=	sshd-auth.c auth2-methods.c \
 	auth2-none.c auth2-passwd.c auth2-pubkey.c auth2-pubkeyfile.c \
 	monitor_wrap.c misc-agent.c \
 	sftp-server.c sftp-common.c sftp-realpath.c
-SRCS+=	authfd.c compat.c dns.c fatal.c hostfile.c readpass.c utf8.c uidswap.c
+SRCS+=	authfd.c compat.c dns.c fatal.c hostfile.c readpass.c uidswap.c
 SRCS+=	${SRCS_BASE} ${SRCS_KEX} ${SRCS_KEXS} ${SRCS_KEY} ${SRCS_KEYP} \
 	${SRCS_KRL} ${SRCS_PROT} ${SRCS_PKT} ${SRCS_UTL} ${SRCS_PKCS11} \
 	${SRCS_SK_CLIENT}
diff --git a/sshd-session/Makefile b/sshd-session/Makefile
index ba38530..e72ed26 100644
--- a/sshd-session/Makefile
+++ b/sshd-session/Makefile
@@ -9,7 +9,7 @@ SRCS=	sshd-session.c auth2-methods.c \
 	auth2-none.c auth2-passwd.c auth2-pubkey.c auth2-pubkeyfile.c \
 	monitor.c monitor_wrap.c \
 	sftp-server.c sftp-common.c sftp-realpath.c srclimit.c
-SRCS+=	authfd.c compat.c dns.c fatal.c hostfile.c readpass.c utf8.c uidswap.c
+SRCS+=	authfd.c compat.c dns.c fatal.c hostfile.c readpass.c uidswap.c
 SRCS+=	misc-agent.c
 SRCS+=	${SRCS_BASE} ${SRCS_KEX} ${SRCS_KEXS} ${SRCS_KEY} ${SRCS_KEYP} \
 	${SRCS_KRL} ${SRCS_PROT} ${SRCS_PKT} ${SRCS_UTL} ${SRCS_PKCS11} \
diff --git a/sshd/Makefile b/sshd/Makefile
index 9049a2f..51bb141 100644
--- a/sshd/Makefile
+++ b/sshd/Makefile
@@ -3,7 +3,7 @@
 .PATH:		${.CURDIR}/..
 
 SRCS=	sshd.c servconf.c sshpty.c srclimit.c groupaccess.c auth2-methods.c
-SRCS+=	dns.c fatal.c compat.c utf8.c authfd.c canohost.c kex-names.c
+SRCS+=	dns.c fatal.c compat.c authfd.c canohost.c kex-names.c
 SRCS+=	${SRCS_BASE} ${SRCS_KEY} ${SRCS_KEYP} ${SRCS_KRL} \
 	${SRCS_MAC} ${SRCS_UTL} ${SRCS_SK_CLIENT} ${SRCS_PKCS11_CLIENT}