From 3077c70f737bf7558227c100123f2eef409c385e Mon Sep 17 00:00:00 2001 From: Alexey Gladkov Date: Thu, 14 May 2020 15:26:19 +0300 Subject: OWL: write(1) improvements * Add prompt/prefix with usernames. * Disable locale support in write(1) entirely for security reasons (dangerous printf formats, control characters, anonymous messages). Signed-off-by: Alexey Gladkov --- term-utils/write.c | 41 +++++++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/term-utils/write.c b/term-utils/write.c index a5a21280c..969f219c7 100644 --- a/term-utils/write.c +++ b/term-utils/write.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -228,7 +229,7 @@ static void signal_handler(int signo) */ static void do_write(const struct write_control *ctl) { - char *login, *pwuid; + char *login, *pwuid, *prompt, *prefix; struct passwd *pwd; time_t now; struct tm *tm; @@ -239,11 +240,29 @@ static void do_write(const struct write_control *ctl) /* Determine our login name(s) before the we reopen() stdout */ if ((pwd = getpwuid(ctl->src_uid)) != NULL) pwuid = pwd->pw_name; - else - pwuid = "???"; + else { + perror("getpwuid"); + pwuid = alloca(4 + sizeof(ctl->src_uid) * CHAR_BIT / 3 + 1 + 1); + if (!pwuid) + exit(1); + sprintf(pwuid, "UID %u", ctl->src_uid); + } if ((login = getlogin()) == NULL) login = pwuid; + if (isatty(STDIN_FILENO)) { + prompt = alloca(strlen(ctl->dst_login) + 2 + 1); + if (!prompt) + exit(1); + sprintf(prompt, "%s> ", ctl->dst_login); + } else + prompt = ""; + + prefix = alloca(strlen(login) + 3 + 1); + if (!prefix) + exit(1); + sprintf(prefix, "<%s> ", login); + if ((freopen(ctl->dst_tty_path, "w", stdout)) == NULL) err(EXIT_FAILURE, "%s", ctl->dst_tty_path); @@ -272,15 +291,26 @@ static void do_write(const struct write_control *ctl) free(host); printf("\r\n"); + fprintf(stderr, "%s", prompt); while (getline(&line, &linelen, stdin) >= 0) { if (signal_received) break; + fputs_careful(prefix, stdout, '^', true, 0); + if (fputs_careful(line, stdout, '^', true, 0) == EOF) err(EXIT_FAILURE, _("carefulputc failed")); + + if (!strchr(line, '\n')) { + fputs_careful("\n", stdout, '^', true, 0); + fputc('\n', stderr); + } + fprintf(stderr, "%s", prompt); } free(line); printf("EOF\r\n"); + if (isatty(STDIN_FILENO)) + fputc('\n', stderr); } int main(int argc, char **argv) @@ -294,9 +324,8 @@ int main(int argc, char **argv) {NULL, 0, NULL, 0} }; - setlocale(LC_ALL, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); + unsetenv("TZ"); + setlocale(LC_CTYPE, ""); close_stdout_atexit(); while ((c = getopt_long(argc, argv, "Vh", longopts, NULL)) != -1) -- 2.25.4