summaryrefslogtreecommitdiffstats
path: root/recipes-security/buck-security
diff options
context:
space:
mode:
authormulhern <mulhern@yoctoproject.org>2013-09-03 20:30:50 -0400
committermulhern <mulhern@yoctoproject.org>2013-10-23 21:57:20 -0400
commit594e95f052d352c4b269a39e994785e4e60ef078 (patch)
treeaab636f39728ce315feb976679f6a5d3533bc980 /recipes-security/buck-security
parentb2a60ba7ff7eb43446e96fc5048109922d58b45d (diff)
downloadmeta-security-594e95f052d352c4b269a39e994785e4e60ef078.tar.gz
buck-security: Parameterize hard-coded file locations.
buck-security hard-codes a number of file locations for the target system on which it operates and also its own dependencies. These hard-coded dependencies have been parameterized and a few other related changes have been made. The changes are more fully explained below. buck-security.bb: * The RDEPENDS_${PN} variable has been made more orderly in anticipation of subsequent changes. It also includes a few other perl modules required by the changes to the application. * The functionality.patch file has been removed and superseded by the take_root_dir.patch patch. * The definition of S is parameterized on BPN not PN; they are different if the package has a native option. * The install step replaces the use directives and an assignment in the buck-security script in a more general way than previously. * The recipes now allows the package to have a native version. take_root_dir.patch: * buck-security * An additional flag, sysroot, that specifies the sysroot of the filesystem that the buck-security utility inspects is added. If the sysroot can not be located the script fails gracefully. * An additional flag, no-sudo, which prevents the script from exiting if it is not run by root is added. * An additional flag, disable-checks, which accepts a comma-separated list of checks to be disabled is added. * The script checks whether there has been an error in parsing the command-line arguments and fails with a usage message if there has. * The log flag now optionally takes a log file name. * The location of the configuration file is calculated relative to the location of the main script and if it can not be found the script fails gracefully. * The various file locations specified in the buck-security configuration file are made relative to the location of the buck-security script or the sysroot as appropriate. * If a log file has been specified the log is not also printed to stdout. * The command actually executed is printed in the log. * Some checks for mutually exclusive options are added. * Output level 3 is now meaningless, so it has been removed. * Various changes have been made to the report format. * Results are sorted lexicographically and, if abspath, do not include the sysroot. * checks/*.pm files * Wherever a directory had been hard-coded it is now parameterized on the sysroot. * In some cases, a test that had previously been run as a bash test was converted to a perl test to allow better handling of results and errors. * The output parameter is no longer accepted by the check procedure since this value is global. * All check procedures now accept an output_type parameter. * The dangling URLs are removed from the help text. * checks/lib/check.pm * The CheckBash and CheckPerl functions have been adapted so that the the filepaths are not hard-coded and so that the actual command is made available to the logging component. * A parameter indicating the outcome type is accepted and passed to the exception checker. * Error output is clearly distinguished from regular output. * A failure in a test is clearly distinguished from an insecure result. * The output is no longer formatted in the check functions. * checks/lib/mkchecksum.pm * The command no longer is run on non-existent directories. * checks/lib/exceptions.pm * The exception file path is located relative to the buck-security script. * If the exceptions are pathnames, the sysroot is prepended. * Correct wildcard semantics is observed. * checks/lib/users.pm * The passwd files are located relative to the sysroot. * Reading from the password file is made more principle. * The test experiences an error if files can not be found rather than the script terminating. * Some dead code is eliminated. * conf/buck-security.conf * The checksum_dir variable is a list instead of a string for easier manipulation. * The new configuration variable sysdir is added and the default is /. * The ssh_config variable is added. * All tests are included in the checks variable. * checks/sshd.pm * The ssh config file is set in the buck-security configuration file instead of hard-coded here. * checks/nopasswd.pm * This is a duplicate of emptypasswd, so it is removed. * RDEPENDS_${PN}_class-native variable is added as some tasks make no sense when run externally. Since they will not be run, there is no point
Diffstat (limited to 'recipes-security/buck-security')
-rw-r--r--recipes-security/buck-security/buck-security_0.6.bb45
-rw-r--r--recipes-security/buck-security/files/functionality.patch38
-rw-r--r--recipes-security/buck-security/files/pseudo.patch74
-rw-r--r--recipes-security/buck-security/files/take_root_dir.patch1686
4 files changed, 1797 insertions, 46 deletions
diff --git a/recipes-security/buck-security/buck-security_0.6.bb b/recipes-security/buck-security/buck-security_0.6.bb
index f58890f..26d553a 100644
--- a/recipes-security/buck-security/buck-security_0.6.bb
+++ b/recipes-security/buck-security/buck-security_0.6.bb
@@ -4,15 +4,42 @@ system. This enables you to quickly overview the security status of your Linux s
4SECTION = "security" 4SECTION = "security"
5LICENSE = "GPL-2.0" 5LICENSE = "GPL-2.0"
6LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6" 6LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6"
7RDEPENDS_${PN} = "perl perl-module-term-ansicolor perl-module-posix perl-module-getopt-long perl-module-time-localtime perl-module-data-dumper perl-module-lib net-tools coreutils gnupg pinentry" 7RDEPENDS_${PN} = "coreutils \
8 gnupg \
9 net-tools \
10 perl \
11 perl-module-data-dumper \
12 perl-module-file-basename \
13 perl-module-file-spec \
14 perl-module-getopt-long \
15 perl-module-lib \
16 perl-module-posix \
17 perl-module-term-ansicolor \
18 perl-module-time-localtime \
19 pinentry \
20 "
8 21
9SRC_URI = "http://sourceforge.net/projects/buck-security/files/buck-security/buck-security_0.6/${PN}_${PV}.tar.gz \ 22RDEPENDS_${PN}_class-native = "coreutils \
10 file://functionality.patch" 23 net-tools \
24 perl \
25 perl-module-data-dumper \
26 perl-module-file-basename \
27 perl-module-file-spec \
28 perl-module-getopt-long \
29 perl-module-lib \
30 perl-module-posix \
31 perl-module-term-ansicolor \
32 perl-module-time-localtime \
33 "
34
35SRC_URI = "http://sourceforge.net/projects/buck-security/files/buck-security/buck-security_0.6/${BPN}_${PV}.tar.gz \
36 file://take_root_dir.patch \
37 "
11 38
12SRC_URI[md5sum] = "edbd40742853fc91ffeae5b2d9ea7bab" 39SRC_URI[md5sum] = "edbd40742853fc91ffeae5b2d9ea7bab"
13SRC_URI[sha256sum] = "5d5dcc58b09c3a4bd87f60f86bb62cd2b0bfd7106a474951f8f520af0042a5b7" 40SRC_URI[sha256sum] = "5d5dcc58b09c3a4bd87f60f86bb62cd2b0bfd7106a474951f8f520af0042a5b7"
14 41
15S = "${WORKDIR}/${PN}_${PV}" 42S = "${WORKDIR}/${BPN}_${PV}"
16 43
17do_configure() { 44do_configure() {
18 : 45 :
@@ -26,11 +53,13 @@ do_install() {
26 install -d ${D}${bindir}/buck 53 install -d ${D}${bindir}/buck
27 cp -r ${S}/* ${D}${bindir}/buck 54 cp -r ${S}/* ${D}${bindir}/buck
28 cp -r ${S}/buck-security ${D}${bindir} 55 cp -r ${S}/buck-security ${D}${bindir}
29 sed -i 's:use lib "checks":use lib "${bindir}/buck/checks":g' ${D}${bindir}/buck-security 56 sed -i 's!use lib "checks"!use lib File::Spec->catfile(dirname(File::Spec->rel2abs(__FILE__)), "buck/checks")!' ${D}${bindir}/buck-security
30 sed -i 's:use lib "checks/lib":use lib "${bindir}/buck/checks/lib":g' ${D}${bindir}/buck-security 57 sed -i 's!use lib "checks/lib"!use lib File::Spec->catfile(dirname(File::Spec->rel2abs(__FILE__)), "buck/checks/lib")!' ${D}${bindir}/buck-security
31 sed -i 's:use lib "lib":use lib "${bindir}/buck/lib":g' ${D}${bindir}/buck-security 58 sed -i 's!use lib "lib"!use lib File::Spec->catfile(dirname(File::Spec->rel2abs(__FILE__)), "buck/lib")!' ${D}${bindir}/buck-security
32 sed -i 's:conf/buck-security.conf:${bindir}/buck/conf/buck-security.conf:g' ${D}${bindir}/buck-security 59 sed -i 's!my $buck_root = "."!my $buck_root = File::Spec->catfile(dirname(File::Spec->rel2abs(__FILE__)), "buck")!' ${D}${bindir}/buck-security
33 60
34} 61}
35 62
36FILES_${PN} = "${bindir}/*" 63FILES_${PN} = "${bindir}/*"
64
65BBCLASSEXTEND = "native"
diff --git a/recipes-security/buck-security/files/functionality.patch b/recipes-security/buck-security/files/functionality.patch
deleted file mode 100644
index 86fbeee..0000000
--- a/recipes-security/buck-security/files/functionality.patch
+++ /dev/null
@@ -1,38 +0,0 @@
1From 216aed597b3f20692a9c9d74dae79fa73e36c75b Mon Sep 17 00:00:00 2001
2From: Andrei Dinu <andrei.adrianx.dinu@intel.com>
3Date: Thu, 1 Aug 2013 10:30:26 +0300
4Subject: [PATCH] added functionality
5
6 * removed sshd from the checks. When needed it can be added
7 in the file.
8 * added saving location for checksums.gpg file
9
10Signed-off-by: Andrei Dinu <andrei.adrianx.dinu@intel.com>
11---
12 conf/buck-security.conf | 3 +--
13 1 file changed, 1 insertion(+), 2 deletions(-)
14
15diff --git a/conf/buck-security.conf b/conf/buck-security.conf
16index eb88982..f573aa8 100644
17--- a/conf/buck-security.conf
18+++ b/conf/buck-security.conf
19@@ -27,7 +27,6 @@ usermask
20 superusers
21 services
22 firewall
23-sshd
24 packages_problematic
25 checksum
26 );
27@@ -48,7 +47,7 @@ $checksum_program = "sha256sum";
28 $checksum_dir = "/sbin/* /bin/* /usr/sbin/* /usr/bin/*";
29
30
31-$checksum_file = "checksums.gpg";
32+$checksum_file = "/usr/bin/checksums.gpg";
33
34
35
36--
371.7.9.5
38
diff --git a/recipes-security/buck-security/files/pseudo.patch b/recipes-security/buck-security/files/pseudo.patch
new file mode 100644
index 0000000..906c1e2
--- /dev/null
+++ b/recipes-security/buck-security/files/pseudo.patch
@@ -0,0 +1,74 @@
1Index: buck-security_0.6/buck-security
2===================================================================
3--- buck-security_0.6.orig/buck-security 2013-09-10 20:58:49.564292001 -0400
4+++ buck-security_0.6/buck-security 2013-09-11 10:07:40.440543001 -0400
5@@ -28,11 +28,6 @@
6 # start time
7 my $start_time = time();
8
9-# Runned by root?
10-if ( $> != 0 ) {
11- print STDERR "Only root can run this program\n";
12- exit 1;
13-}
14
15 # Read Options from command line (--help, --log and --output), run buck --help for more information
16 my $man = 0;
17@@ -41,13 +36,15 @@
18 my $opt_log = ''; # Log? via --log
19 my $opt_checksum = 0;
20 my $opt_sysroot = '';
21+my $opt_pseudo = 0;
22 GetOptions(
23 'output=i' => \$opt_output,
24 'log=s' => \$opt_log,
25 'help|?' => \$help,
26 man => \$man,
27 'make-checksums' => \$opt_checksum,
28- 'sysroot=s' => \$opt_sysroot
29+ 'sysroot=s' => \$opt_sysroot,
30+ 'pseudo' => \$opt_pseudo
31 ) ||
32 pod2usage(
33 -message => "\n",
34@@ -73,6 +70,12 @@
35
36 { package Config; do $config_file }
37
38+if ( $> != 0 && ! $opt_pseudo) {
39+ print STDERR "If you are not using pseudo you must run this script as root.\n";
40+ exit 1;
41+}
42+
43+
44 if ($opt_sysroot) {
45 $Config::sysroot = $opt_sysroot;
46 }
47@@ -98,6 +101,17 @@
48
49
50
51+if ($opt_pseudo) {
52+ @Config::checks = grep
53+ { $_ ne 'checksum' &&
54+ $_ ne 'firewall' &&
55+ $_ ne 'services' &&
56+ $_ ne 'usermask' }
57+ @Config::checks;
58+}
59+
60+
61+
62 if ($opt_checksum != 0) {
63 use mkchecksum;
64 mkchecksum->MkChecksum();
65@@ -219,6 +233,9 @@
66 --sysroot=<root>
67 specify the root directory of the filesystem to be analyzed
68
69+ --pseudo
70+ if set, run with pseudo
71+
72
73
74 =head1 FURTHER INFORMATION
diff --git a/recipes-security/buck-security/files/take_root_dir.patch b/recipes-security/buck-security/files/take_root_dir.patch
new file mode 100644
index 0000000..c4c3a32
--- /dev/null
+++ b/recipes-security/buck-security/files/take_root_dir.patch
@@ -0,0 +1,1686 @@
1Index: buck-security_0.6/buck-security
2===================================================================
3--- buck-security_0.6.orig/buck-security 2013-09-17 21:16:30.170513001 -0400
4+++ buck-security_0.6/buck-security 2013-09-17 21:16:30.266513001 -0400
5@@ -4,6 +4,8 @@
6 use warnings;
7
8 # Perl Core Modules
9+use File::Basename;
10+use File::Spec;
11 use Term::ANSIColor; # for colours
12 use POSIX qw(nice); # for nice
13 use Getopt::Long; # for command line options
14@@ -13,10 +15,13 @@
15
16 use Data::Dumper; # for debugging only
17
18+
19 # Buck Modules
20-use lib "checks"; # include security checks
21-use lib "checks/lib"; # inclue checks libraries
22-use lib "lib"; # include general buck library
23+use lib "checks";
24+use lib "checks/lib";
25+use lib "lib";
26+
27+my $buck_root = ".";
28
29 # VERSION
30 my $VERSION = '0.6';
31@@ -24,38 +29,120 @@
32 # start time
33 my $start_time = time();
34
35-# Runned by root?
36-if ( $> != 0 ) {
37- print STDERR "Only root can run this program\n";
38- exit 1;
39-}
40
41-# Read Options from command line (--help, --log and --output), run buck --help for more information
42 my $man = 0;
43 my $help = 0;
44-my $opt_output = '2'; # verbose level: via --output=X 2 is default
45-my $opt_log = ''; # Log? via --log
46+my $opt_output = 0; # verbose level: via --output=X 2 is default
47+my $opt_log = 0; # Log? via --log
48 my $opt_checksum = 0;
49+my $opt_sysroot = '';
50+my $opt_disable_checks = '';
51+my $opt_no_sudo = 0;
52 GetOptions(
53 'output=i' => \$opt_output,
54- 'log' => \$opt_log,
55+ 'log:s' => \$opt_log,
56 'help|?' => \$help,
57 man => \$man,
58 'make-checksums' => \$opt_checksum,
59+ 'sysroot=s' => \$opt_sysroot,
60+ 'disable-checks=s' => \$opt_disable_checks,
61+ 'no-sudo' => \$opt_no_sudo
62+) ||
63+pod2usage(
64+ -message => "\n",
65+ -exitval => 1,
66+ -verbose => 1
67 );
68
69+
70 # Output Help if needed via pod2usage
71 pod2usage(
72 -message => "\n",
73 -exitval => 0,
74 -verbose => 1
75 ) if $help;
76-pod2usage( -exitstatus => 0, -verbose => 2 ) if $man;
77+
78+pod2usage( -exitval => 0,
79+ -verbose => 2
80+) if $man;
81+
82+pod2usage( -exitval => 1,
83+ -verbose => 2,
84+ -message => "Can not log or check if generating initial checksums for files.\n"
85+) if $opt_checksum && ( $opt_log || $opt_disable_checks );
86+
87+if ( ! $opt_no_sudo && $> != 0 ) {
88+ print STDERR "Specify -no-sudo if you wish to run not as root.\n";
89+ exit 1;
90+}
91
92 # Read Config file
93-my $config_file = "conf/buck-security.conf";
94+my $config_file = File::Spec->catfile($buck_root, "conf/buck-security.conf");
95+if ( ! -f $config_file ) {
96+ print STDERR "The configuration file $config_file was not found.\n";
97+ exit 1;
98+}
99+
100 { package Config; do $config_file }
101
102+if ( $opt_output != 0 ) {
103+ if ( grep { $_ == $opt_output } (1, 2) ) {
104+ no warnings;
105+ $Config::output = $opt_output;
106+ }
107+ else {
108+ print STDERR "Unknown output format $opt_output specified.\n";
109+ exit 1;
110+ }
111+}
112+
113+if ( $opt_sysroot ) {
114+ $Config::sysroot = $opt_sysroot;
115+}
116+$Config::sysroot = File::Spec->rel2abs( $Config::sysroot );
117+if ( ! -d $Config::sysroot ) {
118+ print STDERR "The specified sysroot $Config::sysroot does not exist.\n";
119+ exit 1;
120+}
121+
122+$Config::buck_root = $buck_root;
123+
124+my %disabled_checks = map { $_ => 1 } split( /,/, $opt_disable_checks );
125+@Config::checks = grep( ! defined $disabled_checks { $_ }, @Config::checks);
126+
127+$Config::ssh_config =
128+ File::Spec->catfile( $Config::sysroot, $Config::ssh_config );
129+
130+$Config::checksum_file =
131+ File::Spec->catfile( $Config::buck_root, $Config::checksum_file );
132+@Config::checksum_dir =
133+ map {File::Spec->catfile( $Config::sysroot, $_ )} @Config::checksum_dir;
134+
135+$Config::logdir =
136+ File::Spec->catdir( $Config::buck_root, $Config::logdir );
137+
138+
139+# The -log flag has been set but no log file has been specified.
140+if ( $opt_log eq '' ) {
141+
142+ if ( ! -d $Config::logdir ) {
143+ print STDERR "The specified log directory $Config::logdir does not exist.\n";
144+ exit 1;
145+ }
146+
147+ # Get Date for filename of log
148+ my $year = localtime->year() + 1900;
149+ my $day = sprintf( "%02d", localtime->mday() );
150+ my $month = localtime->mon() + 1;
151+ $month = sprintf( "%02d", $month );
152+ my $hour = sprintf( "%02d", localtime->hour() );
153+ my $min = sprintf( "%02d", localtime->min() );
154+ my $sec = sprintf( "%02d", localtime->sec() );
155+ my $date = $day . $month . $year . "_$hour-$min-$sec";
156+
157+ $opt_log = File::Spec->catfile( $Config::logdir, "buck$date.log" );
158+}
159+
160 if ($opt_checksum != 0) {
161 use mkchecksum;
162 mkchecksum->MkChecksum();
163@@ -73,16 +160,18 @@
164 print
165 "\nWe will run $nr_of_checks security checks now.\nThis may take a while...\n";
166
167+
168+
169+
170 my $log; # String which the Log is written to, later written to fike
171
172 # sub which decides if a log should be written (if --log was given) or not, used instead of print
173 sub logprint {
174 my $string = shift; # string given to sub
175
176- #print and log
177+ #log only
178 if ($opt_log) {
179 $log .= $string; # add string to log string
180- print $string;
181 }
182
183 #print only
184@@ -99,23 +188,40 @@
185 my $pack = $_; # Package-Name
186 my $mod = $pack . '.pm'; # Module Name
187 require $mod;
188- my ( $title, $result, $help_msg, $details ) =
189- $pack->check($opt_output); # run check sub in check module
190- $title = sprintf( "%-45s", "[*] CHECK $nr: $title" );
191- logprint("\n\n$title"); # print title of check
192- if ( $result ne 0 ) { # if something found print [WARNING]
193+ my ( $title, $result, $test, $help_msg, $details_ref, $outcome_type) =
194+ $pack->check(); # run check sub in check module
195+ my $first_line = sprintf( "%-60s", "[$nr] CHECK $pack: $title " );
196+ logprint("\n\n$first_line"); # print title of check
197+ if ( $result != 0 ) { # if something found print [WARNING]
198 print color 'bold red';
199 logprint("[ WARNING ]\n");
200 print color 'reset'; # normal
201- if ($details) {
202+ my @details = @ { $details_ref };
203+ my $details;
204+ if ( $result == 2 ) {
205+ logprint("The security test encountered the following error during execution.\n");
206+ $details = join( "", @details );
207+ }
208+ else {
209+ logprint("The security test discovered a possible insecurity.\n");
210 logprint("$help_msg$line$line\n");
211- logprint("$details\n");
212+ @details = sort( @details );
213+ if ( $outcome_type eq "abspath" ) {
214+ @details = map { substr( $_, length( $Config::sysroot ) ) } @details;
215+ if ( $Config::output > 1 ) {
216+ logprint("Pathnames are relative to $Config::sysroot.\n");
217+ }
218+ }
219+ $details = join( "\n", @details );
220 }
221+ logprint("$details\n") if ( $Config::output > 1 );
222 }
223 else { # if nothing found print [OK]
224 print color 'bold green';
225 logprint("[ OK ]\n");
226+ print color 'reset';
227 }
228+ logprint("Command was: $test\n");
229 print color 'bold blue';
230
231 $nr++;
232@@ -135,22 +241,10 @@
233
234 print color 'reset';
235
236-# LOGGING
237-if ($opt_log) {
238
239- # Get Date for filename of log
240- my $year = localtime->year() + 1900;
241- my $day = sprintf( "%02d", localtime->mday() );
242- my $month = localtime->mon() + 1;
243- $month = sprintf( "%02d", $month );
244- my $hour = sprintf( "%02d", localtime->hour() );
245- my $min = sprintf( "%02d", localtime->min() );
246- my $sec = sprintf( "%02d", localtime->sec() );
247- my $date = $day . $month . $year . "_$hour-$min-$sec";
248
249- # Write Log string to file
250- my $logfile = "logs/buck$date.log";
251- open my $LOG, '>', $logfile or die $!;
252+if ($opt_log) {
253+ open my $LOG, '>', $opt_log or die $!;
254 print $LOG $log;
255 close($LOG);
256 }
257@@ -175,8 +269,9 @@
258 create checksums of important programs to recheck them with buck-security
259 later
260
261- --log
262- logs output in logs-directory
263+ --log=<logfile>
264+ log output to specified file. If flag is set but no file is specified the
265+ log file path is auto-generated.
266
267 --output=1
268 short output, show result only
269@@ -184,8 +279,14 @@
270 --output=2 (default)
271 default output, show details (which files/dirs where found f.e.)
272
273- --output=3
274- long output, also show errors
275+ --sysroot=<root>
276+ specify the root directory of the filesystem to be analyzed
277+
278+ --disable-checks=<checks>
279+ a comma separated list of checks to disable
280+
281+ --no-sudo
282+ do not require the user running the script to be super
283
284
285
286Index: buck-security_0.6/checks/worldwriteablefiles.pm
287===================================================================
288--- buck-security_0.6.orig/checks/worldwriteablefiles.pm 2013-09-17 21:16:30.170513001 -0400
289+++ buck-security_0.6/checks/worldwriteablefiles.pm 2013-09-17 21:16:30.266513001 -0400
290@@ -2,24 +2,43 @@
291
292 use strict;
293 use warnings;
294+
295+use File::Spec;
296+
297 use lib::check; # for the "real" check Sub
298
299 package worldwriteablefiles;
300
301-my $title = "World Writeable Files"; # title of the test
302-my $security_test = "find / ! -fstype proc -type f -perm -2 2> /dev/null"; # the security test
303-my $exception_file = "conf/whitelists/worldwriteablefiles-whitelist.conf"; # the file with exceptions
304+sub check {
305+ use lib::check;
306
307-# help - information about the check
308-my $help = <<HELP;
309+ my $title = "World Writeable Files";
310+ my $package_name = "worldwriteablefiles";
311+ my $exception_file = "conf/whitelists/worldwriteablefiles-whitelist.conf";
312+ my $outcome_type = "abspath";
313+ my $help = <<HELP;
314 The following files are writeable for all users.
315-Learn more at http://buck-security.org/doc.html#c_wwf
316 HELP
317+ check::CheckPerl( $title,
318+ $package_name,
319+ $outcome_type,
320+ $exception_file,
321+ $help );
322+}
323
324-# just forwarding to the "real" check Sub with variables
325-sub check {
326- my $opt_output = $_[1];
327- check::CheckBash( $title, $security_test, $exception_file, $help, $opt_output );
328+sub perl {
329+
330+ my @directories = grep { ! ( $_ =~ m/\/proc$/ ) } glob( File::Spec->catfile( $Config::sysroot, "*" ) );
331+ if ( ! @directories ) {
332+ return ( 0, @directories );
333+ }
334+
335+ my $command = "find " . join( " ", @directories ) . " -perm -2 -type f";
336+
337+ @directories = `$command`;
338+ chomp( @directories );
339+
340+ return ( 0, @directories );
341 }
342
343 1;
344Index: buck-security_0.6/checks/lib/check.pm
345===================================================================
346--- buck-security_0.6.orig/checks/lib/check.pm 2013-09-17 21:16:30.170513001 -0400
347+++ buck-security_0.6/checks/lib/check.pm 2013-09-17 21:16:30.266513001 -0400
348@@ -8,96 +8,76 @@
349
350 # check.pm
351 # executes Bash-Oneliners
352-# Gets Title and command, returns Title, Result (0 or 1 where 0 is good) , and details
353+# Gets Title and command, returns Title, Result (0 or 1 where 0 is good) , the test that was run, the help text, the outcomes, and the errors
354
355 sub CheckBash {
356- my $result = 0;
357 my $title = shift;
358- my $security_test = shift;
359+ my $security_test_ref = shift;
360+ my $outcome_type = shift;
361 my $exception_file = shift;
362 my $help = shift;
363- my $opt_output = shift; # output errors?
364- my @alarms;
365 my @outcomes;
366- my $outcome; # string to return
367- # be verbose
368- if ( $opt_output == '3' ) {
369- @alarms = `$security_test`; # execute test and save outcome WITH errors
370- chomp(@alarms);
371- }
372-
373- # no Errors if --output=1 or 2 (for 1 see below)
374- elsif ( $opt_output == '1' || $opt_output == '2' ) {
375- @alarms = `$security_test 2> /dev/null`; # execute test and save outcome WITHOUT errors
376- chomp(@alarms);
377- }
378-
379- # nothing found, return 0 and exit
380- if ( @alarms eq "" ) {
381- return ( $title, $result, 0 ); # last 0 is for $details
382+ my $security_test = $security_test_ref->();
383+
384+ my @errors = `$security_test 3>&1 1>/dev/null 2>&3`;
385+
386+ if ( @errors ) {
387+ return ( $title, 2, $security_test, $help, \@errors );
388 }
389
390+ @outcomes = `$security_test 2> /dev/null`; # execute test and save outcome WITHOUT errors
391+ chomp(@outcomes);
392+
393 # Now check outcome against exceptions
394- @outcomes = exceptions::CheckAgainstExceptions(\@alarms, $exception_file);
395- # if nothing left, return 0 and exit
396- if ( @outcomes eq 0 ) {
397- return ( $title, $result, 0 ); # second 0 is for $details
398- exit;
399+ @outcomes = exceptions::CheckAgainstExceptions(\@outcomes,
400+ $exception_file,
401+ $outcome_type);
402+
403+ if ( ! @outcomes ) {
404+ return ( $title, 0, $security_test );
405 }
406
407 # found something which wasn't in the exceptions from config, return it
408 else {
409- $outcome = join( "\n", @outcomes ); # translate back to string
410- $result = 1;
411-
412- # supress Details when --output=1
413- if ( $opt_output == '1' ) {
414- $outcome = 0;
415- }
416-
417- return ( $title, $result, $help, $outcome );
418+ return ( $title, 1, $security_test, $help, \@outcomes, $outcome_type );
419 }
420 }
421
422 sub CheckPerl {
423 my $title = shift;
424 my $package_name = shift;
425+ my $outcome_type = shift;
426 my $exception_file = shift;
427 my $help = shift;
428- my $opt_output = shift;
429 my @outcomes;
430- my $result = 0;
431 my $mod = $package_name . '.pm';
432+ my $security_test = "a perl script, too long to display";
433+
434 # excute the check in file at /checks, @outcomes is defined there
435 require $mod;
436- my $outcome; # string to return
437
438- my @alarms = $package_name->perl();
439- # nothing found, return 0 and exit
440- if ( @alarms eq "" ) {
441- return ( $title, $result, 0 ); # last 0 is for $details
442+ my ( $result, @details ) = $package_name->perl();
443+
444+ if ( $result == 1 ) {
445+ return ( $title, 2, $security_test, $help, \@details );
446+ }
447+ if ( ! @details ) {
448+ return ( $title, 0, $security_test );
449 }
450
451 # Now check outcome against exceptions
452- @outcomes = exceptions::CheckAgainstExceptions(\@alarms,$exception_file);
453+ @outcomes = exceptions::CheckAgainstExceptions(\@details,
454+ $exception_file,
455+ $outcome_type);
456
457 # if nothing left, return 0 and exit
458- if ( @outcomes eq 0 ) {
459- return ( $title, $result, 0 ); # second 0 is for $details
460- exit;
461+ if ( ! @outcomes ) {
462+ return ( $title, 0, $security_test );
463 }
464
465 # found something which wasn't in the exceptions from config, return it
466 else {
467- my $outcome = join( "\n", @outcomes ); # translate back to string
468- $result = 1;
469-
470- # supress Details when --output=1
471- if ( $opt_output == '1' ) {
472- $outcome = 0;
473- }
474-
475- return ( $title, $result, $help, $outcome );
476+ return ( $title, 1, $security_test, $help, \@outcomes, $outcome_type );
477 }
478
479 }
480Index: buck-security_0.6/checks/worldwriteabledirs.pm
481===================================================================
482--- buck-security_0.6.orig/checks/worldwriteabledirs.pm 2013-09-17 21:16:30.170513001 -0400
483+++ buck-security_0.6/checks/worldwriteabledirs.pm 2013-09-17 21:16:30.266513001 -0400
484@@ -2,25 +2,43 @@
485
486 use strict;
487 use warnings;
488+
489+use File::Spec;
490+
491 use lib::check; # for the "real" check Sub
492
493 package worldwriteabledirs;
494
495-my $title = "World Writeable Directories"; # title of the test
496-my $security_test =
497- "find / -type d -perm -o+w 2> /dev/null"; # the security test
498-my $exception_file = "conf/whitelists/worldwriteabledirs-whitelist.conf"; # the file with exceptions
499+sub check {
500
501-# help - information about the check
502-my $help = <<HELP;
503+ my $title = "World Writeable Directories";
504+ my $package_name = "worldwriteabledirs";
505+ my $exception_file = "conf/whitelists/worldwriteabledirs-whitelist.conf";
506+ my $outcome_type = "abspath";
507+ my $help = <<HELP;
508 The following directories are writeable for all users.
509-Learn more at http://buck-security.org/doc.html#c_wwd
510 HELP
511+ check::CheckPerl( $title,
512+ $package_name,
513+ $outcome_type,
514+ $exception_file,
515+ $help );
516+}
517
518-# just forwarding to the "real" check Sub with variables
519-sub check {
520- my $opt_output = $_[1];
521- check::CheckBash( $title, $security_test, $exception_file, $help, $opt_output );
522+
523+sub perl {
524+
525+ my @directories = grep { ! ( $_ =~ m/\/proc$/ ) } glob( File::Spec->catfile( $Config::sysroot, "*" ) );
526+ if ( ! @directories ) {
527+ return ( 0, @directories );
528+ }
529+
530+ my $command = "find " . join( " ", @directories ) . " -perm -o+w -type d";
531+
532+ @directories = `$command`;
533+ chomp( @directories );
534+
535+ return ( 0, @directories );
536 }
537
538 1;
539Index: buck-security_0.6/checks/stickytmp.pm
540===================================================================
541--- buck-security_0.6.orig/checks/stickytmp.pm 2013-09-17 21:16:30.170513001 -0400
542+++ buck-security_0.6/checks/stickytmp.pm 2013-09-17 21:16:30.266513001 -0400
543@@ -2,28 +2,56 @@
544
545 use strict;
546 use warnings;
547+use File::Spec;
548 use lib::check; # for the "real" check Sub
549
550 package stickytmp;
551
552-my $title = "Sticky-Bit set for /tmp"; # title of the test
553-my $security_test =
554- 'ls -ld /tmp | awk \'{print $1":"$3":"$4}\''; # the security test
555-my $exception_file =
556- "conf/whitelists/stickytmp-whitelist.conf"; # the file with exceptions
557-# help - information about the check
558-my $help = <<HELP;
559-The permission mode of your /tmp directory isn't secure.
560-Learn more at http://buck-security.org/doc.html#c_tmp
561+sub check {
562+ use lib::check;
563+
564+ my $title = "Mode, user, and group acceptable for tmp directory.";
565+ my $exception_file = "conf/whitelists/stickytmp-whitelist.conf";
566+ my $package_name = 'stickytmp';
567+ my $outcome_type = "other";
568+ my $help = <<HELP;
569+The tmp directory has a mode, user, group combination which has
570+not been explicitly included in the whitelist.
571 HELP
572
573+ check::CheckPerl( $title,
574+ $package_name,
575+ $outcome_type,
576+ $exception_file,
577+ $help );
578+}
579
580
581+sub perl {
582+ use users;
583
584-# just forwarding to the "real" check Sub with variables
585-sub check {
586- my $opt_output = $_[1];
587- check::CheckBash( $title, $security_test, $exception_file, $help, $opt_output );
588+ my $tmpdir = File::Spec->catdir($Config::sysroot, 'tmp');
589+
590+ if ( ! -d $tmpdir ) {
591+ return ( 1, @ { ["Specified tmpdir $tmpdir does not exist."] } );
592+ }
593+
594+ my $command = 'ls -ld ' . $tmpdir;
595+ my $ls_pattern = '^([^\s]+) ([^\s]+) ([^\s]+) ([^\s]+)';
596+ my @outcomes = `$command`;
597+ chomp( @outcomes );
598+ if ( @outcomes != 1) {
599+ return ( 1, @ { ["ls -ld result has multiple lines."] } );
600+ }
601+ else {
602+ my $info = $outcomes[0];
603+ if ( $info =~ m/$ls_pattern/ ) {
604+ return ( 0, @ { ["$1:$3:$4"] } );
605+ }
606+ else {
607+ return ( 1, @ { ["Format of ls -ld result $info is unexpected."] } );
608+ }
609+ }
610 }
611
612 1;
613Index: buck-security_0.6/checks/suids.pm
614===================================================================
615--- buck-security_0.6.orig/checks/suids.pm 2013-09-17 21:16:30.170513001 -0400
616+++ buck-security_0.6/checks/suids.pm 2013-09-17 21:16:30.266513001 -0400
617@@ -2,27 +2,46 @@
618
619 use strict;
620 use warnings;
621+
622+use File::Spec;
623+
624 use lib::check; # for the "real" check Sub
625
626 package suids;
627
628-my $title = "Files where Setuid is used"; # title of the test
629-my $security_test = "find / -perm -4000 -type f"; # the security test
630-my $exception_file =
631- "conf/whitelists/suids-whitelist.conf"; # the whitelist file
632-
633-# help - information about the check
634-my $help = <<HELP;
635-The following programs have the SUID set. This might
636-represent a security risk.
637-Learn more at http://buck-security.org/doc.html#c_suids
638+sub check {
639+ use lib::check;
640+
641+ my $title = "Files where Setuid is used";
642+ my $package_name = "suids";
643+ my $exception_file = "conf/whitelists/suids-whitelist.conf";
644+
645+ my $outcome_type = "abspath";
646+
647+ my $help = <<HELP;
648+The following programs have the SUID set.
649 HELP
650
651+ check::CheckPerl( $title,
652+ $package_name,
653+ $outcome_type,
654+ $exception_file,
655+ $help );
656+}
657+
658+
659+sub perl {
660+ my @directories = grep { ! ( $_ =~ m/\/proc$/ ) } glob( File::Spec->catfile( $Config::sysroot, "*" ) );
661+ if ( ! @directories ) {
662+ return ( 0, @directories );
663+ }
664+
665+ my $command = "find " . join( " ", @directories ) . " -perm -4000 -type f";
666+
667+ @directories = `$command`;
668+ chomp( @directories );
669
670-# just forwarding to the "real" check Sub with variables
671-sub check () {
672- my $opt_output = $_[1];
673- check::CheckBash( $title, $security_test, $exception_file, $help, $opt_output );
674+ return ( 0, @directories );
675 }
676
677 1;
678Index: buck-security_0.6/checks/sgids.pm
679===================================================================
680--- buck-security_0.6.orig/checks/sgids.pm 2013-09-17 21:16:30.170513001 -0400
681+++ buck-security_0.6/checks/sgids.pm 2013-09-17 21:16:30.266513001 -0400
682@@ -2,28 +2,46 @@
683
684 use strict;
685 use warnings;
686+
687+use File::Spec;
688+
689 use lib::check; # for the "real" check Sub
690
691 package sgids;
692
693-my $title = "Files where Setgid is used"; # title of the test
694-my $security_test = "find / -perm -2000 -type f"; # the security test
695-my $exception_file =
696- "conf/whitelists/sgids-whitelist.conf"; # the file with exceptions
697-
698-# help - information about the check
699-my $help = <<HELP;
700-The following programs have the SGID set. This might
701-represent a security risk.
702-Learn more at http://buck-security.org/doc.html#c_sgids
703+sub check {
704+ use lib::check;
705+
706+ my $title = "Files where Setgid is used";
707+ my $package_name = "sgids";
708+ my $exception_file = "conf/whitelists/sgids-whitelist.conf";
709+ my $outcome_type = "abspath";
710+ my $help = <<HELP;
711+The following programs have the SGID set.
712 HELP
713
714+ check::CheckPerl( $title,
715+ $package_name,
716+ $outcome_type,
717+ $exception_file,
718+ $help );
719+}
720
721
722-# just forwarding to the "real" check Sub with variables
723-sub check {
724- my $opt_output = $_[1];
725- check::CheckBash( $title, $security_test, $exception_file, $help, $opt_output );
726+
727+sub perl {
728+
729+ my @directories = grep { ! ( $_ =~ m/\/proc$/ ) } glob( File::Spec->catfile( $Config::sysroot, "*" ) );
730+ if ( ! @directories ) {
731+ return ( 0, @directories );
732+ }
733+
734+ my $command = "find " . join( " ", @directories ) . " -perm -2000 -type f";
735+
736+ @directories = `$command`;
737+ chomp( @directories );
738+
739+ return ( 0, @directories );
740 }
741
742 1;
743Index: buck-security_0.6/checks/usermask.pm
744===================================================================
745--- buck-security_0.6.orig/checks/usermask.pm 2013-09-17 21:16:30.170513001 -0400
746+++ buck-security_0.6/checks/usermask.pm 2013-09-17 21:16:30.266513001 -0400
747@@ -8,22 +8,28 @@
748
749 my $title =
750 "Check umask"; # title of the test
751-my $security_test = 'umask'; # the security test
752+sub security_test {
753+ return 'umask';
754+}
755 my $exception_file =
756 "conf/whitelists/usermask-whitelist.conf"; # the file with exceptions
757
758+my $outcome_type = "other";
759+
760 # help - information about the check
761 my $help = <<HELP;
762-Your default permissions for new files (umask)
763-might represent a security risk.
764-Learn more at http://buck-security.org/doc.html#c_
765+Your default permissions for new files is one
766+which has not been explicitly included in the whitelist.
767 HELP
768
769
770 # just forwarding to the "real" check Sub with variables
771 sub check {
772- my $opt_output = $_[1];
773- check::CheckBash( $title, $security_test, $exception_file, $help, $opt_output );
774+ check::CheckBash( $title,
775+ \&security_test,
776+ $outcome_type,
777+ $exception_file,
778+ $help );
779 }
780
781 1;
782Index: buck-security_0.6/checks/superusers.pm
783===================================================================
784--- buck-security_0.6.orig/checks/superusers.pm 2013-09-17 21:16:30.170513001 -0400
785+++ buck-security_0.6/checks/superusers.pm 2013-09-17 21:16:30.266513001 -0400
786@@ -2,25 +2,56 @@
787
788 use strict;
789 use warnings;
790+
791+use File::Spec;
792+
793 use lib::check; # for the "real" check Sub
794
795 package superusers;
796
797-my $title = "Find superusers"; # title of the test
798-my $security_test = 'grep \':00*:\' /etc/passwd | awk -F: \'{print $1}\''; # the security test
799-my $exception_file =
800- "conf/whitelists/superusers-whitelist.conf"; # the file with exceptions
801+sub check {
802+
803+ my $title = "Find superusers";
804+ my $package_name = "superusers";
805+ my $exception_file = "conf/whitelists/superusers-whitelist.conf";
806
807-# help - information about the check
808-my $help = <<HELP;
809+ my $outcome_type = "other";
810+ my $help = <<HELP;
811 The following users have administrator rights.
812-Learn more at http://buck-security.org/doc.html#c_su
813 HELP
814
815-# just forwarding to the "real" check Sub with variables
816-sub check {
817- my $opt_output = $_[1];
818- check::CheckBash( $title, $security_test, $exception_file, $help, $opt_output );
819+ check::CheckPerl( $title,
820+ $package_name,
821+ $outcome_type,
822+ $exception_file,
823+ $help );
824+}
825+
826+
827+sub perl {
828+ use users;
829+ my @outcomes;
830+
831+ my $PasswdFile = users::GetPasswdFile('passwd');
832+
833+ if (! -f $PasswdFile ) {
834+ return ( 1, @ { ["Password file $PasswdFile does not exist."] } );
835+ }
836+
837+ if (! open( PASSWD, '<', $PasswdFile ) ) {
838+ return ( 1, @ { ["Error opening password file $PasswdFile."] } );
839+ }
840+
841+ my @PasswdFile = <PASSWD>;
842+
843+ my %UsersPasswdNormal = users::PasswordsNormal(@PasswdFile);
844+
845+ while ( my ($k,$v) = each %UsersPasswdNormal ) {
846+ if ( $v->{'userid'} =~ '00*' || $v->{'groupid'} =~ '00*' ) {
847+ push(@outcomes, $k);
848+ }
849+ }
850+ return ( 0, @outcomes );
851 }
852
853 1;
854Index: buck-security_0.6/lib/mkchecksum.pm
855===================================================================
856--- buck-security_0.6.orig/lib/mkchecksum.pm 2013-09-17 21:16:30.170513001 -0400
857+++ buck-security_0.6/lib/mkchecksum.pm 2013-09-17 21:16:30.266513001 -0400
858@@ -9,8 +9,11 @@
859
860 # MkChecksum
861 sub MkChecksum {
862+ my @checksum_dirs = grep( -d $_ , @Config::checksum_dir);
863 # Create checksums
864- `$Config::checksum_program $Config::checksum_dir | gpg -c > $Config::checksum_file; chmod 600 $Config::checksum_file;`;
865+ if (@checksum_dirs) {
866+ `find @checksum_dirs -type f | xargs $Config::checksum_program | gpg -c > $Config::checksum_file; chmod 600 $Config::checksum_file;`;
867+ }
868 }
869
870 1;
871Index: buck-security_0.6/checks/lib/exceptions.pm
872===================================================================
873--- buck-security_0.6.orig/checks/lib/exceptions.pm 2013-09-17 21:16:30.170513001 -0400
874+++ buck-security_0.6/checks/lib/exceptions.pm 2013-09-17 21:16:30.266513001 -0400
875@@ -3,6 +3,8 @@
876 use strict;
877 use warnings;
878
879+use File::Spec;
880+
881 package exceptions;
882
883 # exceptions.pm
884@@ -14,6 +16,7 @@
885
886 sub GetExceptions {
887 my $config_file = shift;
888+ my $outcome_type = shift;
889 open( CONFIG, "<", $config_file )
890 or die "Couldn't read $config_file: $!\n";
891
892@@ -26,6 +29,11 @@
893 chomp;
894 s/#.*//;
895 }
896+
897+ if ( $outcome_type eq "abspath" && $Config::sysroot ne "/" ) {
898+ @exceptions = map { File::Spec->catfile( $Config::sysroot, substr ( $_, 1) ) } @exceptions;
899+ }
900+
901 return @exceptions;
902 }
903
904@@ -39,54 +47,31 @@
905 my $alarms_ref = shift;
906 my @alarms = @{$alarms_ref};
907 my $exception_file = shift;
908- my @outcomes;
909+ my $outcome_type = shift;
910 # EXCEPTION PROCESSING
911 # get exceptions and alarms and compare: @outcomes = alarms which are no exceptions
912 # Code found at http://www.perlmonks.org/?node_id=2461
913
914+ $exception_file = File::Spec->catfile( $Config::buck_root, $exception_file );
915+
916 # only if exception file exists
917 if (-e $exception_file) {
918- my @all_exceptions = GetExceptions($exception_file);
919- # get exceptions with wildcard
920- my @wildcard_exceptions = grep( /\*/, @all_exceptions );
921- # TODO: have to run grep two times to split, not very elegant
922- my @normal_exceptions = grep( !/\*/, @all_exceptions );
923-
924- # remove normal exceptions first
925- my %normal_exceptions = map { $_ => 1 } @normal_exceptions;
926- my %alarms = map { $_ => 1 } @alarms;
927- @outcomes = grep( !defined $normal_exceptions{$_}, @alarms );
928-
929- # Now lets see if there are wildcard exceptions (including a *)
930- if (@wildcard_exceptions) {
931- my %outcomes = map { $_ => 1 }
932- @outcomes; # make hash out of outcomes, set all element to 1
933-
934- # run through outcomes
935- foreach my $hit (@outcomes) {
936-
937- # run through wildcard execption
938- foreach my $wildcard (@wildcard_exceptions) {
939- if ( $hit =~ /^$wildcard/ ) {
940-
941- # if wildcard matches outcome set it to 0 in hash (default is 1)
942- $outcomes{$hit} = 0;
943- }
944- }
945+ my @exceptions = GetExceptions($exception_file, $outcome_type);
946
947+ if ( $outcome_type eq "abspath" ) {
948+ my @all_exceptions;
949+ foreach my $exception (@exceptions) {
950+ @all_exceptions = ( @all_exceptions, glob ( $exception ) );
951+ }
952+ @exceptions = @all_exceptions;
953 }
954
955- # put all the elements still set to 1 (which means no wildcard exception had matched) in @outcomes
956- @outcomes = grep { $outcomes{$_} == 1 } keys %outcomes;
957- @outcomes = sort(@outcomes); # sort it
958- }
959- }
960- # if no exception file all alarms are passed trough
961- else {
962- @outcomes = @alarms;
963+ my %exceptions = map { $_ => 1 } @exceptions;
964+ @alarms = grep( !defined $exceptions{$_}, @alarms );
965 }
966
967- return @outcomes;
968+
969+ return @alarms;
970
971 }
972
973Index: buck-security_0.6/checks/lib/users.pm
974===================================================================
975--- buck-security_0.6.orig/checks/lib/users.pm 2013-09-17 21:16:30.170513001 -0400
976+++ buck-security_0.6/checks/lib/users.pm 2013-09-17 21:16:30.266513001 -0400
977@@ -3,63 +3,33 @@
978 use strict;
979 use warnings;
980
981+use File::Spec;
982
983 package users;
984
985 # users.pm
986 # includes subs for checking user specific stuff
987
988-sub ReadEtcPasswd {
989-
990- my $passwd_file = '/etc/passwd';
991- open(PASSWD, '<', $passwd_file)
992- or die "Couldn't open $passwd_file for reading: $!\n";
993- my @file = <PASSWD>;
994- close(PASSWD);
995- return @file;
996-}
997-
998-sub ReadEtcShadow {
999-
1000- my $passwd_file = '/etc/shadow';
1001- open(PASSWD, '<', $passwd_file)
1002- or die "Couldn't open $passwd_file for reading: $!\n";
1003- my @file = <PASSWD>;
1004- close(PASSWD);
1005- return @file;
1006-}
1007-
1008-
1009-
1010-
1011-sub UsersWithValidShell {
1012- # list of users with valid shell as array
1013- my @users_valid_shell;
1014- my @passwd_file = ReadEtcPasswd();
1015- # root:x:0:0:root:/root:/bin/bash
1016- foreach my $line (@passwd_file) {
1017- $line =~
1018- /(.*):(.*):(.*):(.*):(.*):(.*):(.*)/;
1019- # if $7 (the shell) isnt set to the following add to valid shells
1020- $7 ne '/bin/false' && $7 ne '/usr/sbin/nologin' && $7 ne '/bin/sync'
1021- ?
1022- push(@users_valid_shell, $1)
1023- :
1024- next;
1025- }
1026- return @users_valid_shell;
1027-
1028+sub GetPasswdFile {
1029+ my $filename = $_[0];
1030+ return File::Spec->catfile( $Config::sysroot, "etc/$filename" );
1031 }
1032
1033
1034 # get password items from /etc/passwd
1035 sub PasswordsNormal {
1036 my %UserPasswordNormal;
1037- my @passwd_file = ReadEtcPasswd();
1038+ my @passwd_file = $_[0];
1039 foreach my $line (@passwd_file) {
1040 $line =~
1041 /(.*):(.*):(.*):(.*):(.*):(.*):(.*)/;
1042- $UserPasswordNormal{$1} = $2;
1043+ $UserPasswordNormal{$1} =
1044+ {'password' => $2,
1045+ 'userid' => $3,
1046+ 'groupid' => $4,
1047+ 'info' => $5,
1048+ 'home' => $6,
1049+ 'shell' => $7};
1050 }
1051
1052 return %UserPasswordNormal;
1053@@ -68,14 +38,23 @@
1054 # get password items from /etc/shadow
1055 sub PasswordsShadow {
1056 my %UserPasswordShadow;
1057- my @passwd_file = ReadEtcShadow();
1058+ my @passwd_file = $_[0];
1059 foreach my $line (@passwd_file) {
1060 $line =~
1061 /(.*):(.*):(.*):(.*):(.*):(.*):(.*):(.*):(.*)/;
1062- $UserPasswordShadow{$1} = $2;
1063+ $UserPasswordShadow{$1} =
1064+ {'password' => $2,
1065+ 'days-passed' => $3,
1066+ 'days-may' => $4,
1067+ 'days-must' => $5,
1068+ 'days-warn' => $6,
1069+ 'days-forgive' => $7,
1070+ 'days-disabled' => $8,
1071+ 'reserved' => $9};
1072 }
1073
1074 return %UserPasswordShadow;
1075+
1076 }
1077
1078
1079@@ -95,12 +74,6 @@
1080 }
1081
1082
1083-foreach (@test) {
1084-# print "$_\n";
1085-}
1086-
1087-
1088-
1089 }
1090
1091
1092Index: buck-security_0.6/conf/buck-security.conf
1093===================================================================
1094--- buck-security_0.6.orig/conf/buck-security.conf 2013-09-17 21:16:30.170513001 -0400
1095+++ buck-security_0.6/conf/buck-security.conf 2013-09-17 21:16:30.266513001 -0400
1096@@ -18,18 +18,19 @@
1097 # ACTIVATED CHECKS
1098 ###
1099 @checks = qw(
1100-worldwriteablefiles
1101-worldwriteabledirs
1102+checksum
1103+emptypasswd
1104+firewall
1105+packages_problematic
1106+services
1107+sgids
1108+sshd
1109 stickytmp
1110 suids
1111-sgids
1112-usermask
1113 superusers
1114-services
1115-firewall
1116-sshd
1117-packages_problematic
1118-checksum
1119+usermask
1120+worldwriteablefiles
1121+worldwriteabledirs
1122 );
1123
1124
1125@@ -45,7 +46,12 @@
1126 # create checksums for the following directories (if checksum check is
1127 # enabled)
1128
1129-$checksum_dir = "/sbin/* /bin/* /usr/sbin/* /usr/bin/*";
1130+@checksum_dir = qw(
1131+/sbin
1132+/bin
1133+/usr/sbin
1134+/usr/bin
1135+);
1136
1137
1138 $checksum_file = "checksums.gpg";
1139@@ -74,3 +80,11 @@
1140 python-scapy
1141 tshark
1142 );
1143+
1144+$logdir = "logs";
1145+
1146+$sysdir = '/';
1147+
1148+$output = 2;
1149+
1150+$ssh_config = "etc/ssh/sshd_config";
1151Index: buck-security_0.6/checks/sshd.pm
1152===================================================================
1153--- buck-security_0.6.orig/checks/sshd.pm 2013-09-17 21:16:30.170513001 -0400
1154+++ buck-security_0.6/checks/sshd.pm 2013-09-17 21:16:30.266513001 -0400
1155@@ -9,7 +9,6 @@
1156 # title, filename of this file, exception file and error level
1157 sub check {
1158 use lib::check;
1159- my $opt_output = $_[1];
1160
1161 # the title of the check for the output
1162 my $title = "Check if sshd is secured";
1163@@ -17,14 +16,20 @@
1164 my $package_name = "sshd";
1165 # the exception file
1166 my $exception_file = "conf/whitelists/sshd-whitelist.conf";
1167+
1168+ my $outcome_type = "other";
1169+
1170 # help - information about the check
1171 my $help = <<HELP;
1172 The following sshd options aren't set to a secure value.
1173-Learn more at http://buck-security.org/doc.html#c_sshd
1174 HELP
1175
1176
1177- check::CheckPerl( $title, $package_name, $exception_file, $help, $opt_output );
1178+ check::CheckPerl( $title,
1179+ $package_name,
1180+ $outcome_type,
1181+ $exception_file,
1182+ $help );
1183 }
1184
1185
1186@@ -38,7 +43,11 @@
1187 use readconfig;
1188
1189
1190-my $config_file = '/etc/ssh/sshd_config';
1191+my $config_file = $Config::ssh_config;
1192+if ( ! -f $Config::ssh_config ) {
1193+ return ( 1, @ { [ "sshd configuration file $Config::ssh_config not found." ] } );
1194+}
1195+
1196 my %SSHConfig = readconfig::ReadConfig($config_file, ' '); # separator is whitespace
1197 my @outcomes;
1198
1199@@ -103,7 +112,7 @@
1200 #
1201 # CHECK END
1202 ######################################
1203-return @outcomes;
1204+return ( 0, @outcomes );
1205 }
1206
1207 1;
1208Index: buck-security_0.6/checks/CHECK-BASH_TEMPLATE.pm
1209===================================================================
1210--- buck-security_0.6.orig/checks/CHECK-BASH_TEMPLATE.pm 2013-09-17 21:16:30.170513001 -0400
1211+++ buck-security_0.6/checks/CHECK-BASH_TEMPLATE.pm 2013-09-17 21:16:30.266513001 -0400
1212@@ -10,6 +10,7 @@
1213 my $security_test = "TODO_COMMAND"; # the security test
1214 my $exception_file =
1215 "conf/whitelists/TOD_FILE-whitelist.conf"; # the file with exceptions
1216+my $outcome_type = "abspath or other"; # the type of the expected outcome
1217
1218 # help - information about the check
1219 my $help = <<HELP;
1220@@ -20,8 +21,11 @@
1221
1222 # just forwarding to the "real" check Sub with variables
1223 sub check {
1224- my $opt_output = $_[1];
1225- check::CheckBash( $title, $security_test, $exception_file, $help, $opt_output );
1226+ check::CheckBash( $title,
1227+ $security_test,
1228+ $outcome_type,
1229+ $exception_file,
1230+ $help );
1231 }
1232
1233 1;
1234Index: buck-security_0.6/checks/CHECK-PERL_TEMPLATE.pm
1235===================================================================
1236--- buck-security_0.6.orig/checks/CHECK-PERL_TEMPLATE.pm 2013-09-17 21:16:30.170513001 -0400
1237+++ buck-security_0.6/checks/CHECK-PERL_TEMPLATE.pm 2013-09-17 21:16:30.266513001 -0400
1238@@ -9,7 +9,6 @@
1239 # title, filename of this file, exception file and error level
1240 sub check {
1241 use lib::check;
1242- my $opt_output = $_[1];
1243
1244 # the title of the check for the output
1245 my $title = "TODO_TITLE";
1246@@ -17,12 +16,20 @@
1247 my $package_name = "TODO_PACKAGENAME";
1248 # the exception file
1249 my $exception_file = "conf/whitelists/TODO_FILE-whitelist.conf";
1250+
1251+ # the type of the expected outcome
1252+ my $outcome_type = "abspath or other";
1253+
1254 # help - information about the check
1255 my $help = <<HELP;
1256 TODO_INFORMATION
1257 HELP
1258
1259- check::CheckPerl( $title, $package_name, $exception_file, $help, $opt_output );
1260+ check::CheckPerl( $title,
1261+ $package_name,
1262+ $outcome_type,
1263+ $exception_file,
1264+ $help );
1265 }
1266
1267
1268@@ -39,7 +46,12 @@
1269 #
1270 # CHECK END
1271 ######################################
1272-return @outcomes;
1273+if ( $success ) {
1274+ return ( 0, @outcomes );
1275+}
1276+else {
1277+ return ( 1, @errors );
1278+}
1279 }
1280
1281 1;
1282Index: buck-security_0.6/checks/checksum.pm
1283===================================================================
1284--- buck-security_0.6.orig/checks/checksum.pm 2013-09-17 21:16:30.170513001 -0400
1285+++ buck-security_0.6/checks/checksum.pm 2013-09-17 21:16:30.266513001 -0400
1286@@ -9,7 +9,6 @@
1287 # title, filename of this file, exception file and error level
1288 sub check {
1289 use lib::check;
1290- my $opt_output = $_[1];
1291
1292 # the title of the check for the output
1293 my $title = "Checksums of system programs";
1294@@ -17,15 +16,21 @@
1295 my $package_name = "checksum";
1296 # the exception file
1297 my $exception_file = "conf/whitelists/checksum-whitelist.conf";
1298+
1299+ my $outcome_type = "other";
1300+
1301 # help - information about the check
1302 my $help = <<HELP;
1303-The checksums for the following files have changed,
1304-since you created them. This could indicate an attack.
1305-Learn more at http://buck-security.org/doc.html#c_checksums
1306+The checksums for the following files have changed
1307+since you created them.
1308 HELP
1309
1310
1311- check::CheckPerl( $title, $package_name, $exception_file, $help, $opt_output );
1312+ check::CheckPerl( $title,
1313+ $package_name,
1314+ $outcome_type,
1315+ $exception_file,
1316+ $help );
1317 }
1318
1319
1320@@ -38,19 +43,16 @@
1321 # returns results as list in @outcomes
1322 my $checksums_file = $Config::checksum_file;
1323 my $checksums_prog = $Config::checksum_program;
1324-my @outcomes;
1325 # only if checksum file exists
1326-if (-e $checksums_file) {
1327+if ( -f $checksums_file ) {
1328 print "\n------------------\nSTARTING CHECKSUM CHECK\nDecrypting checksum-file $checksums_file ...\n";
1329- @outcomes = `gpg -d $checksums_file 2> /dev/null | $checksums_prog -cw | grep -v ": OK";`;
1330+ my @outcomes = `gpg -d $checksums_file 2> /dev/null | $checksums_prog -cw | grep -v ": OK";`;
1331+ return ( 0, @outcomes );
1332 }
1333 else {
1334- push(@outcomes, "Couldn't read $checksums_file: $!\n");
1335+ return ( 1, @ { ["Couldn't read $checksums_file: $!\n"] } );
1336 }
1337-#
1338-# CHECK END
1339-######################################
1340-return @outcomes;
1341+
1342 }
1343
1344 1;
1345Index: buck-security_0.6/checks/emptypasswd.pm
1346===================================================================
1347--- buck-security_0.6.orig/checks/emptypasswd.pm 2013-09-17 21:16:30.170513001 -0400
1348+++ buck-security_0.6/checks/emptypasswd.pm 2013-09-17 21:16:30.270513001 -0400
1349@@ -9,7 +9,6 @@
1350 # title, filename of this file, exception file and error level
1351 sub check {
1352 use lib::check;
1353- my $opt_output = $_[1];
1354
1355 # the title of the check for the output
1356 my $title = "Users with empty password";
1357@@ -17,13 +16,19 @@
1358 my $package_name = "emptypasswd";
1359 # the exception file
1360 my $exception_file = "conf/whitelists/emptypasswd-whitelist.conf";
1361+
1362+ my $outcome_type = "other";
1363+
1364 # help - information about the check
1365 my $help = <<HELP;
1366-Users which have an EMPTY password.
1367-TODO
1368+The following users have empty passwords.
1369 HELP
1370
1371- check::CheckPerl( $title, $package_name, $exception_file, $help, $opt_output );
1372+ check::CheckPerl( $title,
1373+ $package_name,
1374+ $outcome_type,
1375+ $exception_file,
1376+ $help );
1377 }
1378
1379
1380@@ -43,19 +48,42 @@
1381 # users which are shadowed (x in /etc/passwd)
1382 my @ShadowUsers;
1383
1384-# user and password items from /etc/passwd
1385-my %UsersPasswdNormal = users::PasswordsNormal();
1386+my $PasswdFile = users::GetPasswdFile('passwd');
1387+
1388+if (! -f $PasswdFile ) {
1389+ return ( 1, @ { ["Password file $PasswdFile does not exist."] } );
1390+}
1391+
1392+if ( ! open (PASSWD, '<', $PasswdFile) ) {
1393+ return ( 1, @ { ["Password file $PasswdFile can not be opened."] } );
1394+}
1395+my @PasswdFile = <PASSWD>;
1396+
1397+my %UsersPasswdNormal = users::PasswordsNormal(@PasswdFile);
1398+
1399+$PasswdFile = users::GetPasswdFile('shadow');
1400+
1401+if (! -f $PasswdFile ) {
1402+ return ( 1, @ { ["Shadow password file $PasswdFile does not exist."] } );
1403+}
1404+
1405+if ( ! open (PASSWD, '<', $PasswdFile) ) {
1406+ return ( 1, @ { ["Shadow password file $PasswdFile can not be opened."] } );
1407+}
1408+
1409+@PasswdFile = <PASSWD>;
1410
1411 # user and password items from /etc/shadow
1412-my %UsersPasswdShadow = users::PasswordsShadow();
1413+my %UsersPasswdShadow = users::PasswordsShadow(@PasswdFile);
1414
1415 # check /etc/passwd first
1416
1417 while ( my ($k,$v) = each %UsersPasswdNormal ) {
1418- if ($v eq '') {
1419+ my $password = $v->{'password'};
1420+ if ($password eq '') {
1421 push(@UsersEmptyPasswd, $k);
1422 }
1423- elsif ($v eq 'x') {
1424+ elsif ($password eq 'x') {
1425 push (@ShadowUsers, $k);
1426 }
1427 }
1428@@ -67,16 +95,15 @@
1429
1430 # only check users that were shadowed in /etc/passwd
1431 if ($k eq $_) {
1432- push(@UsersEmptyPasswd, $k) if $v eq '';
1433+ push(@UsersEmptyPasswd, $k) if $v->{'password'} eq '';
1434 }
1435 }
1436 }
1437
1438-my @outcomes = @UsersEmptyPasswd;
1439 #
1440 # CHECK END
1441 ######################################
1442-return @outcomes;
1443+return ( 0, @UsersEmptyPasswd );
1444 }
1445
1446 1;
1447Index: buck-security_0.6/checks/firewall.pm
1448===================================================================
1449--- buck-security_0.6.orig/checks/firewall.pm 2013-09-17 21:16:30.170513001 -0400
1450+++ buck-security_0.6/checks/firewall.pm 2013-09-17 21:16:30.270513001 -0400
1451@@ -9,7 +9,6 @@
1452 # title, filename of this file, exception file and error level
1453 sub check {
1454 use lib::check;
1455- my $opt_output = $_[1];
1456
1457 # the title of the check for the output
1458 my $title = "Check firewall policies";
1459@@ -17,13 +16,18 @@
1460 my $package_name = "firewall";
1461 # the exception file
1462 my $exception_file = "conf/whitelists/firewall-whitelist.conf";
1463+
1464+ my $outcome_type = "other";
1465+
1466 # help - information about the check
1467 my $help = <<HELP;
1468-The following iptables policies are set to ACCEPT
1469-which might be a security problem.
1470-Learn more at http://buck-security/doc.html#c_firewall
1471+The following iptables policies are set to ACCEPT.
1472 HELP
1473- check::CheckPerl( $title, $package_name, $exception_file, $help, $opt_output );
1474+ check::CheckPerl( $title,
1475+ $package_name,
1476+ $outcome_type,
1477+ $exception_file,
1478+ $help );
1479 }
1480
1481
1482@@ -34,6 +38,10 @@
1483 # CHECK START
1484 # HERE IS THE PERL CODE FOR THE CHECK
1485 # returns results as list in @outcomes
1486+my @errors = `iptables -nL 3>&1 1>/dev/null 2>&3`;
1487+if ( @errors ) {
1488+ return ( 1, @errors );
1489+}
1490
1491 my @policies = `iptables -nL | grep policy`;
1492 my @outcomes;
1493@@ -49,7 +57,7 @@
1494 #
1495 # CHECK END
1496 ######################################
1497-return @outcomes;
1498+return ( 0, @outcomes );
1499 }
1500
1501 1;
1502Index: buck-security_0.6/checks/nopasswd.pm
1503===================================================================
1504--- buck-security_0.6.orig/checks/nopasswd.pm 2013-09-17 21:16:30.170513001 -0400
1505+++ /dev/null 1970-01-01 00:00:00.000000000 +0000
1506@@ -1,80 +0,0 @@
1507-#!/usr/bin/perl
1508-
1509-use strict;
1510-use warnings;
1511-
1512-package emptypasswd;
1513-
1514-# just forwarding to the "real" CheckPerl Sub with variables
1515-# title, filename of this file, exception file and error level
1516-sub check {
1517- use lib::check;
1518- my $opt_output = $_[1];
1519-
1520- # the title of the check for the output
1521- my $title = "Users with empty password";
1522- # the filename of this file
1523- my $package_name = "emptypasswd";
1524- # the exception file
1525- my $exception_file = "conf/whitelists/emptypasswd-whitelist.conf";
1526- # help - information about the check
1527- my $help = <<HELP;
1528-Users which have an EMPTY password.
1529-TODO
1530-HELP
1531-
1532- check::CheckPerl( $title, $package_name, $exception_file, $help, $opt_output );
1533-}
1534-
1535-
1536-
1537-sub perl {
1538-
1539-######################################
1540-# CHECK START
1541-# HERE IS THE PERL CODE FOR THE CHECK
1542-# returns results as list in @outcomes
1543-
1544-# that will be th list of the users with empty pw
1545-my @UsersWithEmptyPasswd;
1546-
1547-# users which are shadowed (x in /etc/passwd)
1548-my @ShadowUsers;
1549-
1550-# user and password items from /etc/passwd
1551-my %UsersPasswdNormal = PasswordsNormal();
1552-
1553-# user and password items from /etc/shadow
1554-my %UsersPasswdShadow = PasswordsShadow();
1555-
1556-# check /etc/passwd first
1557-
1558-while ( my ($k,$v) = each %UsersPasswdNormal ) {
1559- if ($v eq '') {
1560- push(@UsersEmptyPasswd, $k);
1561- }
1562- elsif ($v eq 'x') {
1563- push (@ShadowUsers, $k);
1564- }
1565-}
1566-
1567-# now check shadowed users and their pw item in /etc/shadow
1568-
1569-foreach @ShadowUsers {
1570- while ( my $k, $v = each %UsersPasswdShadow) {
1571-
1572- # only check users that were shadowed in /etc/passwd
1573- if ($k eq $_) {
1574- push(@UsersEmptyPasswd, $k) if $v eq '';
1575- }
1576- @outcomes = @UsersWithEmptyPasswd;
1577-
1578-}
1579-
1580-#
1581-# CHECK END
1582-######################################
1583-return @outcomes;
1584-}
1585-
1586-1;
1587Index: buck-security_0.6/checks/packages_problematic.pm
1588===================================================================
1589--- buck-security_0.6.orig/checks/packages_problematic.pm 2013-09-17 21:16:30.170513001 -0400
1590+++ buck-security_0.6/checks/packages_problematic.pm 2013-09-17 21:16:30.270513001 -0400
1591@@ -9,7 +9,6 @@
1592 # title, filename of this file, exception file and error level
1593 sub check {
1594 use lib::check;
1595- my $opt_output = $_[1];
1596
1597 # the title of the check for the output
1598 my $title = "Search problematic packages";
1599@@ -17,14 +16,19 @@
1600 my $package_name = "packages_problematic";
1601 # the exception file
1602 my $exception_file = "conf/whitelists/packages_problematic-whitelist.conf";
1603+
1604+ my $outcome_type = "other";
1605+
1606 # help - information about the check
1607 my $help = <<HELP;
1608-The following packages are installed and may be a
1609-security risk.
1610-Learn more at http://buck-security.org/doc.html#c_pkg
1611+The following packages are installed.
1612 HELP
1613
1614- check::CheckPerl( $title, $package_name, $exception_file, $help, $opt_output );
1615+ check::CheckPerl( $title,
1616+ $package_name,
1617+ $outcome_type,
1618+ $exception_file,
1619+ $help );
1620 }
1621
1622
1623@@ -48,7 +52,7 @@
1624 #
1625 # CHECK END
1626 ######################################
1627-return @outcomes;
1628+return ( 0, @outcomes );
1629 }
1630
1631 1;
1632Index: buck-security_0.6/checks/services.pm
1633===================================================================
1634--- buck-security_0.6.orig/checks/services.pm 2013-09-17 21:16:30.170513001 -0400
1635+++ buck-security_0.6/checks/services.pm 2013-09-17 21:16:30.270513001 -0400
1636@@ -9,7 +9,6 @@
1637 # title, filename of this file, exception file and error level
1638 sub check {
1639 use lib::check;
1640- my $opt_output = $_[1];
1641
1642 # the title of the check for the output
1643 my $title = "Listening Services";
1644@@ -17,14 +16,20 @@
1645 my $package_name = "services";
1646 # the exception file
1647 my $exception_file = "conf/whitelists/services-whitelist.conf";
1648+
1649+ my $outcome_type = "other";
1650+
1651 # help - information about the check
1652 my $help = <<HELP;
1653 The following programs are listening for incoming
1654 connections. Output format is port:program:listen_mode
1655-Learn more at http://buck-security/doc.html#c_services
1656 HELP
1657
1658- check::CheckPerl( $title, $package_name, $exception_file, $help, $opt_output );
1659+ check::CheckPerl( $title,
1660+ $package_name,
1661+ $outcome_type,
1662+ $exception_file,
1663+ $help );
1664
1665 }
1666
1667@@ -36,6 +41,10 @@
1668 # CHECK START
1669 # HERE IS THE PERL CODE FOR THE CHECK
1670 # returns results as list in @outcomes
1671+my @errors = `netstat -luntp 3>&1 1>/dev/null 2>&3`;
1672+if ( @errors ) {
1673+ return ( 1, @errors );
1674+}
1675
1676 my @netstat = `netstat -luntp`;
1677 #my @netstat = `netstat -luntp | awk '{print \$4, \$7}'`;
1678@@ -74,7 +83,7 @@
1679 #
1680 # CHECK END
1681 ######################################
1682-return @outcomes;
1683+return ( 0, @outcomes );
1684 }
1685
1686 1;