diff --git a/lib/tlitest/config.py b/lib/tlitest/config.py index 5176cbbe..5d3c3636 100644 --- a/lib/tlitest/config.py +++ b/lib/tlitest/config.py @@ -19,6 +19,7 @@ DEFAULT_TLOG_REC_SESSION_SHELL = "/bin/bash" DEFAULT_TLOG_REC_SESSION_NOTICE = "ATTENTION: Your session is being recorded!" DEFAULT_TLOG_REC_SESSION_WRITER = "journal" +DEFAULT_TLOG_REC_SESSION_SESSION_LOCKING = True DEFAULT_TLOG_PLAY_READER = "file" DEFAULT_TLOG_PLAY_PERSIST = False @@ -184,7 +185,8 @@ def generate_config(self, filename): class TlogRecSessionConfig(TlogRecConfig): """TlogPlaySession configuration class, child of TlogRecConfig""" - def __init__(self, shell=DEFAULT_TLOG_REC_SESSION_SHELL, + def __init__(self, session_locking = DEFAULT_TLOG_REC_SESSION_SESSION_LOCKING, + shell=DEFAULT_TLOG_REC_SESSION_SHELL, notice=DEFAULT_TLOG_REC_SESSION_NOTICE, latency=DEFAULT_TLOG_REC_LATENCY, payload=DEFAULT_TLOG_REC_PAYLOAD, @@ -201,6 +203,7 @@ def __init__(self, shell=DEFAULT_TLOG_REC_SESSION_SHELL, syslog_priority=DEFAULT_TLOG_REC_SYSLOG_PRIORITY): self.shell = shell self.notice = notice + self.session_locking = session_locking super().__init__(latency, payload, log_input, log_output, log_window, limit_rate, limit_burst, limit_action, writer, file_writer_path, journal_priority, @@ -212,6 +215,7 @@ def _setup_base_session_config(self): tlog_rec_session_config = { "shell": self.shell, "notice": self.notice, + "session_locking": self.session_locking } return tlog_rec_session_config diff --git a/lib/tlitest/test_tlog_rec_session.py b/lib/tlitest/test_tlog_rec_session.py index eba34d83..8f89ca6e 100644 --- a/lib/tlitest/test_tlog_rec_session.py +++ b/lib/tlitest/test_tlog_rec_session.py @@ -29,6 +29,42 @@ class TestTlogRecSession: os.chmod(tempdir, stat.S_IRWXU + stat.S_IRWXG + stat.S_IRWXO + stat.S_ISUID + stat.S_ISGID + stat.S_ISVTX) + @pytest.mark.tier1 + def test_session_record_to_file_locking_enabled(self): + """ + Check multiple recordings in a session only records one at a time (default) + """ + myname = inspect.stack()[0][3] + logfile = mklogfile(self.tempdir) + sessionclass = TlogRecSessionConfig(writer="file", file_writer_path=logfile) + sessionclass.generate_config(SYSTEM_TLOG_REC_SESSION_CONF) + shell = ssh_pexpect(self.user, 'Secret123', 'localhost') + shell.sendline('echo {}_shell0'.format(myname)) + shell.sendline('stty -echo') + shell.sendline("tlog-rec-session -c 'echo {}_nested_session' >/dev/null".format(myname)) + shell.sendline('exit') + check_recording(shell, "{}_shell0".format(myname), logfile) + check_recording_missing(shell, "{}_nested_session".format(myname), logfile) + shell.close() + + @pytest.mark.tier1 + def test_session_record_to_file_locking_disabled(self): + """ + Check multiple recordings in a session works in tlog-rec-session with locking-enabled setting + """ + myname = inspect.stack()[0][3] + logfile = mklogfile(self.tempdir) + sessionclass = TlogRecSessionConfig(writer="file", file_writer_path=logfile, session_locking=False) + sessionclass.generate_config(SYSTEM_TLOG_REC_SESSION_CONF) + shell = ssh_pexpect(self.user, 'Secret123', 'localhost') + shell.sendline('echo {}_shell0'.format(myname)) + shell.sendline('stty -echo') + shell.sendline("tlog-rec-session -c 'echo {}_nested_session' >/dev/null".format(myname)) + shell.sendline('exit') + check_recording(shell, "{}_shell0".format(myname)) + check_recording(shell, "{}_nested_session".format(myname)) + shell.close() + @pytest.mark.tier1 def test_session_record_to_file(self): """ diff --git a/lib/tlog/rec.c b/lib/tlog/rec.c index b23e565d..88e40cc9 100644 --- a/lib/tlog/rec.c +++ b/lib/tlog/rec.c @@ -1126,6 +1126,7 @@ tlog_rec(struct tlog_errs **perrs, uid_t euid, gid_t egid, clockid_t clock_id; unsigned int session_id; bool lock_acquired = false; + bool session_locking = true; struct json_object *obj; int64_t num; unsigned int latency; @@ -1144,6 +1145,11 @@ tlog_rec(struct tlog_errs **perrs, uid_t euid, gid_t egid, } } + /* Check for the session_locking flag */ + if (json_object_object_get_ex(conf, "session_locking", &obj)) { + session_locking = json_object_get_boolean(obj); + } + /* Check for the version flag */ if (json_object_object_get_ex(conf, "version", &obj)) { if (json_object_get_boolean(obj)) { @@ -1198,7 +1204,7 @@ tlog_rec(struct tlog_errs **perrs, uid_t euid, gid_t egid, TLOG_ERRS_RAISECS(grc, "Failed retrieving session ID"); } - if (opts & TLOG_REC_OPT_LOCK_SESS) { + if (opts & TLOG_REC_OPT_LOCK_SESS && session_locking) { /* Attempt to lock the session */ grc = tlog_session_lock(perrs, session_id, euid, egid, &lock_acquired); if (grc != TLOG_RC_OK) { diff --git a/m4/tlog/rec_session_conf_schema.m4 b/m4/tlog/rec_session_conf_schema.m4 index b7bcd3af..d51fbcc5 100644 --- a/m4/tlog/rec_session_conf_schema.m4 +++ b/m4/tlog/rec_session_conf_schema.m4 @@ -30,6 +30,12 @@ M4_PARAM(`', `shell', `file-env', `SHELL is the ', `The ', `M4_LINES(`path to the shell executable which should be spawned.')')m4_dnl m4_dnl +M4_PARAM(`', `session_locking', `file-env', + `M4_TYPE_BOOL(true)', true, + `n', `true', `Enable locking by session ID', + `If specified, ', `If true ', + `M4_LINES(`locking by session ID is enabled.')')m4_dnl +m4_dnl M4_PARAM(`', `login', `name-', `M4_TYPE_BOOL()', false, `l', `', `Make the shell a login shell',