Tag: syslog

Log bash history to syslog on CentOS 6

I think you should notice the new feature of Bash 4.1: log the bash history to syslog.

If you don’t, try to find it yourself in the official change logs here: http://tiswww.case.edu/php/chet/bash/CHANGES

There is a new configuration option (in config-top.h) that forces bash to
forward all history entries to syslog.

There is little information about it, you may not know how to use the fancy feature. This post will show you how to enable it.

There is no configurable option to enable it, and it is disable by default on CentOS 6, so, we must recompile the BASH to make it work. In order to take the less change to the system, we are going to recompile the BASH with the src rpm package.

1) Download the SRPM package, and verify the file.

From here: http://vault.centos.org/6.4/os/Source/SPackages/bash-4.1.2-14.el6.src.rpm

And always keep a good behavior habit to verify the file download from internet, especially this one, it’s your SHELL !

$ sha1sum bash-4.1.2-14.el6.src.rpm
da020835947d7098cf8c07d49b61dd2e6c482f6b bash-4.1.2-14.el6.src.rpm

If the sha1 checksum of the srpm file shows you “da020835947d7098cf8c07d49b61dd2e6c482f6b” , you get the correct file. The strings comes from the file: http://vault.centos.org/6.4/os/Source/repodata/primary.xml.gz 

2) Prepare your rpmbuild environment

Remember this rule [1] :

Building RPMs should NEVER be done with the root user. It should ALWAYS be done with an unprivileged user

$ sudo yum install -y rpm-build make gcc
 
$ mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
 
$ echo '%_topdir %(echo $HOME)/rpmbuild' > ~/.rpmmacros

3) Install the SRPM package

$ rpm -i bash-4.1.2-14.el6.src.rpm

So many warnings like:

warning: user mockbuild does not exist – using root
warning: group mockbuild does not exist – using root
warning: user mockbuild does not exist – using root
warning: group mockbuild does not exist – using root
warning: user mockbuild does not exist – using root
warning: group mockbuild does not exist – using root
warning: user mockbuild does not exist – using root
warning: group mockbuild does not exist – using root
warning: user mockbuild does not exist – using root
warning: group mockbuild does not exist – using root

….

As you did before, just ignore the warnings. :-)

The command will unpacke some files from SRPM and put them into the directory “rpmbuid” you created just now.

4) Rebuild the SRPM

You will follow this instruction [2]:

  1. cd ~/rpmbuild/SPECS/
  2. rpmbuild -bp mypackage.spec
  3. cd ~/rpmbuild/BUILD/
  4. cp existing_directory existing_directory.orig
  5. cd existing_directory
  6. find the file you wish to change, modify it.
  7. cd ~/rpmbuild/BUILD/
  8. diff -Npru existing_directory.orig exiting_directory > name_of_your_patch_file.patch
  9. cp name_of_your_patch_file.patch ~/rpmbuild/SOURCES/
  10. cd ~/rpmbuild/SPECS/
  11. edit the mypackage.spec file to add the definition of name_of_your_patch_file.patch and the application of your_patch_file — please look in the file to see how that is done.
  12. rpmbuild -ba mypackage.spec

 

$ cd ~/rpmbuild/SPECS/
 
$ rpmbuild -bp bash.spec
 
$ cd ~/rpmbuild/BUILD/
 
$ cp -r bash-4.1 bash-4.1.orig
 
$ cd bash-4.1

Now, it’s hack time !

$ vim config-top.h

Find the following comment out line:

/* #define SYSLOG_HISTORY */

Uncomment it:

#define SYSLOG_HISTORY

And make the next few lines:

#if defined (SYSLOG_HISTORY)
# define SYSLOG_FACILITY LOG_USER
# define SYSLOG_LEVEL LOG_INFO
#endif

Change to:

#if defined (SYSLOG_HISTORY)
# define SYSLOG_FACILITY LOG_LOCAL1
# define SYSLOG_LEVEL LOG_DEBUG
#endif

LOG_USER and LOG_INFO means that bash history will use the “user” facility and “info” level. By default, if we don’t change the facility and level of syslog, the bash history will fill with the /var/log/messages …

Available facility: kern, user, info, mail, daemon, auth, syslog, news, uucp, lpr, ftp, cron, local0-7

Available level: emerg, alert, crit, err, notice, info, debug

So I choose the unusual facility “local1″ and level “debug”.

The bash history has the same effect like this command: logger -p local1.debug “helloworld” .

$ vim bashhist.c
void
bash_syslog_history (line)
const char *line;
{
char trunc[SYSLOG_MAXLEN];
 
if (strlen(line) < SYSLOG_MAXLEN)
syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY: PID=%d UID=%d %s", getpid(), current_user.uid, line);
else
{
strncpy (trunc, line, SYSLOG_MAXLEN);
trunc[SYSLOG_MAXLEN - 1] = '\0';
syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY (TRUNCATED): PID=%d UID=%d %s", getpid(), current_user.uid, trunc);
}
}

Change to:

void
bash_syslog_history (line)
const char *line;
{
char trunc[SYSLOG_MAXLEN];
 
if (strlen(line) < SYSLOG_MAXLEN)
syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY: PPID=%d PID=%d SID=%d UID=%d User=%s %s", getppid(), getpid(), getsid(getpid()), current_user.uid, current_user.user_name, line);
else
{
strncpy (trunc, line, SYSLOG_MAXLEN);
trunc[SYSLOG_MAXLEN - 1] = '\0';
syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY (TRUNCATED): PPID=%d PID=%d SID=%d UID=%d User=%s %s", getppid(), getpid(), getsid(getpid()), current_user.uid, current_user.user_name, trunc);
}
}

Because we want to know the current user’s name not hist uid. SID and PPID is for more information about the command.

When you finish the above hacking, let’s continue the recompiling.

diff -Npru bash-4.1.orig bash-4.1 > bash_history_syslog.patch
 
$ cp bash_history_syslog.patch ~/rpmbuild/SOURCES/
 
$ cd ~/rpmbuild/SPECS/
 
$ vim bash.spec

edit the spec file, add these 2 lines to the right place:

Patch117: bash-setlocale.patch
Patch118: bash-tty-tests.patch
Patch119: bash_history_syslog.patch

%patch117 -p1 -b .setlocale
%patch118 -p1 -b .tty_tests
%patch119 -p1 -b .history_syslog
%patch123 -p1 -b .nobits
%patch124 -p1 -b .examples

All done. Let’s rebuild it.

$ rpmbuild -ba bash.spec

After a long wait, the command should end without any error. And it will generate a rpm file named bash-4.1.2-14.el6.x86_64.rpm located in ~/rpmbuild/RPMS/x86_64/ .

5) Install the custom bash rpm. ( force )

$ sudo rpm -Uvh --force bash-4.1.2-14.el6.x86_64.rpm

Let’s see the new “bash” :

$ ll /bin/bash
 
-rwxr-xr-x 1 root root 1030434 Jul 27 02:38 /bin/bash

 

6) Testing 

I use syslog-ng as my syslog server.

Add the following lines to the config file: /etc/syslog-ng/syslog-ng.conf

filter f_bash { facility(local1) and level(debug); };
destination d_bash { file(“/var/log/bash”); };
log { source(s_sys); filter(f_bash); destination(d_bash); };

Restart the syslog-ng:

$ sudo /etc/init.d/syslog-ng restart

Then, you will see your command occurs in /var/log/bash:

Jul 27 02:59:06 alpha -bash: HISTORY: PPID=16253 PID=16254 SID=16254 UID=1001 User=hello sudo cat /var/log/bash

Of course, you can log to the remote syslog server.

 

Enjoy !

 

Reference:

[1] http://wiki.centos.org/HowTos/SetupRpmBuildEnvironment

[2] http://wiki.centos.org/HowTos/RebuildSRPM