Info: Version 1.8.x is available.
Last modified: $Date: 2024-03-30 11:25:00 +0000 (Sat, 30 Mar 2024) $
This page explains you how to record commandline for SSH login sessions.
Compile the below program. In this page, we assume the location of compiled program as /bin/record_cmdline . We assume the location of SSH server program as /usr/sbin/sshd . We assume the location of login shell program as /bin/bash .
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <syslog.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/file.h> #include <fcntl.h> static void encode(char *buffer, const char *string) { while (1) { const unsigned char c = *(const unsigned char *) string++; if (!c) break; else if (c == '\\') { *buffer++ = '\\'; *buffer++ = '\\'; } else if (c > 32 && c < 127) *buffer++ = c; else { *buffer++ = '\\'; *buffer++ = '0' + (c >> 6); *buffer++ = '0' + ((c >> 3) & 7); *buffer++ = '0' + (c & 7); } } } int main(int raw_argc, char *raw_argv[]) { int i; int argc; int envc; char *filename; char **argv; char **envp; { /* Check that I'm an execute handler process. */ int fd = open("/proc/ccs/.execute_handler", O_RDONLY); close(fd); if (fd == EOF) { fprintf(stderr, "FATAL: I'm not execute_handler.\n"); return 1; } } if (raw_argc < 7) return 1; filename = raw_argv[4]; argc = atoi(raw_argv[5]); envc = atoi(raw_argv[6]); if (raw_argc != argc + envc + 7) return 1; for (i = 5; i < argc + 5; i++) raw_argv[i] = raw_argv[i + 2]; raw_argv[argc + 5] = NULL; for (i = argc + 6; i < argc + envc + 6; i++) raw_argv[i] = raw_argv[i + 1]; raw_argv[argc + envc + 6] = NULL; argv = raw_argv + 5; envp = raw_argv + argc + 6; { /* Record parameters including argv[] and envp[]. */ /* Get exlusive lock for serializing syslog(). */ const int fd = open("/proc/self/exe", O_RDONLY); if (fd == EOF || flock(fd, LOCK_EX) == EOF) return 1; openlog(raw_argv[0], LOG_NDELAY, LOG_USER); syslog(LOG_INFO, "Domain = %s\n", raw_argv[1]); syslog(LOG_INFO, "Caller Program = %s\n", raw_argv[2]); syslog(LOG_INFO, "Process Status = %s\n", raw_argv[3]); syslog(LOG_INFO, "Requested Program = %s\n", filename); syslog(LOG_INFO, "argc=%d\n", argc); syslog(LOG_INFO, "envc=%d\n", envc); for (i = 0; i < argc; i++) { int max_len = strlen(argv[i]) * 4 + 128; int len; char *buffer = calloc(max_len, 1); if (!buffer) return 1; len = snprintf(buffer, 100, "argv[%d] = \"", i); encode(buffer + len, argv[i]); len = strlen(buffer); snprintf(buffer + len, max_len - len - 1, "\""); syslog(LOG_INFO, "%s\n", buffer); free(buffer); } for (i = 0; i < envc; i++) { int max_len = strlen(envp[i]) * 4 + 128; int len; char *buffer = calloc(max_len, 1); if (!buffer) return 1; len = snprintf(buffer, 100, "envp[%d] = \"", i); encode(buffer + len, envp[i]); len = strlen(buffer); snprintf(buffer + len, max_len - len - 1, "\""); syslog(LOG_INFO, "%s\n", buffer); free(buffer); } closelog(); /* Release exclusive lock. */ close(fd); } /* Execute requested program. */ execve(filename, argv, envp); fprintf(stderr, "ERROR: Can't execute %s .\n", filename); return 1; } |
Install TOMOYO Linux and run below commandline in order to initialize TOMOYO Linux.
/usr/lib/ccs/init_policy |
Then, please do below operations before you reboot using TOMOYO Linux kernel.
Append below line to /etc/ccs/exception_policy.conf in order to initialize domain transition when /usr/sbin/sshd is executed.
initialize_domain /usr/sbin/sshd |
Append below line to /etc/ccs/exception_policy.conf in order to suppress domain transition after login shell which is executed by SSH server.
keep_domain <kernel> /usr/sbin/sshd /bin/bash |
Append below lines to /etc/ccs/domain_policy.conf so that program execution requests from login shell which is executed by SSH server are passed to /bin/record_cmdline .
<kernel> /usr/sbin/sshd /bin/bash execute_handler /bin/record_cmdline |
Now, you are ready to start operation. Please reboot using TOMOYO Linux kernel.
Login via SSH and do some operations. You can confirm that commandline parameters are recorded by doing below commandline.
grep record_cmdline /var/log/messages |
TOMOYO Linux's execute_handler functionality intercepts program execution requests from login shell which in executed by SSH server and passes the program execution requests to /bin/record_cmdline . Then, /bin/record_cmdline records parameters passed to program execution requests and actually executes the requested programs.
You can customize /bin/record_cmdline to accept or deny program execution requests based on commandline arguments because parameters passed to execution requests are passed to /bin/record_cmdline .