????
| Current Path : /usr/lib/sonarpush/SonarPush/Providers/ |
| Current File : //usr/lib/sonarpush/SonarPush/Providers/Software.pm |
package SonarPush::Providers::Software;
use base qw(SonarPush::Providers);
use strict;
use SonarPush::Util;
=head1 NAME
SonarPush::Providers::Software - collects software information
=head1 DESCRIPTION
class of tasks for collecing various information about software that
is installed on a machine
=cut
sub apache {
my $self = shift;
my $provider = 'apache';
my $apache = {
name => 'apache',
attributes => {
providedby => $provider,
datatype => 'Text'
},
};
my $apacheMods = {
name => 'apachemodules',
attributes => {
providedby => $provider,
datatype => 'None'
},
value => [],
};
my @apachelocations = ("/usr/local/apache/bin/httpd", "/usr/sbin/httpd", "/usr/sbin/apache2", "/usr/sbin/apache");
foreach my $location (@apachelocations) {
if (-x $location) {
my $version = `$location -v | head -n 1| awk '{print \$3}' | cut -d / -f 2`;
$version =~ s/^\s+|\s+$//g;
$apache->{value} = $version;
last;
}
}
if ((-e "/usr/local/cpanel/modules-install/modsecurity-Linux-i686/progversion")
or (-e "/usr/local/cpanel/modules-install/modsecurity-Linux-x86_64/progversion")) {
my $modSec = {
name => 'mod_security',
attributes => {
providedby => $provider,
datatype => 'Text'
},
};
push(@{ $apacheMods->{value} }, $modSec);
my $flag = 1;
{
local $/;
open(INPUT, "< /usr/local/cpanel/modules-install/modsecurity-Linux-i686/progversion") or $flag = 0;
if (!$flag) {
open(INPUT, "< /usr/local/cpanel/modules-install/modsecurity-Linux-x86_64/progversion") or $flag = 0;
}
if ($flag) {
my $input = <INPUT>;
if ($input =~ /\s*(\S+)\s*/) {
$modSec->{value} = $1;
}
}
}
}
return ($apache, $apacheMods);
}
sub clamav {
my $self = shift;
my $provider = 'clamav';
my $attrs = {
providedby => $provider,
datatype => 'Text'
};
my $xml = {
name => $provider,
attributes => $attrs,
value => [],
};
if (-x "/usr/sbin/clamd") {
my $input = `/usr/sbin/clamd --version`;
$input =~ s/^\s+|\s+$//g;
if (my ($version, $db, $timestamp) = $input =~ /^ClamAV (\S+)\/(\S+)\/(.+)$/) {
push(@{ $xml->{value} }, { name => 'clamversion', value => $version });
push(@{ $xml->{value} }, { name => 'dbversion', value => $db });
push(@{ $xml->{value} }, { name => 'dbtimestamp', value => $timestamp });
map { $_->{attributes} = $attrs } @{ $xml->{value} };
}
}
return $xml;
}
sub cpanel {
my $self = shift;
my $provider = 'cpanel';
my $attrs = {
providedby => $provider,
datatype => 'Text'
};
my $xml = {
name => $provider,
attributes => $attrs,
};
{
local $/;
open(my $file, "< /usr/local/cpanel/version");
if ($file) {
my $version = <$file>;
$version =~ s/^\s+|\s+$//g;
$xml->{value} = $version;
}
}
return $xml;
}
sub dpkglist {
my $self = shift;
my $provider = 'dpkglist';
my %attrs = (
config => {
providedby => $provider,
datatype => 'Text'
},
noConfig => {
providedby => $provider,
datatype => 'None'
},
);
my $xml = {
name => $provider,
attributes => $attrs{noConfig},
value => [],
};
my $file = "/usr/local/lp/var/sonarpush/dpkgexport";
if (-r $file) {
my $flag = 1;
my $input;
{
local $/;
open(INPUT, "< $file") or $flag = 0;
if ($flag) {
$input = <INPUT>;
}
}
if ($flag) {
if ($input =~ /^([0-9]{10})\n(.*)/s) {
my $list = SonarPush::Util::encode_entities($2);
push(@{ $xml->{value} }, { name => 'timestamp', value => $1 });
push(@{ $xml->{value} }, { name => 'list', value => $list });
map { $_->{attributes} = $attrs{config} } @{ $xml->{value} };
}
}
}
return $xml;
}
sub exim {
my $self = shift;
my $provider = 'exim';
my %attrs = (
config => {
providedby => $provider,
datatype => 'Text'
},
);
my $xml = {
name => $provider,
attributes => $attrs{config},
};
if (-x "/usr/sbin/exim") {
my $input = `/usr/sbin/exim -bV`;
if ($input =~ /Exim version (\S+) #(\d+) built (.+)$/m) {
## Can improve a bit here on what is returned
$xml->{value} = $1;
}
}
return $xml;
}
sub lpsoftware {
my $self = shift;
my $provider = 'lp-software';
my %attrs = (
config => {
providedby => $provider,
datatype => 'Text'
},
noConfig => {
providedby => $provider,
datatype => 'None'
},
);
my $xml = {
name => $provider,
attributes => $attrs{noConfig},
value => [],
};
my $sonarVersion = $self->sonar->version;
if (defined($sonarVersion)) {
push(@{ $xml->{value} }, { name => 'SonarPush', value => "Linux-$sonarVersion" });
}
my $input;
my $flag;
my $file = '/usr/local/lp/apps/security/infected.pl';
my $version = 'Unable to determine version.';
if (-e $file) {
my $contents = do {
local $/;
open(my $INPUT, '<', $file);
<$INPUT>;
};
if ($contents =~ /\$version\s*?=\s*?"(.*?)"\s*?;/) {
$version = $1;
}
}
push(@{ $xml->{value} }, { name => 'infected.pl', value => $version });
$file = '/usr/local/apache/conf/modsec.user.conf';
$version = 'Not Present';
if (-e $file) {
my $contents = do {
local $/;
open(my $INPUT, '<', $file);
<$INPUT>;
};
if ($contents) {
if ($contents =~ /### Modsec rules v(\S+) ###/) {
$version = $1;
}
else {
$version = "Custom";
}
}
}
push(@{ $xml->{value} }, { name => 'lp-modsecrules', value => $version });
if (-e "/usr/local/lp/apps/autoupdate/lp-autoupdate.pl") {
my $autoUpdate = { name => 'lp-autoupdate', attributes => $attrs{noConfig}, value => [] };
$flag = 1;
{
local $/;
open(INPUT, "< /usr/local/lp/apps/autoupdate/lp-autoupdate.pl") or $flag = 0;
if ($flag) {
$input = <INPUT>;
}
}
if ($flag) {
if ($input =~ /### lp-autoupdate v(\S+) ###/) {
push(@{ $autoUpdate->{value} }, { name => 'lp-autoupdate.pl', value => $1, attributes => $attrs{config} });
}
}
$flag = 1;
{
local $/;
open(INPUT, "< /usr/local/lp/var/autoupdate/serial") or $flag = 0;
if ($flag) {
$input = <INPUT>;
}
}
if ($flag) {
if ($input =~ /LastUpdate: (\d+)/) {
push(@{ $autoUpdate->{value} }, { name => 'serial', value => $1, attributes => $attrs{config} });
}
}
push(@{ $xml->{value} }, $autoUpdate);
}
if (-e "/usr/local/lp/etc/skel-version") {
$flag = 1;
{
local $/;
open(INPUT, "< $file") or $flag = 0;
if ($flag) {
$input = <INPUT>;
}
}
if ($flag) {
if ($input =~ /\s*(\S+)\s*/) {
push(@{ $xml->{value} }, { name => 'lp-skel', value => $1 });
}
}
}
#lp rpms
my @rpmlist = ("lp-apf", "lp-bfd", "lp-modevasive", "lp-chkrootkit", "lp-rkhunter");
my $rpmverpath = "/usr/local/lp/rpmver/";
foreach my $file (@rpmlist) {
if (-e $rpmverpath . $file) {
$flag = 1;
{
local $/;
open(INPUT, "< " . $rpmverpath . $file) or $flag = 0;
if ($flag) {
$input = <INPUT>;
}
}
if ($flag) {
if ($input =~ /\s*(\S+)\s*/) {
push(@{ $xml->{value} }, { name => $file, value => $1 });
}
}
}
}
$file = "/etc/lwversion";
if (-e $file) {
$flag = 1;
{
local $/;
open(INPUT, "< $file") or $flag = 0;
if ($flag) {
$input = <INPUT>;
}
}
if ($flag) {
if ($input =~ /\s*(\S+)\s*/) {
push(@{ $xml->{value} }, { name => 'initadmin', value => $1 });
}
}
}
# status on patches
my $lpPatches = { name => 'lp-patches', attributes => $attrs{noConfig}, value => [] };
$file = "/usr/local/lp/var/fstabpatchstatus";
if (-e $file) {
$flag = 1;
{
local $/;
open(INPUT, "< $file") or $flag = 0;
if ($flag) {
$input = <INPUT>;
}
}
if ($flag) {
if ($input =~ /\s*([a-zA-Z0-9 ]+)\s*/) {
push(@{ $lpPatches->{value} }, { name => 'CVE-2006-3626', value => $1, attributes => $attrs{config} });
}
}
}
$file = "/usr/local/lp/var/coredumppatchstatus";
if (-e $file) {
$flag = 1;
{
local $/;
open(INPUT, "< $file") or $flag = 0;
if ($flag) {
$input = <INPUT>;
}
}
if ($flag) {
if ($input =~ /\s*([a-zA-Z0-9 ]+)\s*/) {
push(@{ $lpPatches->{value} }, { name => 'CVE-2006-2451', value => $1, attributes => $attrs{config} });
}
}
}
$file = "/proc/driver/snd-page-alloc";
if (-r $file) {
push(@{ $lpPatches->{value} }, { name => 'CVE-2007-4571', value => 'snd-page-alloc present', attributes => $attrs{config} });
}
else {
push(@{ $lpPatches->{value} }, { name => 'CVE-2007-4571', value => 'snd-page-alloc not present', attributes => $attrs{config} });
}
$file = "/usr/local/lp/var/yumvskern.run";
if (-e $file) {
my $node = { name => 'yumvskern', attributes => $attrs{config} };
$file = "/usr/local/lp/var/yumvskern";
if (-e $file) {
$flag = 1;
{
local $/;
open(INPUT, "< $file") or $flag = 0;
if ($flag) {
$input = <INPUT>;
}
}
if ($flag) {
if ($input =~ /\s*([a-zA-Z0-9 ]+)\s*/) {
$node->{value} = $1;
}
}
}
else {
$node->{value} = "noactiontaken";
}
push(@{ $lpPatches->{value} }, $node);
}
push(@{ $xml->{value} }, $lpPatches);
map { $_->{attributes} = $attrs{config} } grep { !exists $_->{attributes} } @{ $xml->{value} };
return $xml;
}
sub mailman {
my $self = shift;
my $provider = 'mailman';
my $attrs = {
providedby => $provider,
datatype => 'Text'
};
my $xml = {
name => $provider,
attributes => $attrs,
};
if (-e "/usr/local/cpanel/3rdparty/mailman/Mailman/Version.py") {
my $flag = 1;
my $input;
{
local $/;
open(INPUT, "< /usr/local/cpanel/3rdparty/mailman/Mailman/Version.py") or $flag = 0;
if ($flag) {
$input = <INPUT>;
}
}
if ($flag) {
if ($input =~ /^VERSION\s=\s\'(\S+)\'$/m) {
$xml->{value} = $1;
}
}
}
return $xml;
}
sub mysql {
my $self = shift;
my $provider = 'mysql';
my $attrs = {
providedby => $provider,
datatype => 'Text'
};
my $xml = {
name => $provider,
attributes => $attrs,
};
my @mysqldlist = ("/usr/libexec/mysqld", "/usr/sbin/mysqld");
my $mysqld;
my $input;
my $found = 0;
foreach $mysqld (@mysqldlist) {
if (-x $mysqld) {
$input = `$mysqld --version`;
## /usr/libexec/mysqld Ver 5.0.45-log for redhat-linux-gnu on x86_64 (Source distribution)
if ($input =~ /^\S+\s+Ver\s+(\S+)\s+for\s+\S+/) {
$xml->{value} = $1;
$found = $mysqld;
last;
}
}
}
return $xml;
}
sub named {
my $self = shift;
my $provider = 'named';
my $attrs = {
providedby => $provider,
datatype => 'Text'
};
my $xml = {
name => $provider,
attributes => {
providedby => $provider,
datatype => 'None'
},
value => [],
};
#look for caching nameserver
my $sourcedir = "/usr/share/doc";
my $matchcount = 0;
if (-d "$sourcedir") {
if (opendir my $dh, "$sourcedir") {
my $file;
while ($file = readdir($dh)) {
if (-d "$sourcedir/$file") {
if ($file =~ /caching-nameserver/) {
$matchcount++;
}
}
}
}
}
if ($matchcount > 0) {
push(@{ $xml->{value} }, { name => 'caching-nameserver', attributes => $attrs, value => "installed" });
}
else {
push(@{ $xml->{value} }, { name => 'caching-nameserver', attributes => $attrs, value => "not installed" });
}
# check for chroot in /etc/sysconfig/named
if (-r "/etc/sysconfig/named") {
my $input;
my $flag = 1;
{
local $/;
open(INPUT, "< /etc/sysconfig/named") or $flag = 0;
if ($flag) {
$input = <INPUT>;
}
}
if ($flag) {
if ($input =~ /^\s*ROOTDIR=/m) {
push(@{ $xml->{value} }, { name => 'chroot', attributes => $attrs, value => 'active' });
}
else {
push(@{ $xml->{value} }, { name => 'chroot', attributes => $attrs, value => 'not active' });
}
}
}
return $xml;
}
sub openssl {
my $self = shift;
my $provider = 'openssl';
my $xml = {
name => $provider,
attributes => {
providedby => $provider,
datatype => 'Text'
},
};
if (-x "/usr/bin/openssl") {
if (my $input = `/usr/bin/openssl version | /usr/bin/awk '{print \$2}'`) {
$input =~ s/\s+$//;
$input =~ s/^\s+//;
$xml->{value} = $input;
}
else {
$xml->{value} = "ERROR";
}
}
return $xml;
}
sub os {
my $self = shift;
my $provider = 'os';
my $xml = {
name => $provider,
attributes => {
providedby => $provider,
datatype => 'Text'
},
};
my $counter = 0;
my $gentoo = 0;
my $redhat = 0;
my $debian = 0;
my $openbsd = 0;
my $freebsd = 0;
my $input = 0;
my $flag = 1;
#take the easy (and accurate) way out, if it exists
if (-x "/usr/bin/lsb_release") {
$input = `/usr/bin/lsb_release -d`;
if ($input =~ /^Description:\t(.+)$/m) {
$xml->{value} = $1;
return $xml;
}
}
if (-e "/etc/redhat-release") {
$counter++;
$redhat = 1;
}
if (-e "/etc/gentoo-release") {
$counter++;
$gentoo = 1;
}
if (-e "/etc/debian_version") {
$counter++;
$debian = 1;
}
if ($counter == 0) {
$xml->{value} = "Unknown";
}
elsif ($counter == 1) {
if ($redhat) {
{
local $/;
open(INPUT, "< /etc/redhat-release") or $flag = 0;
if ($flag) {
$input = <INPUT>;
}
}
if ($flag) {
$input =~ s/\s+$//;
$input =~ s/^\s+//;
$xml->{value} = $input;
}
else {
$xml->{value} = "RedHat/Fedora: could not determine version";
}
}
if ($gentoo) {
{
local $/;
open(INPUT, "< /etc/gentoo-release") or $flag = 0;
if ($flag) {
$input = <INPUT>;
}
}
if ($flag) {
$input =~ s/\s+$//;
$input =~ s/^\s+//;
$xml->{value} = $input;
}
else {
$xml->{value} = "Gentoo: could not determine version";
}
}
if ($debian) {
{
local $/;
open(INPUT, "< /etc/debian_version") or $flag = 0;
if ($flag)
{
$input = <INPUT>;
}
}
if ($flag) {
$input =~ s/\s+$//;
$input =~ s/^\s+//;
$xml->{value} = "Debian: $input";
}
else {
$xml->{value} = "Debian: could not determine version";
}
}
}
else {
$xml->{value} = "ERROR - multiple OS signatures detected";
}
return $xml;
}
sub perl {
my $self = shift;
my $provider = 'perl';
my $xml = {
name => $provider,
attributes => {
providedby => $provider,
datatype => 'Text'
},
};
my ($perl) = `/usr/bin/perl -V`;
$perl =~ m/\(revision (\d+?) version (\d+?) subversion (\d+?)\)/;
$xml->{value} = join('.', $1, $2, $3);
return $xml;
}
sub php {
my $self = shift;
my $provider = 'php';
my $xml = {
name => $provider,
attributes => {
providedby => $provider,
datatype => 'Text'
},
};
my $input = `php -v | grep PHP`;
if ($input =~ /^PHP (\d+\.\d+\.\d+)\s+/m) {
$xml->{value} = $1;
}
return $xml;
}
sub platform {
my $self = shift;
my $provider = 'platform';
my %attrs = (
config => {
providedby => $provider,
datatype => 'Text'
},
noConfig => {
providedby => $provider,
datatype => 'None'
},
);
my $xml = {
name => $provider,
attributes => $attrs{noConfig},
value => [],
};
my %nameFlagMap = (
kernelname => '-s',
kernelrelease => '-r',
kernelversion => '-v',
hardwarename => '-m',
hardwareplatform => '-i',
operatingsystem => '-o',
nodename => '-n',
);
for my $property (sort keys %nameFlagMap) {
my $value = `uname $nameFlagMap{$property}`;
$value =~ s/^\s+|\s+$//g;
push(@{ $xml->{value} }, { name => $property, value => $value, attributes => $attrs{config} });
}
my $kmods = {
name => 'kmodlist',
attributes => $attrs{config},
};
my $modList = `/sbin/lsmod`;
$modList =~ s/^\s+|\s+$//g;
$kmods->{value} = $modList;
return ($xml, $kmods);
}
sub rpmlist {
my $self = shift;
my $provider = 'rpmlist';
my %attrs = (
config => {
providedby => $provider,
datatype => "Text",
},
noConfig => {
providedby => $provider,
datatype => "None",
},
);
my $xml = {
name => $provider,
attributes => $attrs{noConfig},
value => [],
};
my $file = "/usr/local/lp/var/sonarpush/rpmexport";
if (-r $file) {
my $flag = 1;
my $input;
{
local $/;
open(INPUT, "< $file") or $flag = 0;
if ($flag) {
$input = <INPUT>;
}
}
if ($flag) {
if ($input =~ /^([0-9]{10})\n(.*)/s) {
#$trans = array("\n" => "[[cr]]");
#$list = strtr(trim($match[2]), $trans);
my $list = SonarPush::Util::encode_entities($2);
push(@{ $xml->{value} }, { name => 'timestamp', value => $1, attributes => $attrs{config} });
push(@{ $xml->{value} }, { name => 'list', value => $list, attributes => $attrs{config} });
}
}
}
return $xml;
}
sub sshd {
my $self = shift;
my $provider = 'sshd';
my $xml = {
name => $provider,
attributes => {
providedby => $provider,
datatype => 'Text'
},
};
my $SSH_BINARY = '/usr/sbin/sshd';
# Need to take advantage of a hack to get the version
# # sshd -OMGHAX 2>&1
# returns
# OpenSSH_5.1p1, OpenSSL 0.9.8g 19 Oct 2007
# usage: sshd [-46DdeiqTt] [-b bits] [-C connection_spec] [-f config_file]
# [-g login_grace_time] [-h host_key_file] [-k key_gen_time]
# [-o option] [-p port] [-u len]
# Another Format:
# sshd -OMGHAX 2>&1
# sshd: illegal option -- O
# sshd version OpenSSH_3.6.1p2
# Usage: sshd [options]
# Options:
# -f file Configuration file (default /etc/ssh/sshd_config)
# -d Debugging mode (multiple -d means more debugging)
# -i Started from inetd
# -D Do not fork into daemon mode
# -t Only test configuration file and keys
# -q Quiet (no logging)
# -p port Listen on the specified port (default: 22)
# -k seconds Regenerate server key every this many seconds (default: 3600)
# -g seconds Grace period for authentication (default: 600)
# -b bits Size of server RSA key (default: 768 bits)
# -h file File from which to read host key (default: /etc/ssh/ssh_host_key)
# -u len Maximum hostname length for utmp recording
# -4 Use IPv4 only
# -6 Use IPv6 only
# -o option Process the option as if it was read from a configuration file.
my $input = `$SSH_BINARY -OMGBADOPTION 2>&1`;
if ($input =~ /^(.*?), (.*?) (\d){2} (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{4})$/m) {
#if ($input =~ /^(.*?), (.*?) (\d){2} ([A-Za-z]{3}) (\d{4})$/)
$xml->{value} = $1;
}
elsif ($input =~ /^(.*?), (.*?) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d){2} (\d{4})$/m) {
$xml->{value} = $1;
}
elsif ($input =~ /^sshd version (.*?)$/m) {
$xml->{value} = $1;
}
return $xml;
}
sub suexec {
my $self = shift;
my $provider = 'suexec';
my %attrs = (
config => {
providedby => $provider,
datatype => 'Text'
},
);
my $xml = {
name => $provider,
attributes => $attrs{config},
};
if (-x "/usr/local/apache/bin/httpd") {
if (my $input = `/usr/local/apache/bin/httpd -l | grep suexec | awk '{print \$2}'`) {
if ($input ne "") {
$input =~ s/^\s+|\s+$|;//g;
}
else {
$input .= "not found";
}
$xml->{value} = $input;
}
}
return $xml;
}
sub lwVMTemplateRevision {
my ($self) = @_;
my $provider = 'lwVMTemplateRevision';
my $config = {
providedby => $provider,
datatype => 'Text',
};
if (-e '/etc/lw-build') {
my $file = do {
local $/;
open(my $fh, '<', '/etc/lw-build');
<$fh>;
};
my ($build, $revision) = $file =~ /(?:(?:LW BUILD:|revision))\s+(\S+)/g;
$build ||= 'Unkown';
$revision ||= 'Unkown';
return {
name => $provider,
attributes => {
providedby => $provider,
datatype => 'None',
},
value => [
{
name => 'build',
attributes => $config,
value => $build,
},
{
name => 'revision',
attributes => $config,
value => $revision,
}
]
};
}
return;
}
1;