From 7789ca862a72629f9012da8f515bc4e51b82abad Mon Sep 17 00:00:00 2001 From: Daniel Berteaud Date: Fri, 12 Oct 2012 18:57:25 +0200 Subject: [PATCH] Premier commit --- createlinks | 15 ++ root/etc/e-smith/cron.monthly/samba-log-rotate | 53 +++++++ .../db/configuration/defaults/samba-db-logd/DbName | 1 + .../db/configuration/defaults/samba-db-logd/DbUser | 1 + .../db/configuration/defaults/samba-db-logd/status | 1 + .../db/configuration/defaults/samba-db-logd/type | 1 + .../db/configuration/migrate/SambaDBPassword | 27 ++++ .../templates/etc/e-smith/sql/init/sambadblogd | 46 ++++++ root/usr/bin/samba-db-logd | 163 +++++++++++++++++++++ root/var/service/samba-db-logd/log/run | 7 + root/var/service/samba-db-logd/run | 25 ++++ samba_log.sql | 15 ++ smeserver-samba-db-logd.spec | 58 ++++++++ 13 files changed, 413 insertions(+) create mode 100644 createlinks create mode 100644 root/etc/e-smith/cron.monthly/samba-log-rotate create mode 100644 root/etc/e-smith/db/configuration/defaults/samba-db-logd/DbName create mode 100644 root/etc/e-smith/db/configuration/defaults/samba-db-logd/DbUser create mode 100644 root/etc/e-smith/db/configuration/defaults/samba-db-logd/status create mode 100644 root/etc/e-smith/db/configuration/defaults/samba-db-logd/type create mode 100644 root/etc/e-smith/db/configuration/migrate/SambaDBPassword create mode 100644 root/etc/e-smith/templates/etc/e-smith/sql/init/sambadblogd create mode 100755 root/usr/bin/samba-db-logd create mode 100644 root/var/service/samba-db-logd/log/run create mode 100644 root/var/service/samba-db-logd/run create mode 100644 samba_log.sql create mode 100644 smeserver-samba-db-logd.spec diff --git a/createlinks b/createlinks new file mode 100644 index 0000000..45395cb --- /dev/null +++ b/createlinks @@ -0,0 +1,15 @@ +#!/usr/bin/perl -w + +use esmith::Build::CreateLinks qw(:all); + +foreach my $event (qw/bootstrap-console-save workgroup-update/){ + templates2events("/etc/e-smith/sql/init/sambadblogd", $event); +} +safe_symlink("restart", "root/etc/e-smith/events/workgroup-update/services2adjust/squid-db-logd"); +safe_touch('root/var/service/samba-db-logd/down'); +safe_symlink("../daemontools" , 'root/etc/rc.d/init.d/supervise/samba-db-logd'); +safe_symlink("/var/service/samba-db-logd" , 'root/service/samba-db-logd'); +service_link_enhanced("samba-db-logd", "S98", "7"); +service_link_enhanced("samba-db-logd", "K15", "6"); +service_link_enhanced("samba-db-logd", "K35", "0"); +service_link_enhanced("samba-db-logd", "K35", "1"); diff --git a/root/etc/e-smith/cron.monthly/samba-log-rotate b/root/etc/e-smith/cron.monthly/samba-log-rotate new file mode 100644 index 0000000..5a26bc4 --- /dev/null +++ b/root/etc/e-smith/cron.monthly/samba-log-rotate @@ -0,0 +1,53 @@ +#!/bin/bash + +DB_HOST=$(/sbin/e-smith/db configuration getprop samba-db-logd DbHost || echo localhost) +RETENTION=$(/sbin/e-smith/db configuration getprop samba-db-logd Retention || echo 365) + +SQL_DB=$(/sbin/e-smith/db configuration getprop samba-db-logd DbName) +TABNAME="audit" +SQLCMD="mysql ${SQL_DB} --batch"; +MONTH=$(date +%m) +YEAR=$(date +%Y) + +# We rotate on the first day of a new month +if [ "$MONTH" == "1" ]; then + MONTH=12 +else + MONTH=$(($MONTH-1)) +fi + +# Pad with 0 +MONTH=$(printf "%02d" $MONTH) + +DATE=$MONTH"_"$YEAR + +for T in ${TABNAME}; do + # create table 0 + echo "CREATE TABLE IF NOT EXISTS ${T}_0 LIKE ${T};" | $SQLCMD; + + # Rotate table + echo "FLUSH TABLES ${T}; RENAME TABLE ${T} TO ${T}_$DATE; RENAME TABLE ${T}_0 TO ${T}" | ${SQLCMD} >/dev/null 2>&1 + + # Drop _0 table if we rotate more than two times a month + if echo "DESCRIBE ${T}_0;" | ${SQLCMD} >/dev/null 2>&1; then + echo "DROP TABLE ${T}_0;" | $SQLCMD + fi + + #compress 2 + cd /var/lib/mysql/${SQL_DB}/ + echo "FLUSH TABLE ${T}_${DATE};" | $SQLCMD + myisampack -s "${T}_${DATE}.MYI" + myisamchk -s -rq --sort-index --analyze "${T}_${DATE}.MYI" + echo "FLUSH TABLE ${T}_${DATE}" | $SQLCMD +done + +# Now check existing table to drop olds ones +for T in $(echo "show tables" | $SQLCMD | grep -v -P "^Tables_in_"$SQL_DB | grep -v -P "^audit$"); do + TMONTH=$(echo $T | perl -pe 'm/^audit_(\d+)_(\d+)/; print $2;exit') + TYEAR=$(echo $T | perl -pe 'm/^audit_(\d+)_(\d+)/; print $3;exit') + # Drop table if older than configured retention + if [ "$(($(date -d "01/$MONTH/$YEAR" +%s)-$(date -d "01/$TMONTH/$TYEAR" +%s)))" -gt "$((24*3600*$RETENTION))" ]; then + echo "DROP TABLE $T;" | $SQLCMD + fi +done + diff --git a/root/etc/e-smith/db/configuration/defaults/samba-db-logd/DbName b/root/etc/e-smith/db/configuration/defaults/samba-db-logd/DbName new file mode 100644 index 0000000..cf74241 --- /dev/null +++ b/root/etc/e-smith/db/configuration/defaults/samba-db-logd/DbName @@ -0,0 +1 @@ +samba_log diff --git a/root/etc/e-smith/db/configuration/defaults/samba-db-logd/DbUser b/root/etc/e-smith/db/configuration/defaults/samba-db-logd/DbUser new file mode 100644 index 0000000..80d7113 --- /dev/null +++ b/root/etc/e-smith/db/configuration/defaults/samba-db-logd/DbUser @@ -0,0 +1 @@ +samba diff --git a/root/etc/e-smith/db/configuration/defaults/samba-db-logd/status b/root/etc/e-smith/db/configuration/defaults/samba-db-logd/status new file mode 100644 index 0000000..86981e6 --- /dev/null +++ b/root/etc/e-smith/db/configuration/defaults/samba-db-logd/status @@ -0,0 +1 @@ +enabled diff --git a/root/etc/e-smith/db/configuration/defaults/samba-db-logd/type b/root/etc/e-smith/db/configuration/defaults/samba-db-logd/type new file mode 100644 index 0000000..24e1098 --- /dev/null +++ b/root/etc/e-smith/db/configuration/defaults/samba-db-logd/type @@ -0,0 +1 @@ +service diff --git a/root/etc/e-smith/db/configuration/migrate/SambaDBPassword b/root/etc/e-smith/db/configuration/migrate/SambaDBPassword new file mode 100644 index 0000000..e9c00db --- /dev/null +++ b/root/etc/e-smith/db/configuration/migrate/SambaDBPassword @@ -0,0 +1,27 @@ +{ + my $rec = $DB->get('samba-db-logd') + || $DB->new_record('samba-db-logd', {type => 'service'}); + my $pw = $rec->prop('DbPassword'); + if (not $pw or length($pw) < 57){ + use MIME::Base64 qw(encode_base64); + + $pw = "not set due to error"; + if ( open( RANDOM, "/dev/urandom" ) ){ + my $buf; + # 57 bytes is a full line of Base64 coding, and contains + # 456 bits of randomness - given a perfectly random /dev/random + if ( read( RANDOM, $buf, 57 ) != 57 ){ + warn("Short read from /dev/random: $!"); + } + else{ + $pw = encode_base64($buf); + chomp $pw; + } + close RANDOM; + } + else{ + warn "Could not open /dev/urandom: $!"; + } + $rec->set_prop('DbPassword', $pw); + } +} diff --git a/root/etc/e-smith/templates/etc/e-smith/sql/init/sambadblogd b/root/etc/e-smith/templates/etc/e-smith/sql/init/sambadblogd new file mode 100644 index 0000000..1646c70 --- /dev/null +++ b/root/etc/e-smith/templates/etc/e-smith/sql/init/sambadblogd @@ -0,0 +1,46 @@ +{ +my $db = ${'samba-db-logd'}{'DbName'} || 'samba_log'; +my $user = ${'qpsmtpd'}{'DbUser'} || 'samba'; +my $pass = ${'qpsmtpd'}{'DbPassword'} || 'samba'; + +my $dbstruct = `rpm -qd smeserver-samba-db-logd | grep samba_log.sql`; + +$OUT .= <<"END"; +#! /bin/sh +if [ ! -d /var/lib/mysql/$db ]; then + /usr/bin/mysql -e 'create database $db' + /usr/bin/mysql $db < $dbstruct +fi + +/usr/bin/mysql < \$opts{debug}, + "log=s" => \$opts{squidlog}, + "dbhost=s" => \$opts{dbhost}, + "dbname=s" => \$opts{dbname}, + "dbpass=s" => \$opts{dbpass} +); + +# Disable output buffering +select(STDOUT); +$| = 1; +select(STDERR); +$| = 1; + +open STDERR, '>&STDOUT'; + +# Set process name +$0 = 'samba-db-logd'; + +# Get hostname +our $host = `hostname`; +chomp($host); + +### Subroutines + +# Print messages on stderr +# for debuging purpose +sub printlog { + my $msg = shift; + print "$msg\n"; + return; +} + +# Connect to the database +sub db_connect { + my $dbh = DBI->connect("DBI:mysql:database=$opts{dbname};host=$opts{dbhost}", + $opts{dbuser}, $opts{dbpass}, {RaiseError => 1}); + die "Couldn't connect to database\n" unless ($dbh); + return $dbh; +} + +# escape chars for MySQL queries +sub mysql_escape { + my $string = shift; + $string =~ s|'|\\'|g; + return $string; +} + +my $dbh = db_connect; +# Open log file + +printlog("opening log file") if ($opts{debug} ge 1); +my $tail = File::Tail->new(name=>$opts{log}, maxinterval=>15); + +while (defined(my $line=$tail->read)){ + chomp($line); + my ($username, $client_ip, $client_name, $share, + $action, $status, $access_mode, $file_src, $file_dst) = undef; + + # Oct 12 17:20:24 sme8 smbd[11176]: admin|192.168.7.50|pc10-45|intranet|mkdir|Nouveau dossier + if ($line =~ m/^\w+\s\d+\s\d+:\d+:\d+\s\w+\ssmbd\[\d+\]:\s+(\w+)\|(\d+\.\d+\.\d+\.\d+)\|(\w+)\|(\w+)\|(\w+)/){ + $username = $1; + $client_ip = $2; + $client_name = $3; + $share = $4; + $action = $5; + } + else{ + printlog("Couldn't parse this line: $line\n"); + next; + } + my @other = split /\|/, $line; + + if (($action eq 'opendir') || ($action eq 'rmdir') || ($action eq 'mkdir') || ($action eq 'unlink')){ + # Oct 12 17:20:24 sme8 smbd[11176]: admin|192.168.7.50|pc10-45|intranet|opendir|ok|./ + $status = $other[5]; + $file_src = $other[6]; + } + elsif ($action eq 'open'){ + # Oct 12 17:20:28 sme8 smbd[11176]: admin|192.168.7.50|pc10-45|intranet|open|ok|r|Nouveau document + $status = $other[5]; + $access_mode = $other[6]; + $file_src = $other[7]; + } + elsif ($action eq 'rename'){ + # Oct 12 17:20:28 sme8 smbd[11176]: admin|192.168.7.50|pc10-45|intranet|rename|ok|./Nouveau document|Nouveau document 2 + $status = $other[5]; + $file_src = $other[6]; + $file_dst = $other[7]; + } + + my ($sec,$min,$hour,$day,$mon,$year) = localtime; + $year += 1900; + $mon += 1; + my $date = $year.'-'.$mon.'-'.$day; + my $time = $hour.':'.$min.':'.$sec; + + # MySQL escape + # Shouldn't be needed, but just in case logs contains junk + + $username = mysql_escape($username); + $client_ip = mysql_escape($client_ip); + $client_name = mysql_escape($client_name); + $share = mysql_escape($share); + $action = mysql_escape($action); + $access_mode = mysql_escape($access_mode) if (defined $access_mode); + $status = mysql_escape($status); + $file_src = mysql_escape($file_src); + $file_dst = mysql_escape($file_dst) if (defined $file_dst); + + # File names may appear with a space at the end in the logs + $file_src =~ s/\s+$//; + $file_dst =~ s/\s+$// if (defined $file_dst); + + if ($opts{debug} ge 2){ + my $msg = "New audit entry:\ndate: $date\nhour: $time\nusername: $username\n". + "client_ip: $client_ip\nclient_name: $client_name\nshare: $share\n". + "action: $action\nstatus: $status\nfile_src: $file_src"; + $msg .= "\naccess_mode: $access_mode" if (defined $access_mode); + $msg .= "\nfile_dst: $file_dst" if (defined $file_dst); + $msg .= "\n"; + printlog($msg); + } + + my $q = "INSERT INTO audit ". + "(samba_host,date_day,date_time,username,client_ip,client_name,". + "action,"; + $q .= "access_mode," if (defined $access_mode); + $q .= "status,share,file_src"; + $q .= ",file_dst" if (defined $file_dst); + $q .= ") VALUES('$host','$date','$time','$username','$client_ip','$client_name',". + "'$action'"; + $q .= ",'$access_mode'" if (defined $access_mode); + $q .= ",'$status','$share','$file_src'"; + $q .= ",'$file_dst'" if (defined $file_dst); + $q .= ")"; + + printlog("Current query:\n$q\n") if ($opts{debug} ge 3); + + my $qh = $dbh->prepare($q); + $qh->execute or exit(1); +} + +exit(0); diff --git a/root/var/service/samba-db-logd/log/run b/root/var/service/samba-db-logd/log/run new file mode 100644 index 0000000..0034ff8 --- /dev/null +++ b/root/var/service/samba-db-logd/log/run @@ -0,0 +1,7 @@ +#!/bin/sh + +exec \ + /usr/local/bin/setuidgid smelog \ + /usr/local/bin/multilog t s5000000 \ + /var/log/samba-db-logd + diff --git a/root/var/service/samba-db-logd/run b/root/var/service/samba-db-logd/run new file mode 100644 index 0000000..cfba0ce --- /dev/null +++ b/root/var/service/samba-db-logd/run @@ -0,0 +1,25 @@ +#!/usr/bin/perl -w + +use esmith::ConfigDB; +my $c = esmith::ConfigDB->open_ro or die "Couldn't open ConfigDB\n"; +my $rec = $c->get('samba-db-logd'); +my $dbname = $rec->prop('DbName') || 'samba_log'; +my $dbuser = $rec->prop('DbUser') || 'samba'; +my $dbpass = $rec->prop('DbPassword') || 'samba'; +my $dbhost = $rec->prop('DbHost') || 'localhost'; + +my @args = ("--debug=1", "--dbname=$dbname", "--dbuser=$dbuser", "--dbpass=$dbpass"); + +push @args, "--dbhost=$dbhost" if ($dbhost ne 'localhost'); + +my $smbd = $c->get('smbd'); + +if ($smbd ne 'enabled'){ + exec("sv", "d", "/service/samba-db-logd"); + exit(0); +} + +exec("/usr/bin/squid-db-logd", @args) + or die "Cannot run the Samba Database Loggind Daemon"; + +exit(1); diff --git a/samba_log.sql b/samba_log.sql new file mode 100644 index 0000000..31a5e0f --- /dev/null +++ b/samba_log.sql @@ -0,0 +1,15 @@ +CREATE TABLE audit ( + id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, + samba_host VARCHAR(40) NOT NULL, + date_day DATE NOT NULL, + date_time TIME NOT NULL, + username VARCHAR(30) NOT NULL, + client_ip CHAR(15) NOT NULL, + client_name VARCHAR(50) NOT NULL, + action VARCHAR(15) NOT NULL, + access_mode VARCHAR(2) default NULL, + status VARCHAR(10) NOT NULL, + share VARCHAR(30) NOT NULL, + file_src VARCHAR(200) default NULL, + file_dst VARCHAR(200) default NULL +) ENGINE=MYISAM; diff --git a/smeserver-samba-db-logd.spec b/smeserver-samba-db-logd.spec new file mode 100644 index 0000000..18e0672 --- /dev/null +++ b/smeserver-samba-db-logd.spec @@ -0,0 +1,58 @@ +%define version 0.0.1 +%define release 1.beta0 +%define name smeserver-samba-db-logd + + +Summary: samba MySQL logging module for SME Server +Name: %{name} +Version: %{version} +Release: %{release}%{?dist} +License: GPL +Group: Networking/Daemons +Source: %{name}-%{version}.tar.gz + +BuildRoot: /var/tmp/%{name}-%{version}-%{release}-buildroot +BuildArchitectures: noarch +BuildRequires: e-smith-devtools + +Requires: perl(File::Tail) +Requires: perl(Getopt::Long) +Requires: perl(DBI) + +%description +Log samba events in a MySQL database + +%changelog +* Fri Oct 12 2012 Daniel Berteaud 0.2.0-1 +- Initial release + +%prep +%setup -q -n %{name}-%{version} + +%build +%{__mkdir_p} root/var/log/samba-db-logd +perl createlinks + +%install +/bin/rm -rf $RPM_BUILD_ROOT +(cd root ; /usr/bin/find . -depth -print | /bin/cpio -dump $RPM_BUILD_ROOT) +/bin/rm -f %{name}-%{version}-filelist +/sbin/e-smith/genfilelist $RPM_BUILD_ROOT \ + --dir /var/log/samba-db-logd 'attr(0770,smelog,smelog)' \ + --file /usr/bin/samba-db-logd 'attr(0755,root,root)' \ + --file /var/service/samba-db-logd/run 'attr(0755,root,root)' \ + --file /var/service/samba-db-logd/log/run 'attr(0755,root,root)' \ + --file /etc/cron.monthly/samba-log-rotate 'attr(0755,root,root)' \ + > %{name}-%{version}-filelist + +echo "%doc CHANGELOG.git" >> %{name}-%{version}-filelist +echo "%doc samba_log.sql" >> %{name}-%{version}-filelist +%files -f %{name}-%{version}-filelist +%defattr(-,root,root) + +%clean +rm -rf $RPM_BUILD_ROOT + +%post +%preun +