util-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] script: move output limit check to dedicated function
@ 2018-08-19 17:16 Asbjørn Sloth Tønnesen
  2018-08-19 17:16 ` [PATCH 2/2] script: add input log feature Asbjørn Sloth Tønnesen
  0 siblings, 1 reply; 4+ messages in thread
From: Asbjørn Sloth Tønnesen @ 2018-08-19 17:16 UTC (permalink / raw)
  To: util-linux; +Cc: Asbjørn Sloth Tønnesen

Signed-off-by: Asbjørn Sloth Tønnesen <asbjorn@asbjorn.st>
---
 term-utils/script.c | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/term-utils/script.c b/term-utils/script.c
index 6d5ddd84a..dfea87463 100644
--- a/term-utils/script.c
+++ b/term-utils/script.c
@@ -414,6 +414,19 @@ static void write_eof_to_shell(struct script_control *ctl)
 	write_to_shell(ctl, &c, sizeof(char));
 }
 
+static void check_output_limit(struct script_control *ctl)
+{
+	if (ctl->maxsz != 0 && ctl->outsz >= ctl->maxsz) {
+		if (!ctl->quiet)
+			printf(_("Script terminated, max output file size "
+				"%"PRIu64" exceeded.\n"), ctl->maxsz);
+
+		DBG(IO, ul_debug("output size %"PRIu64", exceeded limit %"PRIu64,
+			ctl->outsz, ctl->maxsz));
+		done_log(ctl, _("max output size exceeded"));
+	}
+}
+
 static void handle_io(struct script_control *ctl, int fd, int *eof)
 {
 	char buf[BUFSIZ];
@@ -451,13 +464,7 @@ static void handle_io(struct script_control *ctl, int fd, int *eof)
 		DBG(IO, ul_debug(" master --> stdout %zd bytes", bytes));
 		write_output(ctl, buf, bytes);
 
-		/* check output limit */
-		if (ctl->maxsz != 0 && ctl->outsz >= ctl->maxsz) {
-			if (!ctl->quiet)
-				printf(_("Script terminated, max output file size %"PRIu64" exceeded.\n"), ctl->maxsz);
-			DBG(IO, ul_debug("output size %"PRIu64", exceeded limit %"PRIu64, ctl->outsz, ctl->maxsz));
-			done_log(ctl, _("max output size exceeded"));
-		}
+		check_output_limit(ctl);
 	}
 }
 
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/2] script: add input log feature
  2018-08-19 17:16 [PATCH 1/2] script: move output limit check to dedicated function Asbjørn Sloth Tønnesen
@ 2018-08-19 17:16 ` Asbjørn Sloth Tønnesen
  2018-08-20  8:46   ` Karel Zak
  0 siblings, 1 reply; 4+ messages in thread
From: Asbjørn Sloth Tønnesen @ 2018-08-19 17:16 UTC (permalink / raw)
  To: util-linux; +Cc: Asbjørn Sloth Tønnesen

When script is used to log usage of shell accounts, accessible by
random users (some of whom might be malicious).

This patch adds a new --input-log option, which makes script save
the input data to a file, in an extended timing format also containing
the data, thereby allowing the input to be reconstructed.

Signed-off-by: Asbjørn Sloth Tønnesen <asbjorn@asbjorn.st>
---
 bash-completion/script |  1 +
 term-utils/script.1    | 11 +++++++++-
 term-utils/script.c    | 58 +++++++++++++++++++++++++++++++++++++++++++++-----
 3 files changed, 64 insertions(+), 6 deletions(-)

diff --git a/bash-completion/script b/bash-completion/script
index 57b91a9eb..c670dd5bd 100644
--- a/bash-completion/script
+++ b/bash-completion/script
@@ -25,6 +25,7 @@ _script_module()
 				--flush
 				--force
 				--quiet
+				--input-log
 				--output-limit
 				--timing=
 				--version
diff --git a/term-utils/script.1 b/term-utils/script.1
index 0fb4c4fd7..a55924f68 100644
--- a/term-utils/script.1
+++ b/term-utils/script.1
@@ -87,8 +87,17 @@ being done using `cat foo'.
 Allow the default output destination, i.e. the typescript file, to be a hard
 or symbolic link.  The command will follow a symbolic link.
 .TP
+\fB\-i, \fB\-\-input-log\fR \fIfile\fR
+Log input data to
+.IR file .
+This data contains three fields, separated by a space.  The first
+field indicates how much time elapsed since the previous input.  The second
+field indicates how many characters were input this time.  The third field is
+the input data. This information can be used to log input data, regardless of
+whether it's echoed back by the shell.  Beware this will log passwords in the input.
+.TP
 \fB\-o\fR, \fB\-\-output-limit\fR \fIsize\fR
-Limit the size of the typescript and timing files to
+Limit the combined size of the output files to
 .I size
 and stop the child process after this size is exceeded.  The calculated
 file size does not include the start and done messages that the
diff --git a/term-utils/script.c b/term-utils/script.c
index dfea87463..4ea6d3ccf 100644
--- a/term-utils/script.c
+++ b/term-utils/script.c
@@ -101,13 +101,17 @@ UL_DEBUG_DEFINE_MASKNAMES(script) = UL_DEBUG_EMPTY_MASKNAMES;
 struct script_control {
 	char *shell;		/* shell to be executed */
 	char *command;		/* command to be executed */
+	char *inputlogname;	/* input log file path */
+	FILE *inputlogfp;	/* input log file pointer */
 	char *fname;		/* output file path */
 	FILE *typescriptfp;	/* output file pointer */
 	char *tname;		/* timing file path */
 	FILE *timingfp;		/* timing file pointer */
 	uint64_t outsz;         /* current output file size */
 	uint64_t maxsz;		/* maximum output file size */
-	struct timeval oldtime;	/* previous write or command start time */
+	struct timeval
+		last_timing,	/* previous timing/input write or ... */
+		last_inputlog;	/* ... command start time */
 	int master;		/* pseudoterminal master file descriptor */
 	int slave;		/* pseudoterminal slave file descriptor */
 	int poll_timeout;	/* poll() timeout, used in end of execution */
@@ -124,6 +128,7 @@ struct script_control {
 	 flush:1,		/* flush after each write */
 	 quiet:1,		/* suppress most output */
 	 timing:1,		/* include timing file */
+	 inputlog:1,		/* write input log file */
 	 force:1,		/* write output to links */
 	 isterm:1,		/* is child process running as terminal */
 	 die:1;			/* terminate program */
@@ -172,6 +177,7 @@ static void __attribute__((__noreturn__)) usage(void)
 		" -e, --return                  return exit code of the child process\n"
 		" -f, --flush                   run flush after each write\n"
 		"     --force                   use output file even when it is a link\n"
+		" -i, --input-log=<file>        write input log to file\n"
 		" -o, --output-limit <size>     terminate if output files exceed size\n"
 		" -q, --quiet                   be quiet\n"
 		" -t[<file>], --timing[=<file>] output timing data to stderr or to FILE\n"
@@ -295,6 +301,8 @@ static void __attribute__((__noreturn__)) done_log(struct script_control *ctl, c
 		err(EXIT_FAILURE, "write failed: %s", ctl->tname);
 	if (ctl->typescriptfp && close_stream(ctl->typescriptfp) != 0)
 		err(EXIT_FAILURE, "write failed: %s", ctl->fname);
+	if (ctl->inputlogfp && close_stream(ctl->inputlogfp) != 0)
+		err(EXIT_FAILURE, "write failed: %s", ctl->inputlogname);
 
 	exit(ctl->rc_wanted ? childstatus : EXIT_SUCCESS);
 }
@@ -337,12 +345,12 @@ static void write_output(struct script_control *ctl, char *obuf,
 		DBG(IO, ul_debug("  writing timing info"));
 
 		gettime_monotonic(&now);
-		timersub(&now, &ctl->oldtime, &delta);
+		timersub(&now, &ctl->last_timing, &delta);
 		timing_bytes = fprintf(ctl->timingfp, "%ld.%06ld %zd\n",
 		        (long)delta.tv_sec, (long)delta.tv_usec, bytes);
 		if (ctl->flush)
 			fflush(ctl->timingfp);
-		ctl->oldtime = now;
+		ctl->last_timing = now;
 		if (timing_bytes < 0)
 			timing_bytes = 0;
 	}
@@ -373,6 +381,25 @@ static void write_output(struct script_control *ctl, char *obuf,
 static int write_to_shell(struct script_control *ctl,
 			  char *buf, size_t bufsz)
 {
+	if (ctl->inputlog && ctl->inputlogfp) {
+		struct timeval now, delta;
+		int inputlog_bytes = 0;
+		int bytes = bufsz;
+
+		DBG(IO, ul_debug("  writing input log"));
+
+		gettime_monotonic(&now);
+		timersub(&now, &ctl->last_inputlog, &delta);
+		inputlog_bytes = fprintf(ctl->inputlogfp, "%ld.%06ld %zd %.*s\n",
+		        (long)delta.tv_sec, (long)delta.tv_usec, bufsz, bytes, buf);
+		if (ctl->flush)
+			fflush(ctl->inputlogfp);
+		ctl->last_inputlog = now;
+
+		if (ctl->maxsz != 0)
+			ctl->outsz += inputlog_bytes;
+	}
+
 	return write_all(ctl->master, buf, bufsz);
 }
 
@@ -455,6 +482,9 @@ static void handle_io(struct script_control *ctl, int fd, int *eof)
 			warn(_("write failed"));
 			fail(ctl);
 		}
+
+		check_output_limit(ctl);
+
 		/* without sync write_output() will write both input &
 		 * shell output that looks like double echoing */
 		fdatasync(ctl->master);
@@ -520,6 +550,7 @@ static void handle_signal(struct script_control *ctl, int fd)
 static void do_io(struct script_control *ctl)
 {
 	int ret, eof = 0;
+	struct timeval now;
 	time_t tvec = script_time((time_t *)NULL);
 	enum {
 		POLLFD_SIGNAL = 0,
@@ -551,11 +582,23 @@ static void do_io(struct script_control *ctl)
 		}
 	}
 
+	if (ctl->inputlog) {
+		const char *ilname = ctl->inputlogname;
+
+		if (!(ctl->inputlogfp = fopen(ilname, "w" UL_CLOEXECSTR))) {
+			restore_tty(ctl, TCSANOW);
+			warn(_("cannot open %s"), ilname);
+			fail(ctl);
+		}
+	}
+
 
 	if (ctl->typescriptfp)
 		typescript_message_start(ctl, &tvec);
 
-	gettime_monotonic(&ctl->oldtime);
+	gettime_monotonic(&now);
+	ctl->last_timing = now;
+	ctl->last_inputlog = now;
 
 	while (!ctl->die) {
 		size_t i;
@@ -775,6 +818,7 @@ int main(int argc, char **argv)
 		{"return", no_argument, NULL, 'e'},
 		{"flush", no_argument, NULL, 'f'},
 		{"force", no_argument, NULL, FORCE_OPTION,},
+		{"input-log", required_argument, NULL, 'i'},
 		{"output-limit", required_argument, NULL, 'o'},
 		{"quiet", no_argument, NULL, 'q'},
 		{"timing", optional_argument, NULL, 't'},
@@ -798,7 +842,7 @@ int main(int argc, char **argv)
 
 	script_init_debug();
 
-	while ((ch = getopt_long(argc, argv, "ac:efo:qt::Vh", longopts, NULL)) != -1)
+	while ((ch = getopt_long(argc, argv, "ac:efi:o:qt::Vh", longopts, NULL)) != -1)
 		switch (ch) {
 		case 'a':
 			ctl.append = 1;
@@ -815,6 +859,10 @@ int main(int argc, char **argv)
 		case FORCE_OPTION:
 			ctl.force = 1;
 			break;
+		case 'i':
+			ctl.inputlog = 1;
+			ctl.inputlogname = optarg;
+			break;
 		case 'o':
 			ctl.maxsz = strtosize_or_err(optarg, _("failed to parse output limit size"));
 			break;
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 2/2] script: add input log feature
  2018-08-19 17:16 ` [PATCH 2/2] script: add input log feature Asbjørn Sloth Tønnesen
@ 2018-08-20  8:46   ` Karel Zak
  2018-09-25 20:44     ` Asbjørn Sloth Tønnesen
  0 siblings, 1 reply; 4+ messages in thread
From: Karel Zak @ 2018-08-20  8:46 UTC (permalink / raw)
  To: Asbjørn Sloth Tønnesen; +Cc: util-linux

On Sun, Aug 19, 2018 at 05:16:58PM +0000, Asbjørn Sloth Tønnesen wrote:
> When script is used to log usage of shell accounts, accessible by
> random users (some of whom might be malicious).
> 
> This patch adds a new --input-log option, which makes script save
> the input data to a file, in an extended timing format also containing
> the data, thereby allowing the input to be reconstructed.

I like the feature, but not sure if we really need to introduce a new
log format specific to the input stream.

For long time I think about a new timing file format. Maybe we can add
support for new timing file format where will be possible log
information about more streams (stdin and stdout) and events (for
example signals). In this case we can for stdin use the same concept
like for stdout -- it means raw file with data. The final result will
be three files:

 - stdout (raw, without formatting)
 - stdin  (raw, without formatting)
 - timing (<type> <timestampts> [<offset> , misc...])

where 
  type         = S, I or O  (signal, input or output)
  timestampts  = timing info
 
  type specific information:
     offset = offset in bytes to the log (stream) file (O or I  type)
     signal = signal name for S type
     ..etc.

It would be also nice to have info about version, format in the
timing file header.

And new options like:

   --timing-format <classic,new>
   --recording <stdin,stdout,signals,...>
   --stdout-log <filename>
   --stdin-log <filename>

The default should be backwardly compatible (old format, stdout-only, etc.)

 Karel


-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 2/2] script: add input log feature
  2018-08-20  8:46   ` Karel Zak
@ 2018-09-25 20:44     ` Asbjørn Sloth Tønnesen
  0 siblings, 0 replies; 4+ messages in thread
From: Asbjørn Sloth Tønnesen @ 2018-09-25 20:44 UTC (permalink / raw)
  To: Karel Zak; +Cc: util-linux

Hi Karel,

On 08/20/2018 08:46 AM, Karel Zak wrote:
> On Sun, Aug 19, 2018 at 05:16:58PM +0000, Asbjørn Sloth Tønnesen wrote:
>> When script is used to log usage of shell accounts, accessible by
>> random users (some of whom might be malicious).
>>
>> This patch adds a new --input-log option, which makes script save
>> the input data to a file, in an extended timing format also containing
>> the data, thereby allowing the input to be reconstructed.
> 
> I like the feature, but not sure if we really need to introduce a new
> log format specific to the input stream.
> 
> For long time I think about a new timing file format. Maybe we can add
> support for new timing file format where will be possible log
> information about more streams (stdin and stdout) and events (for
> example signals).

I am working on implementing this, expect patches soon.

I am implementing 2 new formats, so we will have:
- classic - like now, with 1-2 output files
- new - like you described, with 2-3 output files
- combined - with a single output file

I am also adding support for both new formats to scriptreplay.

-- 
Best regards
Asbjørn Sloth Tønnesen

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2018-09-26  3:02 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-19 17:16 [PATCH 1/2] script: move output limit check to dedicated function Asbjørn Sloth Tønnesen
2018-08-19 17:16 ` [PATCH 2/2] script: add input log feature Asbjørn Sloth Tønnesen
2018-08-20  8:46   ` Karel Zak
2018-09-25 20:44     ` Asbjørn Sloth Tønnesen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).