From f726e20d85e366d43983080618b3258ac160fb8f 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 --- util-linux/term-utils/write.c | 41 +++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/util-linux/term-utils/write.c b/util-linux/term-utils/write.c index ee31580f..68ae5f42 100644 --- a/util-linux/term-utils/write.c +++ b/util-linux/term-utils/write.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -243,21 +244,39 @@ static void write_line(char *s) */ 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; - char *host, line[512]; + char *host, line[BUFSIZ - 1]; struct sigaction sigact; /* 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); @@ -286,12 +305,21 @@ static void do_write(const struct write_control *ctl) free(host); printf("\r\n"); + fprintf(stderr, "%s", prompt); while (fgets(line, sizeof(line), stdin) != NULL) { if (signal_received) break; + write_line(prefix); write_line(line); + if (!strchr(line, '\n')) { + write_line("\n"); + fputc('\n', stderr); + } + fprintf(stderr, "%s", prompt); } printf("EOF\r\n"); + if (isatty(STDIN_FILENO)) + fputc('\n', stderr); } int main(int argc, char **argv) @@ -305,9 +333,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