Premier commit

This commit is contained in:
Daniel Berteaud 2012-10-12 18:57:25 +02:00
commit 7789ca862a
13 changed files with 413 additions and 0 deletions

15
createlinks Normal file
View File

@ -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");

View File

@ -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

View File

@ -0,0 +1 @@
samba_log

View File

@ -0,0 +1 @@
samba

View File

@ -0,0 +1 @@
enabled

View File

@ -0,0 +1 @@
service

View File

@ -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);
}
}

View File

@ -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 <<EOF
USE mysql;
REPLACE INTO user (
host,
user,
password)
VALUES (
'localhost',
'$user',
PASSWORD ('$pass'));
REPLACE INTO db (
host,
db,
user,
select_priv, insert_priv, update_priv, delete_priv,
create_priv, alter_priv, index_priv, drop_priv, create_tmp_table_priv,
grant_priv, lock_tables_priv, references_priv)
VALUES (
'localhost',
'$db',
'$user',
'Y', 'Y', 'Y', 'Y',
'Y', 'Y', 'Y', 'Y', 'Y',
'N', 'Y', 'Y');
FLUSH PRIVILEGES;
EOF
END
}

163
root/usr/bin/samba-db-logd Executable file
View File

@ -0,0 +1,163 @@
#!/usr/bin/perl -w
use File::Tail;
use DBI;
use URI;
use Getopt::Long;
use strict;
our %opts = ();
# Set default options
$opts{log} = '/var/log/smb_audit.log';
$opts{debug} = 0;
$opts{dbhost} = 'localhost';
$opts{dbname} = 'samba_log';
$opts{dbuser} = 'samba';
$opts{dbpass} = 'samba';
# get command line arguments
GetOptions(
"debug=i" => \$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);

View File

@ -0,0 +1,7 @@
#!/bin/sh
exec \
/usr/local/bin/setuidgid smelog \
/usr/local/bin/multilog t s5000000 \
/var/log/samba-db-logd

View File

@ -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);

15
samba_log.sql Normal file
View File

@ -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;

View File

@ -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 <daniel@firewall-services.com> 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