diff options
Diffstat (limited to 'recipes-security/bastille/files')
22 files changed, 0 insertions, 8896 deletions
diff --git a/recipes-security/bastille/files/API.pm b/recipes-security/bastille/files/API.pm deleted file mode 100644 index 5060f52..0000000 --- a/recipes-security/bastille/files/API.pm +++ /dev/null @@ -1,2528 +0,0 @@ -# Copyright (C) 1999-2007 Jay Beale -# Copyright (C) 2001-2008 Hewlett-Packard Development Company, L.P. -# Licensed under the GNU General Public License, version 2 - -package Bastille::API; - -## TO DO: -# -# -# 1) Look for more places to insert error handling... -# -# 2) Document this module more -# -# - - -########################################################################## -# -# This module forms the basis for the v1.1 API. -# - ########################################################################## - -# -# This module forms the initial basis for the Bastille Engine, implemented -# presently via a Perl API for Perl modules. -# -# This is still under construction -- it is very usable, but not very well -# documented, yet. -# - -########################################################################## -# -# API Function Listing -# -########################################################################## -# The routines which should be called by Bastille modules are listed here, -# though they are better documented throughout this file. -# -# Distro Specific Stuff: -# -# &GetDistro - figures out what distro we're running, if it knows it... -# &ConfigureForDistro - sets global variables based on the distro -# &GetGlobal - returns hash values defined in ConfigureForDistro -# -# &getGlobalConfig - returns value of hash set up by ReadConfig -# -# Logging Specific Stuff has moved to LogAPI.pm: -# -# &B_log(type,msg) -- takes care of all logging -# -# -# Input functions for the old input method... -# -# File open/close/backup functions -# -# &B_open * -- opens a file handle and logs the action/error (OLD WAY!) -# &B_open_plus -- opens a pair of file handles for the old and new version -# of a file; respects logonly flag. (NEW WAY) -# &B_close * -- closes a file handle and logs the action/error (OLD WAY!) -# &B_close_plus -- closes a pair of file handles opened by B_open_plus, -# backing up one file and renaming the new file to the -# old one's name, logging actions/errors. Respects the -# logonly flag -- needs B_backup file. Finally, sets -# new file's mode,uid,gid to old file's... (NEW WAY) -# &B_backup_file - backs up a file that is being changed/deleted into the -# $GLOBAL_BDIR{"backup"} directory. -# -# Non-content file modification functions -# -# &B_delete_file - deletes the named file, backing up a copy -# &B_create_file - creates the named file, if it doesn't exist -# -# &B_symlink - create a symlink to a file, recording the revert rm -# -# More stuff -# -# &B_createdir - make a directory, if it doesn't exist, record revert rmdir -# &B_cp - copy a file, respecting LOGONLY and revert func. -# &B_mknod - wrap mknod with revert and logonly and prefix functionality -# -# &B_read_sums - reads sum.csv file and parses input into the GLOBAL_SUM hash -# &B_write_sums - writes sum.csv file from GLOBAL_SUM hash -# &B_check_sum($) - take a file name and compares the stored cksum with the current -# cksum of said file -# &B_set_sum($) - takes a file name and gets that files current cksum then sets -# that sum in the GLOBAL_SUM hash -# &B_revert_log - create entry in shell script, executed later by bastille -r -# &showDisclaimer - Print the disclaimer and wait for 5 minutes for acceptance -########################################################################### -# Note: GLOBAL_VERBOSE -# -# All logging functions now check GLOBAL_VERBOSE and, if set, will print -# all the information sent to log files to STDOUT/STDERR as well. -# - -# -# Note: GLOBAL_LOGONLY -# -# All Bastille API functions now check for the existence of a GLOBAL_LOGONLY -# variable. When said variable is set, no function actually modifies the -# system. -# -# Note: GLOBAL_DEBUG -# -# The B_log("DEBUG",...) function now checks GLOBAL_DEBUG and, if set, it will -# print all the information to a new debug-log file. If GLOBAL_VERBOSE is -# set it might log to STDOUT/STDERR as well (not yet implemented, pending -# discussion). Developers should populate appropriate places with &B_log(DEBUG) -# in order to be able to tell users to use this options and send the logs -# for inspection and debugging. -# -# - - -# Libraries for the Backup_file routine: Cwd and File::Path -use Cwd; -use Bastille::OSX_API; -use Bastille::LogAPI; -use File::Path; -use File::Basename; - -# Export the API functions listed below for use by the modules. - -use Exporter; -@ISA = qw ( Exporter ); -@EXPORT = qw( - setOptions GetDistro ConfigureForDistro B_log B_revert_log - SanitizeEnv - B_open B_close B_symlink StopLogging - B_open_plus B_close_plus - B_isFileinSumDB - B_create_file B_read_sums B_check_sum B_set_sum isSumDifferent listModifiedFiles - B_create_dir B_create_log_file - B_delete_file - B_cp B_place B_mknod - showDisclaimer - getSupportedOSHash - B_Backtick - B_System - isProcessRunning - checkProcsForService - - - $GLOBAL_OS $GLOBAL_ACTUAL_OS $CLI - $GLOBAL_LOGONLY $GLOBAL_VERBOSE $GLOBAL_DEBUG $GLOBAL_AUDITONLY $GLOBAL_AUDIT_NO_BROWSER $errorFlag - %GLOBAL_BIN %GLOBAL_DIR %GLOBAL_FILE - %GLOBAL_BDIR %GLOBAL_BFILE - %GLOBAL_CONFIG %GLOBAL_SUM - - %GLOBAL_SERVICE %GLOBAL_SERVTYPE %GLOBAL_PROCESS %GLOBAL_RC_CONFIG - %GLOBAL_TEST - - getGlobal setGlobal getGlobalConfig - - - B_parse_fstab - B_parse_mtab B_is_rpm_up_to_date - - NOTSECURE_CAN_CHANGE SECURE_CANT_CHANGE - NOT_INSTALLED INCONSISTENT MANUAL NOTEST SECURE_CAN_CHANGE - STRING_NOT_DEFINED NOT_INSTALLED_NOTSECURE DONT_KNOW - RELEVANT_HEADERQ NOTRELEVANT_HEADERQ -); - - - -###################################################### -###Testing Functions -################################################################## - -#Define "Constants" for test functions. Note these constants sometimes get -#interpreted as literal strings when used as hash references, so you may -# have to use CONSTANT() to disambiguate, like below. Sorry, it was either -# that or create even *more* global variables. -# See TestDriver.pm for definitions, and test design doc for full explaination -use constant { - NOTSECURE_CAN_CHANGE => 0, - SECURE_CANT_CHANGE => 1, - NOT_INSTALLED => 2, # (where the lack makes the system secure, eg telnet) - INCONSISTENT => 3, - MANUAL => 4, - NOTEST => 5, - SECURE_CAN_CHANGE => 6, - STRING_NOT_DEFINED => 7, - NOT_INSTALLED_NOTSECURE => 8, #(Where the missing s/w makes the system less secure eg IPFilter) - #Intentional duplicates follow - DONT_KNOW => 5, - RELEVANT_HEADERQ => 6, - NOTRELEVANT_HEADERQ => 0 -}; - -&SanitizeEnv; - -# Set up some common error messages. These are independent of -# operating system - -# These will allow us to line up the warnings and error messages -my $err ="ERROR: "; -my $spc =" "; -my $GLOBAL_OS="None"; -my $GLOBAL_ACTUAL_OS="None"; -my %GLOBAL_SUMS=(); -my $CLI=''; - -#OS independent Error Messages Follow, normally "bastille" script filters -#options before interactive or Bastille runs, so this check is often redundant -$GLOBAL_ERROR{"usage"}="\n". - "$spc Usage: bastille [ -b | -c | -x ] [ --os <version> ] [ -f <alternate config> ]\n". - "$spc bastille [ -r | --assess | --assessnobowser ]\n\n". - "$spc --assess : check status of system and report in browser\n". - "$spc --assessnobrowser : check status of system and list report locations\n". - "$spc -b : use a saved config file to apply changes\n". - "$spc directly to system\n". - "$spc -c : use the Curses (non-X11) TUI\n". - "$spc -f <alternate config>: populate answers with a different config file\n". - "$spc -r : revert all Bastille changes to-date\n". - "$spc -x : use the Perl/Tk (X11) GUI\n" . - "$spc --os <version> : ask all questions for the given operating system\n" . - "$spc version. e.g. --os RH6.0\n"; - -# These options don't work universally, so it's best not to -# document them here (yet). Hopefully, we'll get them -# straightened out soon. -#"$spc --log : log-only option\n". -#"$spc -v : verbose mode\n". -#"$spc --debug : debug mode\n"; - - -############################################################################## -# -# Directory structure for Bastille Linux v1.2 and up -# -############################################################################## -# -# /usr/sbin/ -- location of Bastille binaries -# /usr/lib/Bastille -- location of Bastille modules -# /usr/share/Bastille -- location of Bastille data files -# /etc/Bastille -- location of Bastille config files -# -# /var/log/Bastille -- location of Bastille log files -# /var/log/Bastille/revert -- directory holding all Bastille-created revert scripts -# /var/log/Bastille/revert/backup -- directory holding the original files that -# Bastille modifies, with permissions intact -# -############################################################################## - -############################################################################## -# -# Directory structure for HP-UX Bastille v2.0 and up -# -############################################################################## -# -# /opt/sec_mgmt/bastille/bin/ -- location of Bastille binaries -# /opt/sec_mgmt/bastille/lib/ -- location of Bastille modules -# /etc/opt/sec_mgmt/bastille/ -- location of Bastille data and config files -# -# /var/opt/sec_mgmt/bastille/log/ -- location of Bastille log files -# /var/opt/sec_mgmt/bastille/revert -- directory holding all Bastille-created -# revert scripts and save files -# -############################################################################## - - -############################################################################## -############################################################################## -################## Actual functions start here... ########################### -############################################################################## -############################################################################## - -########################################################################### -# setOptions takes six arguments, $GLOBAL_DEBUG, $GLOBAL_LOGONLY, -# $GLOBAL_VERBOSE, $GLOBAL_AUDITONLY, $GLOBAL_AUDIT_NO_BROWSER, and GLOBAL_OS; -########################################################################### -sub setOptions($$$$$$) { - ($GLOBAL_DEBUG,$GLOBAL_LOGONLY,$GLOBAL_VERBOSE,$GLOBAL_AUDITONLY, - $GLOBAL_AUDIT_NO_BROWSER,$GLOBAL_OS) = @_; - if ($GLOBAL_AUDIT_NO_BROWSER) { - $GLOBAL_AUDITONLY = 1; - } - if (not(defined($GLOBAL_OS))){ - $GLOBAL_OS="None"; - } -} -########################################################################### -# -# SanitizeEnv load a proper environment so Bastille cannot be tricked -# and Perl modules work correctly. -# -########################################################################### -sub SanitizeEnv { - delete @ENV{'IFS','CDPATH','ENV','BASH_ENV'}; - $ENV{CDPATH}="."; - $ENV{BASH_ENV}= ""; - # Bin is needed here or else /usr/lib/perl5/5.005/Cwd.pm - # will not find `pwd` - # Detected while testing with -w, jfs - $ENV{PATH} = "/bin:/usr/bin"; - # Giorgi, is /usr/local/bin needed? (jfs) -} - -########################################################################### -# -# GetDistro checks to see if the target is a known distribution and reports -# said distribution. -# -# This is used throughout the script, but also by ConfigureForDistro. -# -# -########################################################################### - -sub GetDistro() { - - my ($release,$distro); - - # Only read files for the distro once. - # if the --os option was used then - if ($GLOBAL_OS eq "None") { - if ( -e "/etc/mandrake-release" ) { - open(MANDRAKE_RELEASE,"/etc/mandrake-release"); - $release=<MANDRAKE_RELEASE>; - - if ( ($release =~ /^Mandrake Linux release (\d+\.\d+\w*)/) or ($release =~ /^Linux Mandrake release (\d+\.\d+\w*)/) ) { - $distro="MN$1"; - } - elsif ( $release =~ /^Mandrakelinux release (\d+\.\d+)\b/ ) { - $distro="MN$1"; - } - else { - print STDERR "$err Couldn't determine Mandrake/Mandriva version! Setting to 10.1!\n"; - $distro="MN10.1"; - } - - close(MANDRAKE_RELEASE); - } - elsif ( -e "/etc/immunix-release" ) { - open(IMMUNIX_RELEASE,"/etc/immunix-release"); - $release=<IMMUNIX_RELEASE>; - unless ($release =~ /^Immunix Linux release (\d+\.\d+\w*)/) { - print STDERR "$err Couldn't determine Immunix version! Setting to 6.2!\n"; - $distro="RH6.2"; - } - else { - $distro="RH$1"; - } - close(*IMMUNIX_RELEASE); - } - elsif ( -e '/etc/fedora-release' ) { - open(FEDORA_RELEASE,'/etc/fedora-release'); - $release=<FEDORA_RELEASE>; - close FEDORA_RELEASE; - if ($release =~ /^Fedora Core release (\d+\.?\d*)/) { - $distro = "RHFC$1"; - } - elsif ($release =~ /^Fedora release (\d+\.?\d*)/) { - $distro = "RHFC$1"; - } - else { - print STDERR "$err Could not determine Fedora version! Setting to Fedora Core 8\n"; - $distro='RHFC8'; - } - } - elsif ( -e "/etc/redhat-release" ) { - open(*REDHAT_RELEASE,"/etc/redhat-release"); - $release=<REDHAT_RELEASE>; - if ($release =~ /^Red Hat Linux release (\d+\.?\d*\w*)/) { - $distro="RH$1"; - } - elsif ($release =~ /^Red Hat Linux .+ release (\d+)\.?\d*([AEW]S)/) { - $distro="RHEL$1$2"; - } - elsif ($release =~ /^Red Hat Enterprise Linux ([AEW]S) release (\d+)/) { - $distro="RHEL$2$1"; - } - elsif ($release =~ /^CentOS release (\d+\.\d+)/) { - my $version = $1; - if ($version =~ /^4\./) { - $distro='RHEL4AS'; - } - elsif ($version =~ /^3\./) { - $distro='RHEL3AS'; - } - else { - print STDERR "$err Could not determine CentOS version! Setting to Red Hat Enterprise 4 AS.\n"; - $distro='RHEL4AS'; - } - } - else { - # JJB/HP - Should this be B_log? - print STDERR "$err Couldn't determine Red Hat version! Setting to 9!\n"; - $distro="RH9"; - } - close(REDHAT_RELEASE); - - } - elsif ( -e "/etc/debian_version" ) { - $stable="3.1"; #Change this when Debian stable changes - open(*DEBIAN_RELEASE,"/etc/debian_version"); - $release=<DEBIAN_RELEASE>; - unless ($release =~ /^(\d+\.\d+\w*)/) { - print STDERR "$err System is not running a stable Debian GNU/Linux version. Setting to $stable.\n"; - $distro="DB$stable"; - } - else { - $distro="DB$1"; - } - close(DEBIAN_RELEASE); - } - elsif ( -e "/etc/SuSE-release" ) { - open(*SUSE_RELEASE,"/etc/SuSE-release"); - $release=<SUSE_RELEASE>; - if ($release =~ /^SuSE Linux (\d+\.\d+\w*)/i) { - $distro="SE$1"; - } - elsif ($release =~ /^SUSE LINUX Enterprise Server (\d+\.?\d?\w*)/i) { - $distro="SESLES$1"; - } - elsif ($release =~ /^SUSE Linux Enterprise Server (\d+\.?\d?\w*)/i) { - $distro="SESLES$1"; - } - elsif ($release =~ /^openSuSE (\d+\.\d+\w*)/i) { - $distro="SE$1"; - } - else { - print STDERR "$err Couldn't determine SuSE version! Setting to 10.3!\n"; - $distro="SE10.3"; - } - close(SUSE_RELEASE); - } - elsif ( -e "/etc/turbolinux-release") { - open(*TURBOLINUX_RELEASE,"/etc/turbolinux-release"); - $release=<TURBOLINUX_RELEASE>; - unless ($release =~ /^Turbolinux Workstation (\d+\.\d+\w*)/) { - print STDERR "$err Couldn't determine TurboLinux version! Setting to 7.0!\n"; - $distro="TB7.0"; - } - else { - $distro="TB$1"; - } - close(TURBOLINUX_RELEASE); - } - else { - # We're either on Mac OS X, HP-UX or an unsupported O/S. - if ( -x '/usr/bin/uname') { - # uname is in /usr/bin on Mac OS X and HP-UX - $release=`/usr/bin/uname -sr`; - } - else { - print STDERR "$err Could not determine operating system version!\n"; - $distro="unknown"; - } - - # Figure out what kind of system we're on. - if ($release ne "") { - if ($release =~ /^Darwin\s+(\d+)\.(\d+)/) { - if ($1 == 6 ) { - $distro = "OSX10.2"; - } - elsif ($1 == 7) { - $distro = "OSX10.3"; - } - elsif ($1 == 8) { - $distro = "OSX10.3"; - } - else { - $distro = "unknown"; - } - } - elsif ( $release =~ /(^HP-UX)\s*B\.(\d+\.\d+)/ ) { - $distro="$1$2"; - } - else { - print STDERR "$err Could not determine operating system version!\n"; - $distro="unknown"; - } - } - } - - $GLOBAL_OS=$distro; - } elsif (not (defined $GLOBAL_OS)) { - print "ERROR: GLOBAL OS Scoping Issue\n"; - } else { - $distro = $GLOBAL_OS; - } - - return $distro; -} - -################################################################################### -# &getActualDistro; # -# # -# This subroutine returns the actual os version in which is running on. This # -# os version is independent of the --os switch feed to bastille. # -# # -################################################################################### -sub getActualDistro { - # set local variable to $GLOBAL_OS - - if ($GLOBAL_ACTUAL_OS eq "None") { - my $os = $GLOBAL_OS; - # undef GLOBAL_OS so that the GetDistro routine will return - # the actualDistro, it might otherwise return the distro set - # by the --os switch. - $GLOBAL_OS = "None"; - $GLOBAL_ACTUAL_OS = &GetDistro; - # reset the GLOBAL_OS variable - $GLOBAL_OS = $os; - } - return $GLOBAL_ACTUAL_OS; -} -# These are helper routines which used to be included inside GetDistro -sub is_OS_supported($) { - my $os=$_[0]; - my $supported=0; - my %supportedOSHash = &getSupportedOSHash; - - foreach my $oSType (keys %supportedOSHash) { - foreach my $supported_os ( @{$supportedOSHash{$oSType}} ) { - if ( $supported_os eq $os ) { - $supported=1; - } - } - } - - return $supported; -} - -############################################################################### -# getSupportedOSHash -# -# This subrountine returns a hash of supported OSTypes, which point to a -# a list of supported distros. When porting to a new distro, add the -# distro id to the hash in its appropriate list. -############################################################################### -sub getSupportedOSHash () { - - my %osHash = ("LINUX" => [ - "DB2.2", "DB3.0", - "RH6.0","RH6.1","RH6.2","RH7.0", - "RH7.1","RH7.2","RH7.3","RH8.0", - "RH9", - "RHEL5", - "RHEL4AS","RHEL4ES","RHEL4WS", - "RHEL3AS","RHEL3ES","RHEL3WS", - "RHEL2AS","RHEL2ES","RHEL2WS", - "RHFC1","RHFC2","RHFC3","RHFC4", - "RHFC5","RHFC6","RHFC7","RHFC8", - "MN6.0","MN6.1 ","MN7.0","MN7.1", - "MN7.2","MN8.0","MN8.1","MN8.2", - "MN10.1", - "SE7.2","SE7.3", "SE8.0","SE8.1","SE9.0","SE9.1", - "SE9.2","SE9.3","SE10.0","SE10.1","SE10.2","SE10.3", - "SESLES8","SESLES9","SESLES10", - "TB7.0" - ], - - "HP-UX" => [ - "HP-UX11.00","HP-UX11.11", - "HP-UX11.22", "HP-UX11.23", - "HP-UX11.31" - ], - - "OSX" => [ - 'OSX10.2','OSX10.3','OSX10.4' - ] - ); - - return %osHash; - -} - - -############################################################################### -# setFileLocations(OSMapFile, currentDistro); -# -# Given a file map location this subroutine will create the GLOBAL_* -# hash entries specified within this file. -############################################################################### -sub setFileLocations($$) { - - my ($fileInfoFile,$currentDistro) = @_; - - # define a mapping from the first argument to the proper hash - my %map = ("BIN" => \%GLOBAL_BIN, - "FILE" => \%GLOBAL_FILE, - "BFILE" => \%GLOBAL_BFILE, - "DIR" => \%GLOBAL_DIR, - "BDIR" => \%GLOBAL_BDIR - ); - my @fileInfo = (); - - # File containing file location information - if(open(FILEINFO, "<$fileInfoFile" )) { - - @fileInfo = <FILEINFO>; - - close(FILEINFO); - - } - else { - print STDERR "$err Unable to find file location information for '$distro'.\n" . - "$spc Contact the Bastille support list for details.\n"; - exit(1); - } - - # Each line of the file map follows the pattern below: - # bdir,init.d,'/etc/rc.d/init.d',RH7.2,RH7.3 - # if the distro information is not available, e.g. - # bdir,init.d,'/etc/rc.d/init.d' - # then the line applies to all distros under the OSType - foreach my $file (@fileInfo) { - # Perl comments are allowed within the file but only entire line comments - if($file !~ /^\s+\#|^\s+$/) { - chomp $file; - # type relates to the map above, type bin will map to GLOBAL_BIN - # id is the identifier used as the hash key by the GLOBAL hash - # fileLocation is the full path to the file - # distroList is an optional list of distros that this particular - # file location, if no distro list is presented the file location - # is considered to apply to all distros - my ($type,$id,$fileLocation,@distroList) = split /\s*,\s*/, $file; - $fileLocation =~ s/^\'(.*)\'$/$1/; - if($#distroList == -1) { - $map{uc($type)}->{$id}=$fileLocation; - } - else { - foreach my $distro (@distroList) { - # if the current distro matches the distro listed then - # this file location applies - if($currentDistro =~ /$distro/) { - $map{uc($type)}->{$id}=$fileLocation; - } - } - } - } - } - unless(defined($map{uc("BFILE")}->{"current_config"})) { - &setGlobal("BFILE","current_config",&getGlobal("BFILE","config")); - } -} - -############################################################################### -# setServiceInfo($OSServiceMapFile, $currentDistro -# -# Given the location of an OS Service map file, which describes -# a service in terms of configurables, processes and a service type. -# The subroutine fills out the GLOBAL_SERVICE, $GLOBAL_RC_CONFIG, GLOBAL_SERVTYPE, and -# GLOBAL_PROCESS hashes for a given service ID. -############################################################################### -sub setServiceInfo($$) { - my ($serviceInfoFile,$currentDistro) = @_; - my @serviceInfo = (); - - if(open(SERVICEINFO, "<$serviceInfoFile" )) { - - @serviceInfo = <SERVICEINFO>; - - close(SERVICEINFO); - - } - else { - print STDERR "$err Unable to find service, service type, and process information\n" . - "$spc for '$distro'.\n" . - "$spc Contact the Bastille support list for details.\n"; - exit(1); - } - - - # The following loop, parses the entire (YOUR OS).service file - # to provide service information for YOUR OS. - # The files format is as follows: - # serviceID,servType,('service' 'configuration' 'list'),('process' 'list')[,DISTROS]* - # if distros are not present then the service is assumed to be - # relevant the the current distro - - -# -# More specifically, this file's format for rc-based daemons is: -# -# script_name,rc,(rc-config-file rc-config-file ...),(rc-variable1 rc-variable2 ...),('program_name1 program_name2 ...') -# -# ...where script_name is a file in /etc/init.d/ and -# ...program_nameN is a program launced by the script. -# -# This file's format for inet-based daemons is: -# -# identifier, inet, line name/file name, program name -# -# label,inet,(port1 port2 ...),(daemon1 daemon2 ...) -# -# ...where label is arbitrary, portN is one of the ports -# ...this one listens on, and daemonN is a program launched -# ...in response to a connection on a port. - - foreach my $service (@serviceInfo) { - # This file accepts simple whole line comments perl style - if($service !~ /^\s+\#|^\s+$/) { - chomp $service; - my ($serviceID,$servType,$strConfigList,$strServiceList, - $strProcessList,@distroList) = split /\s*,\s*/, $service; - - sub MakeArrayFromString($){ - my $entryString = $_[0]; - my @destArray = (); - if ($entryString =~ /\'\S+\'/) { #Make sure we have something to extract before we try - @destArray = split /\'\s+\'/, $entryString; - $destArray[0] =~ s/^\(\'(.+)$/$1/; # Remove leading quotation mark - $destArray[$#destArray] =~ s/^(.*)\'\)$/$1/; #Remove trailing quotation mark - } - return @destArray; - } - - # produce a list of configuration files from the files - # format ('configuration' 'files') - my @configList = MakeArrayFromString($strConfigList); - - # produce a list of service configurables from the files - # format ('service' 'configurable') - my @serviceList = MakeArrayFromString($strServiceList); - - # produce a list of process names from the files format - # ('my' 'process' 'list') - my @processList = MakeArrayFromString($strProcessList); - - # if distros were not specified then accept the service information - if($#distroList == -1) { - @{$GLOBAL_SERVICE{$serviceID}} = @serviceList; - $GLOBAL_SERVTYPE{$serviceID} = $servType; - @{$GLOBAL_PROCESS{$serviceID}} = @processList; - @{$GLOBAL_RC_CONFIG{$serviceID}} = @configList; - } - else { - # only if the current distro matches one of the listed distros - # include the service information. - foreach my $distro (@distroList) { - if($currentDistro =~ /$distro/) { - @{$GLOBAL_SERVICE{$serviceID}} = @serviceList; - $GLOBAL_SERVTYPE{$serviceID} = $servType; - @{$GLOBAL_PROCESS{$serviceID}} = @processList; - @{$GLOBAL_RC_CONFIG{$serviceID}} = @configList; - } - } - } - } - } -} - - - -############################################################################### -# getFileAndServiceInfo($distro,$actualDistro) -# -# This subrountine, given distribution information, will import system file -# and service information into the GLOBA_* hashes. -# -# NOTE: $distro and $actualDistro will only differ when the --os switch is -# used to generate a configuration file for an arbitrary operating -# system. -# -############################################################################### -sub getFileAndServiceInfo($$) { - - my ($distro,$actualDistro) = @_; - - # defines the path to the OS map information for any supported OS type. - # OS map information is used to determine file locations for a given - # distribution. - my %oSInfoPath = ( - "LINUX" => "/usr/share/Bastille/OSMap/", - "HP-UX" => "/etc/opt/sec_mgmt/bastille/OSMap/", - "OSX" => "/usr/share/Bastille/OSMap/" - ); - - # returns the OS, LINUX, HP-UX, or OSX, associated with this - # distribution - my $actualOS = &getOSType($actualDistro); - my $oS = &getOSType($distro); - - if(defined $actualOS && defined $oS) { - my $bastilleInfoFile = $oSInfoPath{$actualOS} . "${actualOS}.bastille"; - my $systemInfoFile = $oSInfoPath{$actualOS} . "${oS}.system"; - my $serviceInfoFile = $oSInfoPath{$actualOS} . "${oS}.service"; - - if(-f $bastilleInfoFile) { - &setFileLocations($bastilleInfoFile,$actualDistro); - } - else { - print STDERR "$err Unable to find bastille file information.\n" . - "$spc $bastilleInfoFile does not exist on the system"; - exit(1); - } - - if(-f $systemInfoFile) { - &setFileLocations($systemInfoFile,$distro); - } - else { - print STDERR "$err Unable to find system file information.\n" . - "$spc $systemInfoFile does not exist on the system"; - exit(1); - } - # Service info File is optional - if(-f $serviceInfoFile) { - &setServiceInfo($serviceInfoFile,$distro); - } - } - else { - print STDERR "$err Unable to determine operating system type\n" . - "$spc for $actualDistro or $distro\n"; - exit(1); - } - -} - - -# returns the Operating System type associated with the specified -# distribution. -sub getOSType($) { - - my $distro = $_[0]; - - my %supportedOSHash = &getSupportedOSHash; - foreach my $oSType (keys %supportedOSHash) { - foreach my $oSDistro (@{$supportedOSHash{$oSType}}) { - if($distro eq $oSDistro) { - return $oSType; - } - } - } - - return undef; - -} - - -# Test subroutine used to debug file location info for new Distributions as -# they are ported. -sub dumpFileInfo { - print "Dumping File Information\n"; - foreach my $hashref (\%GLOBAL_BIN,\%GLOBAL_DIR,\%GLOBAL_FILE,\%GLOBAL_BFILE,\%GLOBAL_BDIR) { - foreach my $id (keys %{$hashref}) { - print "$id: ${$hashref}{$id}\n"; - } - print "-----------------------\n\n"; - } -} - -# Test subroutine used to debug service info for new Distributions as -# they are ported. -sub dumpServiceInfo { - print "Dumping Service Information\n"; - foreach my $serviceId (keys %GLOBAL_SERVICE) { - print "$serviceId:\n"; - print "Type - $GLOBAL_SERVTYPE{$serviceId}\n"; - print "Service List:\n"; - foreach my $service (@{$GLOBAL_SERVICE{$serviceId}}) { - print "$service "; - } - print "\nProcess List:\n"; - foreach my $process (@{$GLOBAL_PROCESS{$serviceId}}) { - print "$process "; - } - print "\n----------------------\n"; - } -} - - -########################################################################### -# -# &ConfigureForDistro configures the API for a given distribution. This -# includes setting global variables that tell the Bastille API about -# given binaries and directories. -# -# WARNING: If a distro is not covered here, Bastille may not be 100% -# compatible with it, though 1.1 is written to be much smarter -# about unknown distros... -# -########################################################################### -sub ConfigureForDistro { - - my $retval=1; - - # checking to see if the os version given is in fact supported - my $distro = &GetDistro; - - # checking to see if the actual os version is in fact supported - my $actualDistro = &getActualDistro; - $ENV{'LOCALE'}=''; # So that test cases checking for english results work ok. - if ((! &is_OS_supported($distro)) or (! &is_OS_supported($actualDistro)) ) { - # if either is not supported then print out a list of supported versions - if (! &is_OS_supported($distro)) { - print STDERR "$err '$distro' is not a supported operating system.\n"; - } - else { - print STDERR "$err Bastille is unable to operate correctly on this\n"; - print STDERR "$spc $distro operating system.\n"; - } - my %supportedOSHash = &getSupportedOSHash; - print STDERR "$spc Valid operating system versions are as follows:\n"; - - foreach my $oSType (keys %supportedOSHash) { - - print STDERR "$spc $oSType:\n$spc "; - - my $os_number = 1; - foreach my $os (@{$supportedOSHash{$oSType}}) { - print STDERR "'$os' "; - if ($os_number == 5){ - print STDERR "\n$spc "; - $os_number = 1; - } - else { - $os_number++; - } - - } - print STDERR "\n"; - } - - print "\n" . $GLOBAL_ERROR{"usage"}; - exit(1); - } - - # First, let's make sure that we do not create any files or - # directories with more permissive permissions than we - # intend via setting the Perl umask - umask(077); - - &getFileAndServiceInfo($distro,$actualDistro); - -# &dumpFileInfo; # great for debuging file location issues -# &dumpServiceInfo; # great for debuging service information issues - - # OS dependent error messages (after configuring file locations) - my $nodisclaim_file = &getGlobal('BFILE', "nodisclaimer"); - - $GLOBAL_ERROR{"disclaimer"}="$err Unable to touch $nodisclaim_file:" . - "$spc You must use Bastille\'s -n flag (for example:\n" . - "$spc bastille -f -n) or \'touch $nodisclaim_file \'\n"; - - return $retval; -} - - -########################################################################### -########################################################################### -# # -# The B_<perl_function> file utilities are replacements for their Perl # -# counterparts. These replacements log their actions and their errors, # -# but are very similar to said counterparts. # -# # -########################################################################### -########################################################################### - - -########################################################################### -# B_open is used for opening a file for reading. B_open_plus is the preferred -# function for writing, since it saves a backup copy of the file for -# later restoration. -# -# B_open opens the given file handle, associated with the given filename -# and logs appropriately. -# -########################################################################### - -sub B_open { - my $retval=1; - my ($handle,$filename)=@_; - - unless ($GLOBAL_LOGONLY) { - $retval = open $handle,$filename; - } - - ($handle) = "$_[0]" =~ /[^:]+::[^:]+::([^:]+)/; - &B_log("ACTION","open $handle,\"$filename\";\n"); - unless ($retval) { - &B_log("ERROR","open $handle, $filename failed...\n"); - } - - return $retval; -} - -########################################################################### -# B_open_plus is the v1.1 open command. -# -# &B_open_plus($handle_file,$handle_original,$file) opens the file $file -# for reading and opens the file ${file}.bastille for writing. It is the -# counterpart to B_close_plus, which will move the original file to -# $GLOBAL_BDIR{"backup"} and will place the new file ${file}.bastille in its -# place. -# -# &B_open_plus makes the appropriate log entries in the action and error -# logs. -########################################################################### - -sub B_open_plus { - - my ($handle_file,$handle_original,$file)=@_; - my $retval=1; - my $return_file=1; - my $return_old=1; - - my $original_file = $file; - - # Open the original file and open a copy for writing. - unless ($GLOBAL_LOGONLY) { - # if the temporary filename already exists then the open operation will fail. - if ( $file eq "" ){ - &B_log("ERROR","Internal Error - Attempt Made to Open Blank Filename"); - $return_old=0; - $return_file=0; - return 0; #False - } elsif (-e "${file}.bastille") { - &B_log("ERROR","Unable to open $file as the swap file ". - "${file}.bastille\" already exists. Rename the swap ". - "file to allow Bastille to make desired file modifications."); - $return_old=0; - $return_file=0; - } - else { - $return_old = open $handle_original,"$file"; - $return_file = open $handle_file,("> $file.bastille"); - } - } - - # Error handling/logging here... - #&B_log("ACTION","# Modifying file $original_file via temporary file $original_file.bastille\n"); - unless ($return_file) { - $retval=0; - &B_log("ERROR","open file: \"$original_file.bastille\" failed...\n"); - } - unless ($return_old) { - $retval=0; - &B_log("ERROR","open file: \"$original_file\" failed.\n"); - } - - return $retval; - -} - -########################################################################### -# B_close was the v1.0 close command. It is still used in places in the -# code. -# However the use of B _close_plus, which implements a new, smarter, -# backup scheme is preferred. -# -# B_close closes the given file handle, associated with the given filename -# and logs appropriately. -########################################################################### - - -sub B_close { - my $retval=1; - - unless ($GLOBAL_LOGONLY) { - $retval = close $_[0]; - } - - &B_log("ACTION", "close $_[0];\n"); - unless ($retval) { - &B_log("ERROR", "close $_[0] failed...\n"); - } - - return $retval; -} - - -########################################################################### -# B_close_plus is the v1.1 close command. -# -# &B_close_plus($handle_file,$handle_original,$file) closes the files -# $file and ${file}.bastille, backs up $file to $GLOBAL_BDIR{"backup"} and -# renames ${file}.bastille to $file. This backup is made using the -# internal API function &B_backup_file. Further, it sets the new file's -# permissions and uid/gid to the same as the old file. -# -# B_close_plus is the counterpart to B_open_plus, which opened $file and -# $file.bastille with the file handles $handle_original and $handle_file, -# respectively. -# -# &B_close_plus makes the appropriate log entries in the action and error -# logs. -########################################################################### - -sub B_close_plus { - my ($handle_file,$handle_original,$file)=@_; - my ($mode,$uid,$gid); - my @junk; - - my $original_file; - - my $retval=1; - my $return_file=1; - my $return_old=1; - - # Append the global prefix, but save the original for B_backup_file b/c - # it appends the prefix on its own... - - $original_file=$file; - - # - # Close the files and prepare for the rename - # - - if (($file eq "") or (not(-e $file ))) { - &B_log("ERROR","Internal Error, attempted to close a blank filename ". - "or nonexistent file."); - return 0; #False - } - - unless ($GLOBAL_LOGONLY) { - $return_file = close $handle_file; - $return_old = close $handle_original; - } - - # Error handling/logging here... - #&B_log("ACTION","#Closing $original_file and backing up to " . &getGlobal('BDIR', "backup")); - #&B_log("ACTION","/$original_file\n"); - - unless ($return_file) { - $retval=0; - &B_log("ERROR","close $original_file failed...\n"); - } - unless ($return_old) { - $retval=0; - &B_log("ERROR","close $original_file.bastille failed.\n"); - } - - # - # If we've had no errors, backup the old file and put the new one - # in its place, with the Right permissions. - # - - unless ( ($retval == 0) or $GLOBAL_LOGONLY) { - - # Read the permissions/owners on the old file - - @junk=stat ($file); - $mode=$junk[2]; - $uid=$junk[4]; - $gid=$junk[5]; - - # Set the permissions/owners on the new file - - chmod $mode, "$file.bastille" or &B_log("ERROR","Not able to retain permissions on $original_file!!!\n"); - chown $uid, $gid, "$file.bastille" or &B_log("ERROR","Not able to retain owners on $original_file!!!\n"); - - # Backup the old file and put a new one in place. - - &B_backup_file($original_file); - rename "$file.bastille", $file or - &B_log("ERROR","B_close_plus: not able to move $original_file.bastille to $original_file\n"); - - # We add the file to the GLOBAL_SUMS hash if it is not already present - &B_set_sum($file); - - } - - return $retval; -} - -########################################################################### -# &B_backup_file ($file) makes a backup copy of the file $file in -# &getGlobal('BDIR', "backup"). Note that this routine is intended for internal -# use only -- only Bastille API functions should call B_backup_file. -# -########################################################################### - -sub B_backup_file { - - my $file=$_[0]; - my $complain = 1; - my $original_file = $file; - - my $backup_dir = &getGlobal('BDIR', "backup"); - my $backup_file = $backup_dir . $original_file; - - my $retval=1; - - # First, separate the file into the directory and the relative filename - - my $directory =""; - if ($file =~ /^(.*)\/([^\/]+)$/) { - #$relative_file=$2; - $directory = $1; - } else { - $directory=cwd; - } - - # Now, if the directory does not exist, create it. - # Later: - # Try to set the same permissions on the patch directory that the - # original had...? - - unless ( -d ($backup_dir . $directory) ) { - mkpath(( $backup_dir . $directory),0,0700); - - } - - # Now we backup the file. If there is already a backup file there, - # we will leave it alone, since it exists from a previous run and - # should be the _original_ (possibly user-modified) distro's version - # of the file. - - if ( -e $file ) { - - unless ( -e $backup_file ) { - my $command=&getGlobal("BIN","cp"); - &B_Backtick("$command -p $file $backup_file"); - &B_revert_log (&getGlobal("BIN","mv"). " $backup_file $file"); - } - - } else { - # The file we were trying to backup doesn't exist. - - $retval=0; - # This is a non-fatal error, not worth complaining about - $complain = 0; - #&ErrorLog ("# Failed trying to backup file $file -- it doesn't exist!\n"); - } - - # Check to make sure that the file does exist in the backup location. - - unless ( -e $backup_file ) { - $retval=0; - if ( $complain == 1 ) { - &B_log("ERROR","Failed trying to backup $file -- the copy was not created.\n"); - } - } - - return $retval; -} - - -########################################################################### -# &B_read_sums reads in the sum.csv file which contains information -# about Bastille modified files. The file structure is as follows: -# -# filename,filesize,cksum -# -# It reads the information into the GLOBAL_SUM hash i.e. -# $GLOBAL_SUM{$file}{sum} = $cksum -# $GLOBAL_SUM{$file}{filesize} = $size -# For the first run of Bastille on a given system this subroutine -# is a no-op, and returns "undefined." -########################################################################### - -sub B_read_sums { - - my $sumFile = &getGlobal('BFILE',"sum.csv"); - - if ( -e $sumFile ) { - - open( SUM, "< $sumFile") or &B_log("ERROR","Unable to open $sumFile for read.\n$!\n"); - - while( my $line = <SUM> ) { - chomp $line; - my ($file,$filesize,$sum,$flag) = split /,/, $line; - if(-e $file) { - $GLOBAL_SUM{"$file"}{filesize} = $filesize; - $GLOBAL_SUM{"$file"}{sum} = $sum; - } - } - - close(SUM); - } else { - return undef; - } -} - - -########################################################################### -# &B_write_sums writes out the sum.csv file which contains information -# about Bastille modified files. The file structure is as follows: -# -# filename,filesize,cksum -# -# It writes the information from the GLOBAL_SUM hash i.e. -# -# $file,$GLOBAL_SUM{$file}{sum},$GLOBAL_SUM{$file}{filesize} -# -# This subroutine requires access to the GLOBAL_SUM hash. -########################################################################### - -sub B_write_sums { - - my $sumFile = &getGlobal('BFILE',"sum.csv"); - - if ( %GLOBAL_SUM ) { - - open( SUM, "> $sumFile") or &B_log("ERROR","Unable to open $sumFile for write.\n$!\n"); - - for my $file (sort keys %GLOBAL_SUM) { - if( -e $file) { - print SUM "$file,$GLOBAL_SUM{\"$file\"}{filesize},$GLOBAL_SUM{\"$file\"}{sum}\n"; - } - } - - close(SUM); - } - -} - - -########################################################################### -# &B_check_sum($file) compares the stored cksum and filesize of the given -# file compared to the current cksum and filesize respectively. -# This subroutine also keeps the state of the sum check by setting the -# checked flag which tells the subroutine that on this run this file -# has already been checked. -# -# $GLOBAL_SUM{$file}{checked} = 1; -# -# This subroutine requires access to the GLOBAL_SUM hash. -# -# Returns 1 if sum checks out and 0 if not -########################################################################### - -sub B_check_sum($) { - my $file = $_[0]; - my $cksum = &getGlobal('BIN',"cksum"); - - if (not(%GLOBAL_SUM)) { - &B_read_sums; - } - - if(-e $file) { - my ($sum,$size,$ckfile) = split(/\s+/, `$cksum $file`); - my $commandRetVal = ($? >> 8); # find the command's return value - - if($commandRetVal != 0) { - &B_log("ERROR","$cksum reported the following error:\n$!\n"); - return 0; - } else { - if ( exists $GLOBAL_SUM{$file} ) { - # if the file size or file sum differ from those recorded. - if (( $GLOBAL_SUM{$file}{filesize} == $size) and - ($GLOBAL_SUM{$file}{sum} == $sum )) { - return 1; #True, since saved state matches up, all is well. - } else { - return 0; #False, since saved state doesn't match - } - } else { - &B_log("ERROR","File: $file does not exist in sums database."); - return 0; - } - } - } else { - &B_log("ERROR","The file: $file does not exist for comparison in B_check_sum."); - return 0; - } -} - -# Don't think we need this anymore as function now check_sums returns -# results directly -#sub isSumDifferent($) { -# my $file = $_[0]; -# if(exists $GLOBAL_SUM{$file}) { -# return $GLOBAL_SUM{$file}{flag} -# } -#} - -sub listModifiedFiles { - my @listModifiedFiles=sort keys %GLOBAL_SUM; - return @listModifiedFiles; -} - -########################################################################### -# &B_isFileinSumDB($file) checks to see if a given file's sum was saved. -# -# $GLOBAL_SUM{$file}{filesize} = $size; -# $GLOBAL_SUM{$file}{sum} = $cksum; -# -# This subroutine requires access to the GLOBAL_SUM hash. -########################################################################### - -sub B_isFileinSumDB($) { - my $file = $_[0]; - - if (not(%GLOBAL_SUM)) { - &B_log("DEBUG","Reading in DB from B_isFileinSumDB"); - &B_read_sums; - } - if (exists($GLOBAL_SUM{"$file"})){ - &B_log("DEBUG","$file is in sum database"); - return 1; #true - } else { - &B_log("DEBUG","$file is not in sum database"); - return 0; #false - } -} - -########################################################################### -# &B_set_sum($file) sets the current cksum and filesize of the given -# file into the GLOBAL_SUM hash. -# -# $GLOBAL_SUM{$file}{filesize} = $size; -# $GLOBAL_SUM{$file}{sum} = $cksum; -# -# This subroutine requires access to the GLOBAL_SUM hash. -########################################################################### - -sub B_set_sum($) { - - my $file = $_[0]; - my $cksum = &getGlobal('BIN',"cksum"); - if( -e $file) { - - my ($sum,$size,$ckfile) = split(/\s+/, `$cksum $file`); - my $commandRetVal = ($? >> 8); # find the command's return value - - if($commandRetVal != 0) { - - &B_log("ERROR","$cksum reported the following error:\n$!\n"); - - } - else { - - # new file size and sum are added to the hash - $GLOBAL_SUM{$file}{filesize} = $size; - $GLOBAL_SUM{$file}{sum} = $sum; - &B_write_sums; - - } - } else { - &B_log("ERROR","Can not save chksum for file: $file since it does not exist"); - } -} - - -########################################################################### -# -# &B_delete_file ($file) deletes the file $file and makes a backup to -# the backup directory. -# -########################################################################## - - -sub B_delete_file($) { #Currently Linux only (TMPDIR) - #consideration: should create clear_sum routine if this is ever used to remove - # A Bastille-generated file. - - # - # This API routine deletes the named file, backing it up first to the - # backup directory. - # - - my $filename=shift @_; - my $retval=1; - - # We have to append the prefix ourselves since we don't use B_open_plus - - my $original_filename=$filename; - - &B_log("ACTION","Deleting (and backing-up) file $original_filename\n"); - &B_log("ACTION","rm $original_filename\n"); - - unless ($filename) { - &B_log("ERROR","B_delete_file called with no arguments!\n"); - } - - unless ($GLOBAL_LOGONLY) { - if ( B_backup_file($original_filename) ) { - unless ( unlink $filename ) { - &B_log("ERROR","Couldn't unlink file $original_filename"); - $retval=0; - } - } - else { - $retval=0; - &B_log("ERROR","B_delete_file did not delete $original_filename since it could not back it up\n"); - } - } - - $retval; - -} - - -########################################################################### -# &B_create_file ($file) creates the file $file, if it doesn't already -# exist. -# It will set a default mode of 0700 and a default uid/gid or 0/0. -# -# &B_create_file, to support Bastille's revert functionality, writes an -# rm $file command to the end of the file &getGlobal('BFILE', "created-files"). -# -########################################################################## - - -sub B_create_file($) { - - my $file = $_[0]; - my $retval=1; - - # We have to create the file ourselves since we don't use B_open_plus - - my $original_file = $file; - - if ($file eq ""){ - &B_log("ERROR","Internal Error, attempt made to create blank filename"); - return 0; #False - } - - unless ( -e $file ) { - - unless ($GLOBAL_LOGONLY) { - - # find the directory in which the file is to reside. - my $dirName = dirname($file); - # if the directory does not exist then - if(! -d $dirName) { - # create it. - mkpath ($dirName,0,0700); - } - - $retval=open CREATE_FILE,">$file"; - - if ($retval) { - close CREATE_FILE; - chmod 0700,$file; - # Make the revert functionality - &B_revert_log( &getGlobal('BIN','rm') . " $original_file \n"); - } else { - &B_log("ERROR","Couldn't create file $original_file even though " . - "it didn't already exist!\n"); - } - } - &B_log("ACTION","Created file $original_file\n"); - } else { - &B_log("DEBUG","Didn't create file $original_file since it already existed.\n"); - $retval=0; - } - - $retval; -} - - -########################################################################### -# &B_create_dir ($dir) creates the directory $dir, if it doesn't already -# exist. -# It will set a default mode of 0700 and a default uid/gid or 0/0. -# -########################################################################## - - -sub B_create_dir($) { - - my $dir = $_[0]; - my $retval=1; - - # We have to append the prefix ourselves since we don't use B_open_plus - - my $original_dir=$dir; - - unless ( -d $dir ) { - unless ($GLOBAL_LOGONLY) { - $retval=mkdir $dir,0700; - - if ($retval) { - # Make the revert functionality - &B_revert_log (&getGlobal('BIN','rmdir') . " $original_dir\n"); - } - else { - &B_log("ERROR","Couldn't create dir $original_dir even though it didn't already exist!"); - } - - } - &B_log("ACTION","Created directory $original_dir\n"); - } - else { - &B_log("ACTION","Didn't create directory $original_dir since it already existed.\n"); - $retval=0; - } - - $retval; -} - - - -########################################################################### -# &B_symlink ($original_file,$new_symlink) creates a symbolic link from -# $original_file to $new_symlink. -# -# &B_symlink respects $GLOBAL_LOGONLY. It supports -# the revert functionality that you've come to know and love by adding every -# symbolic link it creates to &getGlobal('BFILE', "created-symlinks"), currently set to: -# -# /root/Bastille/revert/revert-created-symlinks -# -# The revert script, if it works like I think it should, will run this file, -# which should be a script or rm's... -# -########################################################################## - -sub B_symlink($$) { - my ($source_file,$new_symlink)=@_; - my $retval=1; - my $original_source = $source_file; - my $original_symlink = $new_symlink; - - unless ($GLOBAL_LOGONLY) { - $retval=symlink $source_file,$new_symlink; - if ($retval) { - &B_revert_log (&getGlobal('BIN',"rm") . " $original_symlink\n"); - } - } - - &B_log("ACTION", "Created a symbolic link called $original_symlink from $original_source\n"); - &B_log("ACTION", "symlink \"$original_source\",\"$original_symlink\";\n"); - unless ($retval) { - &B_log("ERROR","Couldn't symlink $original_symlink -> $original_source\n"); - } - - $retval; - -} - - -sub B_cp($$) { - - my ($source,$target)=@_; - my $retval=0; - - my $had_to_backup_target=0; - - use File::Copy; - - my $original_source=$source; - my $original_target=$target; - - if( -e $target and -f $target ) { - &B_backup_file($original_target); - &B_log("ACTION","About to copy $original_source to $original_target -- had to backup target\n"); - $had_to_backup_target=1; - } - - $retval=copy($source,$target); - if ($retval) { - &B_log("ACTION","cp $original_source $original_target\n"); - - # - # We want to add a line to the &getGlobal('BFILE', "created-files") so that the - # file we just put at $original_target gets deleted. - # - &B_revert_log(&getGlobal('BIN',"rm") . " $original_target\n"); - } else { - &B_log("ERROR","Failed to copy $original_source to $original_target\n"); - } - # We add the file to the GLOBAL_SUMS hash if it is not already present - &B_set_sum($target); - $retval; -} - - - -############################################################################ -# &B_place puts a file in place, using Perl's File::cp. This file is taken -# from &getGlobal('BDIR', "share") and is used to place a file that came with -# Bastille. -# -# This should be DEPRECATED in favor of &B_cp, since the only reason it exists -# is because of GLOBAL_PREFIX, which has been broken for quite some time. -# Otherwise, the two routines are identical. -# -# It respects $GLOBAL_LOGONLY. -# If $target is an already-existing file, it is backed up. -# -# revert either appends another "rm $target" to &getGlobal('BFILE', "revert-actions") or -# backs up the file that _was_ there into the &getGlobal('BDIR', "backup"), -# appending a "mv" to revert-actions to put it back. -# -############################################################################ - -sub B_place { # Only Linux references left (Firewall / TMPDIR) - - my ($source,$target)=@_; - my $retval=0; - - my $had_to_backup_target=0; - - use File::Copy; - - my $original_source=$source; - $source = &getGlobal('BDIR', "share") . $source; - my $original_target=$target; - - if ( -e $target and -f $target ) { - &B_backup_file($original_target); - &B_log("ACTION","About to copy $original_source to $original_target -- had to backup target\n"); - $had_to_backup_target=1; - } - $retval=copy($source,$target); - if ($retval) { - &B_log("ACTION","placed file $original_source as $original_target\n"); - # - # We want to add a line to the &getGlobal('BFILE', "created-files") so that the - # file we just put at $original_target gets deleted. - &B_revert_log(&getGlobal('BIN',"rm") . " $original_target\n"); - } else { - &B_log("ERROR","Failed to place $original_source as $original_target\n"); - } - - # We add the file to the GLOBAL_SUMS hash if it is not already present - &B_set_sum($target); - - $retval; -} - - - - - -############################################################################# -############################################################################# -############################################################################# - -########################################################################### -# &B_mknod ($file) creates the node $file, if it doesn't already -# exist. It uses the prefix and suffix, like this: -# -# mknod $prefix $file $suffix -# -# This is just a wrapper to the mknod program, which tries to introduce -# revert functionality, by writing rm $file to the end of the -# file &getGlobal('BFILE', "created-files"). -# -########################################################################## - - -sub B_mknod($$$) { - - my ($prefix,$file,$suffix) = @_; - my $retval=1; - - # We have to create the filename ourselves since we don't use B_open_plus - - my $original_file = $file; - - unless ( -e $file ) { - my $command = &getGlobal("BIN","mknod") . " $prefix $file $suffix"; - - if ( system($command) == 0) { - # Since system will return 0 on success, invert the error code - $retval=1; - } - else { - $retval=0; - } - - if ($retval) { - - # Make the revert functionality - &B_revert_log(&getGlobal('BIN',"rm") . " $original_file\n"); - } else { - &B_log("ERROR","Couldn't mknod $prefix $original_file $suffix even though it didn't already exist!\n"); - } - - - &B_log("ACTION","mknod $prefix $original_file $suffix\n"); - } - else { - &B_log("ACTION","Didn't mknod $prefix $original_file $suffix since $original_file already existed.\n"); - $retval=0; - } - - $retval; -} - -########################################################################### -# &B_revert_log("reverse_command") prepends a command to a shell script. This -# shell script is intended to be run by bastille -r to reverse the changes that -# Bastille made, returning the files which Bastille changed to their original -# state. -########################################################################### - -sub B_revert_log($) { - - my $revert_command = $_[0]; - my $revert_actions = &getGlobal('BFILE', "revert-actions"); - my $revertdir= &getGlobal('BDIR', "revert"); - my @lines; - - - if (! (-e $revert_actions)) { - mkpath($revertdir); #if this doesn't work next line catches - if (open REVERT_ACTIONS,">" . $revert_actions){ # create revert file - close REVERT_ACTIONS; # chown to root, rwx------ - chmod 0700,$revert_actions; - chown 0,0,$revert_actions; - } - else { - &B_log("FATAL","Can not create revert-actions file: $revert_actions.\n" . - " Unable to add the following command to the revert\n" . - " actions script: $revert_command\n"); - } - - } - - &B_open_plus (*REVERT_NEW, *REVERT_OLD, $revert_actions); - - while (my $line=<REVERT_OLD>) { #copy file into @lines - push (@lines,$line); - } - print REVERT_NEW $revert_command . "\n"; #make the revert command first in the new file - while (my $line = shift @lines) { #write the rest of the lines of the file - print REVERT_NEW $line; - } - close REVERT_OLD; - close REVERT_NEW; - if (rename "${revert_actions}.bastille", $revert_actions) { #replace the old file with the new file we - chmod 0700,$revert_actions; # just made / mirrors B_close_plus logic - chown 0,0,$revert_actions; - } else { - &B_log("ERROR","B_revert_log: not able to move ${revert_actions}.bastille to ${revert_actions}!!! $!) !!!\n"); - } -} - - -########################################################################### -# &getGlobalConfig($$) -# -# returns the requested GLOBAL_CONFIG hash value, ignoring the error -# if the value does not exist (because every module uses this to find -# out if the question was answered "Y") -########################################################################### -sub getGlobalConfig ($$) { - my $module = $_[0]; - my $key = $_[1]; - if (exists $GLOBAL_CONFIG{$module}{$key}) { - my $answer=$GLOBAL_CONFIG{$module}{$key}; - &B_log("ACTION","Answer to question $module.$key is \"$answer\".\n"); - return $answer; - } else { - &B_log("ACTION","Answer to question $module.$key is undefined."); - return undef; - } -} - -########################################################################### -# &getGlobal($$) -# -# returns the requested GLOBAL_* hash value, and logs an error -# if the variable does not exist. -########################################################################### -sub getGlobal ($$) { - my $type = uc($_[0]); - my $key = $_[1]; - - # define a mapping from the first argument to the proper hash - my %map = ("BIN" => \%GLOBAL_BIN, - "FILE" => \%GLOBAL_FILE, - "BFILE" => \%GLOBAL_BFILE, - "DIR" => \%GLOBAL_DIR, - "BDIR" => \%GLOBAL_BDIR, - "ERROR" => \%GLOBAL_ERROR, - "SERVICE" => \%GLOBAL_SERVICE, - "SERVTYPE" => \%GLOBAL_SERVTYPE, - "PROCESS" => \%GLOBAL_PROCESS, - "RCCONFIG" => \%GLOBAL_RC_CONFIG - ); - - # check to see if the desired key is in the desired hash - if (exists $map{$type}->{$key}) { - # get the value from the right hash with the key - return $map{$type}->{$key}; - } else { - # i.e. Bastille tried to use $GLOBAL_BIN{'cp'} but it does not exist. - # Note that we can't use B_log, since it uses getGlobal ... recursive before - # configureForDistro is run. - print STDERR "ERROR: Bastille tried to use \$GLOBAL_${type}\{\'$key\'} but it does not exist.\n"; - return undef; - } -} - -########################################################################### -# &getGlobal($$) -# -# sets the requested GLOBAL_* hash value -########################################################################### -sub setGlobal ($$$) { - my $type = uc($_[0]); - my $key = $_[1]; - my $input_value = $_[2]; - - # define a mapping from the first argument to the proper hash - my %map = ("BIN" => \%GLOBAL_BIN, - "FILE" => \%GLOBAL_FILE, - "BFILE" => \%GLOBAL_BFILE, - "DIR" => \%GLOBAL_DIR, - "BDIR" => \%GLOBAL_BDIR, - "ERROR" => \%GLOBAL_ERROR, - "SERVICE" => \%GLOBAL_SERVICE, - "SERVTYPE" => \%GLOBAL_SERVTYPE, - "PROCESS" => \%GLOBAL_PROCESS, - ); - - if ($map{$type}->{$key} = $input_value) { - return 1; - } else { - &B_log('ERROR','Internal Error, Unable to set global config value:' . $type . ", " .$key); - return 0; - } -} - - -########################################################################### -# &showDisclaimer: -# Print the disclaimer and wait for 2 minutes for acceptance -# Do NOT do so if any of the following conditions hold -# 1. the -n option was used -# 2. the file ~/.bastille_disclaimer exists -########################################################################### - -sub showDisclaimer($) { - - my $nodisclaim = $_[0]; - my $nodisclaim_file = &getGlobal('BFILE', "nodisclaimer"); - my $response; - my $WAIT_TIME = 300; # we'll wait for 5 minutes - my $developersAnd; - my $developersOr; - if ($GLOBAL_OS =~ "^HP-UX") { - $developersAnd ="HP AND ITS"; - $developersOr ="HP OR ITS"; - }else{ - $developersAnd ="JAY BEALE, THE BASTILLE DEVELOPERS, AND THEIR"; - $developersOr ="JAY BEALE, THE BASTILLE DEVELOPERS, OR THEIR"; - } - my $DISCLAIMER = - "\n" . - "Copyright (C) 1999-2006 Jay Beale\n" . - "Copyright (C) 1999-2001 Peter Watkins\n" . - "Copyright (C) 2000 Paul L. Allen\n" . - "Copyright (C) 2001-2007 Hewlett-Packard Development Company, L.P.\n" . - "Bastille is free software; you are welcome to redistribute it under\n" . - "certain conditions. See the \'COPYING\' file in your distribution for terms.\n\n" . - "DISCLAIMER. Use of Bastille can help optimize system security, but does not\n" . - "guarantee system security. Information about security obtained through use of\n" . - "Bastille is provided on an AS-IS basis only and is subject to change without\n" . - "notice. Customer acknowledges they are responsible for their system\'s security.\n" . - "TO THE EXTENT ALLOWED BY LOCAL LAW, Bastille (\"SOFTWARE\") IS PROVIDED TO YOU \n" . - "\"AS IS\" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, WHETHER ORAL OR WRITTEN,\n" . - "EXPRESS OR IMPLIED. $developersAnd SUPPLIERS\n" . - "DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE \n" . - "IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\n" . - "Some countries, states and provinces do not allow exclusions of implied\n" . - "warranties or conditions, so the above exclusion may not apply to you. You may\n" . - "have other rights that vary from country to country, state to state, or province\n" . - "to province. EXCEPT TO THE EXTENT PROHIBITED BY LOCAL LAW, IN NO EVENT WILL\n" . - "$developersOr SUBSIDIARIES, AFFILIATES OR\n" . - "SUPPLIERS BE LIABLE FOR DIRECT, SPECIAL, INCIDENTAL, CONSEQUENTIAL OR OTHER\n" . - "DAMAGES (INCLUDING LOST PROFIT, LOST DATA, OR DOWNTIME COSTS), ARISING OUT OF\n" . - "THE USE, INABILITY TO USE, OR THE RESULTS OF USE OF THE SOFTWARE, WHETHER BASED\n" . - "IN WARRANTY, CONTRACT, TORT OR OTHER LEGAL THEORY, AND WHETHER OR NOT ADVISED\n" . - "OF THE POSSIBILITY OF SUCH DAMAGES. Your use of the Software is entirely at your\n" . - "own risk. Should the Software prove defective, you assume the entire cost of all\n" . - "service, repair or correction. Some countries, states and provinces do not allow\n" . - "the exclusion or limitation of liability for incidental or consequential \n" . - "damages, so the above limitation may not apply to you. This notice will only \n". - "display on the first run on a given system.\n". - "To suppress the disclaimer on other machines, use Bastille\'s -n flag (example: bastille -n).\n"; - - -# If the user has specified not to show the disclaimer, or -# the .bastille_disclaimer file already exists, then return - if( ( $nodisclaim ) || -e $nodisclaim_file ) { return 1; } - -# otherwise, show the disclaimer - print ($DISCLAIMER); - -# there is a response - my $touch = &getGlobal('BIN', "touch"); - my $retVal = system("$touch $nodisclaim_file"); - if( $retVal != 0 ) { - &ErrorLog ( &getGlobal('ERROR','disclaimer')); - } -} # showDisclaimer - - - - -################################################################ -# &systemCall -#Function used by exported methods B_Backtick and B_system -#to handle the mechanics of system calls. -# This function also manages error handling. -# Input: a system call -# Output: a list containing the status, sstdout and stderr -# of the the system call -# -################################################################ -sub systemCall ($){ - no strict; - local $command=$_[0]; # changed scoping so eval below can read it - - local $SIG{'ALRM'} = sub { die "timeout" }; # This subroutine exits the "eval" below. The program - # can then move on to the next operation. Used "local" - # to avoid name space collision with disclaim alarm. - local $WAIT_TIME=120; # Wait X seconds for system commands - local $commandOutput = ''; - my $errOutput = ''; - eval{ - $errorFile = &getGlobal('BFILE','stderrfile'); - unlink($errorFile); #To make sure we don't mix output - alarm($WAIT_TIME); # start a time-out for command to complete. Some commands hang, and we want to - # fail gracefully. When we call "die" it exits this eval statement - # with a value we use below - $commandOutput = `$command 2> $errorFile`; # run the command and gather its output - my $commandRetVal = ($? >> 8); # find the commands return value - if ($commandRetVal == 0) { - &B_log("ACTION","Executed Command: " . $command . "\n"); - &B_log("ACTION","Command Output: " . $commandOutput . "\n"); - die "success"; - } else { - die "failure"; - }; - }; - - my $exitcode=$@; - alarm(0); # End of the timed operation - - my $cat = &getGlobal("BIN","cat"); - if ( -e $errorFile ) { - $errOutput = `$cat $errorFile`; - } - - if ($exitcode) { # The eval command above will exit with one of the 3 values below - if ($exitcode =~ /timeout/) { - &B_log("WARNING","No response received from $command after $WAIT_TIME seconds.\n" . - "Command Output: " . $commandOutput . "\n"); - return (0,'',''); - } elsif ($exitcode =~ /success/) { - return (1,$commandOutput,$errOutput); - } elsif ($exitcode =~ /failure/) { - return (0,$commandOutput,$errOutput); - } else { - &B_log("FATAL","Unexpected return state from command execution: $command\n" . - "Command Output: " . $commandOutput . "\n"); - } - } -} - -############################################# -# Use this **only** for commands used that are -# intended to test system state and -# not make any system change. Use this in place of the -# prior use of "backticks throughout Bastille -# Handles basic output redirection, but not for stdin -# Input: Command -# Output: Results -############################################# - -sub B_Backtick($) { - my $command=$_[0]; - my $combineOutput=0; - my $stdoutRedir = ""; - my $stderrRedir = ""; - my $echo = &getGlobal('BIN','echo'); - - if (($command =~ s/2>&1//) or - (s/>&2//)){ - $combineOutput=1; - } - if ($command =~ s/>\s*([^>\s])+// ) { - $stdoutRedir = $1; - } - if ($command =~ s/2>\s*([^>\s])+// ) { - $stderrRedir = $1; - } - - my ($ranFine, $stdout, $stderr) = &systemCall($command); - if ($ranFine) { - &B_log("DEBUG","Command: $command succeeded for test with output: $stdout , ". - "and stderr: $stderr"); - } else { - &B_log("DEBUG","Command: $command failed for test with output: $stdout , ". - "and stderr: $stderr"); - } - if ($combineOutput) { - $stdout .= $stderr; - $stderr = $stdout; #these should be the same - } - if ($stdoutRedir ne "") { - system("$echo \'$stdout\' > $stdoutRedir"); - } - if ($stderrRedir ne "") { - system("$echo \'$stderr\' > $stderrRedir"); - } - return $stdout; -} - -#################################################################### -# &B_System($command,$revertcommand); -# This function executes a command, then places the associated -# revert command in revert file. It takes two parameters, the -# command and the command that reverts that command. -# -# uses ActionLog and ErrorLog for logging purposes. -################################################################### -sub B_System ($$) { - my ($command,$revertcmd)=@_; - - my ($ranFine, $stdout, $stderr) = &systemCall($command); - if ($ranFine) { - &B_revert_log ("$revertcmd \n"); - if ($stderr ne '' ) { - &B_log("ACTION",$command . "suceeded with STDERR: " . - $stderr . "\n"); - } - return 1; - } else { - my $warningString = "Command Failed: " . $command . "\n" . - "Command Output: " . $stdout . "\n"; - if ($stderr ne '') { - $warningString .= "Error message: " . $stderr; - } - &B_log("WARNING", $warningString); - return 0; - } -} - - -########################################################################### -# &isProcessRunning($procPattern); -# -# If called in scalar context this subroutine will return a 1 if the -# pattern specified can be matched against the process table. It will -# return a 0 otherwise. -# If called in the list context this subroutine will return the list -# of processes which matched the pattern supplied -# -# scalar return values: -# 0: pattern not in process table -# 1: pattern is in process table -# -# list return values: -# proc lines from the process table if they are found -########################################################################### -sub isProcessRunning($) { - - my $procPattern= $_[0]; - my $ps = &getGlobal('BIN',"ps"); - - my $isRunning=0; - # process table. - my @psTable = `$ps -elf`; - # list of processes that match the $procPattern - my @procList; - foreach my $process (@psTable) { - if($process =~ $procPattern) { - $isRunning = 1; - push @procList, $process . "\n"; - } - } - - &B_log("DEBUG","$procPattern search yielded $isRunning\n\n"); - # if this subroutine was called in scalar context - if( ! wantarray ) { - return $isRunning; - } - - return @procList; -} - - -########################################################################### -# &checkProcsForService($service); -# -# Checks if the given service is running by analyzing the process table. -# This is a helper function to checkServiceOnLinux and checkServiceOnHP -# -# Return values: -# SECURE_CANT_CHANGE() if the service is off -# INCONSISTENT() if the state of the service cannot be determined -# -# Mostly used in "check service" direct-return context, but added option use. -# to ignore warning if a check for a service ... where a found service doesn't -# have direct security problems. -# -########################################################################### -sub checkProcsForService ($;$) { - my $service=$_[0]; - my $ignore_warning=$_[1]; - - my @psnames=@{ &getGlobal('PROCESS',$service)}; - - my @processes; - # inetd services don't have a separate process - foreach my $psname (@psnames) { - my @procList = &isProcessRunning($psname); - if(@procList >= 0){ - splice @processes,$#processes+1,0,@procList; - } - } - - if($#processes >= 0){ - if ((defined($ignore_warning)) and ($ignore_warning eq "ignore_warning")) { - &B_log("WARNING","The following processes were still running even though " . - "the corresponding service appears to be turned off. Bastille " . - "question and action will be skipped.\n\n" . - "@processes\n\n"); - # processes were still running, service is not off, but we don't know how - # to configure it so we skip the question - return INCONSISTENT(); - } else { - return NOTSECURE_CAN_CHANGE(); # In the case we're ignoring the warning, - # ie: checking to make *sure* a process - # is running, the answer isn't inconsistent - } - } else { - &B_log("DEBUG","$service is off. Found no processes running on the system."); - # no processes, so service is off - return SECURE_CANT_CHANGE(); - } - # Can't determine the state of the service by looking at the processes, - # so return INCONSISTENT(). - return INCONSISTENT(); -} - -########################################################################### -# B_parse_fstab() -# -# Search the filesystem table for a specific mount point. -# -# scalar return value: -# The line form the table that matched the mount point, or the null string -# if no match was found. -# -# list return value: -# A list of parsed values from the line of the table that matched, with -# element [3] containing a reference to a hash of the mount options. The -# keys are: acl, dev, exec, rw, suid, sync, or user. The value of each key -# can be either 0 or 1. To access the hash, use code similar to this: -# %HashResult = %{(&B_parse_fstab($MountPoint))[3]}; -# -########################################################################### - -sub B_parse_fstab($) -{ - my $name = shift; - my $file = &getGlobal('FILE','fstab'); - my ($enable, $disable, $infile); - my @lineopt; - my $retline = ""; - my @retlist = (); - - unless (open FH, $file) { - &B_log('ERROR',"B_parse_fstab couldn't open fstab file at path $file.\n"); - return 0; - } - while (<FH>) { - s/\#.*//; - next unless /\S/; - @retlist = split; - next unless $retlist[1] eq $name; - $retline .= $_; - if (wantarray) { - my $option = { # initialize to defaults - acl => 0, # for ext2, etx3, reiserfs - dev => 1, - exec => 1, - rw => 1, - suid => 1, - sync => 0, - user => 0, - }; - - my @lineopt = split(',',$retlist[3]); - foreach my $entry (@lineopt) { - if ($entry eq 'acl') { - $option->{'acl'} = 1; - } - elsif ($entry eq 'nodev') { - $option->{'dev'} = 0; - } - elsif ($entry eq 'noexec') { - $option->{'exec'} = 0; - } - elsif ($entry eq 'ro') { - $option->{'rw'} = 0; - } - elsif ($entry eq 'nosuid') { - $option->{'suid'} = 0; - } - elsif ($entry eq 'sync') { - $option->{'sync'} = 1; - } - elsif ($entry eq 'user') { - $option->{'user'} = 1; - } - } - $retlist[3]= $option; - } - last; - } - - if (wantarray) - { - return @retlist; - } - else - { - return $retline; - } - -} - - -########################################################################### -# B_parse_mtab() -# -# This routine returns a hash of devices and their mount points from mtab, -# simply so you can get a list of mounted filesystems. -# -########################################################################### - -sub B_parse_mtab -{ - my $mountpoints; - open(MTAB,&getGlobal('FILE','mtab')); - while(my $mtab_line = <MTAB>) { - #test if it's a device - if ($mtab_line =~ /^\//) - { - #parse out device and mount point - $mtab_line =~ /^(\S+)\s+(\S+)/; - $mountpoints->{$1} = $2; - } - } - return $mountpoints; -} - - -########################################################################### -# B_is_rpm_up_to_date() -# -# -########################################################################### - -sub B_is_rpm_up_to_date(@) -{ - my($nameB,$verB,$relB,$epochB) = @_; - my $installedpkg = $nameB; - - if ($epochB =~ /(none)/) { - $epochB = 0; - } - - my $rpmA = `rpm -q --qf '%{VERSION}-%{RELEASE}-%{EPOCH}\n' $installedpkg`; - my $nameA = $nameB; - my ($verA,$relA,$epochA); - - my $retval; - - # First, if the RPM isn't installed, let's handle that. - if ($rpmA =~ /is not installed/) { - $retval = -1; - return $retval; - } - else { - # Next, let's try to parse the EVR information without as few - # calls as possible to rpm. - if ($rpmA =~ /([^-]+)-([^-]+)-([^-]+)$/) { - $verA = $1; - $relA = $2; - $epochA = $3; - } - else { - $nameA = `rpm -q --qf '%{NAME}' $installedpkg`; - $verA = `rpm -q --qf '%{VERSION}' $installedpkg`; - $relA = `rpm -q --qf '%{RELEASE}' $installedpkg`; - $epochA = `rpm -q --qf '%{EPOCH}' $installedpkg`; - } - } - - # Parse "none" as 0. - if ($epochA =~ /(none)/) { - $epochA = 0; - } - - # Handle the case where only one of them is zero. - if ($epochA == 0 xor $epochB == 0) - { - if ($epochA != 0) - { - $retval = 1; - } - else - { - $retval = 0; - } - } - else - { - # ...otherwise they are either both 0 or both non-zero and - # so the situation isn't trivial. - - # Check epoch first - highest epoch wins. - my $rpmcmp = &cmp_vers_part($epochA, $epochB); - #print "epoch rpmcmp is $rpmcmp\n"; - if ($rpmcmp > 0) - { - $retval = 1; - } - elsif ($rpmcmp < 0) - { - $retval = 0; - } - else - { - # Epochs were the same. Check Version now. - $rpmcmp = &cmp_vers_part($verA, $verB); - #print "epoch rpmcmp is $rpmcmp\n"; - if ($rpmcmp > 0) - { - $retval = 1; - } - elsif ($rpmcmp < 0) - { - $retval = 0; - } - else - { - # Versions were the same. Check Release now. - my $rpmcmp = &cmp_vers_part($relA, $relB); - #print "epoch rpmcmp is $rpmcmp\n"; - if ($rpmcmp >= 0) - { - $retval = 1; - } - elsif ($rpmcmp < 0) - { - $retval = 0; - } - } - } - } - return $retval; -} - -################################################# -# Helper function for B_is_rpm_up_to_date() -################################################# - -#This cmp_vers_part function taken from Kirk Bauer's Autorpm. -# This version comparison code was sent in by Robert Mitchell and, although -# not yet perfect, is better than the original one I had. He took the code -# from freshrpms and did some mods to it. Further mods by Simon Liddington -# <sjl96v@ecs.soton.ac.uk>. -# -# Splits string into minors on . and change from numeric to non-numeric -# characters. Minors are compared from the beginning of the string. If the -# minors are both numeric then they are numerically compared. If both minors -# are non-numeric and a single character they are alphabetically compared, if -# they are not a single character they are checked to be the same if the are not -# the result is unknown (currently we say the first is newer so that we have -# a choice to upgrade). If one minor is numeric and one non-numeric then the -# numeric one is newer as it has a longer version string. -# We also assume that (for example) .15 is equivalent to 0.15 - -sub cmp_vers_part($$) { - my($va, $vb) = @_; - my(@va_dots, @vb_dots); - my($a, $b); - my($i); - - if ($vb !~ /^pre/ and $va =~ s/^pre(\d+.*)$/$1/) { - if ($va eq $vb) { return -1; } - } elsif ($va !~ /^pre/ and $vb =~ s/^pre(\d+.*)$/$1/) { - if ($va eq $vb) { return 1; } - } - - @va_dots = split(/\./, $va); - @vb_dots = split(/\./, $vb); - - $a = shift(@va_dots); - $b = shift(@vb_dots); - # We also assume that (for example) .15 is equivalent to 0.15 - if ($a eq '' && $va ne '') { $a = "0"; } - if ($b eq '' && $vb ne '') { $b = "0"; } - while ((defined($a) && $a ne '') || (defined($b) && $b ne '')) { - # compare each minor from left to right - if ((not defined($a)) || ($a eq '')) { return -1; } # the longer version is newer - if ((not defined($b)) || ($b eq '')) { return 1; } - if ($a =~ /^\d+$/ && $b =~ /^\d+$/) { - # I have changed this so that when the two strings are numeric, but one or both - # of them start with a 0, then do a string compare - Kirk Bauer - 5/28/99 - if ($a =~ /^0/ or $b =~ /^0/) { - # We better string-compare so that netscape-4.6 is newer than netscape-4.08 - if ($a ne $b) {return ($a cmp $b);} - } - # numeric compare - if ($a != $b) { return $a <=> $b; } - } elsif ($a =~ /^\D+$/ && $b =~ /^\D+$/) { - # string compare - if (length($a) == 1 && length($b) == 1) { - # only minors with one letter seem to be useful for versioning - if ($a ne $b) { return $a cmp $b; } - } elsif (($a cmp $b) != 0) { - # otherwise we should at least check they are the same and if not say unknown - # say newer for now so at least we get choice whether to upgrade or not - return -1; - } - } elsif ( ($a =~ /^\D+$/ && $b =~ /^\d+$/) || ($a =~ /^\d+$/ && $b =~ /^\D+$/) ) { - # if we get a number in one and a word in another the one with a number - # has a longer version string - if ($a =~ /^\d+$/) { return 1; } - if ($b =~ /^\d+$/) { return -1; } - } else { - # minor needs splitting - $a =~ /\d+/ || $a =~ /\D+/; - # split the $a minor into numbers and non-numbers - my @va_bits = ($`, $&, $'); - $b =~ /\d+/ || $b =~ /\D+/; - # split the $b minor into numbers and non-numbers - my @vb_bits = ($`, $&, $'); - for ( my $j=2; $j >= 0; $j--) { - if ($va_bits[$j] ne '') { unshift(@va_dots,$va_bits[$j]); } - if ($vb_bits[$j] ne '') { unshift(@vb_dots,$vb_bits[$j]); } - } - } - $a = shift(@va_dots); - $b = shift(@vb_dots); - } - return 0; -} - -1; - diff --git a/recipes-security/bastille/files/AccountPermission.pm b/recipes-security/bastille/files/AccountPermission.pm deleted file mode 100644 index cfbaab1..0000000 --- a/recipes-security/bastille/files/AccountPermission.pm +++ /dev/null @@ -1,1060 +0,0 @@ -package Bastille::API::AccountPermission; -use strict; - -use Bastille::API; - -use Bastille::API::HPSpecific; - -require Exporter; -our @ISA = qw(Exporter); -our @EXPORT_OK = qw( -B_chmod -B_chmod_if_exists -B_chown -B_chown_link -B_chgrp -B_chgrp_link -B_userdel -B_groupdel -B_remove_user_from_group -B_check_owner_group -B_is_unowned_file -B_is_ungrouped_file -B_check_permissions -B_permission_test -B_find_homes -B_is_executable -B_is_suid -B_is_sgid -B_get_user_list -B_get_group_list -B_remove_suid -); -our @EXPORT = @EXPORT_OK; - -########################################################################### -# &B_chmod ($mode, $file) sets the mode of $file to $mode. $mode must -# be stored in octal, so if you want to give mode 700 to /etc/aliases, -# you need to use: -# -# &B_chmod ( 0700 , "/etc/aliases"); -# -# where the 0700 denotes "octal 7-0-0". -# -# &B_chmod ($mode_changes,$file) also respects the symbolic methods of -# changing file permissions, which are often what question authors are -# really seeking. -# -# &B_chmod ("u-s" , "/bin/mount") -# or -# &B_chmod ("go-rwx", "/bin/mount") -# -# -# &B_chmod respects GLOBAL_LOGONLY and uses -# &B_revert_log used to insert a shell command that will return -# the permissions to the pre-Bastille state. -# -# B_chmod allow for globbing now, as of 1.2.0. JJB -# -########################################################################## - - -sub B_chmod($$) { - my ($new_perm,$file_expr)=@_; - my $old_perm; - my $old_perm_raw; - my $new_perm_formatted; - my $old_perm_formatted; - - my $retval=1; - - my $symbolic = 0; - my ($chmod_noun,$add_remove,$capability) = (); - # Handle symbolic possibilities too - if ($new_perm =~ /([ugo]+)([+-]{1})([rwxst]+)/) { - $symbolic = 1; - $chmod_noun = $1; - $add_remove = $2; - $capability = $3; - } - - my $file; - my @files = glob ($file_expr); - - foreach $file (@files) { - - # Prepend global prefix, but save the original filename for B_backup_file - my $original_file=$file; - - # Store the old permissions so that we can log them. - unless (stat $file) { - &B_log("ERROR","Couldn't stat $original_file from $old_perm to change permissions\n"); - next; - } - - $old_perm_raw=(stat(_))[2]; - $old_perm= (($old_perm_raw/512) % 8) . - (($old_perm_raw/64) % 8) . - (($old_perm_raw/8) % 8) . - ($old_perm_raw % 8); - - # If we've gone symbolic, calculate the new permissions in octal. - if ($symbolic) { - # - # We calculate the new permissions by applying a bitmask to - # the current permissions, by OR-ing (for +) or XOR-ing (for -). - # - # We create this mask by first calculating a perm_mask that forms - # the right side of this, then multiplying it by 8 raised to the - # appropriate power to affect the correct digit of the octal mask. - # This means that we raise 8 to the power of 0,1,2, or 3, based on - # the noun of "other","group","user", or "suid/sgid/sticky". - # - # Actually, we handle multiple nouns by summing powers of 8. - # - # The only tough part is that we have to handle suid/sgid/sticky - # differently. - # - - # We're going to calculate a mask to OR or XOR with the current - # file mode. This mask is $mask. We calculate this by calculating - # a sum of powers of 8, corresponding to user/group/other, - # multiplied with a $premask. The $premask is simply the - # corresponding bitwise expression of the rwx bits. - # - # To handle SUID, SGID or sticky in the simplest way possible, we - # simply add their values to the $mask first. - - my $perm_mask = 00; - my $mask = 00; - - # Check for SUID, SGID or sticky as these are exceptional. - if ($capability =~ /s/) { - if ($chmod_noun =~ /u/) { - $mask += 04000; - } - if ($chmod_noun =~ /g/) { - $mask += 02000; - } - } - if ($capability =~ /t/) { - $mask += 01000; - } - - # Now handle the normal attributes - if ($capability =~ /[rwx]/) { - if ($capability =~ /r/) { - $perm_mask |= 04; - } - if ($capability =~ /w/) { - $perm_mask |= 02; - } - if ($capability =~ /x/) { - $perm_mask |= 01; - } - - # Now figure out which 3 bit octal digit we're affecting. - my $power = 0; - if ($chmod_noun =~ /u/) { - $mask += $perm_mask * 64; - } - if ($chmod_noun =~ /g/) { - $mask += $perm_mask * 8; - } - if ($chmod_noun =~ /o/) { - $mask += $perm_mask * 1; - } - } - # Now apply the mask to get the new permissions - if ($add_remove eq '+') { - $new_perm = $old_perm_raw | $mask; - } - elsif ($add_remove eq '-') { - $new_perm = $old_perm_raw & ( ~($mask) ); - } - } - - # formating for simple long octal output of the permissions in string form - $new_perm_formatted=sprintf "%5lo",$new_perm; - $old_perm_formatted=sprintf "%5lo",$old_perm_raw; - - &B_log("ACTION","change permissions on $original_file from $old_perm_formatted to $new_perm_formatted\n"); - - &B_log("ACTION", "chmod $new_perm_formatted,\"$original_file\";\n"); - - # Change the permissions on the file - - if ( -e $file ) { - unless ($GLOBAL_LOGONLY) { - $retval=chmod $new_perm,$file; - if($retval){ - # if the distribution is HP-UX then the modifications should - # also be made to the IPD (installed product database) - if(&GetDistro =~ "^HP-UX"){ - &B_swmodify($file); - } - # making changes revert-able - &B_revert_log(&getGlobal('BIN', "chmod") . " $old_perm $file\n"); - } - } - unless ($retval) { - &B_log("ERROR","Couldn't change permissions on $original_file from $old_perm_formatted to $new_perm_formatted\n"); - $retval=0; - } - } - else { - &B_log("ERROR", "chmod: File $original_file doesn't exist!\n"); - $retval=0; - } - } - - $retval; - -} - -########################################################################### -# &B_chmod_if_exists ($mode, $file) sets the mode of $file to $mode *if* -# $file exists. $mode must be stored in octal, so if you want to give -# mode 700 to /etc/aliases, you need to use: -# -# &B_chmod_if_exists ( 0700 , "/etc/aliases"); -# -# where the 0700 denotes "octal 7-0-0". -# -# &B_chmod_if_exists respects GLOBAL_LOGONLY and uses -# &B_revert_log to reset the permissions of the file. -# -# B_chmod_if_exists allow for globbing now, as of 1.2.0. JJB -# -########################################################################## - - -sub B_chmod_if_exists($$) { - my ($new_perm,$file_expr)=@_; - # If $file_expr has a glob character, pass it on (B_chmod won't complain - # about nonexistent files if given a glob pattern) - if ( $file_expr =~ /[\*\[\{]/ ) { # } just to match open brace for vi - &B_log("ACTION","Running chmod $new_perm $file_expr"); - return(&B_chmod($new_perm,$file_expr)); - } - # otherwise, test for file existence - if ( -e $file_expr ) { - &B_log("ACTION","File exists, running chmod $new_perm $file_expr"); - return(&B_chmod($new_perm,$file_expr)); - } -} - -########################################################################### -# &B_chown ($uid, $file) sets the owner of $file to $uid, like this: -# -# &B_chown ( 0 , "/etc/aliases"); -# -# &B_chown respects $GLOBAL_LOGONLY and uses -# &B_revert_log to insert a shell command that will return -# the file/directory owner to the pre-Bastille state. -# -# Unlike Perl, we've broken the chown function into B_chown/B_chgrp to -# make error checking simpler. -# -# As of 1.2.0, this now supports file globbing. JJB -# -########################################################################## - - -sub B_chown($$) { - my ($newown,$file_expr)=@_; - my $oldown; - my $oldgown; - - my $retval=1; - - my $file; - my @files = glob($file_expr); - - foreach $file (@files) { - - # Prepend prefix, but save original filename - my $original_file=$file; - - $oldown=(stat $file)[4]; - $oldgown=(stat $file)[5]; - - &B_log("ACTION","change ownership on $original_file from $oldown to $newown\n"); - &B_log("ACTION","chown $newown,$oldgown,\"$original_file\";\n"); - if ( -e $file ) { - unless ($GLOBAL_LOGONLY) { - # changing the files owner using perl chown function - $retval = chown $newown,$oldgown,$file; - if($retval){ - # if the distribution is HP-UX then the modifications should - # also be made to the IPD (installed product database) - if(&GetDistro =~ "^HP-UX"){ - &B_swmodify($file); - } - # making ownership change revert-able - &B_revert_log(&getGlobal('BIN', "chown") . " $oldown $file\n"); - } - } - unless ($retval) { - &B_log("ERROR","Couldn't change ownership to $newown on file $original_file\n"); - } - } - else { - &B_log("ERROR","chown: File $original_file doesn't exist!\n"); - $retval=0; - } - } - - $retval; -} - -########################################################################### -# &B_chown_link just like &B_chown but one exception: -# if the input file is a link it will not change the target's ownship, it only change the link itself's ownship -########################################################################### -sub B_chown_link($$){ - my ($newown,$file_expr)=@_; - my $chown = &getGlobal("BIN","chown"); - my @files = glob($file_expr); - my $retval = 1; - - foreach my $file (@files) { - # Prepend prefix, but save original filename - my $original_file=$file; - my $oldown=(stat $file)[4]; - my $oldgown=(stat $file)[5]; - - &B_log("ACTION","change ownership on $original_file from $oldown to $newown\n"); - &B_log("ACTION","chown -h $newown,\"$original_file\";\n"); - if ( -e $file ) { - unless ($GLOBAL_LOGONLY) { - `$chown -h $newown $file`; - $retval = ($? >> 8); - if($retval == 0 ){ - # if the distribution is HP-UX then the modifications should - # also be made to the IPD (installed product database) - if(&GetDistro =~ "^HP-UX"){ - &B_swmodify($file); - } - # making ownership change revert-able - &B_revert_log("$chown -h $oldown $file\n"); - } - } - unless ( ! $retval) { - &B_log("ERROR","Couldn't change ownership to $newown on file $original_file\n"); - } - } - else { - &B_log("ERROR","chown: File $original_file doesn't exist!\n"); - $retval=0; - } - } -} - - -########################################################################### -# &B_chgrp ($gid, $file) sets the group owner of $file to $gid, like this: -# -# &B_chgrp ( 0 , "/etc/aliases"); -# -# &B_chgrp respects $GLOBAL_LOGONLY and uses -# &B_revert_log to insert a shell command that will return -# the file/directory group to the pre-Bastille state. -# -# Unlike Perl, we've broken the chown function into B_chown/B_chgrp to -# make error checking simpler. -# -# As of 1.2.0, this now supports file globbing. JJB -# -########################################################################## - - -sub B_chgrp($$) { - my ($newgown,$file_expr)=@_; - my $oldown; - my $oldgown; - - my $retval=1; - - my $file; - my @files = glob($file_expr); - - foreach $file (@files) { - - # Prepend global prefix, but save original filename for &B_backup_file - my $original_file=$file; - - $oldown=(stat $file)[4]; - $oldgown=(stat $file)[5]; - - &B_log("ACTION", "Change group ownership on $original_file from $oldgown to $newgown\n"); - &B_log("ACTION", "chown $oldown,$newgown,\"$original_file\";\n"); - if ( -e $file ) { - unless ($GLOBAL_LOGONLY) { - # changing the group for the file/directory - $retval = chown $oldown,$newgown,$file; - if($retval){ - # if the distribution is HP-UX then the modifications should - # also be made to the IPD (installed product database) - if(&GetDistro =~ "^HP-UX"){ - &B_swmodify($file); - } - &B_revert_log(&getGlobal('BIN', "chgrp") . " $oldgown $file\n"); - } - } - unless ($retval) { - &B_log("ERROR","Couldn't change ownership to $newgown on file $original_file\n"); - } - } - else { - &B_log("ERROR","chgrp: File $original_file doesn't exist!\n"); - $retval=0; - } - } - - $retval; -} - -########################################################################### -# &B_chgrp_link just like &B_chgrp but one exception: -# if the input file is a link -# it will not change the target's ownship, it only change the link itself's ownship -########################################################################### -sub B_chgrp_link($$) { - my ($newgown,$file_expr)=@_; - my $chgrp = &getGlobal("BIN","chgrp"); - my @files = glob($file_expr); - my $retval=1; - - foreach my $file (@files) { - # Prepend prefix, but save original filename - my $original_file=$file; - my $oldgown=(stat $file)[5]; - - &B_log("ACTION","change group ownership on $original_file from $oldgown to $newgown\n"); - &B_log("ACTION","chgrp -h $newgown \"$original_file\";\n"); - if ( -e $file ) { - unless ($GLOBAL_LOGONLY) { - # do not follow link with option -h - `$chgrp -h $newgown $file`; - $retval = ($? >> 8); - if($retval == 0 ){ - # if the distribution is HP-UX then the modifications should - # also be made to the IPD (installed product database) - if(&GetDistro =~ "^HP-UX"){ - &B_swmodify($file); - } - # making ownership change revert-able - &B_revert_log("$chgrp" . " -h $oldgown $file\n"); - } - } - unless (! $retval) { - &B_log("ERROR","Couldn't change group ownership to $newgown on file $original_file\n"); - } - } - else { - &B_log("ERROR","chgrp: File $original_file doesn't exist!\n"); - $retval=0; - } - } -} - -########################################################################### -# B_userdel($user) removes $user from the system, chmoding her home -# directory to 000, root:root owned, and removes the user from all -# /etc/passwd, /etc/shadow and /etc/group lines. -# -# In the future, we may also choose to make a B_lock_account routine. -# -# This routine depends on B_remove_user_from_group. -########################################################################### - -sub B_userdel($) { - - my $user_to_remove = $_[0]; - - if (&GetDistro =~ /^HP-UX/) { - return 0; - - # Not yet suported on HP-UX, where we'd need to support - # the TCB files and such. - } - - # - # First, let's chmod/chown/chgrp the user's home directory. - # - - # Get the user's home directory from /etc/passwd - if (open PASSWD,&getGlobal('FILE','passwd')) { - my @lines=<PASSWD>; - close PASSWD; - - # Get the home directory - my $user_line = grep '^\s*$user_to_remove\s*:',@lines; - my $home_directory = (split /\s*:\s*/,$user_line)[5]; - - # Chmod that home dir to 0000,owned by uid 0, gid 0. - if (&B_chmod_if_exists(0000,$home_directory)) { - &B_chown(0,$home_directory); - &B_chgrp(0,$home_directory); - } - } - else { - &B_log('ERROR',"B_userdel couldn't open the passwd file to remove a user."); - return 0; - } - - # - # Next find out what groups the user is in, so we can call - # B_remove_user_from_group($user,$group) - # - # TODO: add this to the helper functions for the test suite. - # - - my @groups = (); - - # Parse /etc/group, looking for our user. - if (open GROUP,&getGlobal('FILE','group')) { - my @lines = <GROUP>; - close GROUP; - - foreach my $line (@lines) { - - # Parse the line -- first field is group, last is users in group. - if ($line =~ /([^\#^:]+):[^:]+:[^:]+:(.*)/) { - my $group = $1; - my $users_section = $2; - - # Get the user list and check if our user is in it. - my @users = split /\s*,\s*/,$users_section; - foreach my $user (@users) { - if ($user_to_remove eq $user) { - push @groups,$group; - last; - } - } - } - } - } - - # Now remove the user from each of those groups. - foreach my $group (@groups) { - &B_remove_user_from_group($user_to_remove,$group); - } - - # Remove the user's /etc/passwd and /etc/shadow lines - &B_delete_line(&getGlobal('FILE','passwd'),"^$user_to_remove\\s*:"); - &B_delete_line(&getGlobal('FILE','shadow'),"^$user_to_remove\\s*:"); - - - # - # We should delete the user's group as well, if it's a single-user group. - # - if (open ETCGROUP,&getGlobal('FILE','group')) { - my @group_lines = <ETCGROUP>; - close ETCGROUP; - chomp @group_lines; - - if (grep /^$user_to_remove\s*:[^:]*:[^:]*:\s*$/,@group_lines > 0) { - &B_groupdel($user_to_remove); - } - } - -} - -########################################################################### -# B_groupdel($group) removes $group from /etc/group. -########################################################################### - -sub B_groupdel($) { - - my $group = $_[0]; - - # First read /etc/group to make sure the group is in there. - if (open GROUP,&getGlobal('FILE','group')) { - my @lines=<GROUP>; - close GROUP; - - # Delete the line in /etc/group if present - if (grep /^$group:/,@lines > 0) { - # The group is named in /etc/group - &B_delete_line(&getGlobal('FILE','group'),"^$group:/"); - } - } - -} - - -########################################################################### -# B_remove_user_from_group($user,$group) removes $user from $group, -# by modifying $group's /etc/group line, pulling the user out. This -# uses B_chunk_replace thrice to replace these patterns: -# -# ":\s*$user\s*," --> ":" -# ",\s*$user" -> "" -# -########################################################################### - -sub B_remove_user_from_group($$) { - - my ($user_to_remove,$group) = @_; - - # - # We need to find the line from /etc/group that defines the group, parse - # it, and put it back together without this user. - # - - # Open the group file - unless (open GROUP,&getGlobal('FILE','group')) { - &B_log('ERROR',"&B_remove_user_from_group couldn't read /etc/group to remove $user_to_remove from $group.\n"); - return 0; - } - my @lines = <GROUP>; - close GROUP; - chomp @lines; - - # - # Read through the lines to find the one we care about. We'll construct a - # replacement and then use B_replace_line to make the switch. - # - - foreach my $line (@lines) { - - if ($line =~ /^\s*$group\s*:/) { - - # Parse this line. - my @group_entries = split ':',$line; - my @users = split ',',($group_entries[3]); - - # Now, recreate it. - my $first_user = 1; - my $group_line = $group_entries[0] . ':' . $group_entries[1] . ':' . $group_entries[2] . ':'; - - # Add every user except the one we're removing. - foreach my $user (@users) { - - # Remove whitespace. - $user =~ s/\s+//g; - - if ($user ne $user_to_remove) { - # Add the user to the end of the line, prefacing - # it with a comma if it's not the first user. - - if ($first_user) { - $group_line .= "$user"; - $first_user = 0; - } - else { - $group_line .= ",$user"; - } - } - } - - # The line is now finished. Replace the original line. - $group_line .= "\n"; - &B_replace_line(&getGlobal('FILE','group'),"^\\s*$group\\s*:",$group_line); - } - - } - return 1; -} - -########################################################################### -# &B_check_owner_group($$$) -# -# Checks if the given file has the given owner and/or group. -# If the given owner is "", checks group only. -# If the given group is "", checks owner only. -# -# return values: -# 1: file has the given owner and/or group -# or file exists, and both the given owner and group are "" -# 0: file does not has the given owner or group -# or file does not exists -############################################################################ - -sub B_check_owner_group ($$$){ - my ($fileName, $owner, $group) = @_; - - if (-e $fileName) { - my @junk=stat ($fileName); - my $uid=$junk[4]; - my $gid=$junk[5]; - - # Check file owner - if ($owner ne "") { - if (getpwnam($owner) != $uid) { - return 0; - } - } - - # Check file group - if ($group ne "") { - if (getgrnam($group) != $gid) { - return 0; - } - } - - return 1; - } - else { - # Something is wrong if the file not exist - return 0; - } -} - -########################################################################## -# this subroutine will test whether the given file is unowned -########################################################################## -sub B_is_unowned_file($) { - my $file =$_; - my $uid = (stat($file))[4]; - my $uname = (getpwuid($uid))[0]; - if ( $uname =~ /.+/ ) { - return 1; - } - return 0; -} - -########################################################################## -# this subroutine will test whether the given file is ungrouped -########################################################################## -sub B_is_ungrouped_file($){ - my $file =$_; - my $gid = (stat($file))[5]; - my $gname = (getgrgid($gid))[0]; - if ( $gname =~ /.+/ ) { - return 1; - } - return 0; -} - - - - -########################################################################### -# &B_check_permissions($$) -# -# Checks if the given file has the given permissions or stronger, where we -# define stronger as "less accessible." The file argument must be fully -# qualified, i.e. contain the absolute path. -# -# return values: -# 1: file has the given permissions or better -# 0: file does not have the given permsssions -# undef: file permissions cannot be determined -########################################################################### - -sub B_check_permissions ($$){ - my ($fileName, $reqdPerms) = @_; - my $filePerms; # actual permissions - - - if (-e $fileName) { - if (stat($fileName)) { - $filePerms = (stat($fileName))[2] & 07777; - } - else { - &B_log ("ERROR", "Can't stat $fileName.\n"); - return undef; - } - } - else { - # If the file does not exist, permissions are as good as they can get. - return 1; - } - - # - # We can check whether the $filePerms are as strong by - # bitwise ANDing them with $reqdPerms and checking if the - # result is still equal to $filePerms. If it is, the - # $filePerms are strong enough. - # - if ( ($filePerms & $reqdPerms) == $filePerms ) { - return 1; - } - else { - return 0; - } - -} - -########################################################################## -# B_permission_test($user, $previlege,$file) -# $user can be -# "owner" -# "group" -# "other" -# $previlege can be: -# "r" -# "w" -# "x" -# "suid" -# "sgid" -# "sticky" -# if previlege is set to suid or sgid or sticky, then $user can be empty -# this sub routine test whether the $user has the specified previlige to $file -########################################################################## - -sub B_permission_test($$$){ - my ($user, $previlege, $file) = @_; - - if (-e $file ) { - my $mode = (stat($file))[2]; - my $bitpos; - # bitmap is | suid sgid sticky | rwx | rwx | rwx - if ($previlege =~ /suid/ ) { - $bitpos = 11; - } - elsif ($previlege =~ /sgid/ ) { - $bitpos = 10; - } - elsif ($previlege =~ /sticky/ ) { - $bitpos = 9; - } - else { - if ( $user =~ /owner/) { - if ($previlege =~ /r/) { - $bitpos = 8; - } - elsif ($previlege =~ /w/) { - $bitpos =7; - } - elsif ($previlege =~ /x/) { - $bitpos =6; - } - else { - return 0; - } - } - elsif ( $user =~ /group/) { - if ($previlege =~ /r/) { - $bitpos =5; - } - elsif ($previlege =~ /w/) { - $bitpos =4; - } - elsif ($previlege =~ /x/) { - $bitpos =3; - } - else { - return 0; - } - } - elsif ( $user =~ /other/) { - if ($previlege =~ /r/) { - $bitpos =2; - } - elsif ($previlege =~ /w/) { - $bitpos =1; - } - elsif ($previlege =~ /x/) { - $bitpos =0; - } - else { - return 0; - } - } - else { - return 0; - } - } - $mode /= 2**$bitpos; - if ($mode % 2) { - return 1; - } - return 0; - } -} - -########################################################################## -# this subroutine will return a list of home directory -########################################################################## -sub B_find_homes(){ - # find loginable homes - my $logins = &getGlobal("BIN","logins"); - my @lines = `$logins -ox`; - my @homes; - foreach my $line (@lines) { - chomp $line; - my @data = split /:/, $line; - if ($data[7] =~ /PS/ && $data[5] =~ /home/) { - push @homes, $data[5]; - } - } - return @homes; -} - - -########################################################################### -# B_is_executable($) -# -# This routine reports on whether a file is executable by the current -# process' effective UID. -# -# scalar return values: -# 0: file is not executable -# 1: file is executable -# -########################################################################### - -sub B_is_executable($) -{ - my $name = shift; - my $executable = 0; - - if (-x $name) { - $executable = 1; - } - return $executable; -} - -########################################################################### -# B_is_suid($) -# -# This routine reports on whether a file is Set-UID and owned by root. -# -# scalar return values: -# 0: file is not SUID root -# 1: file is SUID root -# -########################################################################### - -sub B_is_suid($) -{ - my $name = shift; - - my @FileStatus = stat($name); - my $IsSuid = 0; - - if (-u $name) #Checks existence and suid - { - if($FileStatus[4] == 0) { - $IsSuid = 1; - } - } - - return $IsSuid; -} - -########################################################################### -# B_is_sgid($) -# -# This routine reports on whether a file is SGID and group owned by -# group root (gid 0). -# -# scalar return values: -# 0: file is not SGID root -# 1: file is SGID root -# -########################################################################### - -sub B_is_sgid($) -{ - my $name = shift; - - my @FileStatus = stat($name); - my $IsSgid = 0; - - if (-g $name) #checks existence and sgid - { - if($FileStatus[5] == 0) { - $IsSgid = 1; - } - } - - return $IsSgid; -} - -########################################################################### -# B_get_user_list() -# -# This routine outputs a list of users on the system. -# -########################################################################### - -sub B_get_user_list() -{ - my @users; - open(PASSWD,&getGlobal('FILE','passwd')); - while(<PASSWD>) { - #Get the users - if (/^([^:]+):/) - { - push (@users,$1); - } - } - return @users; -} - -########################################################################### -# B_get_group_list() -# -# This routine outputs a list of groups on the system. -# -########################################################################### - -sub B_get_group_list() -{ - my @groups; - open(GROUP,&getGlobal('FILE','group')); - while(my $group_line = <GROUP>) { - #Get the groups - if ($group_line =~ /^([^:]+):/) - { - push (@groups,$1); - } - } - return @groups; -} - - -########################################################################### -# &B_remove_suid ($file) removes the suid bit from $file if it -# is set and the file exist. If you would like to remove the suid bit -# from /bin/ping then you need to use: -# -# &B_remove_suid("/bin/ping"); -# -# &B_remove_suid respects GLOBAL_LOGONLY. -# &B_remove_suid uses &B_chmod to make the permission changes -# &B_remove_suid allows for globbing. tyler_e -# -########################################################################### - -sub B_remove_suid($) { - my $file_expr = $_[0]; - - &B_log("ACTION","Removing SUID bit from \"$file_expr\"."); - unless ($GLOBAL_LOGONLY) { - my @files = glob($file_expr); - - foreach my $file (@files) { - # check file existence - if(-e $file){ - # stat current file to get raw permissions - my $old_perm_raw = (stat $file)[2]; - # test to see if suidbit is set - my $suid_bit = (($old_perm_raw/2048) % 2); - if($suid_bit == 1){ - # new permission without the suid bit - my $new_perm = ((($old_perm_raw/512) % 8 ) - 4) . - (($old_perm_raw/64) % 8 ) . - (($old_perm_raw/8) % 8 ) . - (($old_perm_raw) % 8 ); - if(&B_chmod(oct($new_perm), $file)){ - &B_log("ACTION","Removed SUID bit from \"$file\"."); - } - else { - &B_log("ERROR","Could not remove SUID bit from \"$file\"."); - } - } # No action if SUID bit is not set - }# No action if file does not exist - }# Repeat for each file in the file glob - } # unless Global_log -} - - - -1; - diff --git a/recipes-security/bastille/files/FileContent.pm b/recipes-security/bastille/files/FileContent.pm deleted file mode 100644 index 0a5d609..0000000 --- a/recipes-security/bastille/files/FileContent.pm +++ /dev/null @@ -1,1153 +0,0 @@ -package Bastille::API::FileContent; -use strict; - -use Bastille::API; - -require Exporter; -our @ISA = qw(Exporter); -our @EXPORT_OK = qw( -B_blank_file -B_insert_line_after -B_insert_line_before -B_insert_line -B_append_line -B_prepend_line -B_replace_line -B_replace_lines -B_replace_pattern -B_match_line -B_match_line_only -B_match_chunk -B_return_matched_lines -B_hash_comment_line -B_hash_uncomment_line -B_delete_line -B_chunk_replace -B_print -B_getValueFromFile -B_getValueFromString - -B_TODO -B_TODOFlags -); -our @EXPORT = @EXPORT_OK; - - - -########################################################################### -# &B_blank_file ($filename,$pattern) blanks the file $filename, unless the -# pattern $pattern is present in the file. This lets us completely redo -# a file, if it isn't the one we put in place on a previous run... -# -# B_blank_file respects $GLOBAL_LOGONLY and uses B_open_plus and B_close_plus -# so that it makes backups and only modifies files when we're not in "-v" -# mode... -# -# If the file does not exist, the function does nothing, and gives an error -# to the Error Log -# -########################################################################### - -sub B_blank_file($$) { - - my ($filename,$pattern) = @_; - my $retval; - - # If this variable is true, we won't blank the file... - - my $found_pattern=0; - - if ($retval=&B_open_plus (*BLANK_NEW,*BLANK_OLD,$filename) ) { - - my @lines; - - while (my $line = <BLANK_OLD>) { - - push @lines,$line; - if ($line =~ $pattern) { - $found_pattern=1; - } - } - - # Only copy the old file if the new one didn't match. - if ($found_pattern) { - while ( my $line = shift @lines ) { - &B_print(*BLANK_NEW,$line); - } - } - else { - &B_log("ACTION","Blanked file $filename\n"); - } - &B_close_plus(*BLANK_NEW,*BLANK_OLD,$filename); - } - else { - &B_log("ERROR","Couldn't blank file $filename since we couldn't open it or its replacement\n"); - } - - return $retval; - -} - -########################################################################### -# &B_insert_line_after ($filename,$pattern,$line_to_insert,$line_to_follow) -# modifies $filename, inserting $line_to_insert unless one or more lines -# in the file matches $pattern. The $line_to_insert will be placed -# immediately after $line_to_follow, if it exists. If said line does not -# exist, the line will not be inserted and this routine will return 0. -# -# B_insert_line uses B_open_plus and B_close_plus, so that the file -# modified is backed up... -# -# Here's examples of where you might use this: -# -# You'd like to insert a line in Apache's configuration file, in a -# particular section. -# -########################################################################### - -sub B_insert_line_after($$$$) { - - my ($filename,$pattern,$line_to_insert,$line_to_follow) = @_; - - my @lines; - my $found_pattern=0; - my $found_line_to_follow=0; - - my $retval=1; - - if ( &B_open_plus (*INSERT_NEW,*INSERT_OLD,$filename) ) { - - # Read through the file looking for a match both on the $pattern - # and the line we are supposed to be inserting after... - - my $ctr=1; - while (my $line=<INSERT_OLD>) { - push (@lines,$line); - if ($line =~ $pattern) { - $found_pattern=1; - } - if ( ($found_line_to_follow < 1) and ($line =~ $line_to_follow)) { - $found_line_to_follow=$ctr; - } - $ctr++; - } - - # Log an error if we never found the line we were to insert after - unless ($found_line_to_follow ) { - $retval=0; - &B_log("ERROR","Never found the line that we were supposed to insert after in $filename\n"); - } - - # Now print the file back out, inserting our line if we should... - - $ctr=1; - while (my $line = shift @lines) { - &B_print(*INSERT_NEW,$line); - if ( ($ctr == $found_line_to_follow) and ($found_pattern == 0) ) { - &B_print(*INSERT_NEW,$line_to_insert); - &B_log("ACTION","Inserted the following line in $filename:\n"); - &B_log("ACTION","$line_to_insert"); - } - $ctr++; - } - - &B_close_plus (*INSERT_NEW,*INSERT_OLD,$filename); - - } - else { - $retval=0; - &B_log("ERROR","Couldn't insert line to $filename, since open failed."); - } - - return $retval; - -} -########################################################################### -# &B_insert_line_before ($filename,$pattern,$line_to_insert,$line_to_preceed) -# modifies $filename, inserting $line_to_insert unless one or more lines -# in the file matches $pattern. The $line_to_insert will be placed -# immediately before $line_to_preceed, if it exists. If said line does not -# exist, the line will not be inserted and this routine will return 0. -# -# B_insert_line uses B_open_plus and B_close_plus, so that the file -# modified is backed up... -# -# Here's examples of where you might use this: -# -# You'd like to insert a line in Apache's configuration file, in a -# particular section. -# -########################################################################### - -sub B_insert_line_before($$$$) { - - my ($filename,$pattern,$line_to_insert,$line_to_preceed) = @_; - - my @lines; - my $found_pattern=0; - my $found_line_to_preceed=0; - - my $retval=1; - - if ( &B_open_plus (*INSERT_NEW,*INSERT_OLD,$filename) ) { - - # Read through the file looking for a match both on the $pattern - # and the line we are supposed to be inserting after... - - my $ctr=1; - while (my $line=<INSERT_OLD>) { - push (@lines,$line); - if ($line =~ $pattern) { - $found_pattern=1; - } - if ( ($found_line_to_preceed < 1) and ($line =~ $line_to_preceed)) { - $found_line_to_preceed=$ctr; - } - $ctr++; - } - - # Log an error if we never found the line we were to preceed - unless ($found_line_to_preceed ) { - $retval=0; - &B_log("ERROR","Never found the line that we were supposed to insert before in $filename\n"); - } - - # Now print the file back out, inserting our line if we should... - - $ctr=1; - while (my $line = shift @lines) { - if ( ($ctr == $found_line_to_preceed) and ($found_pattern == 0) ) { - &B_print(*INSERT_NEW,$line_to_insert); - &B_log("ACTION","Inserted the following line in $filename:\n"); - &B_log("ACTION","$line_to_insert"); - } - &B_print(*INSERT_NEW,$line); - $ctr++; - } - - &B_close_plus (*INSERT_NEW,*INSERT_OLD,$filename); - - } - else { - $retval=0; - &B_log("ERROR","Couldn't insert line to $filename, since open failed."); - } - - return $retval; - -} - -########################################################################### -# &B_insert_line ($filename,$pattern,$line_to_insert,$line_to_follow) -# -# has been renamed to B_insert_line_after() -# -# This name will continue to work, as a shim for code that has not been -# transitioned. -########################################################################### - -sub B_insert_line($$$$) { - - my $rtn_value = &B_insert_line_after(@_); - - return ($rtn_value); -} - - -########################################################################### -# &B_append_line ($filename,$pattern,$line_to_append) modifies $filename, -# appending $line_to_append unless one or more lines in the file matches -# $pattern. This is an enhancement to the append_line_if_no_such_line_exists -# idea. -# -# Additionally, if $pattern is set equal to "", the line is always appended. -# -# B_append_line uses B_open_plus and B_close_plus, so that the file -# modified is backed up... -# -# Here's examples of where you might use this: -# -# You'd like to add a root line to /etc/ftpusers if none exists. -# You'd like to add a Options Indexes line to Apache's config. file, -# after you delete all Options lines from said config file. -# -########################################################################### - -sub B_append_line($$$) { - - my ($filename,$pattern,$line_to_append) = @_; - - my $found_pattern=0; - my $retval=1; - - if ( &B_open_plus (*APPEND_NEW,*APPEND_OLD,$filename) ) { - while (my $line=<APPEND_OLD>) { - &B_print(*APPEND_NEW,$line); - if ($line =~ $pattern) { - $found_pattern=1; - } - } - # Changed != 0 to $pattern so that "" works instead of 0 and perl - # does not give the annoying - # Argument "XX" isn't numeric in ne at ... - if ( $pattern eq "" or ! $found_pattern ) { - &B_print(*APPEND_NEW,$line_to_append); - &B_log("ACTION","Appended the following line to $filename:\n"); - &B_log("ACTION","$line_to_append"); - } - &B_close_plus (*APPEND_NEW,*APPEND_OLD,$filename); - } - else { - $retval=0; - &B_log("ERROR","# Couldn't append line to $filename, since open failed."); - } - - return $retval; - -} - -########################################################################### -# &B_prepend_line ($filename,$pattern,$line_to_prepend) modifies $filename, -# pre-pending $line_to_prepend unless one or more lines in the file matches -# $pattern. This is an enhancement to the prepend_line_if_no_such_line_exists -# idea. -# -# B_prepend_line uses B_open_plus and B_close_plus, so that the file -# modified is backed up... -# -# Here's examples of where you might use this: -# -# You'd like to insert the line "auth required pam_deny.so" to the top -# of the PAM stack file /etc/pam.d/rsh to totally deactivate rsh. -# -########################################################################### - -sub B_prepend_line($$$) { - - my ($filename,$pattern,$line_to_prepend) = @_; - - my @lines; - my $found_pattern=0; - my $retval=1; - - if ( &B_open_plus (*PREPEND_NEW,*PREPEND_OLD,$filename) ) { - while (my $line=<PREPEND_OLD>) { - push (@lines,$line); - if ($line =~ $pattern) { - $found_pattern=1; - } - } - unless ($found_pattern) { - &B_print(*PREPEND_NEW,$line_to_prepend); - } - while (my $line = shift @lines) { - &B_print(*PREPEND_NEW,$line); - } - - &B_close_plus (*PREPEND_NEW,*PREPEND_OLD,$filename); - - # Log the action - &B_log("ACTION","Pre-pended the following line to $filename:\n"); - &B_log("ACTION","$line_to_prepend"); - } - else { - $retval=0; - &B_log("ERROR","Couldn't prepend line to $filename, since open failed.\n"); - } - - return $retval; - -} - - -########################################################################### -# &B_replace_line ($filename,$pattern,$line_to_switch_in) modifies $filename, -# replacing any lines matching $pattern with $line_to_switch_in. -# -# It returns the number of lines it replaced (or would have replaced, if -# LOGONLY mode wasn't on...) -# -# B_replace_line uses B_open_plus and B_close_plus, so that the file -# modified is backed up... -# -# Here an example of where you might use this: -# -# You'd like to replace any Options lines in Apache's config file with: -# Options Indexes FollowSymLinks -# -########################################################################### - -sub B_replace_line($$$) { - - my ($filename,$pattern,$line_to_switch_in) = @_; - my $retval=0; - - if ( &B_open_plus (*REPLACE_NEW,*REPLACE_OLD,$filename) ) { - while (my $line=<REPLACE_OLD>) { - unless ($line =~ $pattern) { - &B_print(*REPLACE_NEW,$line); - } - else { - # Don't replace the line if it's already there. - unless ($line eq $line_to_switch_in) { - &B_print(*REPLACE_NEW,$line_to_switch_in); - - $retval++; - &B_log("ACTION","File modification in $filename -- replaced line\n" . - "$line\n" . - "with:\n" . - "$line_to_switch_in"); - } - # But if it is there, make sure it stays there! (by Paul Allen) - else { - &B_print(*REPLACE_NEW,$line); - } - } - } - &B_close_plus (*REPLACE_NEW,*REPLACE_OLD,$filename); - } - else { - $retval=0; - &B_log("ERROR","Couldn't replace line(s) in $filename because open failed.\n"); - } - - return $retval; -} - -########################################################################### -# &B_replace_lines ($filename,$patterns_and_substitutes) modifies $filename, -# replacing the line matching the nth $pattern specified in $patterns_and_substitutes->[n]->[0] -# with the corresponding substitutes in $patterns_and_substitutes->[n]->-[1] -# -# It returns the number of lines it replaced (or would have replaced, if -# LOGONLY mode wasn't on...) -# -# B_replace_lines uses B_open_plus and B_close_plus, so that the file -# modified is backed up... -# -# Here an example of where you might use this: -# -# You'd like to replace /etc/opt/ssh/sshd_config file -# (^#|^)Protocol\s+(.*)\s*$ ==> Protocol 2 -# (^#|^)X11Forwarding\s+(.*)\s*$ ==> X11Forwarding yes -# (^#|^)IgnoreRhosts\s+(.*)\s*$ ==> gnoreRhosts yes -# (^#|^)RhostsAuthentication\s+(.*)\s*$ ==> RhostsAuthentication no -# (^#|^)RhostsRSAAuthentication\s+(.*)\s*$ ==> RhostsRSAAuthentication no -# (^#|^)PermitRootLogin\s+(.*)\s*$ ==> PermitRootLogin no -# (^#|^)PermitEmptyPasswords\s+(.*)\s*$ ==> PermitEmptyPasswords no -# my $patterns_and_substitutes = [ -# [ '(^#|^)Protocol\s+(.*)\s*$' => 'Protocol 2'], -# ['(^#|^)X11Forwarding\s+(.*)\s*$' => 'X11Forwarding yes'], -# ['(^#|^)IgnoreRhosts\s+(.*)\s*$' => 'gnoreRhosts yes'], -# ['(^#|^)RhostsAuthentication\s+(.*)\s*$' => 'RhostsAuthentication no'], -# ['(^#|^)RhostsRSAAuthentication\s+(.*)\s*$' => 'RhostsRSAAuthentication no'], -# ['(^#|^)PermitRootLogin\s+(.*)\s*$' => 'PermitRootLogin no'], -# ['(^#|^)PermitEmptyPasswords\s+(.*)\s*$' => 'PermitEmptyPasswords no'] -#] -# B_replaces_lines($sshd_config,$patterns_and_substitutes); -########################################################################### - -sub B_replace_lines($$){ - my ($filename, $pairs) = @_; - my $retval = 0; - if ( &B_open_plus (*REPLACE_NEW,*REPLACE_OLD,$filename) ) { - while (my $line = <REPLACE_OLD>) { - my $switch; - my $switch_before = $line; - chomp($line); - foreach my $pair (@$pairs) { - $switch = 0; - - my $pattern = $pair->[0] ; - my $replace = $pair->[1]; - my $evalstr = '$line' . "=~ s/$pattern/$replace/"; - eval $evalstr; - if ($@) { - &B_log("ERROR", "eval $evalstr failed.\n"); - } - #if ( $line =~ s/$pair->[0]/$pair->[1]/) { - # $switch = 1; - # last; - #} - } - &B_print(*REPLACE_NEW,"$line\n"); - if ($switch) { - $retval++; - B_log("ACTION","File modification in $filename -- replaced line\n" . - "$switch_before\n" . - "with:\n" . - "$line\n"); - } - } - &B_close_plus (*REPLACE_NEW,*REPLACE_OLD,$filename); - return 1; - } - else { - $retval=0; - &B_log("ERROR","Couldn't replace line(s) in $filename because open failed.\n"); - } -} - -################################################################################################ -# &B_replace_pattern ($filename,$pattern,$pattern_to_remove,$text_to_switch_in) -# modifies $filename, acting on only lines that match $pattern, replacing a -# string that matches $pattern_to_remove with $text_to_switch_in. -# -# Ex: -# B_replace_pattern('/etc/httpd.conf','^\s*Options.*\bIncludes\b','Includes','IncludesNoExec') -# -# replaces all "Includes" with "IncludesNoExec" on Apache Options lines. -# -# It returns the number of lines it altered (or would have replaced, if -# LOGONLY mode wasn't on...) -# -# B_replace_pattern uses B_open_plus and B_close_plus, so that the file -# modified is backed up... -# -################################################################################################# - -sub B_replace_pattern($$$$) { - - my ($filename,$pattern,$pattern_to_remove,$text_to_switch_in) = @_; - my $retval=0; - - if ( &B_open_plus (*REPLACE_NEW,*REPLACE_OLD,$filename) ) { - while (my $line=<REPLACE_OLD>) { - unless ($line =~ $pattern) { - &B_print(*REPLACE_NEW,$line); - } - else { - my $orig_line =$line; - $line =~ s/$pattern_to_remove/$text_to_switch_in/; - - &B_print(*REPLACE_NEW,$line); - - $retval++; - &B_log("ACTION","File modification in $filename -- replaced line\n" . - "$orig_line\n" . - "via pattern with:\n" . - "$line\n\n"); - } - } - &B_close_plus (*REPLACE_NEW,*REPLACE_OLD,$filename); - } - else { - $retval=0; - &B_log("ERROR","Couldn't pattern-replace line(s) in $filename because open failed.\n"); - } - - return $retval; -} - - -########################################################################### -# &B_match_line($file,$pattern); -# -# This subroutine will return a 1 if the pattern specified can be matched -# against the file specified. It will return a 0 otherwise. -# -# return values: -# 0: pattern not in file or the file is not readable -# 1: pattern is in file -########################################################################### -sub B_match_line($$) { - # file to be checked and pattern to check for. - my ($file,$pattern) = @_; - # if the file is readable then - if(-r $file) { - # if the file can be opened then - if(open FILE,"<$file") { - # look at each line in the file - while (my $line = <FILE>) { - # if a line matches the pattern provided then - if($line =~ $pattern) { - # return the pattern was found - B_log('DEBUG','Pattern: ' . $pattern . ' matched in file: ' . - $file . "\n"); - return 1; - } - } - } - # if the file cann't be opened then - else { - # send a note to that affect to the errorlog - &B_log("ERROR","Unable to open file for read.\n$file\n$!\n"); - } - } - B_log('DEBUG','Pattern: ' . $pattern . ' not matched in file: ' . - $file . "\n"); - # the provided pattern was not matched against a line in the file - return 0; -} - -########################################################################### -# &B_match_line_only($file,$pattern); -# -# This subroutine checks if the specified pattern can be matched and if -# it's the only content in the file. The only content means it's only but -# may have several copies in the file. -# -# return values: -# 0: pattern not in file or pattern is not the only content -# or the file is not readable -# 1: pattern is in file and it's the only content -############################################################################ -sub B_match_line_only($$) { - my ($file,$pattern) = @_; - - # if matched, set to 1 later - my $retval = 0; - - # if the file is readable then - if(-r $file) { - # if the file can be opened then - if(&B_open(*FILED, $file)) { - # pattern should be matched at least once - # pattern can not be mismatched - while (my $line = <FILED>) { - if ($line =~ $pattern) { - $retval = 1; - } - else { - &B_close(*FILED); - return 0; - } - } - } - &B_close(*FILED); - } - - return $retval; -} - -########################################################################### -# &B_return_matched_lines($file,$pattern); -# -# This subroutine returns lines in a file matching a given regular -# expression, when called in the default list mode. When called in scalar -# mode, returns the number of elements found. -########################################################################### -sub B_return_matched_lines($$) -{ - my ($filename,$pattern) = @_; - my @lines = (); - - open(READFILE, $filename); - while (<READFILE>) { - chomp; - next unless /$pattern/; - push(@lines, $_); - } - if (wantarray) - { - return @lines; - } - else - { - return scalar (@lines); - } -} - -########################################################################### -# &B_match_chunk($file,$pattern); -# -# This subroutine will return a 1 if the pattern specified can be matched -# against the file specified on a line-agnostic form. This allows for -# patterns which by necessity must match against a multi-line pattern. -# This is the natural analogue to B_replace_chunk, which was created to -# provide multi-line capability not provided by B_replace_line. -# -# return values: -# 0: pattern not in file or the file is not readable -# 1: pattern is in file -########################################################################### - -sub B_match_chunk($$) { - - my ($file,$pattern) = @_; - my @lines; - my $big_long_line; - my $retval=1; - - open CHUNK_FILE,$file; - - # Read all lines into one scalar. - @lines = <CHUNK_FILE>; - close CHUNK_FILE; - - foreach my $line ( @lines ) { - $big_long_line .= $line; - } - - # Substitution routines get weird unless last line is terminated with \n - chomp $big_long_line; - $big_long_line .= "\n"; - - # Exit if we don't find a match - unless ($big_long_line =~ $pattern) { - $retval = 0; - } - - return $retval; -} - -########################################################################### -# &B_hash_comment_line ($filename,$pattern) modifies $filename, replacing -# any lines matching $pattern with a "hash-commented" version, like this: -# -# -# finger stream tcp nowait nobody /usr/sbin/tcpd in.fingerd -# becomes: -# #finger stream tcp nowait nobody /usr/sbin/tcpd in.fingerd -# -# Also: -# tftp dgram udp wait root /usr/lbin/tftpd tftpd\ -# /opt/ignite\ -# /var/opt/ignite -# becomes: -# #tftp dgram udp wait root /usr/lbin/tftpd tftpd\ -# # /opt/ignite\ -# # /var/opt/ignite -# -# -# B_hash_comment_line uses B_open_plus and B_close_plus, so that the file -# modified is backed up... -# -########################################################################### - -sub B_hash_comment_line($$) { - - my ($filename,$pattern) = @_; - my $retval=1; - - if ( &B_open_plus (*HASH_NEW,*HASH_OLD,$filename) ) { - my $line; - while ($line=<HASH_OLD>) { - unless ( ($line =~ $pattern) and ($line !~ /^\s*\#/) ) { - &B_print(*HASH_NEW,$line); - } - else { - &B_print(*HASH_NEW,"#$line"); - &B_log("ACTION","File modification in $filename -- hash commented line\n" . - "$line\n" . - "like this:\n" . - "#$line\n\n"); - # while the line has a trailing \ then we should also comment out the line below - while($line =~ m/\\\n$/) { - if($line=<HASH_OLD>) { - &B_print(*HASH_NEW,"#$line"); - &B_log("ACTION","File modification in $filename -- hash commented line\n" . - "$line\n" . - "like this:\n" . - "#$line\n\n"); - } - else { - $line = ""; - } - } - - } - } - &B_close_plus (*HASH_NEW,*HASH_OLD,$filename); - } - else { - $retval=0; - &B_log("ERROR","Couldn't hash-comment line(s) in $filename because open failed.\n"); - } - - return $retval; -} - - -########################################################################### -# &B_hash_uncomment_line ($filename,$pattern) modifies $filename, -# removing any commenting from lines that match $pattern. -# -# #finger stream tcp nowait nobody /usr/sbin/tcpd in.fingerd -# becomes: -# finger stream tcp nowait nobody /usr/sbin/tcpd in.fingerd -# -# -# B_hash_uncomment_line uses B_open_plus and B_close_plus, so that the file -# modified is backed up... -# -########################################################################### - -sub B_hash_uncomment_line($$) { - - my ($filename,$pattern) = @_; - my $retval=1; - - if ( &B_open_plus (*HASH_NEW,*HASH_OLD,$filename) ) { - my $line; - while ($line=<HASH_OLD>) { - unless ( ($line =~ $pattern) and ($line =~ /^\s*\#/) ) { - &B_print(*HASH_NEW,$line); - } - else { - $line =~ /^\s*\#+(.*)$/; - $line = "$1\n"; - - &B_print(*HASH_NEW,"$line"); - &B_log("ACTION","File modification in $filename -- hash uncommented line\n"); - &B_log("ACTION",$line); - # while the line has a trailing \ then we should also uncomment out the line below - while($line =~ m/\\\n$/) { - if($line=<HASH_OLD>) { - $line =~ /^\s*\#+(.*)$/; - $line = "$1\n"; - &B_print(*HASH_NEW,"$line"); - &B_log("ACTION","File modification in $filename -- hash uncommented line\n"); - &B_log("ACTION","#$line"); - &B_log("ACTION","like this:\n"); - &B_log("ACTION","$line"); - } - else { - $line = ""; - } - } - } - } - &B_close_plus (*HASH_NEW,*HASH_OLD,$filename); - } - else { - $retval=0; - &B_log("ERROR","Couldn't hash-uncomment line(s) in $filename because open failed.\n"); - } - - return $retval; -} - - - -########################################################################### -# &B_delete_line ($filename,$pattern) modifies $filename, deleting any -# lines matching $pattern. It uses B_replace_line to do this. -# -# B_replace_line uses B_open_plus and B_close_plus, so that the file -# modified is backed up... -# -# Here an example of where you might use this: -# -# You'd like to remove any timeout= lines in /etc/lilo.conf, so that your -# delay=1 modification will work. - -# -########################################################################### - - -sub B_delete_line($$) { - - my ($filename,$pattern)=@_; - my $retval=&B_replace_line($filename,$pattern,""); - - return $retval; -} - - -########################################################################### -# &B_chunk_replace ($file,$pattern,$replacement) reads $file replacing the -# first occurrence of $pattern with $replacement. -# -########################################################################### - -sub B_chunk_replace($$$) { - - my ($file,$pattern,$replacement) = @_; - - my @lines; - my $big_long_line; - my $retval=1; - - &B_open (*OLDFILE,$file); - - # Read all lines into one scalar. - @lines = <OLDFILE>; - &B_close (*OLDFILE); - foreach my $line ( @lines ) { - $big_long_line .= $line; - } - - # Substitution routines get weird unless last line is terminated with \n - chomp $big_long_line; - $big_long_line .= "\n"; - - # Exit if we don't find a match - unless ($big_long_line =~ $pattern) { - return 0; - } - - $big_long_line =~ s/$pattern/$replacement/s; - - $retval=&B_open_plus (*NEWFILE,*OLDFILE,$file); - if ($retval) { - &B_print (*NEWFILE,$big_long_line); - &B_close_plus (*NEWFILE,*OLDFILE,$file); - } - - return $retval; -} - -########################################################################### -# &B_print ($handle,@list) prints the items of @list to the file handle -# $handle. It logs the action and respects the $GLOBAL_LOGONLY variable. -# -########################################################################### - -sub B_print { - my $handle=shift @_; - - my $result=1; - - unless ($GLOBAL_LOGONLY) { - $result=print $handle @_; - } - - ($handle) = "$handle" =~ /[^:]+::[^:]+::([^:]+)/; - - $result; -} - - -########################################################################## -# &B_getValueFromFile($regex,$file); -# Takes a regex with a single group "()" and returns the unique value -# on any non-commented lines -# This (and B_return_matched_lines are only used in this file, though are -# probably more generally useful. For now, leaving these here serve the following -#functions: -# a) still gets exported/associated as part of the Test_API package, and -# is still availble for a couple operations that can't be deferred to the -# main test loop, as they save values so that individual tests don't have to -# recreate (copy / paste) the logic to get them. -# -# It also avoids the circular "use" if we incldued "use Test API" at the top -# of this file (Test API "uses" this file. -# Returns the uncommented, unique values of a param=value pair. -# -# Return values: -# 'Not Defined' if the value is not present or not uniquely defined. -# $value if the value is present and unique -# -########################################################################### -sub B_getValueFromFile ($$){ - my $inputRegex=$_[0]; - my $file=$_[1]; - my ($lastvalue,$value)=''; - - my @lines=&B_return_matched_lines($file, $inputRegex); - - return &B_getValueFromString($inputRegex,join('/n',@lines)); -} - -########################################################################## -# &B_getValueFromString($param,$string); -# Takes a regex with a single group "()" and returns the unique value -# on any non-commented lines -# This (and B_return_matched_lines are only used in this file, though are -# probably more generally useful. For now, leaving these here serve the following -#functions: -# a) still gets exported/associated as part of the Test_API package, and -# is still availble for a couple operations that can't be deferred to the -# main test loop, as they save values so that individual tests don't have to -# recreate (copy / paste) the logic to get them. -# -# It also avoids the circular "use" if we incldued "use Test API" at the top -# of this file (Test API "uses" this file. -# Returns the uncommented, unique values of a param=value pair. -# -# Return values: -# 'Not Unique' if the value is not uniquely defined. -# undef if the value isn't defined at all -# $value if the value is present and unique -# -########################################################################### -sub B_getValueFromString ($$){ - my $inputRegex=$_[0]; - my $inputString=$_[1]; - my $lastValue=''; - my $value=''; - - my @lines=split(/\n/,$inputString); - - &B_log("DEBUG","B_getvaluefromstring called with regex: $inputRegex and input: " . - $inputString); - foreach my $line (grep(/$inputRegex/,@lines)) { - $line =~ /$inputRegex/; - $value=$1; - if (($lastValue eq '') and ($value ne '')) { - $lastValue = $value; - } elsif (($lastValue ne $value) and ($value ne '')) { - B_log("DEBUG","getvaluefromstring returned Not Unique"); - return 'Not Unique'; - } - } - if ((not(defined($value))) or ($value eq '')) { - &B_log("DEBUG","Could not find regex match in string"); - return undef; - } else { - &B_log("DEBUG","B_getValueFromString Found: $value ; using: $inputRegex"); - return $value; - } -} - -############################################################### -# This function adds something to the To Do List. -# Arguments: -# 1) The string you want to add to the To Do List. -# 2) Optional: Question whose TODOFlag should be set to indicate -# A pending manual action in subsequent reports. Only skip this -# If there's no security-audit relevant action you need the user to -# accomplish -# Ex: -# &B_TODO("------\nInstalling IPFilter\n----\nGo get Ipfilter","IPFilter.install_ipfilter"); -# -# -# Returns: -# 0 - If error condition -# True, if sucess, specifically: -# "appended" if the append operation was successful -# "exists" if no change was made since the entry was already present -############################################################### -sub B_TODO ($;$) { - my $text = $_[0]; - my $FlaggedQuestion = $_[1]; - my $multilineString = ""; - - # trim off any leading and trailing new lines, regexes separated for "clarity" - $text =~ s/^\n+(.*)/$1/; - $text =~ s/(.*)\n+$/$1/; - - if ( ! -e &getGlobal('BFILE',"TODO") ) { - # Make the TODO list file for HP-UX Distro - &B_create_file(&getGlobal('BFILE', "TODO")); - &B_append_line(&getGlobal('BFILE', "TODO"),'a$b', - "Please take the steps below to make your system more secure,\n". - "then delete the item from this file and record what you did along\n". - "with the date and time in your system administration log. You\n". - "will need that information in case you ever need to revert your\n". - "changes.\n\n"); - } - - - if (open(TODO,"<" . &getGlobal('BFILE', "TODO"))) { - while (my $line = <TODO>) { - # getting rid of all meta characters. - $line =~ s/(\\|\||\(|\)|\[|\]|\{|\}|\^|\$|\*|\+|\?|\.)//g; - $multilineString .= $line; - } - chomp $multilineString; - $multilineString .= "\n"; - - close(TODO); - } - else { - &B_log("ERROR","Unable to read TODO.txt file.\n" . - "The following text could not be appended to the TODO list:\n" . - $text . - "End of TODO text\n"); - return 0; #False - } - - my $textPattern = $text; - - # getting rid of all meta characters. - $textPattern =~ s/(\\|\||\(|\)|\[|\]|\{|\}|\^|\$|\*|\+|\?|\.)//g; - - if( $multilineString !~ "$textPattern") { - my $datestamp = "{" . localtime() . "}"; - unless ( &B_append_line(&getGlobal('BFILE', "TODO"), "", $datestamp . "\n" . $text . "\n\n\n") ) { - &B_log("ERROR","TODO Failed for text: " . $text ); - } - #Note that we only set the flag on the *initial* entry in the TODO File - #Not on subsequent detection. This is to avoid the case where Bastille - #complains on a subsequent Bastille run of an already-performed manual - #action that the user neglected to delete from the TODO file. - # It does, however lead to a report of "nonsecure" when the user - #asked for the TODO item, performed it, Bastille detected that and cleared the - # Item, and then the user unperformed the action. I think this is proper behavior. - # rwf 06/06 - - if (defined($FlaggedQuestion)) { - &B_TODOFlags("set",$FlaggedQuestion); - } - return "appended"; #evals to true, and also notes what happened - } else { - return "exists"; #evals to true, and also - } - -} - - -##################################################################### -# &B_TODOFlags() -# -# This is the interface to the TODO flags. Test functions set these when they -# require a TODO item to be completed to get to a "secure" state. -# The prune/reporting function checks these to ensure no flags are set before -# reporting an item "secure" -# "Methods" are load | save | isSet <Question> | set <Question> | unset <Question> -# -###################################################################### - -sub B_TODOFlags($;$) { - my $action = $_[0]; - my $module = $_[1]; - - use File::Spec; - - my $todo_flag = &getGlobal("BFILE","TODOFlag"); - - &B_log("DEBUG","B_TODOFlags action: $action , module: $module"); - - if ($action eq "load") { - if (-e $todo_flag ) { - &B_open(*TODO_FLAGS, $todo_flag); - my @lines = <TODO_FLAGS>; - foreach my $line (@lines) { - chomp($line); - $GLOBAL_CONFIG{"$line"}{"TODOFlag"}="yes"; - } - return (&B_close(*TODO_FLAGS)); #return success of final close - } else { - return 1; #No-op is okay - } - } elsif ($action eq "save") { - # Make sure the file exists, else create - #Note we use open_plus and and create file, so if Bastille is - #reverted, all the flags will self-clear (file deleted) - my $flagNumber = 0; - my $flagData = ''; - foreach my $key (keys %GLOBAL_CONFIG) { - if ($GLOBAL_CONFIG{$key}{"TODOFlag"} eq "yes") { - ++$flagNumber; - $flagData .= "$key\n"; - } - } - if (not( -e $todo_flag)) { - &B_log("DEBUG","Initializing TODO Flag file: $todo_flag"); - &B_create_file($todo_flag); # Make sure it exists - } - &B_blank_file($todo_flag, - "This will not appear in the file; ensures blanking"); - return &B_append_line($todo_flag, "", "$flagData"); #return success of save - } elsif (($action eq "isSet") and ($module ne "")) { - if ($GLOBAL_CONFIG{"$module"}{"TODOFlag"} eq "yes") { - return 1; #TRUE - } else { - return 0; #FALSE - } - } elsif (($action eq "set") and ($module ne "")) { - $GLOBAL_CONFIG{"$module"}{"TODOFlag"} = "yes"; - } elsif (($action eq "clear") and ($module ne "")) { - $GLOBAL_CONFIG{"$module"}{"TODOFlag"} = ""; - } else { - &B_log("ERROR","TODO_Flag Called with invalid parameters: $action , $module". - "audit report may be incorrect."); - return 0; #FALSE - } -} - -1; - - diff --git a/recipes-security/bastille/files/HPSpecific.pm b/recipes-security/bastille/files/HPSpecific.pm deleted file mode 100644 index 7e7d709..0000000 --- a/recipes-security/bastille/files/HPSpecific.pm +++ /dev/null @@ -1,1983 +0,0 @@ -package Bastille::API::HPSpecific; - -use strict; -use Bastille::API; -use Bastille::API::FileContent; - -require Exporter; -our @ISA = qw(Exporter); -our @EXPORT_OK = qw( -getIPFLocation -getGlobalSwlist -B_check_system -B_swmodify -B_load_ipf_rules -B_Schedule -B_ch_rc -B_set_value -B_chperm -B_install_jail -B_list_processes -B_list_full_processes -B_deactivate_inetd_service -B_get_rc -B_set_rc -B_chrootHPapache -isSystemTrusted -isTrustedMigrationAvailable -checkServiceOnHPUX -B_get_path -convertToTrusted -isOKtoConvert -convertToShadow -getSupportedSettings -B_get_sec_value -secureIfNoNameService -isUsingRemoteNameService -remoteServiceCheck -remoteNISPlusServiceCheck -B_create_nsswitch_file -B_combine_service_results - -%priorBastilleNDD -%newNDD -); -our @EXPORT = @EXPORT_OK; - - - -# "Constants" for use both in testing and in lock-down -our %priorBastilleNDD = ( - "ip_forward_directed_broadcasts" =>["ip", "0"], - "ip_forward_src_routed" =>["ip", "0"], - "ip_forwarding" =>["ip", "0"], - "ip_ire_gw_probe" =>["ip", "0"], - "ip_pmtu_strategy" =>["ip", "1"], - "ip_respond_to_echo_broadcast" =>["ip", "0"], - "ip_send_redirects" =>["ip", "0"], - "ip_send_source_quench" =>["ip", "0"], - "tcp_syn_rcvd_max" =>["tcp","1000"], - "tcp_conn_request_max" =>["tcp","4096"] ); - -our %newNDD = ( - "ip_forward_directed_broadcasts" =>["ip", "0"], - "ip_forward_src_routed" =>["ip", "0"], - "ip_forwarding" =>["ip", "0"], - "ip_ire_gw_probe" =>["ip", "0"], - "ip_pmtu_strategy" =>["ip", "1"], - "ip_respond_to_echo_broadcast" =>["ip", "0"], - "ip_send_redirects" =>["ip", "0"], - "ip_send_source_quench" =>["ip", "0"], - "tcp_syn_rcvd_max" =>["tcp","4096"], - "tcp_conn_request_max" =>["tcp","4096"], - "arp_cleanup_interval" =>["arp","60000"], - "ip_respond_to_timestamp" =>["ip", "0"], - "ip_respond_to_timestamp_broadcast" => ["ip","0"] ); - - -#################################################################### -# -# This module makes up the HP-UX specific API routines. -# -#################################################################### -# -# Subroutine Listing: -# &HP_ConfigureForDistro: adds all used file names to global -# hashes and generates a global IPD -# hash for SD modification lookup. -# -# &getGlobalSwlist($): Takes a fully qualified file name -# and returns product:filset info -# for that file. returns undef if -# the file is not present in the IPD -# -# &B_check_system: Runs a series of system queries to -# determine if Bastille can be safely -# ran on the current system. -# -# &B_swmodify($): Takes a file name and runs the -# swmodify command on it so that the -# IPD is updated after changes -# -# &B_System($$): Takes a system command and the system -# command that should be used to revert -# whatever was done. Returns 1 on -# success and 0 on failure -# -# &B_Backtick($) Takes a command to run and returns its stdout -# to be used in place of the prior prevelent use -# of un-error-handled backticks -# -# &B_load_ipf_rules($): Loads a set of ipfrules into ipf, storing -# current rules for later reversion. -# -# &B_Schedule($$): Takes a pattern and a crontab line. -# Adds or replaces the crontab line to -# the crontab file, depending on if a -# line matches the pattern -# -# &B_ch_rc($$): Takes a the rc.config.d flag name and -# new value as well as the init script -# location. This will stop a services -# and set the service so that it will -# not be restarted. -# -# &B_set_value($$$): Takes a param, value, and a filename -# and sets the given value in the file. -# Uses ch_rc, but could be rewritten using -# Bastille API calls to make it work on Linux -# -# &B_TODO($): Appends the give string to the TODO.txt -# file. -# -# &B_chperm($$$$): Takes new perm owner and group of given -# file. TO BE DEPRECATED!!! -# -# &B_install_jail($$): Takes the jail name and the jail config -# script location for a give jail... -# These scripts can be found in the main -# directory e.g. jail.bind.hpux -# -##################################################################### - -############################################################################## -# -# HP-UX Bastille directory structure -# -############################################################################## -# -# /opt/sec_mgmt/bastille/bin/ -- location of Bastille binaries -# /opt/sec_mgmt/bastille/lib/ -- location of Bastille modules -# /opt/sec_mgmt/bastille/doc/ -- location of Bastille doc files -# -# /etc/opt/sec_mgmt/bastille/ -- location of Bastille config files -# -# /var/opt/sec_mgmt/bastille/log -- location of Bastille log files -# /var/opt/sec_mgmt/bastille/revert -- directory holding all Bastille- -# created revert scripts -# /var/opt/sec_mgmt/bastille/revert/backup -- directory holding the original -# files that Bastille modifies, -# with permissions intact -# -############################################################################## - -sub getIPFLocation () { # Temporary until we get defined search space support - my $ipf=&getGlobal('BIN','ipf_new'); - my $ipfstat=&getGlobal('BIN','ipfstat_new'); - if (not(-e $ipf)) { # Detect if the binaries moved - $ipf = &getGlobal('BIN','ipf'); - $ipfstat=&getGlobal('BIN','ipfstat'); - } - return ($ipf, $ipfstat); -} - -############################################## -# Given a combination of service results, provided -# in an array, this function combines the result into -# a reasonable aggregate result -############################################## - -sub B_combine_service_results(@){ - my @results = @_; - - #TODO: Consider greater sophistication wrt inconsistent, or not installed. - - foreach my $result (@results) { - if (not(($result == SECURE_CAN_CHANGE) or - ($result == SECURE_CANT_CHANGE) or - ($result == NOT_INSTALLED()))) { - return NOTSECURE_CAN_CHANGE(); - } - } - return SECURE_CANT_CHANGE(); -} - -#################################################################### -# &getGlobalSwlist ($file); -# This function returns the product and fileset information for -# a given file or directory if it exists in the IPD otherwise -# it returns undefined "undef" -# -# uses $GLOBAL_SWLIST{"$FILE"} -#################################################################### -sub getGlobalSwlist($){ - no strict; - my $file = $_[0]; - - - if(! %GLOBAL_SWLIST) { - # Generating swlist database for swmodify changes that will be required - # The database will be a hash of fully qualified file names that reference - # the files product name and fileset. These values are required to use - # swmodify... - - # Files tagged 'is_volatile' in the IPD are not entered in the swlist database - # in order to avoid invoking swmodify if the file is changed later. Attempting to - # swmodify 'volatile' files is both unneccessary and complicated since swverify will - # not evaluate volatile files anyway, and adding another value to the swlist database - # would require complex code changes. - - # temp variable to keep swlist command /usr/sbin/swlist - my $swlist = &getGlobal('BIN',"swlist"); - - # listing of each directory and file that was installed by SD on the target machine - my @fileList = `$swlist -a is_volatile -l file`; - - # listing of each patch and the patches that supersede each. - # hash which is indexed by patch.fileset on the system - my %patchSuperseded; - - my @patchList = `${swlist} -l fileset -a superseded_by *.*,c=patch 2>&1`; - # check to see if any patches are present on the system - if(($? >> 8) == 0) { - - # determining patch suppression for swmodify. - foreach my $patchState (@patchList) { - # removing empty lines and commented lines. - if($patchState !~ /^\s*\#/ && $patchState !~ /^\s*$/) { - - # removing leading white space - $patchState =~ s/^\s+//; - my @patches = split /\s+/, $patchState; - if($#patches == 0){ - # patch is not superseded - $patchSuperseded{$patches[0]} = 0; - } - else { - # patch is superseded - $patchSuperseded{$patches[0]} = 1; - } - } - } - } - else { - &B_log("DEBUG","No patches found on the system.\n"); - } - - if($#fileList >= 0){ - # foreach line of swlist output - foreach my $fileEntry ( @fileList ){ - #filter out commented portions - if( $fileEntry !~ /^\s*\#/ ){ - chomp $fileEntry; - # split the output into three fields: product.fileset, filename, flag_isvolatile - my( $productInfo, $file, $is_volatile ) = $fileEntry =~ /^\s*(\S+): (\S+)\t(\S+)/ ; - # do not register volatile files - next if ($is_volatile =~ /true/); # skip to next file entry - $productInfo =~ s/\s+//; - $file =~ s/\s+//; - # if the product is a patch - if($productInfo =~ /PH(CO|KL|NE|SS)/){ - # if the patch is not superseded by another patch - if($patchSuperseded{$productInfo} == 0){ - # add the patch to the list of owner for this file - push @{$GLOBAL_SWLIST{"$file"}}, $productInfo; - } - } - # not a patch. - else { - # add the product to the list of owners for this file - push @{$GLOBAL_SWLIST{"$file"}}, $productInfo; - } - - } - } - } - else{ - # defining GLOBAL_SWLIST in error state. - $GLOBAL_SWLIST{"ERROR"} = "ERROR"; - &B_log("ERROR","Could not execute swlist. Swmodifys will not be attempted"); - } - } - - if(exists $GLOBAL_SWLIST{"$file"}){ - return $GLOBAL_SWLIST{"$file"}; - } - else { - return undef; - } -} - -################################################################### -# &B_check_system; -# This subroutine is called to validate that bastille may be -# safely run on the current system. It will check to insure -# that there is enough file system space, mounts are rw, nfs -# mounts are not mounted noroot, and swinstall, swremove and -# swmodify are not running -# -# uses ErrorLog -# -################################################################## -sub B_check_system { - # exitFlag is one if a conflict with the successful execution - # of bastille is found. - my $exitFlag = 0; - - my $ignoreCheck = &getGlobal("BDIR","config") . "/.no_system_check"; - if( -e $ignoreCheck ) { - return $exitFlag; - } - - # first check for swinstall, swmodify, or swremove processes - my $ps = &getGlobal('BIN',"ps") . " -el"; - my @processTable = `$ps`; - foreach my $process (@processTable) { - if($process =~ /swinstall/ ) { - &B_log("ERROR","Bastille cannot run while a swinstall is in progress.\n" . - "Complete the swinstall operation and then run Bastille.\n\n"); - $exitFlag = 1; - } - - if($process =~ /swremove/ ) { - &B_log("ERROR","Bastille cannot run while a swremove is in progress.\n" . - "Complete the swremove operation and then run Bastille.\n\n"); - $exitFlag = 1; - } - - if($process =~ /swmodify/ ) { - &B_log("ERROR","Bastille cannot run while a swmodify is in progress.\n" . - "Complete the swmodify operation and then run Bastille.\n\n"); - $exitFlag = 1; - } - - } - - # check for root read only mounts for /var /etc /stand / - # Bastille is required to make changes to these file systems. - my $mount = &getGlobal('BIN',"mount"); - my $rm = &getGlobal('BIN',"rm"); - my $touch = &getGlobal('BIN',"touch"); - - my @mnttab = `$mount`; - - if(($? >> 8) != 0) { - &B_log("WARNING","Unable to use $mount to determine if needed partitions\n" . - "are root writable, based on disk mount options.\n" . - "Bastille will continue but note that disk\n" . - "mount checks were skipped.\n\n"); - } - else { - foreach my $record (@mnttab) { - my @fields = split /\s+/, $record; - if ((defined $fields[0]) && (defined $fields[2]) && (defined $fields[3])) { - my $mountPoint = $fields[0]; - my $mountType = $fields[2]; - my $mountOptions = $fields[3]; - - # checks for /stand and /var/* removed - if($mountPoint =~ /^\/$|^\/etc|^\/var$/) { - - if($mountOptions =~ /^ro,|,ro,|,ro$/) { - &B_log("ERROR","$mountPoint is mounted read-only. Bastille needs to make\n" . - "modifications to this file system. Please remount\n" . - "$mountPoint read-write and then run Bastille again.\n\n"); - $exitFlag = 1; - } - # looking for an nfs mounted file system - if($mountType =~/.+:\//){ - my $fileExisted=0; - if(-e "$mountPoint/.bastille") { - $fileExisted=1; - } - - `$touch $mountPoint/.bastille 1>/dev/null 2>&1`; - - if( (! -e "$mountPoint/.bastille") || (($? >> 8) != 0) ) { - &B_log("ERROR","$mountPoint is an nfs mounted file system that does\n" . - "not allow root to write to. Bastille needs to make\n" . - "modifications to this file system. Please remount\n" . - "$mountPoint giving root access and then run Bastille\n" . - "again.\n\n"); - - $exitFlag = 1; - } - # if the file did not exist befor the touch then remove the generated file - if(! $fileExisted) { - `$rm -f $mountPoint/.bastille 1>/dev/null 2>&1`; - } - } - } - } - else { - &B_log("WARNING","Unable to use $mount to determine if needed partitions\n" . - "are root writable, based on disk mount options.\n" . - "Bastille will continue but note that disk\n" . - "mount checks were skipped.\n\n"); - } - } - - } - - # checks for enough disk space in directories that Bastille writes to. - my $bdf = &getGlobal('BIN',"bdf"); - #directories that Bastille writes to => required space in kilobytes. - my %bastilleDirs = ( "/etc/opt/sec_mgmt/bastille" => "4", "/var/opt/sec_mgmt/bastille"=> "1000"); - for my $directory (sort keys %bastilleDirs) { - my @diskUsage = `$bdf $directory`; - - if(($? >> 8) != 0) { - &B_log("WARNING","Unable to use $bdf to determine disk usage for\n" . - "$directory\n" . - "Bastille will continue but note that disk\n" . - "usage checks were skipped.\n\n"); - - } - else { - # removing bdf header line from usage information. - shift @diskUsage; - my $usageString= ""; - - foreach my $usageRecord (@diskUsage) { - chomp $usageRecord; - $usageString .= $usageRecord; - } - - $usageString =~ s/^\s+//; - - my @fields = split /\s+/, $usageString; - if($#fields != 5) { - &B_log("WARNING","Unable to use $bdf to determine disk usage for\n" . - "$directory\n" . - "Bastille will continue but note that disk\n" . - "usage checks were skipped.\n\n"); - } - else { - - my $mountPoint = $fields[5]; - my $diskAvail = $fields[3]; - - if($diskAvail <= $bastilleDirs{"$directory"}) { - &B_log("ERROR","$mountPoint does not contain enough available space\n" . - "for Bastille to run properly. $directory needs\n" . - "at least $bastilleDirs{$directory} kilobytes of space.\n" . - "Please clear at least that amount of space from\n" . - "$mountPoint and run Bastille again.\n" . - "Current Free Space available = ${diskAvail} k\n\n"); - $exitFlag = 1; - } - } - } - } - - # check to make sure that we are in at least run level 2 before we attempt to run - my $who = &getGlobal('BIN', "who") . " -r"; - my $levelInfo = `$who`; - if(($? >> 8) != 0 ) { - &B_log("WARNING","Unable to use \"$who\" to determine system run.\n" . - "level Bastille will continue but note that the run\n" . - "level check was skipped.\n\n"); - } - else { - chomp $levelInfo; - my @runlevel = split /\s+/, $levelInfo; - if ((! defined $runlevel[3]) or ($runlevel[3] < 2)) { - &B_log("WARNING","Bastille requires a run-level of 2 or more to run properly.\n" . - "Please move your system to a higher run level and then\n" . - "run 'bastille -b'.\n\n"); - if(defined $runlevel[3]) { - &B_log("ERROR","Current run-level is '$runlevel[3]'.\n\n"); - $exitFlag=1; - } - else { - &B_log("WARNING","Unable to use \"$who\" to determine system run.\n" . - "level Bastille will continue but note that the run\n" . - "level check was skipped.\n\n"); - } - } - else { - &B_log("DEBUG","System run-level is $runlevel[3]\n"); - } - } - - if($exitFlag) { - exit(1); - } - -} - -################################################################### -# &B_swmodify($file); -# This subroutine is called after a file is modified. It will -# redefine the file in the IPD with it's new properties. If -# the file is not in the IPD it does nothing. -# -# uses B_System to make the swmodifications. -################################################################## -sub B_swmodify($){ - my $file = $_[0]; - if(defined &getGlobalSwlist($file)){ - my $swmodify = &getGlobal('BIN',"swmodify"); - my @productsInfo = @{&getGlobalSwlist($file)}; - # running swmodify on files that were altered by this function but - # were created and maintained by SD - foreach my $productInfo (@productsInfo) { - &B_System("$swmodify -x files='$file' $productInfo", - "$swmodify -x files='$file' $productInfo"); - } - } -} - -#################################################################### -# &B_load_ipf_rules($ipfruleset); -# This function enables an ipfruleset. It's a little more -# specific than most API functions, but necessary because -# ipf doesn't return correct exit codes (syntax error results -# in a 0 exit code) -# -# uses ActionLog and ErrorLog to log -# calls crontab directly (to list and to read in new jobs) -################################################################### -sub B_load_ipf_rules ($) { - my $ipfruleset=$_[0]; - - &B_log("DEBUG","# sub B_load_ipf_rules"); - - # TODO: grab ipf.conf dynamically from the rc.config.d files - my $ipfconf = &getGlobal('FILE','ipf.conf'); - - # file system changes - these are straightforward, and the API - # will take care of the revert - &B_create_file($ipfconf); - &B_blank_file($ipfconf, 'a$b'); - &B_append_line($ipfconf, 'a$b', $ipfruleset); - - # runtime changes - - # define binaries - my $grep = &getGlobal('BIN', 'grep'); - my ($ipf, $ipfstat) = &getIPFLocation; - # create backup rules - # This will exit with a non-zero exit code because of the grep - my @oldrules = `$ipfstat -io 2>&1 | $grep -v empty`; - - my @errors=`$ipf -I -Fa -f $ipfconf 2>&1`; - - if(($? >> 8) == 0) { - - &B_set_rc("IPF_START","1"); - &B_set_rc("IPF_CONF","$ipfconf"); - - # swap the rules in - &B_System("$ipf -s","$ipf -s"); - - # now create a "here" document with the previous version of - # the rules and put it into the revert-actions script - &B_revert_log("$ipf -I -Fa -f - <<EOF\n@{oldrules}EOF"); - - if (@errors) { - &B_log("ERROR","ipfilter produced the following errors when\n" . - " loading $ipfconf. You probably had an invalid\n" . - " rule in ". &getGlobal('FILE','customipfrules') ."\n". - "@errors\n"); - } - - } else { - &B_log("ERROR","Unable to run $ipf\n"); - } - -} - - - -#################################################################### -# &B_Schedule($pattern,$cronjob); -# This function schedules a cronjob. If $pattern exists in the -# crontab file, that job will be replaced. Otherwise, the job -# will be appended. -# -# uses ActionLog and ErrorLog to log -# calls crontab directly (to list and to read in new jobs) -################################################################### -sub B_Schedule ($$) { - my ($pattern,$cronjob)=@_; - $cronjob .= "\n"; - - &B_log("DEBUG","# sub B_Schedule"); - my $crontab = &getGlobal('BIN','crontab'); - - my @oldjobs = `$crontab -l 2>/dev/null`; - my @newjobs; - my $patternfound=0; - - foreach my $oldjob (@oldjobs) { - if (($oldjob =~ m/$pattern/ ) and (not($patternfound))) { - push @newjobs, $cronjob; - $patternfound=1; - &B_log("ACTION","changing existing cron job which matches $pattern with\n" . - "$cronjob"); - } elsif ($oldjob !~ m/$pattern/ ) { - &B_log("ACTION","keeping existing cron job $oldjob"); - push @newjobs, $oldjob; - } #implied: else if pattern matches, but we've - #already replaced one, then toss the others. - } - - unless ($patternfound) { - &B_log("ACTION","adding cron job\n$cronjob\n"); - push @newjobs, $cronjob; - } - - if(open(CRONTAB, "|$crontab - 2> /dev/null")) { - print CRONTAB @newjobs; - - # now create a "here" document with the previous version of - # the crontab file and put it into the revert-actions script - &B_revert_log("$crontab <<EOF\n" . "@oldjobs" . "EOF"); - close CRONTAB; - } - - # Now check to make sure it happened, since cron will exit happily - # (retval 0) with no changes if there are any syntax errors - my @editedjobs = `$crontab -l 2>/dev/null`; - - if (@editedjobs ne @newjobs) { - &B_log("ERROR","failed to add cron job:\n$cronjob\n" . - " You probably had an invalid crontab file to start with."); - } - -} - - -#This function turns off a service, given a service name defined in HP-UX.service - -sub B_ch_rc($) { - - my ($service_name)=@_; - - if (&GetDistro != "^HP-UX") { - &B_log("ERROR","Tried to call ch_rc $service_name on a non-HP-UX\n". - " system! Internal Bastille error."); - return undef; - } - my $configfile=""; - my $command = &getGlobal('BIN', 'ch_rc'); - - my $startup_script=&getGlobal('DIR','initd') . "/". $service_name; - my @rc_parameters= @{ &getGlobal('SERVICE',$service_name) }; - my @rcFiles=@{ &getGlobal('RCCONFIG',$service_name) }; - my $rcFile=''; - if (@rcFiles == 1){ - $rcFile=$rcFiles[0]; - } else { - &B_log("FATAL","Multiple RC Files not yet supported... internal error."); - } - - # if the service-related process is not run, and the control variable is stilll 1 - # there is a inconsistency. in this case we only need to change the control variable - my @psnames=@{ &getGlobal('PROCESS',$service_name)}; - my @processes; - foreach my $psname (@psnames) { - $psname .= '\b'; # avoid embedded match; anchor search pattern to trailing word boundry - my @procList = &isProcessRunning($psname); - if(@procList >= 0){ - splice @processes,$#processes+1,0,@procList; - } - } -#Actually set the rc variable - foreach my $rcVariable (@rc_parameters){ - my $orig_value = &B_get_rc($rcVariable); - if ($orig_value eq "" ) { #If variable not set, used the defined file - $configfile=&getGlobal("DIR","rc.config.d") . "/" . $rcFile; - if (not( -f $configfile )) { - &B_create_file($configfile); - } - } - &B_log("DEBUG","In B_ch_rc (no procs), setting $rcVariable to 0 in $configfile" . - ", with an original value of $orig_value with rcfile: $rcFile"); - if ( ! @processes) { # IF there are no processes we don't neet to perform a "stop" - &B_set_rc($rcVariable, "0", $configfile); - } else { - if ( $orig_value !~ "1" ) { #If param is not already 1, the "stop" script won't work - &B_set_rc($rcVariable, "1",$configfile); - } - &B_System ($startup_script . " stop", #stop service, then restart if the user runs bastille -r - $startup_script . " start"); - # set parameter, so that service will stay off after reboots - &B_set_rc($rcVariable, "0", $configfile); - } - } -} - - -# This routine sets a value in a given file -sub B_set_value($$$) { - my ($param, $value, $file)=@_; - - &B_log("DEBUG","B_set_value: $param, $value, $file"); - if (! -e $file ) { - &B_create_file("$file"); - } - - # If a value is already set to something other than $value then reset it. - #Note that though this tests for "$value ="the whole line gets replaced, so - #any pre-existing values are also replaced. - &B_replace_line($file,"^$param\\s*=\\s*","$param=$value\n"); - # If the value is not already set to something then set it. - &B_append_line($file,"^$param\\s*=\\s*$value","$param=$value\n"); - -} - - -################################################################################## -# &B_chperm($owner,$group,$mode,$filename(s)) -# This function changes ownership and mode of a list of files. Takes four -# arguments first the owner next the group and third the new mode in oct and -# last a list of files that the permissions changes should take affect on. -# -# uses: &swmodify and &B_revert_log -################################################################################## -sub B_chperm($$$$) { - my ($newown, $newgrp, $newmode, $file_expr) = @_; - my @files = glob($file_expr); - - my $return = 1; - - foreach my $file (@files){ - my @filestat = stat $file; - my $oldmode = (($filestat[2]/512) % 8) . - (($filestat[2]/64) % 8) . - (($filestat[2]/8) % 8) . - (($filestat[2]) % 8); - - if((chown $newown, $newgrp, $file) != 1 ){ - &B_log("ERROR","Could not change ownership of $file to $newown:$newgrp\n"); - $return = 0; - } - else{ - &B_log("ACTION","Changed ownership of $file to $newown:$newgrp\n"); - # swmodifying file if possible... - &B_swmodify($file); - &B_revert_log(&getGlobal('BIN',"chown") . " $filestat[4]:$filestat[5] $file\n"); - } - - my $newmode_formatted=sprintf "%5lo",$newmode; - - if((chmod $newmode, $file) != 1){ - &B_log("ERROR","Could not change mode of $file to $newmode_formatted\n"); - $return = 0; - } - else{ - &B_log("ACTION","Changed mode of $file to $newmode_formatted\n"); - &B_revert_log(&getGlobal('BIN',"chmod") . " $oldmode $file\n"); - } - - - } - return $return; -} - -############################################################################ -# &B_install_jail($jailname, $jailconfigfile); -# This function takes two arguments ( jail_name, jail_config ) -# It's purpose is to take read in config files that define a -# chroot jail and then generate it bases on that specification -############################################################################ -sub B_install_jail($$) { - - my $jailName = $_[0]; # Name of the jail e.g bind - my $jailConfig = $_[1]; # Name of the jails configuration file - # create the root directory of the jail if it does not exist - &B_create_dir( &getGlobal('BDIR','jail')); - &B_chperm(0,0,0555,&getGlobal('BDIR','jail')); - - # create the Jail dir if it does not exist - &B_create_dir( &getGlobal('BDIR','jail') . "/" . $jailName); - &B_chperm(0,0,0555,&getGlobal('BDIR','jail') . "/". $jailName); - - - my $jailPath = &getGlobal('BDIR','jail') . "/" . $jailName; - my @lines; # used to store no commented no empty config file lines - # open configuration file for desired jail and parse in commands - if(open(JAILCONFIG,"< $jailConfig")) { - while(my $line=<JAILCONFIG>){ - if($line !~ /^\s*\#|^\s*$/){ - chomp $line; - push(@lines,$line); - } - } - close JAILCONFIG; - } - else{ - &B_log("ERROR","Open Failed on filename: $jailConfig\n"); - return 0; - } - # read through commands and execute - foreach my $line (@lines){ - &B_log("ACTION","Install jail: $line\n"); - my @confCmd = split /\s+/,$line; - if($confCmd[0] =~ /dir/){ # if the command say to add a directory - if($#confCmd == 4) { # checking dir Cmd form - if(! (-d $jailPath . "/" . $confCmd[1])){ - #add a directory and change its permissions according - #to the conf file - &B_create_dir( $jailPath . "/" . $confCmd[1]); - &B_chperm((getpwnam($confCmd[3]))[2], - (getgrnam($confCmd[4]))[2], - oct($confCmd[2]), - $jailPath . "/" . $confCmd[1]); - } - } - else { - &B_log("ERROR","Badly Formed Configuration Line:\n$line\n\n"); - } - } - elsif($confCmd[0] =~ /file/) { - if($#confCmd == 5) { # checking file cmd form - if(&B_cp($confCmd[1],$jailPath . "/" . $confCmd[2])){ - # for copy command cp file and change perms - &B_chperm($confCmd[4],$confCmd[5],oct($confCmd[3]),$jailPath . "/" . $confCmd[2]); - } - else { - &B_log("ERROR","Could not complete copy on specified files:\n" . - "$line\n"); - } - } - else { - &B_log("ERROR","Badly Formed Configuration Line:\n" . - "$line\n\n"); - } - } - elsif($confCmd[0] =~ /slink/) { - if($#confCmd == 2) { # checking file cmd form - if(!(-e $jailPath . "/" . $confCmd[2])){ - #for symlink command create the symlink - &B_symlink($jailPath . "/" . $confCmd[1], $confCmd[2]); - } - } - else { - &B_log("ERROR","Badly Formed Configuration Line:\n" . - "$line\n\n"); - } - } - else { - &B_log("ERROR","Unrecognized Configuration Line:\n" . - "$line\n\n"); - } - } - return 1; -} - - - -########################################################################### -# &B_list_processes($service) # -# # -# This subroutine uses the GLOBAL_PROCESS hash to determine if a # -# service's corresponding processes are running on the system. # -# If any of the processes are found to be running then the process # -# name(s) is/are returned by this subroutine in the form of an list # -# If none of the processes that correspond to the service are running # -# then an empty list is returned. # -########################################################################### -sub B_list_processes($) { - - # service name - my $service = $_[0]; - # list of processes related to the service - my @processes=@{ &getGlobal('PROCESS',$service)}; - - # current systems process information - my $ps = &getGlobal('BIN',"ps"); - my $psTable = `$ps -elf`; - - # the list to be returned from the function - my @running_processes; - - # for every process associated with the service - foreach my $process (@processes) { - # if the process is in the process table then - if($psTable =~ m/$process/) { - # add the process to the list, which will be returned - push @running_processes, $process; - } - - } - - # return the list of running processes - return @running_processes; - -} - -############################################################################# -# &B_list_full_processes($service) # -# # -# This subroutine simply grep through the process table for those matching # -# the input argument TODO: Allow B_list process to levereage this code # -# ... Not done this cycle to avoid release risk (late in cycle) # -############################################################################# -sub B_list_full_processes($) { - - # service name - my $procName = $_[0]; - my $ps = &getGlobal('BIN',"ps"); - my @psTable = split(/\n/,`$ps -elf`); - - # for every process associated with the service - my @runningProcessLines = grep(/$procName/ , @psTable); - # return the list of running processes - return @runningProcessLines; -} - -################################################################################ -# &B_deactivate_inetd_service($service); # -# # -# This subroutine will disable all inetd services associated with the input # -# service name. Service name must be a reference to the following hashes # -# GLOBAL_SERVICE GLOBAL_SERVTYPE and GLOBAL_PROCESSES. If processes are left # -# running it will note these services in the TODO list as well as instruct the# -# user in how they remaining processes can be disabled. # -################################################################################ -sub B_deactivate_inetd_service($) { - my $service = $_[0]; - my $servtype = &getGlobal('SERVTYPE',"$service"); - my $inetd_conf = &getGlobal('FILE',"inetd.conf"); - - # check the service type to ensure that it can be configured by this subroutine. - if($servtype ne 'inet') { - &B_log("ACTION","The service \"$service\" is not an inet service so it cannot be\n" . - "configured by this subroutine\n"); - return 0; - } - - # check for the inetd configuration files existence so it may be configured by - # this subroutine. - if(! -e $inetd_conf ) { - &B_log("ACTION","The file \"$inetd_conf\" cannot be located.\n" . - "Unable to configure inetd\n"); - return 0; - } - - # list of service identifiers present in inetd.conf file. - my @inetd_entries = @{ &getGlobal('SERVICE',"$service") }; - - foreach my $inetd_entry (@inetd_entries) { - &B_hash_comment_line($inetd_conf, "^\\s*$inetd_entry"); - } - - # list of processes associated with this service which are still running - # on the system - my @running_processes = &B_list_processes($service); - - if($#running_processes >= 0) { - my $todoString = "\n" . - "---------------------------------------\n" . - "Deactivating Inetd Service: $service\n" . - "---------------------------------------\n" . - "The following process(es) are associated with the inetd service \"$service\".\n" . - "They are most likely associated with a session which was initiated prior to\n" . - "running Bastille. To disable a process see \"kill(1)\" man pages or reboot\n" . - "the system\n" . - "Active Processes:\n" . - "###################################\n"; - foreach my $running_process (@running_processes) { - $todoString .= "\t$running_process\n"; - } - $todoString .= "###################################\n"; - - &B_TODO($todoString); - } - -} - - -################################################################################ -# B_get_rc($key); # -# # -# This subroutine will use the ch_rc binary to get rc.config.d variables # -# values properly escaped and quoted. # -################################################################################ -sub B_get_rc($) { - - my $key=$_[0]; - my $ch_rc = &getGlobal('BIN',"ch_rc"); - - # get the current value of the given parameter. - my $currentValue=`$ch_rc -l -p $key`; - chomp $currentValue; - - if(($? >> 8) == 0 ) { - # escape all meta characters. - # $currentValue =~ s/([\"\`\$\\])/\\$1/g; - # $currentValue = '"' . $currentValue . '"'; - } - else { - return undef; - } - - return $currentValue; -} - - - -################################################################################ -# B_set_rc($key,$value); # -# # -# This subroutine will use the ch_rc binary to set rc.config.d variables. As # -# well as setting the variable this subroutine will set revert strings. # -# # -################################################################################ -sub B_set_rc($$;$) { - - my ($key,$value,$configfile)=@_; - my $ch_rc = &getGlobal('BIN',"ch_rc"); - - # get the current value of the given parameter. - my $currentValue=&B_get_rc($key); - if(defined $currentValue ) { - if ($currentValue =~ /^\"(.*)\"$/ ) { - $currentValue = '"\"' . $1 . '\""'; - } - if ($value =~ /^\"(.*)\"$/ ) { - $value = '"\"' . $1 . '\""'; - } - if ( &B_System("$ch_rc -a -p $key=$value $configfile", - "$ch_rc -a -p $key=$currentValue $configfile") ) { - #ch_rc success - return 1; - } - else { - #ch_rc failure. - return 0; - } - } - else { - &B_log("ERROR","ch_rc was unable to lookup $key\n"); - return 0; - } - -} - - -################################################################################ -# &ChrootHPApache($chrootScript,$httpd_conf,$httpd_bin, -# $apachectl,$apacheJailDir,$serverString); -# -# This subroutine given an chroot script, supplied by the vendor, a -# httpd.conf file, the binary location of httpd, the control script, -# the jail directory, and the servers identification string, descriptive -# string for TODO etc. It makes modifications to httpd.conf so that when -# Apache starts it will chroot itself into the jail that the above -# mentions script creates. -# -# uses B_replace_line B_create_dir B_System B_TODO -# -############################################################################### -sub B_chrootHPapache($$$$$$) { - - my ($chrootScript,$httpd_conf,$httpd_bin,$apachectl,$apacheJailDir,$serverString)= @_; - - my $exportpath = "export PATH=/usr/bin;"; - my $ps = &getGlobal('BIN',"ps"); - my $isRunning = 0; - my $todo_header = 0; - - # checking for a 2.0 version of the apache chroot script. - if(-e $chrootScript ) { - - if(open HTTPD, $httpd_conf) { - while (my $line = <HTTPD>){ - if($line =~ /^\s*Chroot/) { - &B_log("DEBUG","Apache is already running in a chroot as specified by the following line:\n$line\n" . - "which appears in the httpd.conf file. No Apache Chroot action was taken.\n"); - return; - } - } - close(HTTPD); - } - - if(`$ps -ef` =~ $httpd_bin ) { - $isRunning=1; - &B_System("$exportpath " . $apachectl . " stop","$exportpath " . $apachectl . " start"); - } - &B_replace_line($httpd_conf, '^\s*#\s*Chroot' , - "Chroot " . $apacheJailDir); - if(-d &getGlobal('BDIR',"jail")){ - &B_log("DEBUG","Jail directory already exists. No action taken.\n"); - } - else{ - &B_log("ACTION","Jail directory was created.\n"); - &B_create_dir( &getGlobal('BDIR','jail')); - } - - if(-d $apacheJailDir){ - &B_log("DEBUG","$serverString jail already exists. No action taken.\n"); - } - else{ - &B_System(&getGlobal('BIN',"umask") . " 022; $exportpath " . $chrootScript, - &getGlobal('BIN',"echo") . " \"Your $serverString is now running outside of it's\\n" . - "chroot jail. You must manually migrate your web applications\\n" . - "back to your Apache server's httpd.conf defined location(s).\\n". - "After you have completed this, feel free to remove the jail directories\\n" . - "from your machine. Your apache jail directory is located in\\n" . - &getGlobal('BDIR',"jail") . "\\n\" >> " . &getGlobal('BFILE',"TOREVERT")); - - } - if($isRunning){ - &B_System("$exportpath " . $apachectl . " start","$exportpath " . $apachectl . " stop"); - &B_log("ACTION","$serverString is now running in an chroot jail.\n"); - } - - &B_log("ACTION","The jail is located in " . $apacheJailDir . "\n"); - - if ($todo_header !=1){ - &B_TODO("\n---------------------------------\nApache Chroot:\n" . - "---------------------------------\n"); - } - &B_TODO("$serverString Chroot Jail:\n" . - "httpd.conf contains the Apache dependencies. You should\n" . - "review this file to ensure that the dependencies made it\n" . - "into the jail. Otherwise, you run a risk of your Apache server\n" . - "not having access to all its modules and functionality.\n"); - - - } - -} - - -sub isSystemTrusted { - my $getprdef = &getGlobal('BIN',"getprdef"); - my $definition = &B_Backtick("$getprdef -t 2>&1"); - if($definition =~ "System is not trusted.") { - return 0; - } else { - return 1; - } -} - - -sub isTrustedMigrationAvailable { - my $distroVersion=''; - - if (&GetDistro =~ '^HP-UX11.(\d*)') { - $distroVersion=$1; - if ($distroVersion < 23) { # Not available before 11.23 - return 0; #FALSE - } elsif ($distroVersion >= 31) { #Bundled with 11.31 and after - &B_log('DEBUG','isTrustedMigrationAvailable: HP-UX 11.31 always has trusted mode extensions'); - return 1; - } elsif ($distroVersion == 23) { # Optional on 11.23 if filesets installed - if ( -x &getGlobal('BIN',"userdbget") ) { - &B_log('DEBUG','isTrustedMigrationAvailable: Trusted Extensions Installed'); - return 1; - } else { - &B_log('DEBUG','isTrustedMigrationAvailable: Trusted Extensions Not Installed'); - return 0; #FALSE - } - } else { - &B_log('DEBUG','isTrustedMigrationAvailable: ' . &GetDistro . - ' not currently supported for trusted extentions.'); - return 0; #FALSE - } - } else { - &B_log('WARNING','isTrustedMigrationAvailable: HP-UX routine called on Linux system'); - return 0; #FALSE - } -} - - - -########################################################################### -# &checkServiceOnHPUX($service); -# -# Checks if the given service is running on an HP/UX system. This is -# called by B_is_Service_Off(), which is the function that Bastille -# modules should call. -# -# Return values: -# NOTSECURE_CAN_CHANGE() if the service is on -# SECURE_CANT_CHANGE() if the service is off -# INCONSISTENT() if the state of the service cannot be determined -# NOT_INSTALLED() if the s/w isn't insalled -# -########################################################################### -sub checkServiceOnHPUX($) { - my $service=$_[0]; - - # get the list of parameters which could be used to initiate the service - # (could be in /etc/rc.config.d, /etc/inetd.conf, or /etc/inittab, so we - # check all of them) - my @params= @{ &getGlobal('SERVICE',$service) }; - my $grep =&getGlobal('BIN', 'grep'); - my $inetd=&getGlobal('FILE', 'inetd.conf'); - my $inittab=&getGlobal('FILE', 'inittab'); - my $retVals; - my $startup=&getGlobal('DIR','initd') ; - my @inet_bins= @{ &getGlobal('PROCESS',$service) }; - - my $entry_found = 0; - - &B_log("DEBUG","CheckHPUXservice: $service"); - my $full_initd_path = $startup . "/" . $service; - if ($GLOBAL_SERVTYPE{$service} eq "rc") { # look for the init script in /sbin/init.d - if (not(-e $full_initd_path )) { - return NOT_INSTALLED(); - } - } else { #inet-based service, so look for inetd.conf entries. - &B_log("DEBUG","Checking inet service $service"); - my @inet_entries= @{ &getGlobal('SERVICE',$service) }; - foreach my $service (@inet_entries) { - &B_log('DEBUG',"Checking for inetd.conf entry of $service in checkService on HPUX"); - my $service_regex = '^[#\s]*' . $service . '\s+'; - if ( &B_match_line($inetd, $service_regex) ) { # inet entry search - &B_log('DEBUG',"$service present, entry exists"); - $entry_found = 1 ; - } - } - if ($entry_found == 0 ) { - return NOT_INSTALLED(); - } - } - - foreach my $param (@params) { - &B_log("DEBUG","Checking to see if service $service is off.\n"); - if (&getGlobal('SERVTYPE', $service) =~ /rc/) { - my $ch_rc=&getGlobal('BIN', 'ch_rc'); - my $on=&B_Backtick("$ch_rc -l -p $param"); - - $on =~ s/\s*\#.*$//; # remove end-of-line comments - $on =~ s/^\s*\"(.+)\"\s*$/$1/; # remove surrounding double quotes - $on =~ s/^\s*\'(.+)\'\s*$/$1/; # remove surrounding single quotes - $on =~ s/^\s*\"(.+)\"\s*$/$1/; # just in case someone did '"blah blah"' - - chomp $on; - &B_log("DEBUG","ch_rc returned: $param=$on in checkServiceOnHPUX"); - - if ($on =~ /^\d+$/ && $on != 0) { - # service is on - &B_log("DEBUG","CheckService found $param service is set to \'on\' in scripts."); - return NOTSECURE_CAN_CHANGE(); - } - elsif($on =~ /^\s*$/) { - # if the value returned is an empty string return - # INCONSISTENT(), since we don't know what the hard-coded default is. - return INCONSISTENT(); - } - } else { - # those files which rely on comments to determine what gets - # turned on, such as inetd.conf and inittab - my $inettabs=&B_Backtick("$grep -e '^[[:space:]]*$param' $inetd $inittab"); - if ($inettabs =~ /.+/) { # . matches anything except newlines - # service is not off - &B_log("DEBUG","Checking inetd.conf and inittab; found $inettabs"); - ########################### BREAK out, don't skip question - return NOTSECURE_CAN_CHANGE(); - } - } - } # foreach $param - - # boot-time parameters are not set; check processes - # checkprocs for services returns INCONSISTENT() if a service is found - # since a found-service is inconsistent with the above checks. - B_log("DEBUG","Boot-Parameters not set, checking processes."); - if (&runlevel < 2) { # Below runlevel 2, it is unlikely that - #services will be running, so just check "on-disk" state - &B_log("NOTE","Running during boot sequence, so skipping process checks"); - return SECURE_CANT_CHANGE(); - } else { - return &checkProcsForService($service); - } -} - -sub runlevel { - my $who = &getGlobal("BIN", "who"); - my $runlevel = &B_Backtick("$who -r"); - if ($runlevel =~ s/.* run-level (\S).*/$1/) { - &B_log("DEBUG","Runlevel is: $runlevel"); - return $runlevel; - } else { - &B_log("WARNING","Can not determine runlevel, assuming runlevel 3"); - &B_log("DEBUG","Runlevel command output: $runlevel"); - return "3"; #safer since the who command didn't work, we'll assume - # runlevel 3 since that provides more checks. - } -} - -# -# given a profile file, it will return a PATH array set by the file. -# -sub B_get_path($) { - my $file = $_[0]; - my $sh = &getGlobal("BIN", "sh"); - # use (``)[0] is becuase, signal 0 maybe trapped which will produce some stdout - my $path = (`$sh -c '. $file 1>/dev/null 2>&1 < /dev/null ; echo \$PATH'`)[0]; - my @path_arr = split(":", $path); - my %tmp_path; - my %path; - for my $tmpdir (@path_arr) { - chomp $tmpdir; - if ($tmpdir ne "" && ! $tmp_path{$tmpdir}) { - $tmp_path{$tmpdir}++; - } - } - return keys %tmp_path; -} - -# Convert to trusted mode if it's not already -sub convertToTrusted { - &B_log("DEBUG","# sub convertToTrusted \n"); - if( ! &isSystemTrusted) { - - my ($ok, $message) = &isOKtoConvert; - - my $ts_header="\n---------------------------------\nTrusted Systems:\n" . - "---------------------------------\n"; - - if ($ok) { - # actually do the conversion - if(&B_System(&getGlobal('BIN','tsconvert'), &getGlobal('BIN','tsconvert') . " -r")){ - # adjust change times for user passwords to keep them valid - # default is to expire them when converting to a trusted system, - # which can be problematic, especially since some older versions of - # SecureShell do not allow the user to change the password - &B_System(&getGlobal('BIN','modprpw') . " -V", ""); - - my $getprdef = &getGlobal('BIN','getprdef'); - my $oldsettings = &B_Backtick("$getprdef -m lftm,exptm,mintm,expwarn,umaxlntr"); - $oldsettings =~ s/ //g; - - # remove password lifetime and increasing login tries so they - # don't lock themselves out of the system entirely. - # set default expiration time and the like. - my $newsettings="lftm=0,exptm=0,mintm=0,expwarn=0,umaxlntr=10"; - - &B_System(&getGlobal('BIN','modprdef') . " -m $newsettings", - &getGlobal('BIN','modprdef') . " -m $oldsettings"); - - &B_TODO($ts_header . - "Your system has been converted to a trusted system.\n" . - "You should review the security settings available on a trusted system.\n". - "$message"); - - # to get rid of "Cron: Your job did not contain a valid audit ID." - # error, we re-read the crontab file after converting to trusted mode - # Nothing is necessary in "revert" since we won't be in trusted mode - # at that time. - # crontab's errors can be spurious, and this will report an 'error' - # of the crontab file is missing, so we send stderr to the bit bucket - my $crontab = &getGlobal('BIN',"crontab"); - &B_System("$crontab -l 2>/dev/null | $crontab",""); - } - - } else { - &B_TODO($ts_header . $message); - return 0; # not ok to convert, so we didn't - } - } - else { - &B_log("DEBUG","System is already in trusted mode, no action taken.\n"); - return 1; - } - - # just to make sure - if( &isSystemTrusted ) { - return 1; - } else { - &B_log("ERROR","Trusted system conversion was unsuccessful for an unknown reason.\n" . - " You may try using SAM/SMH to do the conversion instead of Bastille.\n"); - return 0; - } -} - -# isOKtoConvert - check for conflicts between current system state and trusted -# mode -# -# Return values -# 0 - conflict found, see message for details -# 1 - no conflicts, see message for further instructions -# -sub isOKtoConvert { - &B_log("DEBUG","# sub isOKtoConvert \n"); - # initialize text for TODO instructions - my $specialinstructions=" - convert to trusted mode\n"; - - # These are somewhat out-of-place, but only affect the text of the message. - # Each of these messages is repeated in a separate TODO item in the - # appropriate subroutine. - if (&getGlobalConfig("AccountSecurity","single_user_password") eq "Y") { - if (&GetDistro =~ "^HP-UX11.(.*)" and $1<23 ) { - $specialinstructions .= " - set a single user password\n"; - } - } - - if (&getGlobalConfig("AccountSecurity","passwordpolicies") eq "Y") { - $specialinstructions .= " - set trusted mode password policies\n"; - } - - if (&getGlobalConfig("AccountSecurity", "PASSWORD_HISTORY_DEPTHyn") eq "Y") { - $specialinstructions .= " - set a password history depth\n"; - } - - if (&getGlobalConfig("AccountSecurity","system_auditing") eq "Y") { - $specialinstructions .= " - enable auditing\n"; - } - - my $saminstructions= - "The security settings can be modified by running SAM as follows:\n" . - "# sam\n" . - "Next, go to the \"Auditing and Security Area\" and review\n" . - "each sub-section. Make sure that you review all of your\n" . - "settings, as some policies may seem restrictive.\n\n" . - "On systems using the System Management Homepage, you can\n". - "change your settings via the Tools:Security Attributes Configuration\n". - "section. On some systems, you may also have the option of using SMH.\n\n"; - - # First, check for possible conflicts and corner cases - - # check nsswitch for possible conflicts - my $nsswitch = &getGlobal('FILE', 'nsswitch.conf'); - if ( -e $nsswitch) { - open(FILE, $nsswitch); - while (<FILE>) { - if (/nis/ or /compat/ or /ldap/) { - my $message = "Bastille found a possible conflict between trusted mode and\n" . - "$nsswitch. Please remove all references to\n" . - "\"compat\", \"nis\" and \"ldap\" in $nsswitch\n" . - "and rerun Bastille, or use SAM/SMH to\n" . - "$specialinstructions\n". - "$saminstructions"; - close(FILE); - return (0,$message); - } - } - close(FILE); - } - - # check the namesvrs config file for possible NIS conflicts - #Changed to unless "Y AND Y" since question can be skipped when nis is off - # but corner cases can still exist, so check then too. - unless ( &getGlobalConfig('MiscellaneousDaemons','nis_client') eq "Y" and - &getGlobalConfig('MiscellaneousDaemons','nis_server') eq "Y" ) { - my $namesvrs = &getGlobal('FILE', 'namesvrs'); - if (open(FILE, $namesvrs)) { - while (<FILE>) { - if (/^NIS.*=["]?1["]?$/) { - my $message= "Possible conflict between trusted mode and NIS found.\n". - "Please use SAM/SMH to\n" . - " - turn off NIS\n" . - "$specialinstructions\n". - "$saminstructions"; - close(FILE); - return (0,$message); - } - } - close(FILE); - } else { - &B_log("ERROR","Unable to open $namesvrs for reading."); - my $message= "Possible conflict between trusted mode and NIS found.\n". - "Please use SAM/SMH to\n" . - " - turn off NIS\n" . - "$specialinstructions\n". - "$saminstructions"; - return (0,$message); - } - if ( &B_match_line (&getGlobal("FILE","passwd"),"^\+:.*")) { - my $message= '"+" entry found in passwd file. These are not\n' . - "compatible with Trusted Mode. Either remove the entries\n" . - "and re-run Bastille, or re-run Bastille, and direct it to\n" . - "disable NIS client and server.\n"; - return (0,$message); - } - - } - - - # check for conflicts with DCE integrated login - my $authcmd = &getGlobal('BIN','auth.adm'); - if ( -e $authcmd ) { - my $retval = system("PATH=/usr/bin $authcmd -q 1>/dev/null 2>&1"); - if ($retval != 0 and $retval != 1) { - my $message="It appears that DCE integrated login is configured on this system.\n" . - "DCE integrated login is incompatible with trusted systems and\n" . - "auditing. Bastille is unable to\n" . - "$specialinstructions" . - "You will need to configure auditing and password policies using DCE.\n\n"; - return (0,$message); - } - } - - if ( -e &getGlobal('FILE','shadow') ) { - my $message="This system has already been converted to shadow passwords.\n" . - "Shadow passwords are incompatible with trusted mode.\n" . - "Bastille is unable to\n" . - "$specialinstructions" . - "If you desire these features, you should use\n". - "\'pwunconv\' to change back to standard passwords,\n". - "and then rerun Bastille.\n\n"; - return (0,$message); - } - - return (1,$saminstructions); -} - -# This routine allows Bastille to determine trusted-mode extension availability - -sub convertToShadow { - - if (&isSystemTrusted) { - # This is an internal error...Bastille should not call this routine - # in this case. Error is here for robustness against future changes. - &B_log("ERROR","This system is already converted to trusted mode.\n" . - " Converting to shadow passwords will not be attempted.\n"); - return 0; - } - - # configuration files on which shadowed passwords depend - my $nsswitch_conf = &getGlobal('FILE',"nsswitch.conf"); - - # binaries used to convert to a shadowed password - my $pwconv = &getGlobal('BIN',"pwconv"); - my $echo = &getGlobal('BIN','echo'); # the echo is used to pipe a yes into the pwconv program as - # pwconv requires user interaction. - - # the binary used in a system revert. - my $pwunconv = &getGlobal('BIN',"pwunconv"); - #check the password file for nis usage and if the nis client - #or server is running. - if(-e $nsswitch_conf) { - # check the file for nis, nis+, compat, or dce usage. - if(&B_match_line($nsswitch_conf, '^\s*passwd:.+(nis|nisplus|dce|compat)')) { - my $shadowTODO = "\n---------------------------------\nHide encrypted passwords:\n" . - "---------------------------------\n" . - "This version of password shadowing does not support any repository other\n" . - "than files. In order to convert your password database to shadowed passwords\n" . - "there can be no mention of nis, nisplus, compat, or dce in the passwd\n" . - "field of the \"$nsswitch_conf\" file. Please make the necessary edits to\n" . - "the $nsswitch_conf file and run Bastille again using the command:\n" . - "\"bastille -b\"\n"; - # Adding the shadowTODO comment to the TODO list. - &B_TODO("$shadowTODO"); - # Notifing the user that the shadowed password coversion has failed. - &B_log("ERROR","Password Shadowing Conversion Failed\n" . - "$shadowTODO"); - # exiting the subroutine. - return 0; - } - - } - - # convert the password file to a shadowed repository. - if (( -e $pwconv ) and ( -e $pwunconv ) and - ( &B_System("$echo \"yes\" | $pwconv","$pwunconv") ) ){ - &B_TODO( "\n---------------------------------\nShadowing Password File:\n" . - "---------------------------------\n" . - "Your password file has been converted to use password shadowing.\n" . - "This version of password shadowing does not support any repository other\n" . - "than files. There can be no mention of nis, nisplus, compat, or dce\n" . - "in the passwd field of the \"$nsswitch_conf\" file.\n\n" ); - } else { - &B_log("ERROR","Conversion to shadow mode failed. The system may require ". - "a patch to be capable of switching to shadow mode, or the ". - "system my be in a state where conversion is not possible."); - } -} - - - -########################################################################## -# &getSupportedSettings(); -# Manipulates %trustedParameter and %isSupportedSetting, file-scoped variables -# -# Reads the password policy support matrix, which in-turn gives Bastille the -# places it should look for a given password policy setting. - -# Note the file was created like this so if could be maintained in an Excel(tm) -# spreadsheet, to optimize reviewability. TODO: consider other formats - -# File Format: -# HEADERS:<comment>,[<OS Version> <Mode> <Extensions>,]... -# [ -# :<label>:<trusted equivalent>,,,,,,,,,,,,<comment> -# <action> (comment), [<test value>,]... -# ] ... -# Example; -# HEADERS:Information Source (trusted equiv),11.11 Standard no-SMSE,11.11 Trusted no-SMSE,11.11 Shadow no-SMSE,11.23 Standard no-SMSE,11.23 Trusted no-SMSE,11.23 Shadow no-SMSE,11.23 Standard SMSE,11.23 Shadow SMSE,11.23 Trusted SMSE,11.31 Trusted SMSE,11.31 Shadow SMSE,11.31 Standard SMSE,Other Exceptions -#:ABORT_LOGIN_ON_MISSING_HOMEDIR,,,,,,,,,,,,,root -#/etc/security.dsc (search),x,,xx,x,x,x,!,!,!,!,!,!, -#/etc/default/security(search),y,y,y,y,y,y,y,y,y,y,y,y, -#getprdef (execute with <Trusted Equiv> argument),x,x,x,x,x,x,x,x,x,x,x,x, - -########################################################################### -our %trustedParameter = (); -our %isSupportedSetting = (); - -sub getSupportedSettings() { - - my $line; # For a config file line - my $linecount = 0; - my $currentsetting = ""; - my @fields; # Fields in a given line - my @columns; #Column Definitions - - - &B_open(*SETTINGSFILE,&getGlobal('BFILE','AccountSecSupport')); - my @settingLines=<SETTINGSFILE>; - &B_close(*SETTINGSFILE); - - #Remove blank-lines and comments - @settingLines = grep(!/^#/,@settingLines); - @settingLines = grep(!/^(\s*,+)*$/,@settingLines); - - foreach $line (@settingLines) { - ++$linecount; - @fields = split(/,/,$line); - if ($line =~ /^Information Source:/) { #Sets up colums - my $fieldcount = 1; #Skipping first field - while ((defined($fields[$fieldcount])) and - ($fields[$fieldcount] =~ /\d+\.\d+/)){ - my @subfields = split(/ /,$fields[$fieldcount]); - my $fieldsCount = @subfields; - if ($fieldsCount != 3){ - &B_log("ERROR","Invalid subfield count: $fieldsCount in:". - &getGlobal('BFILE','AccountSecSupport') . - " line: $linecount and field: $fieldcount"); - } - $columns[$fieldcount] = {OSVersion => $subfields[0], - Mode => $subfields[1], - Extension => $subfields[2] }; - &B_log("DEBUG","Found Header Column, $columns[$fieldcount]{'OSVersion'}, ". - $columns[$fieldcount]{'Mode'} ." , " . - $columns[$fieldcount]{'Extension'}); - ++$fieldcount; - } # New Account Seting ex: - } elsif ($line =~ /^:([^,:]+)(?::([^,]+))?/) { # :PASSWORD_WARNDAYS:expwarn,,,,,,,,,,,, - $currentsetting = $1; - if (defined($2)) { - $trustedParameter{"$currentsetting"}=$2; - } - &B_log("DEBUG","Found Current Setting: ". $currentsetting . - "/" . $trustedParameter{"$currentsetting"}); - } elsif (($line =~ /(^[^, :\)\(]+)[^,]*,((?:(?:[!y?nx]|!!),)+)/) and #normal line w/ in setting ex: - ($currentsetting ne "")){ # security.dsc (search),x,x,x,x,x,!,!!,!,!,!,!, - my $placeToLook = $1; - my $fieldcount = 1; #Skip the first one, which we used in last line - while (defined($fields[$fieldcount])) { - &B_log("DEBUG","Setting $currentsetting : $columns[$fieldcount]{OSVersion} , ". - "$columns[$fieldcount]{Mode} , ". - "$columns[$fieldcount]{Extension} , ". - "$placeToLook, to $fields[$fieldcount]"); - $isSupportedSetting{"$currentsetting"} - {"$columns[$fieldcount]{OSVersion}"} - {"$columns[$fieldcount]{Mode}"} - {"$columns[$fieldcount]{Extension}"} - {"$placeToLook"} = - $fields[$fieldcount]; - ++$fieldcount; - } - } else { - if ($line !~ /^,*/) { - &B_log("ERROR","Incorrectly Formatted Line at ". - &getGlobal('BFILE','AccountSecSupport') . ": $linecount"); - } - } - } -} - -########################################################################## -# &B_get_sec_value($param); -# This subroutine finds the value for a given user policy parameter. -# Specifically, it supports the parameters listed in the internal data structure - -# Return values: -# 'Not Defined' if the value is not present or not uniquely defined. -# $value if the value is present and unique -# -########################################################################### -sub B_get_sec_value($) { - my $param=$_[0]; - - my $os_version; - if (&GetDistro =~ /^HP-UX\D*(\d+\.\d+)/ ){ - $os_version=$1; - } else { - &B_log("ERROR","B_get_sec_value only supported on HP-UX"); - return undef; - } -# my $sec_dsc = &getGlobal('FILE', 'security.dsc'); - my $sec_file = &getGlobal('FILE', 'security'); - my $getprdef = &getGlobal('BIN','getprdef'); - my $getprpw = &getGlobal('BIN','getprpw'); - my $userdbget = &getGlobal('BIN','userdbget'); - my $passwd = &getGlobal('BIN','passwd'); - - my $sec_flags = ""; - my @sec_settings=(); - my $user_sec_setting=""; - - my $security_mode="Standard"; - my $security_extension="no-SMSE"; - - &B_log("DEBUG","Entering get_sec_value for: $param"); - - sub isok ($) { # Locally-scoped subroutine, takes supported-matrix entry as argument - my $supportedMatrixEntry = $_[0]; - - if ($supportedMatrixEntry =~ /!/) { #Matrix Entry for "Documented and/or tested" - &B_log("DEBUG","isOk TRUE: $supportedMatrixEntry"); - return 1; - } else { - &B_log("DEBUG","isOk FALSE: $supportedMatrixEntry"); - return 0; #FALSE - } - } #end local subroutine - - #Get Top Array item non-destructively - sub getTop (@) { - my @incomingArray = @_; - my $topval = pop(@incomingArray); - push(@incomingArray,$topval); #Probably redundant, but left in just in case. - return $topval; - } - - sub ifExistsPushOnSecSettings($$) { - my $sec_settings = $_[0]; - my $pushval = $_[1]; - - if ($pushval ne ""){ - push (@$sec_settings, $pushval); - } - } - - #prpw and prdef both use "YES" instead of "1" like the other settings. - sub normalizePolicy($){ - my $setting = $_[0]; - - $setting =~ s/YES/1/; - $setting =~ s/NO/1/; - - return $setting; - } - - - - if ((%trustedParameter == ()) or (%isSupportedSetting == ())) { - # Manipulates %trustedParameter and %isSupportedSetting - &getSupportedSettings; - } - - #First determine the security mode - my $shadowFile = &getGlobal("FILE","shadow"); - my $passwdFile = &getGlobal("FILE","passwd"); - - if (&isSystemTrusted) { - $security_mode = 'Trusted'; - } elsif ((-e $shadowFile) and #check file exist, and that passwd has no non-"locked" accounts - (not(&B_match_line($passwdFile,'^[^\:]+:[^:]*[^:*x]')))) { - $security_mode = 'Shadow'; - } else { - $security_mode = 'Standard'; - } - if (&isTrustedMigrationAvailable) { - $security_extension = 'SMSE'; - } else { - $security_extension = 'no-SMSE'; - } - &B_log("DEBUG","Security mode: $security_mode extension: $security_extension"); - # Now look up the value from each applicable database, from highest precedence - # to lowest: - &B_log("DEBUG","Checking $param in userdbget"); - if (&isok($isSupportedSetting{$param}{$os_version}{$security_mode} - {$security_extension}{"userdbget_-a"})) { - &ifExistsPushOnSecSettings(\@sec_settings, - &B_getValueFromString('\w+\s+\w+=(\S+)', - &B_Backtick("$userdbget -a $param"))); - &B_log("DEBUG", $param . ":userdbget setting: ". &getTop(@sec_settings)); - } - &B_log("DEBUG","Checking $param in passwd"); - if (&isok($isSupportedSetting{$param}{$os_version}{$security_mode} - {$security_extension}{"passwd_-sa"})) { - if ($param eq "PASSWORD_MINDAYS") { - &ifExistsPushOnSecSettings(\@sec_settings, - &B_getValueFromString('(?:\w+\s+){2}[\d\/]+\s+(\d+)\s+\d+', - &B_Backtick("$passwd -s -a"))); - } elsif ($param eq "PASSWORD_MAXDAYS") { - &ifExistsPushOnSecSettings(\@sec_settings, - &B_getValueFromString('(?:\w+\s+){2}[\d\/]+\s+\d+\s+(\d+)', - &B_Backtick("$passwd -s -a"))); - } elsif ($param eq "PASSWORD_WARNDAYS") { - &ifExistsPushOnSecSettings(\@sec_settings, - &B_getValueFromString('(?:\w+\s+){2}[\d\/]+(?:\s+\d+){2}\s+(\d+)', - &B_Backtick("$passwd -s -a"))); - } - &B_log("DEBUG", $param . ":passwd -sa setting: ". &getTop(@sec_settings)); - } - &B_log("DEBUG","Checking $param in get prpw"); - if (&isok($isSupportedSetting{$param}{$os_version}{$security_mode} - {$security_extension}{"getprpw"})) { - my $logins = &getGlobal("BIN","logins"); - my @userArray = split(/\n/,`$logins`); - my $userParamVals = ''; - foreach my $rawuser (@userArray) { - $rawuser =~ /^(\S+)/; - my $user = $1; - my $nextParamVal=&B_Backtick("$getprpw -l -m $trustedParameter{$param} $user"); - $nextParamVal =~ s/\w*=(-*[\w\d]*)/$1/; - if ($nextParamVal != -1) { #Don't count users for which the local DB is undefined - $userParamVals .= $user . "::::" . $nextParamVal ."\n"; - } - } #Note getValueFromStrings deals with duplicates, returning "Not Unigue" - my $policySetting = &B_getValueFromString('::::(\S+)',"$userParamVals"); - &ifExistsPushOnSecSettings (\@sec_settings, &normalizePolicy($policySetting)); - &B_log("DEBUG", $param . ":prpw setting: ". &getTop(@sec_settings)); - } - &B_log("DEBUG","Checking $param in get prdef"); - if (&isok($isSupportedSetting{$param}{$os_version}{$security_mode} - {$security_extension}{"getprdef"})) { - $_ = &B_Backtick ("$getprdef -m " . $trustedParameter{$param}); - /\S+=(\S+)/; - my $policySetting = $1; - &ifExistsPushOnSecSettings(\@sec_settings, &normalizePolicy($policySetting)); - &B_log("DEBUG", $param . ":prdef setting: ". &getTop(@sec_settings)); - - } - &B_log("DEBUG","Checking $param in default security"); - if (&isok($isSupportedSetting{$param}{$os_version}{$security_mode} - {$security_extension}{"/etc/default/security"})) { - &ifExistsPushOnSecSettings(\@sec_settings,&B_getValueFromFile('^\s*'. $param . - '\s*=\s*([^\s#]+)\s*$', $sec_file)); - &B_log("DEBUG", $param . ":default setting: ". &getTop(@sec_settings)); - } - #Commented below code in 3.0 release to avoid implication that bastille - #had ever set these values explicitly, and the implications to runnable - #config files where Bastille would then apply the defaults as actual policy - #with possible conversion to shadow or similar side-effect. - -# &B_log("DEBUG","Checking $param in security.dsc"); - #security.dsc, only added in if valid for OS/mode/Extension, and nothing else - #is defined (ie: @sec_settings=0) -# if ((&isok($isSupportedSetting{$param}{$os_version}{$security_mode} -# {$security_extension}{"/etc/security.dsc"})) and (@sec_settings == 0)) { -# &ifExistsPushOnSecSettings(\@sec_settings, &B_getValueFromFile('^' . $param . -# ';(?:[-\w/]*;){2}([-\w/]+);', $sec_dsc)); -# &B_log("DEBUG", $param . ":security.dsc: ". &getTop(@sec_settings)); -# } - - # Return what we found - my $last_setting=undef; - my $current_setting=undef; - while (@sec_settings > 0) { - $current_setting = pop(@sec_settings); - &B_log("DEBUG","Comparing $param configuration for identity: " . - $current_setting); - if ((defined($current_setting)) and ($current_setting ne '')) { - if (not(defined($last_setting))){ - $last_setting=$current_setting; - } elsif (($last_setting ne $current_setting) or - ($current_setting eq 'Not Unique')){ - &B_log("DEBUG","$param setting not unique."); - return 'Not Unique'; # Inconsistent state found, return 'Not Unique' - } - } - } - if ((not(defined($last_setting))) or ($last_setting eq '')) { - return undef; - } else { - return $last_setting; - } - -} #End B_get_sec_value - -sub secureIfNoNameService($){ - my $retval = $_[0]; - - if (&isUsingRemoteNameService) { - return MANUAL(); - } else { - return $retval; - } -} - -#Specifically for cleartext protocols like NIS, which are not "secure" -sub isUsingRemoteNameService(){ - - if (&remoteServiceCheck('nis|nisplus|dce') == SECURE_CAN_CHANGE()){ - return 0; #false - } else { - return 1; - } -} - - - -########################################### -## This is a wrapper for two functions that -## test the existence of nis-like configurations -## It is used by both the front end test and the back-end run -############################################## -sub remoteServiceCheck($){ - my $regex = $_[0]; - - my $nsswitch_conf = &getGlobal('FILE',"nsswitch.conf"); - my $passwd = &getGlobal('FILE',"passwd"); - - # check the file for nis usage. - if (-e $nsswitch_conf) { - if (&B_match_line($nsswitch_conf, '^\s*passwd:.*('. $regex . ')')) { - return NOTSECURE_CAN_CHANGE(); - } elsif ((&B_match_line($nsswitch_conf, '^\s*passwd:.*(compat)')) and - (&B_match_line($passwd, '^\s*\+'))) { - return NOTSECURE_CAN_CHANGE(); # true - } - } elsif ((&B_match_line($passwd, '^\s*\+'))) { - return NOTSECURE_CAN_CHANGE(); - } - - my $oldnisdomain=&B_get_rc("NIS_DOMAIN"); - if ((($oldnisdomain eq "") or ($oldnisdomain eq '""')) and (&checkServiceOnHPUX('nis.client'))){ - return SECURE_CAN_CHANGE(); - } - return NOTSECURE_CAN_CHANGE(); -} - -############################################# -# remoteNISPlusServiceCheck -# test the existence of nis+ configuration -############################################# -sub remoteNISPlusServiceCheck () { - - my $nsswitch_conf = &getGlobal('FILE',"nsswitch.conf"); - - # check the file for nis+ usage. - if (-e $nsswitch_conf) { - if (&B_match_line($nsswitch_conf, 'nisplus')) { - return NOTSECURE_CAN_CHANGE(); - } - } - - return &checkServiceOnHPUX('nisp.client'); -} - - -########################################################################## -# This subroutine creates nsswitch.conf file if the file not exists, -# and then append serveral services into the file if the service not -# exists in the file. -########################################################################## -sub B_create_nsswitch_file ($) { - my $regex = $_[0]; - - my $nsswitch = &getGlobal('FILE',"nsswitch.conf"); - - if( ! -f $nsswitch ) { - &B_create_file($nsswitch); - # we don't need to revert the permissions change because we just - # created the file - chmod(0444, $nsswitch); - - &B_append_line($nsswitch,'\s*passwd:', "passwd: $regex\n"); - &B_append_line($nsswitch,'\s*group:', "group: $regex\n"); - &B_append_line($nsswitch,'\s*hosts:', "hosts: $regex\n"); - &B_append_line($nsswitch,'\s*networks:', "networks: $regex\n"); - &B_append_line($nsswitch,'\s*protocols:', "protocols: $regex\n"); - &B_append_line($nsswitch,'\s*rpc:', "rpc: $regex\n"); - &B_append_line($nsswitch,'\s*publickey:', "publickey: $regex\n"); - &B_append_line($nsswitch,'\s*netgroup:', "netgroup: $regex\n"); - &B_append_line($nsswitch,'\s*automount:', "automount: $regex\n"); - &B_append_line($nsswitch,'\s*aliases:', "aliases: $regex\n"); - &B_append_line($nsswitch,'\s*services:', "services: $regex\n"); - } -} - -1; - diff --git a/recipes-security/bastille/files/Miscellaneous.pm b/recipes-security/bastille/files/Miscellaneous.pm deleted file mode 100644 index b3bdf10..0000000 --- a/recipes-security/bastille/files/Miscellaneous.pm +++ /dev/null @@ -1,166 +0,0 @@ -package Bastille::API::Miscellaneous; -use strict; - -use File::Path; -use Bastille::API; -use Bastille::API::HPSpecific; -use Bastille::API::FileContent; - -require Exporter; -our @ISA = qw(Exporter); -our @EXPORT_OK = qw( -PrepareToRun -B_is_package_installed -); -our @EXPORT = @EXPORT_OK; - - -########################################################################### -# -# PrepareToRun sets up Bastille to run. It checks the ARGV array for -# special options and runs ConfigureForDistro to set necessary file -# locations and other global variables. -# -########################################################################### - -sub PrepareToRun { - - # Make sure we're root! - if ( $> != 0 ) { - &B_log("ERROR","Bastille must run as root!\n"); - exit(1); - } - - - # Make any directories that don't exist... - foreach my $dir (keys %GLOBAL_BDIR) { - my $BdirPath = $GLOBAL_BDIR{$dir}; - if ( $BdirPath =~ /^\s*\// ) { #Don't make relative directories - mkpath ($BdirPath,0,0700); - } - } - - if(&GetDistro =~ "^HP-UX") { - &B_check_system; - } - - &B_log("ACTION","\n########################################################\n" . - "# Begin Bastille Run #\n" . - "########################################################\n\n"); - - #read sum file if it exists. - &B_read_sums; - - -# No longer necessary as flags are no longer in sum file, and sums are -# are now checked "real time" - - # check the integrity of the files listed -# for my $file (sort keys %GLOBAL_SUM) { -# &B_check_sum($file); -# } - # write out the newly flagged sums -# &B_write_sums; - - -} - - - -########################################################################### -# &B_is_package_installed($package); -# -# This function checks for the existence of the package named. -# -# TODO: Allow $package to be an expression. -# TODO: Allow optional $version, $release, $epoch arguments so we can -# make sure that the given package is at least as recent as some -# given version number. -# -# scalar return values: -# 0: $package is not installed -# 1: $package is installed -########################################################################### - -sub B_is_package_installed($) { - no strict; - my $package = $_[0]; -# Create a "global" variable with values scoped to this function -# We do this to avoid having to repeatedly swlist/rpm -# when we run B_is_package_installed -local %INSTALLED_PACKAGE_LIST; - - my $distro = &GetDistro; - if ($distro =~ /^HP-UX/) { - if (&checkProcsForService('swagent','ignore_warning') == SECURE_CANT_CHANGE()) { - &B_log("WARNING","Software Distributor Agent(swagent) is not running. Can not tell ". - "if package: $package is installed or not. Bastille will assume not. ". - "If the package is actually installed, Bastille may report or configure incorrectly.". - "To use Bastille-results as-is, please check to ensure $package is not installed, ". - "or re-run with the swagent running to get correct results."); - return 0; #FALSE - } - my $swlist=&getGlobal('BIN','swlist'); - if (%INSTALLED_PACKAGE_LIST == () ) { # re-use prior results - if (open(SWLIST, "$swlist -a state -l fileset |")) { - while (my $line = <SWLIST>){ - if ($line =~ /^ {2}\S+\.(\S+)\s*(\w+)/) { - $INSTALLED_PACKAGE_LIST{$1} = $2; - } - } - close SWLIST; - } else { - &B_log("ERROR","B_is_package_installed was unable to run the swlist command: $swlist,\n"); - return FALSE; - } - } - # Now find the entry - if ($INSTALLED_PACKAGE_LIST{$package} == 'configured') { - return TRUE; - } else { - return FALSE; - } - } #End HP-UX Section - # This routine only works on RPM-based distros: Red Hat, Fedora, Mandrake and SuSE - elsif ( ($distro !~ /^RH/) and ($distro !~ /^MN/) and($distro !~ /^SE/) ) { - return 0; - } else { #This is a RPM-based distro - # Run an rpm command -- librpm is extremely messy, dynamic and not - # so much a perl thing. It's actually barely a C/C++ thing... - if (open RPM,"rpm -q $package") { - # We should get only one line back, but let's parse a few - # just in case. - my @lines = <RPM>; - close RPM; - # - # This is what we're trying to parse: - # $ rpm -q jay - # package jay is not installed - # $ rpm -q bash - # bash-2.05b-305.1 - # - - foreach $line (@lines) { - if ($line =~ /^package\s$package\sis\snot\sinstalled/) { - return 0; - } - elsif ($line =~ /^$package\-/) { - return 1; - } - } - - # If we've read every line without finding one of these, then - # our parsing is broken - &B_log("ERROR","B_is_package_installed was unable to find a definitive RPM present or not present line.\n"); - return 0; - } else { - &B_log("ERROR","B_is_package_installed was unable to run the RPM command,\n"); - return 0; - } - } -} - - - -1; - diff --git a/recipes-security/bastille/files/ServiceAdmin.pm b/recipes-security/bastille/files/ServiceAdmin.pm deleted file mode 100644 index 879223a..0000000 --- a/recipes-security/bastille/files/ServiceAdmin.pm +++ /dev/null @@ -1,690 +0,0 @@ -package Bastille::API::ServiceAdmin; -use strict; - -use Bastille::API; - -use Bastille::API::HPSpecific; -use Bastille::API::FileContent; - -require Exporter; -our @ISA = qw(Exporter); -our @EXPORT_OK = qw( -B_chkconfig_on -B_chkconfig_off -B_service_start -B_service_stop -B_service_restart -B_is_service_off -checkServiceOnLinux -remoteServiceCheck -remoteNISPlusServiceCheck -B_create_nsswitch_file -); -our @EXPORT = @EXPORT_OK; - - -####### -# &B_chkconfig_on and &B_chkconfig_off() are great for systems that didn't use -# a more modern init system. This is a bit of a problem on Fedora, though, -# which used upstart from Fedora 9 to Fedora 14, then switched to a new -# Red Hat-created system called systemd for Fedora 15 and 16 (so far). -# OpenSUSE also moved to systemd, starting with 12.1. Version 11.4 did not -# use systemd. -# It is also a problem on Ubuntu, starting at version 6.10, where they also -# used upstart. -##### - - - - -########################################################################### -# &B_chkconfig_on ($daemon_name) creates the symbolic links that are -# named in the "# chkconfig: ___ _ _ " portion of the init.d files. We -# need this utility, in place of the distro's chkconfig, because of both -# our need to add revert functionality and our need to harden distros that -# are not mounted on /. -# -# It uses the following global variables to find the links and the init -# scripts, respectively: -# -# &getGlobal('DIR', "rcd") -- directory where the rc_.d subdirs can be found -# &getGlobal('DIR', "initd") -- directory the rc_.d directories link to -# -# Here an example of where you might use this: -# -# You'd like to tell the system to run the firewall at boot: -# B_chkconfig_on("bastille-firewall") -# -########################################################################### - -# PW: Blech. Copied B_chkconfig_off() and changed a few things, -# then changed a few more things.... - -sub B_chkconfig_on { - - my $startup_script=$_[0]; - my $retval=1; - - my $chkconfig_line; - my ($runlevelinfo,@runlevels); - my ($start_order,$stop_order,$filetolink); - - &B_log("ACTION","# chkconfig_on enabling $startup_script\n"); - - # In Debian system there is no chkconfig script, run levels are checked - # one by one (jfs) - if (&GetDistro =~/^DB.*/) { - $filetolink = &getGlobal('DIR', "initd") . "/$startup_script"; - if (-x $filetolink) - { - foreach my $level ("0","1","2","3","4","5","6" ) { - my $link = ''; - $link = &getGlobal('DIR', "rcd") . "/rc" . "$level" . ".d/K50" . "$startup_script"; - $retval=symlink($filetolink,$link); - } - } - return $retval; - } - # - # On SUSE, chkconfig-based rc scripts have been replaced with a whole different - # system. chkconfig on SUSE is actually a shell script that does some stuff and then - # calls insserv, their replacement. - # - - if (&GetDistro =~ /^SE/) { - # only try to chkconfig on if init script is found - if ( -e (&getGlobal('DIR', "initd") . "/$startup_script") ) { - $chkconfig_line=&getGlobal('BIN','chkconfig'); - &B_System("$chkconfig_line $startup_script on", "$chkconfig_line $startup_script off"); - # chkconfig doesn't take affect until reboot, need to restart service also - B_service_restart("$startup_script"); - return 1; #success - } - return 0; #failure - } - - # - # Run through the init script looking for the chkconfig line... - # - $retval = open CHKCONFIG,&getGlobal('DIR', "initd") . "/$startup_script"; - unless ($retval) { - &B_log("ACTION","# Didn't chkconfig_on $startup_script because we couldn't open " . &getGlobal('DIR', "initd") . "/$startup_script\n"); - } - else { - - READ_LOOP: - while (my $line=<CHKCONFIG>) { - - # We're looking for lines like this one: - # # chkconfig: 2345 10 90 - # OR this - # # chkconfig: - 10 90 - - if ($line =~ /^#\s*chkconfig:\s*([-\d]+)\s*(\d+)\s*(\d+)/ ) { - $runlevelinfo = $1; - $start_order = $2; - $stop_order = $3; - # handle a run levels arg of '-' - if ( $runlevelinfo eq '-' ) { - &B_log("ACTION","chkconfig_on saw '-' for run levels for \"$startup_script\", is defaulting to levels 3,4,5\n"); - $runlevelinfo = '345'; - } - @runlevels = split(//,$runlevelinfo); - # make sure the orders have 2 digits - $start_order =~ s/^(\d)$/0$1/; - $stop_order =~ s/^(\d)$/0$1/; - last READ_LOOP; - } - } - close CHKCONFIG; - - # Do we have what we need? - if ( (scalar(@runlevels) < 1) || (! $start_order =~ /^\d{2}$/) || (! $stop_order =~ /^\d{2}$/) ) { - # problem - &B_log("ERROR","# B_chkconfig_on $startup_script failed -- no valid run level/start/stop info found\n"); - return(-1); - } - - # Now, run through creating symlinks... - &B_log("ACTION","# chkconfig_on will use run levels ".join(",",@runlevels)." for \"$startup_script\" with S order $start_order and K order $stop_order\n"); - - $retval=0; - # BUG: we really ought to readdir() on &getGlobal('DIR', "rcd") to get all levels - foreach my $level ( "0","1","2","3","4","5","6" ) { - my $link = ''; - # we make K links in run levels not specified in the chkconfig line - $link = &getGlobal('DIR', "rcd") . "/rc" . $level . ".d/K$stop_order" . $startup_script; - my $klink = $link; - # now we see if this is a specified run level; if so, make an S link - foreach my $markedlevel ( @runlevels ) { - if ( $level == $markedlevel) { - $link = &getGlobal('DIR', "rcd") . "/rc" . $level . ".d/S$start_order" . $startup_script; - } - } - my $target = &getGlobal('DIR', "initd") ."/" . $startup_script; - my $local_return; - - if ( (-e "$klink") && ($klink ne $link) ) { - # there's a K link, but this level needs an S link - unless ($GLOBAL_LOGONLY) { - $local_return = unlink("$klink"); - if ( ! $local_return ) { - # unlinking old, bad $klink failed - &B_log("ERROR","Unlinking $klink failed\n"); - } else { - &B_log("ACTION","Removed link $klink\n"); - # If we removed the link, add a link command to the revert file - &B_revert_log (&getGlobal('BIN','ln') . " -s $target $klink\n"); - } # close what to do if unlink works - } # if not GLOBAL_LOGONLY - } # if $klink exists and ne $link - - # OK, we've disposed of any old K links, make what we need - if ( (! ( -e "$link" )) && ($link ne '') ) { - # link doesn't exist and the start/stop number is OK; make it - unless ($GLOBAL_LOGONLY) { - # create the link - $local_return = &B_symlink($target,$link); - if ($local_return) { - $retval++; - &B_log("ACTION","Created link $link\n"); - } else { - &B_log("ERROR","Couldn't create $link when trying to chkconfig on $startup_script\n"); - } - } - - } # link doesn't exist - } # foreach level - - } - - if ($retval < @runlevels) { - $retval=0; - } - - $retval; - -} - - -########################################################################### -# &B_chkconfig_off ($daemon_name) deletes the symbolic links that are -# named in the "# chkconfig: ___ _ _ " portion of the init.d files. We -# need this utility, in place of the distro's chkconfig, because of both -# our need to add revert functionality and our need to harden distros that -# are not mounted on /. -# -# chkconfig allows for a REVERT of its work by writing to an executable -# file &getGlobal('BFILE', "removed-symlinks"). -# -# It uses the following global variables to find the links and the init -# scripts, respectively: -# -# &getGlobal('DIR', "rcd") -- directory where the rc_.d subdirs can be found -# &getGlobal('DIR', "initd") -- directory the rc_.d directories link to -# -# Here an example of where you might use this: -# -# You'd like to tell stop running sendmail in daemon mode on boot: -# B_chkconfig_off("sendmail") -# -########################################################################### - - - -sub B_chkconfig_off { - - my $startup_script=$_[0]; - my $retval=1; - - my $chkconfig_line; - my @runlevels; - my ($start_order,$stop_order,$filetolink); - - if (&GetDistro =~/^DB.*/) { - $filetolink = &getGlobal('DIR', "initd") . "/$startup_script"; - if (-x $filetolink) - { - # Three ways to do this in Debian: - # 1.- have the initd script set to 600 mode - # 2.- Remove the links in rcd (re-installing the package - # will break it) - # 3.- Use update-rc.d --remove (same as 2.) - # (jfs) - &B_chmod(0600,$filetolink); - $retval=6; - - # The second option - #foreach my $level ("0","1","2","3","4","5","6" ) { - #my $link = ''; - #$link = &getGlobal('DIR', "rcd") . "/rc" . "$level" . ".d/K50" . "$startup_script"; - #unlink($link); - #} - } - } - - # - # On SUSE, chkconfig-based rc scripts have been replaced with a whole different - # system. chkconfig on SUSE is actually a shell script that does some stuff and then - # calls insserv, their replacement. - # - elsif (&GetDistro =~ /^SE/) { - # only try to chkconfig off if init script is found - if ( -e (&getGlobal('DIR', "initd") . "/$startup_script") ) { - $chkconfig_line=&getGlobal('BIN','chkconfig'); - &B_System("$chkconfig_line $startup_script on", "$chkconfig_line $startup_script off"); - # chkconfig doesn't take affect until reboot, need to stop service - # since expectation is that the daemons are disabled even without a reboot - B_service_stop("$startup_script"); - return 1; #success - } - return 0; #failure - } - else { - - # Run through the init script looking for the chkconfig line... - - - $retval = open CHKCONFIG,&getGlobal('DIR', "initd") . "/$startup_script"; - unless ($retval) { - &B_log("ACTION","Didn't chkconfig_off $startup_script because we couldn't open " . &getGlobal('DIR', "initd") . "/$startup_script\n"); - } - else { - - READ_LOOP: - while (my $line=<CHKCONFIG>) { - - # We're looking for lines like this one: - # # chkconfig: 2345 10 90 - - if ($line =~ /^#\s*chkconfig:\s*([-\d]+)\s*(\d+)\s*(\d+)/ ) { - @runlevels=split //,$1; - $start_order=$2; - $stop_order=$3; - - - # Change single digit run levels to double digit -- otherwise, - # the alphabetic ordering chkconfig depends on fails. - if ($start_order =~ /^\d$/ ) { - $start_order = "0" . $start_order; - &B_log("ACTION","chkconfig_off converted start order to $start_order\n"); - } - if ($stop_order =~ /^\d$/ ) { - $stop_order = "0" . $stop_order; - &B_log("ACTION","chkconfig_off converted stop order to $stop_order\n"); - } - - last READ_LOOP; - } - } - close CHKCONFIG; - - # If we never found a chkconfig line, can we just run through all 5 - # rcX.d dirs from 1 to 5...? - - # unless ( $start_order and $stop_order ) { - # @runlevels=("1","2","3","4","5"); - # $start_order = "*"; $stop_order="*"; - # } - - # Now, run through removing symlinks... - - - - $retval=0; - - # Handle the special case that the run level specified is solely "-" - if ($runlevels[0] =~ /-/) { - @runlevels = ( "0","1","2","3","4","5","6" ); - } - - foreach my $level ( @runlevels ) { - my $link = &getGlobal('DIR', "rcd") . "/rc" . $level . ".d/S$start_order" . $startup_script; - my $new_link = &getGlobal('DIR', "rcd") . "/rc" . $level . ".d/K$stop_order" . $startup_script; - my $target = &getGlobal('DIR', "initd") ."/" . $startup_script; - my $local_return; - - - # Replace the S__ link in this level with a K__ link. - if ( -e $link ) { - unless ($GLOBAL_LOGONLY) { - $local_return=unlink $link; - if ($local_return) { - $local_return=symlink $target,$new_link; - unless ($local_return) { - &B_log("ERROR","Linking $target to $new_link failed.\n"); - } - } - else { # unlinking failed - &B_log("ERROR","Unlinking $link failed\n"); - } - - } - if ($local_return) { - $retval++; - &B_log("ACTION","Removed link $link\n"); - - # - # If we removed the link, add a link command to the revert file - # Write out the revert information for recreating the S__ - # symlink and deleting the K__ symlink. - &B_revert_log(&getGlobal('BIN',"ln") . " -s $target $link\n"); - &B_revert_log(&getGlobal('BIN',"rm") . " -f $new_link\n"); - } - else { - &B_log("ERROR","B_chkconfig_off $startup_script failed\n"); - } - - } - } # foreach - - } # else-unless - - } # else-DB - if ($retval < @runlevels) { - $retval=0; - } - - $retval; - -} - - -########################################################################### -# &B_service_start ($daemon_name) -# Starts service on RedHat/SUSE-based Linux distributions which have the -# service command: -# -# service $daemon_name start -# -# Other Linux distros that also support this method of starting -# services can be added to use this function. -# -# Here an example of where you might use this: -# -# You'd like to tell the system to start the vsftpd daemon: -# &B_service_start("vsftpd") -# -# Uses &B_System in HP_API.pm -# To match how the &B_System command works this method: -# returns 1 on success -# returns 0 on failure -########################################################################### - -sub B_service_start { - - my $daemon=$_[0]; - - if ( (&GetDistro !~ /^SE/) and (&GetDistro !~ /^RH/) and - (&GetDistro !~ /^RHFC/) and (&GetDistro !~ /^MN/) ) { - &B_log("ERROR","Tried to call service_start on a system lacking a service command! Internal Bastille error."); - return undef; - } - - # only start service if init script is found - if ( -e (&getGlobal('DIR', 'initd') . "/$daemon") ) { - &B_log("ACTION","# service_start enabling $daemon\n"); - - my $service_cmd=&getGlobal('BIN', 'service'); - if ($service_cmd) { - # Start the service, - # Also provide &B_System revert command - - return (&B_System("$service_cmd $daemon start", - "$service_cmd $daemon stop")); - } - } - - # init script not found, do not try to start, return failure - return 0; -} - -########################################################################### -# &B_service_stop ($daemon_name) -# Stops service on RedHat/SUSE-based Linux distributions which have the -# service command: -# -# service $daemon_name stop -# -# Other Linux distros that also support this method of starting -# services can be added to use this function. -# Stops service. -# -# -# Here an example of where you might use this: -# -# You'd like to tell the system to stop the vsftpd daemon: -# &B_service_stop("vsftpd") -# -# Uses &B_System in HP_API.pm -# To match how the &B_System command works this method: -# returns 1 on success -# returns 0 on failure -########################################################################### - -sub B_service_stop { - - my $daemon=$_[0]; - - if ( (&GetDistro !~ /^SE/) and (&GetDistro !~ /^RH/) and - (&GetDistro !~ /^RHFC/) and (&GetDistro !~ /^MN/) ) { - &B_log("ERROR","Tried to call service_stop on a system lacking a service command! Internal Bastille error."); - return undef; - } - - # only stop service if init script is found - if ( -e (&getGlobal('DIR', 'initd') . "/$daemon") ) { - &B_log("ACTION","# service_stop disabling $daemon\n"); - - my $service_cmd=&getGlobal('BIN', 'service'); - if ($service_cmd) { - - # Stop the service, - # Also provide &B_System revert command - - return (&B_System("$service_cmd $daemon stop", - "$service_cmd $daemon start")); - } - } - - # init script not found, do not try to stop, return failure - return 0; -} - - -########################################################################### -# &B_service_restart ($daemon_name) -# Restarts service on RedHat/SUSE-based Linux distributions which have the -# service command: -# -# service $daemon_name restart -# -# Other Linux distros that also support this method of starting -# services can be added to use this function. -# -# Here an example of where you might use this: -# -# You'd like to tell the system to restart the vsftpd daemon: -# &B_service_restart("vsftpd") -# -# Uses &B_System in HP_API.pm -# To match how the &B_System command works this method: -# returns 1 on success -# returns 0 on failure -########################################################################### - -sub B_service_restart { - - my $daemon=$_[0]; - - if ( (&GetDistro !~ /^SE/) and (&GetDistro !~ /^RH/) and - (&GetDistro !~ /^RHFC/) and (&GetDistro !~ /^MN/) ) { - &B_log("ERROR","Tried to call service_restart on a system lacking a service command! Internal Bastille error."); - return undef; - } - - # only restart service if init script is found - if ( -e (&getGlobal('DIR', 'initd') . "/$daemon") ) { - &B_log("ACTION","# service_restart re-enabling $daemon\n"); - - my $service_cmd=&getGlobal('BIN', 'service'); - if ($service_cmd) { - - # Restart the service - return (&B_System("$service_cmd $daemon restart", - "$service_cmd $daemon restart")); - } - } - - # init script not found, do not try to restart, return failure - return 0; -} - -########################################################################### -# &B_is_service_off($;$) -# -# Runs the specified test to determine whether or not the question should -# be answered. -# -# return values: -# NOTSECURE_CAN_CHANGE()/0: service is on -# SECURE_CANT_CHANGE()/1: service is off -# undef: test is not defined -########################################################################### - -sub B_is_service_off ($){ - my $service=$_[0]; - - if(&GetDistro =~ "^HP-UX"){ - #die "Why do I think I'm on HPUX?!\n"; - return &checkServiceOnHPUX($service); - } - elsif ( (&GetDistro =~ "^RH") || (&GetDistro =~ "^SE") ) { - return &checkServiceOnLinux($service); - } - else { - &B_log("DEBUG","B_is_service off called for unsupported OS"); - # not yet implemented for other distributions of Linux - # when GLOBAL_SERVICE, GLOBAL_SERVTYPE and GLOBAL_PROCESS are filled - # in for Linux, then - # at least inetd and inittab services should be similar to the above, - # whereas chkconfig would be used on some Linux distros to determine - # if non-inetd/inittab services are running at boot time. Looking at - # processes should be similar. - return undef; - } -} - -########################################################################### -# &checkServiceOnLinux($service); -# -# Checks if the given service is running on a Linux system. This is -# called by B_is_Service_Off(), which is the function that Bastille -# modules should call. -# -# Return values: -# NOTSECURE_CAN_CHANGE() if the service is on -# SECURE_CANT_CHANGE() if the service is off -# undef if the state of the service cannot be determined -# -########################################################################### -sub checkServiceOnLinux($) { - my $service=$_[0]; - - # get the list of parameters which could be used to initiate the service - # (could be in /etc/rc.d/rc?.d, /etc/inetd.conf, or /etc/inittab, so we - # check all of them) - - my @params = @{ &getGlobal('SERVICE', $service) }; - my $chkconfig = &getGlobal('BIN', 'chkconfig'); - my $grep = &getGlobal('BIN', 'grep'); - my $inittab = &getGlobal('FILE', 'inittab'); - my $serviceType = &getGlobal('SERVTYPE', $service);; - - # A kludge to get things running because &getGlobal('SERVICE' doesn't - # return the expected values. - @params = (); - push (@params, $service); - - foreach my $param (@params) { - &B_log("DEBUG","Checking to see if service $service is off.\n"); - - if ($serviceType =~ /rc/) { - my $on = &B_Backtick("$chkconfig --list $param 2>&1"); - if ($on =~ /^$param:\s+unknown/) { - # This service isn't installed on the system - return NOT_INSTALLED(); - } - if ($on =~ /^error reading information on service $param: No such file or directory/) { - # This service isn't installed on the system - return NOT_INSTALLED(); - } - if ($on =~ /^error/) { - # This probably - &B_log("DEBUG","chkconfig returned: $param=$on\n"); - return undef; - } - $on =~ s/^$param\s+//; # remove the service name and spaces - $on =~ s/[0-6]:off\s*//g; # remove any runlevel:off entries - $on =~ s/:on\s*//g; # remove the :on from the runlevels - # what remains is a list of runlevels in which the service is on, - # or a null string if it is never turned on - chomp $on; # newline should be gone already (\s) - &B_log("DEBUG","chkconfig returned: $param=$on\n"); - - if ($on =~ /^\d+$/) { - # service is not off - ########################### BREAK out, don't skip question - return NOTSECURE_CAN_CHANGE(); - } - } - elsif ($serviceType =~ /inet/) { - my $on = &B_Backtick("$chkconfig --list $param 2>&1"); - if ($on =~ /^$param:\s+unknown/) { - # This service isn't installed on the system - return NOT_INSTALLED(); - } - if ($on =~ /^error reading information on service $param: No such file or directory/) { - # This service isn't installed on the system - return NOT_INSTALLED(); - } - if ($on =~ /^error/ ) { - # Something else is wrong? - # return undef - return undef; - } - if ($on =~ tr/\n// > 1) { - $on =~ s/^xinetd.+\n//; - } - $on =~ s/^\s*$param:?\s+//; # remove the service name and spaces - chomp $on; # newline should be gone already (\s) - &B_log("DEBUG","chkconfig returned: $param=$on\n"); - - if ($on =~ /^on$/) { - # service is not off - ########################### BREAK out, don't skip question - return NOTSECURE_CAN_CHANGE(); - } - } - else { - # perhaps the service is started by inittab - my $inittabline = &B_Backtick("$grep -E '^[^#].{0,3}:.*:.+:.*$param' $inittab"); - if ($inittabline =~ /.+/) { # . matches anything except newlines - # service is not off - &B_log("DEBUG","Checking inittab; found $inittabline\n"); - ########################### BREAK out, don't skip question - return NOTSECURE_CAN_CHANGE(); - } - } - } # foreach my $param - - - # boot-time parameters are not set; check processes - # Note the checkProcsforService returns INCONSISTENT() if a process is found - # assuming the checks above - return &checkProcsForService($service); -} - -1; - - diff --git a/recipes-security/bastille/files/accept_os_flag_in_backend.patch b/recipes-security/bastille/files/accept_os_flag_in_backend.patch deleted file mode 100644 index 4a438e4..0000000 --- a/recipes-security/bastille/files/accept_os_flag_in_backend.patch +++ /dev/null @@ -1,34 +0,0 @@ -Upstream Status: Inappropriate [No upstream maintenance] - -Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> - ---- - -Index: Bastille/BastilleBackEnd -=================================================================== ---- Bastille.orig/BastilleBackEnd 2013-08-21 12:40:54.000000000 -0400 -+++ Bastille/BastilleBackEnd 2013-08-21 12:43:21.895950001 -0400 -@@ -52,11 +52,13 @@ - my $force = 0; - my $debug = 0; - my $alternate_config=undef; -+my $os_version=undef; - - if( Getopt::Long::GetOptions( "n" => \$nodisclaim, - "v" => \$verbose, - "force" => \$force, - "f=s" => \$alternate_config, -+ "os=s" => \$os_version, - "debug" => \$debug) ) { - $error = 0; # no parse error - -@@ -66,7 +68,8 @@ - - &setOptions( - debug => $debug, -- verbose => $verbose); -+ verbose => $verbose, -+ os => $os_version); - &ConfigureForDistro; - - if ( $error ) { # GetOptions couldn't parse all of the args diff --git a/recipes-security/bastille/files/allow_os_with_assess.patch b/recipes-security/bastille/files/allow_os_with_assess.patch deleted file mode 100644 index e112f90..0000000 --- a/recipes-security/bastille/files/allow_os_with_assess.patch +++ /dev/null @@ -1,43 +0,0 @@ -Upstream Status: Inappropriate [No upstream maintenance] - -Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> - ---- - -Index: Bastille/bin/bastille -=================================================================== ---- Bastille.orig/bin/bastille 2013-08-21 08:59:06.647950000 -0400 -+++ Bastille/bin/bastille 2013-08-21 15:55:53.193631711 -0400 -@@ -195,7 +195,6 @@ - systemFileLocations - - isAssessing='no' --nonXArg='no' - - if [ $PERL_V_MAJ -eq $MIN_V_MAJ -a $PERL_V_MIN -lt $MIN_V_MIN -o $PERL_V_MAJ -lt $MIN_V_MAJ ]; then # invalid Perl - printErr -@@ -316,12 +315,10 @@ - '--os') - options_left="$options_left --os" - optarg='yes' -- nonXArg='yes' - ;; - '-f') - options_left="$options_left -f" - optarg='yes' -- nonXArg='yes' - ;; - # Non-exclusive (undocumented and unsupported) options follow: - # There is no validity/combination checking done with these. -@@ -345,11 +342,6 @@ - fi - done - --#Detect case where -f or --os attempted use with --assess -- if [ \( x$nonXArg = xyes \) -a \( x$isAssessing = xyes \) ]; then -- printUsage -- exit 2 -- fi - - # We have a valid version of perl! Verify that all the required - # modules can be found. diff --git a/recipes-security/bastille/files/call_output_config.patch b/recipes-security/bastille/files/call_output_config.patch deleted file mode 100644 index 1e898b1..0000000 --- a/recipes-security/bastille/files/call_output_config.patch +++ /dev/null @@ -1,19 +0,0 @@ -Upstream Status: Inappropriate [No upstream maintenance] - -Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> - ---- - -Index: Bastille/Bastille_Curses.pm -=================================================================== ---- Bastille.orig/Bastille_Curses.pm 2013-08-21 08:58:53.899950000 -0400 -+++ Bastille/Bastille_Curses.pm 2013-08-21 09:20:20.295950005 -0400 -@@ -84,7 +84,7 @@ - } - - # Output answers to the script and display -- &checkAndSaveConfig(&getGlobal('BFILE', "config")); -+ &outputConfig; - - # Run Bastille - diff --git a/recipes-security/bastille/files/config b/recipes-security/bastille/files/config deleted file mode 100755 index 9e5e206..0000000 --- a/recipes-security/bastille/files/config +++ /dev/null @@ -1,106 +0,0 @@ -# Q: Would you like to enforce password aging? [Y] -AccountSecurity.passwdage="Y" -# Q: Should Bastille disable clear-text r-protocols that use IP-based authentication? [Y] -AccountSecurity.protectrhost="Y" -# Q: Should we disallow root login on tty's 1-6? [N] -AccountSecurity.rootttylogins="Y" -# Q: What umask would you like to set for users on the system? [077] -AccountSecurity.umask="077" -# Q: Do you want to set the default umask? [Y] -AccountSecurity.umaskyn="Y" -# Q: Would you like to deactivate the Apache web server? [Y] -Apache.apacheoff="Y" -# Q: Would you like to password protect single-user mode? [Y] -BootSecurity.passsum="Y" -# Q: Should we restrict console access to a small group of user accounts? [N] -ConfigureMiscPAM.consolelogin="Y" -# Q: Which accounts should be able to login at console? [root] -ConfigureMiscPAM.consolelogin_accounts="root" -# Q: Would you like to put limits on system resource usage? [N] -ConfigureMiscPAM.limitsconf="Y" -# Q: Would you like to set more restrictive permissions on the administration utilities? [N] -FilePermissions.generalperms_1_1="Y" -# Q: Would you like to disable SUID status for mount/umount? -FilePermissions.suidmount="Y" -# Q: Would you like to disable SUID status for ping? [Y] -FilePermissions.suidping="Y" -# Q: Would you like to disable SUID status for traceroute? [Y] -FilePermissions.suidtrace="Y" -# Q: Do you need the advanced networking options? -Firewall.ip_advnetwork="Y" -# Q: Should Bastille run the firewall and enable it at boot time? [N] -Firewall.ip_enable_firewall="Y" -# Q: Would you like to run the packet filtering script? [N] -Firewall.ip_intro="Y" -# Q: Interfaces for DHCP queries: [ ] -Firewall.ip_s_dhcpiface=" " -# Q: DNS servers: [0.0.0.0/0] -Firewall.ip_s_dns="10.184.9.1" -# Q: ICMP allowed types: [destination-unreachable echo-reply time-exceeded] -Firewall.ip_s_icmpallowed="destination-unreachable echo-reply time-exceeded" -# Q: ICMP services to audit: [ ] -Firewall.ip_s_icmpaudit=" " -# Q: ICMP types to disallow outbound: [destination-unreachable time-exceeded] -Firewall.ip_s_icmpout="destination-unreachable time-exceeded" -# Q: Internal interfaces: [ ] -Firewall.ip_s_internaliface=" " -# Q: TCP service names or port numbers to allow on private interfaces: [ ] -Firewall.ip_s_internaltcp=" " -# Q: UDP service names or port numbers to allow on private interfaces: [ ] -Firewall.ip_s_internaludp=" " -# Q: Masqueraded networks: [ ] -Firewall.ip_s_ipmasq=" " -# Q: Kernel modules to masquerade: [ftp raudio vdolive] -Firewall.ip_s_kernelmasq="ftp raudio vdolive" -# Q: NTP servers to query: [ ] -Firewall.ip_s_ntpsrv=" " -# Q: Force passive mode? [N] -Firewall.ip_s_passiveftp="N" -# Q: Public interfaces: [eth+ ppp+ slip+] -Firewall.ip_s_publiciface="eth+ ppp+ slip+" -# Q: TCP service names or port numbers to allow on public interfaces:[ ] -Firewall.ip_s_publictcp=" " -# Q: UDP service names or port numbers to allow on public interfaces:[ ] -Firewall.ip_s_publicudp=" " -# Q: Reject method: [DENY] -Firewall.ip_s_rejectmethod="DENY" -# Q: Enable source address verification? [Y] -Firewall.ip_s_srcaddr="Y" -# Q: TCP services to audit: [telnet ftp imap pop3 finger sunrpc exec login linuxconf ssh] -Firewall.ip_s_tcpaudit="telnet ftp imap pop3 finger sunrpc exec login linuxconf ssh" -# Q: TCP services to block: [2049 2065:2090 6000:6020 7100] -Firewall.ip_s_tcpblock="2049 2065:2090 6000:6020 7100" -# Q: Trusted interface names: [lo] -Firewall.ip_s_trustiface="lo" -# Q: UDP services to audit: [31337] -Firewall.ip_s_udpaudit="31337" -# Q: UDP services to block: [2049 6770] -Firewall.ip_s_udpblock="2049 6770" -# Q: Would you like to add additional logging? [Y] -Logging.morelogging="Y" -# Q: Would you like to set up process accounting? [N] -Logging.pacct="N" -# Q: Do you have a remote logging host? [N] -Logging.remotelog="N" -# Q: Would you like to disable acpid and/or apmd? [Y] -MiscellaneousDaemons.apmd="Y" -# Q: Would you like to deactivate NFS and Samba? [Y] -MiscellaneousDaemons.remotefs="Y" -# Q: Would you like to disable printing? [N] -Printing.printing="Y" -# Q: Would you like to disable printing? [N] -Printing.printing_cups="Y" -# Q: Would you like to display "Authorized Use" messages at log-in time? [Y] -SecureInetd.banners="Y" -# Q: Should Bastille ensure inetd's FTP service does not run on this system? [y] -SecureInetd.deactivate_ftp="Y" -# Q: Should Bastille ensure the telnet service does not run on this system? [y] -SecureInetd.deactivate_telnet="Y" -# Q: Who is responsible for granting authorization to use this machine? -SecureInetd.owner="its owner" -# Q: Would you like to set a default-deny on TCP Wrappers and xinetd? [N] -SecureInetd.tcpd_default_deny="Y" -# Q: Do you want to stop sendmail from running in daemon mode? [Y] -Sendmail.sendmaildaemon="Y" -# Q: Would you like to install TMPDIR/TMP scripts? [N] -TMPDIR.tmpdir="N" diff --git a/recipes-security/bastille/files/do_not_apply_config.patch b/recipes-security/bastille/files/do_not_apply_config.patch deleted file mode 100644 index 574aa98..0000000 --- a/recipes-security/bastille/files/do_not_apply_config.patch +++ /dev/null @@ -1,40 +0,0 @@ -Upstream Status: Inappropriate [No upstream maintenance] - -Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> - ---- - -Index: Bastille/Bastille_Curses.pm -=================================================================== ---- Bastille.orig/Bastille_Curses.pm 2013-08-27 16:43:39.130959000 -0400 -+++ Bastille/Bastille_Curses.pm 2013-08-27 16:43:39.794959000 -0400 -@@ -83,11 +83,6 @@ - # Output answers to the script and display - &outputConfig; - -- # Run Bastille -- -- &Run_Bastille_with_Config; -- -- - # Display Credits - - open CREDITS,"/usr/share/Bastille/Credits"; -Index: Bastille/InteractiveBastille -=================================================================== ---- Bastille.orig/InteractiveBastille 2013-08-27 16:43:39.434959000 -0400 -+++ Bastille/InteractiveBastille 2013-08-27 17:18:55.758959000 -0400 -@@ -531,10 +531,10 @@ - " Please address bug reports and suggestions to jay\@bastille-linux.org\n" . - "\n"; - -- $InterfaceEndScreenDescription = "We will now implement the choices you have made here.\n\n" . -+ $InterfaceEndScreenDescription = "We will now record the choices you have made here.\n\n" . - "Answer NO if you want to go back and make changes!\n"; -- $InterfaceEndScreenQuestion = "Are you finished answering the questions, i.e. may we make the changes?"; -- $InterfaceEndScreenNoEpilogue = "Please use Back/Next buttons to move among the questions you wish to\nchange.\n\nChoose YES on this question later to implement your choices.\n"; -+ $InterfaceEndScreenQuestion = "Are you finished answering the questions, i.e. may we record the answers and exit?"; -+ $InterfaceEndScreenNoEpilogue = "Please use Back/Next buttons to move among the questions you wish to\nchange.\n\nChoose YES on this question later to record your choices.\n"; - require Bastille_Curses; - } elsif ($GLOBAL_AUDITONLY) { - diff --git a/recipes-security/bastille/files/edit_usage_message.patch b/recipes-security/bastille/files/edit_usage_message.patch deleted file mode 100644 index 72cdc2f..0000000 --- a/recipes-security/bastille/files/edit_usage_message.patch +++ /dev/null @@ -1,32 +0,0 @@ -Upstream Status: Inappropriate [No upstream maintenance] - -Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> - ---- - -Index: Bastille/bin/bastille -=================================================================== ---- Bastille.orig/bin/bastille 2013-08-25 14:16:35.614779001 -0400 -+++ Bastille/bin/bastille 2013-08-25 14:16:38.674779000 -0400 -@@ -60,7 +60,7 @@ - printUsage () { - cat >&2 << EOF - $ERRSPACES Usage: bastille [ -b | -c | -x ] [ --os <version>] [ -f <alternate config> ] --$ERRSPACES bastille [-r | -l | -h | --assess | --assessnobrowser ] -+$ERRSPACES bastille [-r | -l | -h | --assess | --assessnobrowser ] [ --os <version> ] - $ERRSPACES -b : use a saved config file to apply changes - $ERRSPACES directly to system - $ERRSPACES -c : use the Curses (non-X11) GUI, not available on HP-UX -Index: Bastille/Bastille/API.pm -=================================================================== ---- Bastille.orig/Bastille/API.pm 2013-08-25 08:15:40.266779002 -0400 -+++ Bastille/Bastille/API.pm 2013-08-25 14:18:22.750778811 -0400 -@@ -206,7 +206,7 @@ - #options before interactive or Bastille runs, so this check is often redundant - $GLOBAL_ERROR{"usage"}="\n". - "$spc Usage: bastille [ -b | -c | -x ] [ --os <version> ] [ -f <alternate config> ]\n". -- "$spc bastille [ -r | --assess | --assessnobowser ]\n\n". -+ "$spc bastille [ -r | --assess | --assessnobowser ] [ --os <version> ]\n\n". - "$spc --assess : check status of system and report in browser\n". - "$spc --assessnobrowser : check status of system and list report locations\n". - "$spc -b : use a saved config file to apply changes\n". diff --git a/recipes-security/bastille/files/find_existing_config.patch b/recipes-security/bastille/files/find_existing_config.patch deleted file mode 100644 index c075875..0000000 --- a/recipes-security/bastille/files/find_existing_config.patch +++ /dev/null @@ -1,64 +0,0 @@ -Upstream Status: Inappropriate [No upstream maintenance] - -Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> - ---- - -Index: Bastille/bin/bastille -=================================================================== ---- Bastille.orig/bin/bastille 2013-06-20 14:58:01.065796000 -0400 -+++ Bastille/bin/bastille 2013-08-20 15:16:18.472378000 -0400 -@@ -102,8 +102,9 @@ - # defines OS specific file locations based on uname - systemFileLocations - -+ config_files=`find $config_repository -type f -name \*config 2>/dev/null` -+ - if [ -f $last_config ]; then -- config_files=`find $config_repository -type f -name \*config 2>/dev/null` - for config_cursor in `echo $config_files` - do - if /usr/bin/diff $last_config $config_cursor >/dev/null 2>&1 -@@ -112,8 +113,8 @@ - fi - done - if [ -n "$match" ]; then -- echo "The last bastille run corresponds to the following profiles:" -- echo "$match" -+ printf "The last Bastille run corresponds to the following profiles:\n" -+ printf "$match" - else - cat >&2 << EOF - NOTE: The last config file applied, -@@ -122,18 +123,28 @@ - $ERRSPACES $config_repository. - $ERRSPACES This probably means that Bastille was last run interactively and - $ERRSPACES changes were made to the config file, but they have not yet been --$ERRSPACES applied, or that the source config file was moved. If you do have pending -+$ERRSPACES applied, or that the source config file was moved. If you do have pending - $ERRSPACES changes in a config file, you can apply them by running - $ERRSPACES 'bastille -b -f <config file>.' - EOF - - fi - else -- echo "NOTE: The system is in its pre-bastilled state.\n" -+ for config_cursor in `echo $config_files` -+ do -+ match="$match $config_cursor\n" -+ done -+ if [ -n "$match" ]; then -+ printf "The following Bastille profiles were located:\n" -+ printf "$match" -+ else -+ printf "No Bastille profiles were located.\n" -+ fi -+ printf "No log files of profiles from previous executions of Bastille have been found. It is likely that Bastille has not been run on this machine.\n" - fi -- - } - -+ - # First, make sure we're root - if [ `PATH="/usr/bin:/bin"; id -u` -ne 0 ]; then - echo "ERROR: Bastille must be run as root user" >&2 diff --git a/recipes-security/bastille/files/fix_missing_use_directives.patch b/recipes-security/bastille/files/fix_missing_use_directives.patch deleted file mode 100644 index 05f145a..0000000 --- a/recipes-security/bastille/files/fix_missing_use_directives.patch +++ /dev/null @@ -1,54 +0,0 @@ -Upstream Status: Inappropriate [No upstream maintenance] - -Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> - ---- - -Index: Bastille/Bastille/Firewall.pm -=================================================================== ---- Bastille.orig/Bastille/Firewall.pm 2008-09-14 19:56:54.000000000 -0400 -+++ Bastille/Bastille/Firewall.pm 2013-08-20 16:28:44.588378000 -0400 -@@ -21,6 +21,7 @@ - package Bastille::Firewall; - - use Bastille::API; -+use Bastille::API::AccountPermission; - use Bastille::API::FileContent; - use Bastille::API::ServiceAdmin; - -Index: Bastille/Bastille/SecureInetd.pm -=================================================================== ---- Bastille.orig/Bastille/SecureInetd.pm 2008-09-14 19:56:58.000000000 -0400 -+++ Bastille/Bastille/SecureInetd.pm 2013-08-20 16:45:02.252378001 -0400 -@@ -12,6 +12,7 @@ - use lib "/usr/lib"; - - use Bastille::API; -+use Bastille::API::AccountPermission; - use Bastille::API::HPSpecific; - use Bastille::API::ServiceAdmin; - use Bastille::API::FileContent; -Index: Bastille/Bastille/ConfigureMiscPAM.pm -=================================================================== ---- Bastille.orig/Bastille/ConfigureMiscPAM.pm 2005-09-12 23:47:28.000000000 -0400 -+++ Bastille/Bastille/ConfigureMiscPAM.pm 2013-08-20 18:36:07.340378001 -0400 -@@ -5,6 +5,7 @@ - use lib "/usr/lib"; - - use Bastille::API; -+use Bastille::API::FileContent; - - # To DO: - # -Index: Bastille/Bastille/Printing.pm -=================================================================== ---- Bastille.orig/Bastille/Printing.pm 2008-09-14 19:56:58.000000000 -0400 -+++ Bastille/Bastille/Printing.pm 2013-08-20 19:05:01.532378002 -0400 -@@ -5,6 +5,7 @@ - use lib "/usr/lib"; - - use Bastille::API; -+use Bastille::API::AccountPermission; - use Bastille::API::HPSpecific; - use Bastille::API::ServiceAdmin; - use Bastille::API::FileContent; diff --git a/recipes-security/bastille/files/fix_number_of_modules.patch b/recipes-security/bastille/files/fix_number_of_modules.patch deleted file mode 100644 index 743e549..0000000 --- a/recipes-security/bastille/files/fix_number_of_modules.patch +++ /dev/null @@ -1,38 +0,0 @@ -Upstream Status: Inappropriate [No upstream maintenance] - -Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> - ---- - -Index: Bastille/Bastille_Curses.pm -=================================================================== ---- Bastille.orig/Bastille_Curses.pm 2013-08-24 18:21:54.445288000 -0400 -+++ Bastille/Bastille_Curses.pm 2013-08-24 18:29:16.981288000 -0400 -@@ -36,9 +36,6 @@ - use Curses; - use Curses::Widgets; - -- # Number_Modules is the number of modules loaded in by Load_Questions -- $Number_Modules=0; -- - # - # Highlighted button is the button currently chosen in the button bar - # We preserve this from question to question... -@@ -397,7 +394,7 @@ - my $title; - - if ($module) { -- $title=$module . " of $Number_Modules"; -+ $title=$module; - } - - txt_field( 'window' => $window, -@@ -488,7 +485,7 @@ - my $title; - - if ($module) { -- $title=$module . " of $Number_Modules"; -+ $title=$module; - } - - noecho; diff --git a/recipes-security/bastille/files/fix_version_parse.patch b/recipes-security/bastille/files/fix_version_parse.patch deleted file mode 100644 index 5923c04..0000000 --- a/recipes-security/bastille/files/fix_version_parse.patch +++ /dev/null @@ -1,27 +0,0 @@ -Upstream Status: Inappropriate [No upstream maintenance] - -Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> - ---- - -Index: Bastille/bin/bastille -=================================================================== ---- Bastille.orig/bin/bastille -+++ Bastille/bin/bastille -@@ -162,11 +162,12 @@ fi - # We check that the version is at least the minimum - - PERL_VERSION=`${CURRENT_PERL_PATH}/perl -version | -- head -2 | # the second line contains the version -+ head -n 2 | # the second line contains the version - tr " " "\n" | # split words into separate lines -- sed -e "s/^v//" | # to get rid of the v in v5.6.0 -- grep "^[1-9]\." | # find a "word" that starts with number dot -- sed -e "s/_/./"` # substitute _patchlevel with .patchlevel -+ grep "^(v" | # find a "word" that starts with '(v' -+ sed -e "s/^(v//" -e "s/)//" -e "s/_/./"` -+ # to get rid of the (v in v5.6.0 -+ # substitute _patchlevel with .patchlevel - # (used in 5.005_03 and prior) - - # everything before the first . diff --git a/recipes-security/bastille/files/fixed_defined_warnings.patch b/recipes-security/bastille/files/fixed_defined_warnings.patch deleted file mode 100644 index e7996e3..0000000 --- a/recipes-security/bastille/files/fixed_defined_warnings.patch +++ /dev/null @@ -1,65 +0,0 @@ -From c59b84ca3bda8e4244d47901b6966f28dd675434 Mon Sep 17 00:00:00 2001 -From: Andrei Dinu <andrei.adrianx.dinu@intel.com> -Date: Thu, 23 May 2013 15:12:23 +0300 -Subject: [PATCH] added yocto-standard to bastille - -In order to make Bastille functional and avoid errors -regarding distros, if not any given distro is identified, -yocto-standard distro is added to the distro variable -in Bastille. - -Fixed also some warnings regarding defined statements -in API.pm. - -Upstream Status: Inappropriate [No upstream maintenance] - -Signed-off-by: Andrei Dinu <andrei.adrianx.dinu@intel.com> - -Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> - ---- - Bastille/API.pm | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -Index: Bastille/Bastille/API.pm -=================================================================== ---- Bastille.orig/Bastille/API.pm 2008-09-14 19:56:53.000000000 -0400 -+++ Bastille/Bastille/API.pm 2013-08-21 08:55:26.715950001 -0400 -@@ -445,8 +445,8 @@ - $release=`/usr/bin/uname -sr`; - } - else { -- print STDERR "$err Could not determine operating system version!\n"; -- $distro="unknown"; -+ print STDERR "$err Could not determine operating system version!\n"; -+ $distro="unknown" - } - - # Figure out what kind of system we're on. -@@ -1284,7 +1284,7 @@ - - my $sumFile = &getGlobal('BFILE',"sum.csv"); - -- if ( defined %GLOBAL_SUM ) { -+ if ( %GLOBAL_SUM ) { - - open( SUM, "> $sumFile") or &B_log("ERROR","Unable to open $sumFile for write.\n$!\n"); - -@@ -1318,7 +1318,7 @@ - my $file = $_[0]; - my $cksum = &getGlobal('BIN',"cksum"); - -- if (not(defined(%GLOBAL_SUM))) { -+ if (not(%GLOBAL_SUM)) { - &B_read_sums; - } - -@@ -1375,7 +1375,7 @@ - sub B_isFileinSumDB($) { - my $file = $_[0]; - -- if (not(defined(%GLOBAL_SUM))) { -+ if (not(%GLOBAL_SUM)) { - &B_log("DEBUG","Reading in DB from B_isFileinSumDB"); - &B_read_sums; - } diff --git a/recipes-security/bastille/files/organize_distro_discovery.patch b/recipes-security/bastille/files/organize_distro_discovery.patch deleted file mode 100644 index d64d1e2..0000000 --- a/recipes-security/bastille/files/organize_distro_discovery.patch +++ /dev/null @@ -1,476 +0,0 @@ -Upstream Status: Inappropriate [No upstream maintenance] - -Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> - ---- - -Index: Bastille/Bastille/API.pm -=================================================================== ---- Bastille.orig/Bastille/API.pm 2013-08-22 04:32:38.269968002 -0400 -+++ Bastille/Bastille/API.pm 2013-08-22 11:29:53.137968002 -0400 -@@ -141,7 +141,7 @@ - checkProcsForService - - -- $GLOBAL_OS $GLOBAL_ACTUAL_OS $CLI -+ $CLI - $GLOBAL_LOGONLY $GLOBAL_VERBOSE $GLOBAL_DEBUG $GLOBAL_AUDITONLY $GLOBAL_AUDIT_NO_BROWSER $errorFlag - %GLOBAL_BIN %GLOBAL_DIR %GLOBAL_FILE - %GLOBAL_BDIR %GLOBAL_BFILE -@@ -198,7 +198,7 @@ - my $err ="ERROR: "; - my $spc =" "; - my $GLOBAL_OS="None"; --my $GLOBAL_ACTUAL_OS="None"; -+my $GLOBAL_INFERRED_OS="None"; - my %GLOBAL_SUMS=(); - my $CLI=''; - -@@ -306,7 +306,7 @@ - - ########################################################################### - # --# GetDistro checks to see if the target is a known distribution and reports -+# InferDistro checks to see if the target is a known distribution and reports - # said distribution. - # - # This is used throughout the script, but also by ConfigureForDistro. -@@ -314,205 +314,194 @@ - # - ########################################################################### - --sub GetDistro() { -+sub InferDistro() { - - my ($release,$distro); - -- # Only read files for the distro once. -- # if the --os option was used then -- if ($GLOBAL_OS eq "None") { -- if ( -e "/etc/mandrake-release" ) { -- open(MANDRAKE_RELEASE,"/etc/mandrake-release"); -- $release=<MANDRAKE_RELEASE>; -- -- if ( ($release =~ /^Mandrake Linux release (\d+\.\d+\w*)/) or ($release =~ /^Linux Mandrake release (\d+\.\d+\w*)/) ) { -- $distro="MN$1"; -- } -- elsif ( $release =~ /^Mandrakelinux release (\d+\.\d+)\b/ ) { -- $distro="MN$1"; -- } -- else { -- print STDERR "$err Couldn't determine Mandrake/Mandriva version! Setting to 10.1!\n"; -- $distro="MN10.1"; -- } -- -- close(MANDRAKE_RELEASE); -- } -- elsif ( -e "/etc/immunix-release" ) { -- open(IMMUNIX_RELEASE,"/etc/immunix-release"); -- $release=<IMMUNIX_RELEASE>; -- unless ($release =~ /^Immunix Linux release (\d+\.\d+\w*)/) { -- print STDERR "$err Couldn't determine Immunix version! Setting to 6.2!\n"; -- $distro="RH6.2"; -- } -- else { -- $distro="RH$1"; -- } -- close(*IMMUNIX_RELEASE); -- } -- elsif ( -e '/etc/fedora-release' ) { -- open(FEDORA_RELEASE,'/etc/fedora-release'); -- $release=<FEDORA_RELEASE>; -- close FEDORA_RELEASE; -- if ($release =~ /^Fedora Core release (\d+\.?\d*)/) { -- $distro = "RHFC$1"; -- } -- elsif ($release =~ /^Fedora release (\d+\.?\d*)/) { -- $distro = "RHFC$1"; -- } -- else { -- print STDERR "$err Could not determine Fedora version! Setting to Fedora Core 8\n"; -- $distro='RHFC8'; -- } -+ if ( -e "/etc/mandrake-release" ) { -+ open(MANDRAKE_RELEASE,"/etc/mandrake-release"); -+ $release=<MANDRAKE_RELEASE>; -+ -+ if ( ($release =~ /^Mandrake Linux release (\d+\.\d+\w*)/) or ($release =~ /^Linux Mandrake release (\d+\.\d+\w*)/) ) { -+ $distro="MN$1"; -+ } -+ elsif ( $release =~ /^Mandrakelinux release (\d+\.\d+)\b/ ) { -+ $distro="MN$1"; -+ } -+ else { -+ print STDERR "$err Could not infer Mandrake/Mandriva version! Setting to 10.1!\n"; -+ $distro="MN10.1"; -+ } -+ -+ close(MANDRAKE_RELEASE); -+ } -+ elsif ( -e "/etc/immunix-release" ) { -+ open(IMMUNIX_RELEASE,"/etc/immunix-release"); -+ $release=<IMMUNIX_RELEASE>; -+ unless ($release =~ /^Immunix Linux release (\d+\.\d+\w*)/) { -+ print STDERR "$err Could not infer Immunix version! Setting to 6.2!\n"; -+ $distro="RH6.2"; -+ } -+ else { -+ $distro="RH$1"; - } -- elsif ( -e "/etc/redhat-release" ) { -- open(*REDHAT_RELEASE,"/etc/redhat-release"); -- $release=<REDHAT_RELEASE>; -- if ($release =~ /^Red Hat Linux release (\d+\.?\d*\w*)/) { -- $distro="RH$1"; -- } -- elsif ($release =~ /^Red Hat Linux .+ release (\d+)\.?\d*([AEW]S)/) { -- $distro="RHEL$1$2"; -- } -- elsif ($release =~ /^Red Hat Enterprise Linux ([AEW]S) release (\d+)/) { -- $distro="RHEL$2$1"; -+ close(*IMMUNIX_RELEASE); -+ } -+ elsif ( -e '/etc/fedora-release' ) { -+ open(FEDORA_RELEASE,'/etc/fedora-release'); -+ $release=<FEDORA_RELEASE>; -+ close FEDORA_RELEASE; -+ if ($release =~ /^Fedora Core release (\d+\.?\d*)/) { -+ $distro = "RHFC$1"; -+ } -+ elsif ($release =~ /^Fedora release (\d+\.?\d*)/) { -+ $distro = "RHFC$1"; -+ } -+ else { -+ print STDERR "$err Could not infer Fedora version! Setting to Fedora Core 8\n"; -+ $distro='RHFC8'; -+ } -+ } -+ elsif ( -e "/etc/redhat-release" ) { -+ open(*REDHAT_RELEASE,"/etc/redhat-release"); -+ $release=<REDHAT_RELEASE>; -+ if ($release =~ /^Red Hat Linux release (\d+\.?\d*\w*)/) { -+ $distro="RH$1"; -+ } -+ elsif ($release =~ /^Red Hat Linux .+ release (\d+)\.?\d*([AEW]S)/) { -+ $distro="RHEL$1$2"; -+ } -+ elsif ($release =~ /^Red Hat Enterprise Linux ([AEW]S) release (\d+)/) { -+ $distro="RHEL$2$1"; -+ } -+ elsif ($release =~ /^CentOS release (\d+\.\d+)/) { -+ my $version = $1; -+ if ($version =~ /^4\./) { -+ $distro='RHEL4AS'; - } -- elsif ($release =~ /^CentOS release (\d+\.\d+)/) { -- my $version = $1; -- if ($version =~ /^4\./) { -- $distro='RHEL4AS'; -- } -- elsif ($version =~ /^3\./) { -- $distro='RHEL3AS'; -- } -- else { -- print STDERR "$err Could not determine CentOS version! Setting to Red Hat Enterprise 4 AS.\n"; -- $distro='RHEL4AS'; -- } -- } -- else { -- # JJB/HP - Should this be B_log? -- print STDERR "$err Couldn't determine Red Hat version! Setting to 9!\n"; -- $distro="RH9"; -- } -- close(REDHAT_RELEASE); -- -- } -- elsif ( -e "/etc/debian_version" ) { -- $stable="3.1"; #Change this when Debian stable changes -- open(*DEBIAN_RELEASE,"/etc/debian_version"); -- $release=<DEBIAN_RELEASE>; -- unless ($release =~ /^(\d+\.\d+\w*)/) { -- print STDERR "$err System is not running a stable Debian GNU/Linux version. Setting to $stable.\n"; -- $distro="DB$stable"; -+ elsif ($version =~ /^3\./) { -+ $distro='RHEL3AS'; - } - else { -- $distro="DB$1"; -- } -- close(DEBIAN_RELEASE); -- } -- elsif ( -e "/etc/SuSE-release" ) { -- open(*SUSE_RELEASE,"/etc/SuSE-release"); -- $release=<SUSE_RELEASE>; -- if ($release =~ /^SuSE Linux (\d+\.\d+\w*)/i) { -- $distro="SE$1"; -- } -- elsif ($release =~ /^SUSE LINUX Enterprise Server (\d+\.?\d?\w*)/i) { -- $distro="SESLES$1"; -- } -- elsif ($release =~ /^SUSE Linux Enterprise Server (\d+\.?\d?\w*)/i) { -- $distro="SESLES$1"; -- } -- elsif ($release =~ /^openSuSE (\d+\.\d+\w*)/i) { -- $distro="SE$1"; -+ print STDERR "$err Could not infer CentOS version! Setting to Red Hat Enterprise 4 AS.\n"; -+ $distro='RHEL4AS'; - } -- else { -- print STDERR "$err Couldn't determine SuSE version! Setting to 10.3!\n"; -- $distro="SE10.3"; -- } -- close(SUSE_RELEASE); -- } -- elsif ( -e "/etc/turbolinux-release") { -- open(*TURBOLINUX_RELEASE,"/etc/turbolinux-release"); -- $release=<TURBOLINUX_RELEASE>; -- unless ($release =~ /^Turbolinux Workstation (\d+\.\d+\w*)/) { -- print STDERR "$err Couldn't determine TurboLinux version! Setting to 7.0!\n"; -- $distro="TB7.0"; -- } -- else { -- $distro="TB$1"; -- } -- close(TURBOLINUX_RELEASE); -+ } -+ else { -+ # JJB/HP - Should this be B_log? -+ print STDERR "$err Could not infer Red Hat version! Setting to 9!\n"; -+ $distro="RH9"; -+ } -+ close(REDHAT_RELEASE); -+ -+ } -+ elsif ( -e "/etc/debian_version" ) { -+ $stable="3.1"; #Change this when Debian stable changes -+ open(*DEBIAN_RELEASE,"/etc/debian_version"); -+ $release=<DEBIAN_RELEASE>; -+ unless ($release =~ /^(\d+\.\d+\w*)/) { -+ print STDERR "$err System is not running a stable Debian GNU/Linux version. Setting to $stable.\n"; -+ $distro="DB$stable"; -+ } -+ else { -+ $distro="DB$1"; -+ } -+ close(DEBIAN_RELEASE); -+ } -+ elsif ( -e "/etc/SuSE-release" ) { -+ open(*SUSE_RELEASE,"/etc/SuSE-release"); -+ $release=<SUSE_RELEASE>; -+ if ($release =~ /^SuSE Linux (\d+\.\d+\w*)/i) { -+ $distro="SE$1"; -+ } -+ elsif ($release =~ /^SUSE LINUX Enterprise Server (\d+\.?\d?\w*)/i) { -+ $distro="SESLES$1"; -+ } -+ elsif ($release =~ /^SUSE Linux Enterprise Server (\d+\.?\d?\w*)/i) { -+ $distro="SESLES$1"; -+ } -+ elsif ($release =~ /^openSuSE (\d+\.\d+\w*)/i) { -+ $distro="SE$1"; -+ } -+ else { -+ print STDERR "$err Could not infer SuSE version! Setting to 10.3!\n"; -+ $distro="SE10.3"; - } -+ close(SUSE_RELEASE); -+ } -+ elsif ( -e "/etc/turbolinux-release") { -+ open(*TURBOLINUX_RELEASE,"/etc/turbolinux-release"); -+ $release=<TURBOLINUX_RELEASE>; -+ unless ($release =~ /^Turbolinux Workstation (\d+\.\d+\w*)/) { -+ print STDERR "$err Could not infer TurboLinux version! Setting to 7.0!\n"; -+ $distro="TB7.0"; -+ } - else { -- # We're either on Mac OS X, HP-UX or an unsupported O/S. -- if ( -x '/usr/bin/uname') { -+ $distro="TB$1"; -+ } -+ close(TURBOLINUX_RELEASE); -+ } -+ else { -+ # We're either on Mac OS X, HP-UX or an unsupported O/S. -+ if ( -x '/usr/bin/uname') { - # uname is in /usr/bin on Mac OS X and HP-UX -- $release=`/usr/bin/uname -sr`; -- } -- else { -- print STDERR "$err Could not determine operating system version!\n"; -- $distro="unknown" -- } -- -- # Figure out what kind of system we're on. -- if ($release ne "") { -- if ($release =~ /^Darwin\s+(\d+)\.(\d+)/) { -- if ($1 == 6 ) { -- $distro = "OSX10.2"; -- } -- elsif ($1 == 7) { -- $distro = "OSX10.3"; -- } -- elsif ($1 == 8) { -- $distro = "OSX10.3"; -- } -- else { -- $distro = "unknown"; -- } -+ $release=`/usr/bin/uname -sr`; -+ } -+ else { -+ print STDERR "$err Could not infer operating system version from filesystem context. Setting inferred distro to 'unknown'.\n"; -+ $distro="unknown"; -+ } -+ -+ # Figure out what kind of system we're on. -+ if ($release ne "") { -+ if ($release =~ /^Darwin\s+(\d+)\.(\d+)/) { -+ if ($1 == 6 ) { -+ $distro = "OSX10.2"; - } -- elsif ( $release =~ /(^HP-UX)\s*B\.(\d+\.\d+)/ ) { -- $distro="$1$2"; -+ elsif ($1 == 7) { -+ $distro = "OSX10.3"; - } -+ elsif ($1 == 8) { -+ $distro = "OSX10.3"; -+ } - else { -- print STDERR "$err Could not determine operating system version!\n"; -- $distro="unknown"; -+ print STDERR "$err Could not infer operating system version from filesystem context. Setting inferred distro to 'unknown'.\n"; -+ $distro = "unknown"; - } - } -+ elsif ( $release =~ /(^HP-UX)\s*B\.(\d+\.\d+)/ ) { -+ $distro="$1$2"; -+ } -+ else { -+ print STDERR "$err Could not infer operating system version from filesystem context. Setting inferred distro to 'unknown'.\n"; -+ $distro="unknown"; -+ } - } -- -- $GLOBAL_OS=$distro; -- } elsif (not (defined $GLOBAL_OS)) { -- print "ERROR: GLOBAL OS Scoping Issue\n"; -- } else { -- $distro = $GLOBAL_OS; - } -- - return $distro; - } - - ################################################################################### --# &getActualDistro; # -+# &getInferredDistro; # - # # - # This subroutine returns the actual os version in which is running on. This # - # os version is independent of the --os switch feed to bastille. # - # # - ################################################################################### --sub getActualDistro { -- # set local variable to $GLOBAL_OS -+sub getInferredDistro { -+ if ($GLOBAL_INFERRED_OS eq "None") { -+ $GLOBAL_INFERRED_OS = &InferDistro; -+ } -+ return $GLOBAL_INFERRED_OS; -+} - -- if ($GLOBAL_ACTUAL_OS eq "None") { -- my $os = $GLOBAL_OS; -- # undef GLOBAL_OS so that the GetDistro routine will return -- # the actualDistro, it might otherwise return the distro set -- # by the --os switch. -- $GLOBAL_OS = "None"; -- $GLOBAL_ACTUAL_OS = &GetDistro; -- # reset the GLOBAL_OS variable -- $GLOBAL_OS = $os; -+sub GetDistro { -+ if ($GLOBAL_OS eq "None") { -+ return &getInferredDistro; - } -- return $GLOBAL_ACTUAL_OS; -+ return $GLOBAL_OS; - } -+ - # These are helper routines which used to be included inside GetDistro - sub is_OS_supported($) { - my $os=$_[0]; -@@ -556,7 +545,8 @@ - "SE7.2","SE7.3", "SE8.0","SE8.1","SE9.0","SE9.1", - "SE9.2","SE9.3","SE10.0","SE10.1","SE10.2","SE10.3", - "SESLES8","SESLES9","SESLES10", -- "TB7.0" -+ "TB7.0", -+ "Yocto" - ], - - "HP-UX" => [ -@@ -882,23 +872,19 @@ - ########################################################################### - sub ConfigureForDistro { - -- my $retval=1; -- -- # checking to see if the os version given is in fact supported - my $distro = &GetDistro; - -- # checking to see if the actual os version is in fact supported -- my $actualDistro = &getActualDistro; -+ my $inferredDistro = &getInferredDistro; -+ -+ if (! ($inferredDistro eq $distro) ) { -+ print STDERR "WARNING: Inferred distro $inferredDistro is not the same as specified distro $distro. Using specified distro.\n"; -+ } -+ - $ENV{'LOCALE'}=''; # So that test cases checking for english results work ok. -- if ((! &is_OS_supported($distro)) or (! &is_OS_supported($actualDistro)) ) { -- # if either is not supported then print out a list of supported versions -- if (! &is_OS_supported($distro)) { -- print STDERR "$err '$distro' is not a supported operating system.\n"; -- } -- else { -- print STDERR "$err Bastille is unable to operate correctly on this\n"; -- print STDERR "$spc $distro operating system.\n"; -- } -+ -+ if (! &is_OS_supported($distro)) { -+ print STDERR "$err '$distro' is not a supported operating system.\n"; -+ - my %supportedOSHash = &getSupportedOSHash; - print STDERR "$spc Valid operating system versions are as follows:\n"; - -@@ -930,7 +916,7 @@ - # intend via setting the Perl umask - umask(077); - -- &getFileAndServiceInfo($distro,$actualDistro); -+ &getFileAndServiceInfo($distro,$distro); - - # &dumpFileInfo; # great for debuging file location issues - # &dumpServiceInfo; # great for debuging service information issues -@@ -942,7 +928,7 @@ - "$spc You must use Bastille\'s -n flag (for example:\n" . - "$spc bastille -f -n) or \'touch $nodisclaim_file \'\n"; - -- return $retval; -+ return 1; - } - - -Index: Bastille/Bastille/LogAPI.pm -=================================================================== ---- Bastille.orig/Bastille/LogAPI.pm 2013-08-22 04:32:38.269968002 -0400 -+++ Bastille/Bastille/LogAPI.pm 2013-08-22 04:32:47.509968002 -0400 -@@ -111,7 +111,7 @@ - # do this here to prevent bootstrapping problem, where we need to - # write an error that the errorlog location isn't defined. - my $logdir="/var/log/Bastille"; -- if(&getActualDistro =~ "^HP-UX"){ -+ if(&getInferredDistro =~ "^HP-UX"){ - $logdir = "/var/opt/sec_mgmt/bastille/log/"; - } - diff --git a/recipes-security/bastille/files/remove_questions_text_file_references.patch b/recipes-security/bastille/files/remove_questions_text_file_references.patch deleted file mode 100644 index bd094ee..0000000 --- a/recipes-security/bastille/files/remove_questions_text_file_references.patch +++ /dev/null @@ -1,30 +0,0 @@ -Upstream Status: Inappropriate [No upstream maintenance] - -Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> - ---- - -Index: Bastille/OSMap/LINUX.bastille -=================================================================== ---- Bastille.orig/OSMap/LINUX.bastille 2008-01-25 18:31:35.000000000 -0500 -+++ Bastille/OSMap/LINUX.bastille 2013-08-22 04:48:32.677968002 -0400 -@@ -12,7 +12,6 @@ - - bfile,InteractiveBastille,'/usr/sbin/InteractiveBastille' - bfile,BastilleBackEnd,'/usr/sbin/BastilleBackEnd' --bfile,Questions,'/usr/share/Bastille/Questions.txt' - bfile,QuestionsModules,'/usr/share/Bastille/Modules.txt' - bfile,TODO,'/var/log/Bastille/TODO' - bfile,TODOFlag,'/var/log/Bastille/TODOFlag.txt' -Index: Bastille/OSMap/OSX.bastille -=================================================================== ---- Bastille.orig/OSMap/OSX.bastille 2007-09-11 18:09:26.000000000 -0400 -+++ Bastille/OSMap/OSX.bastille 2013-08-22 04:48:47.245968001 -0400 -@@ -10,7 +10,6 @@ - bdir,share,'/usr/share/Bastille' - - bfile,BastilleBackEnd,'/var/root/Bastille/BastilleBackEnd' --bfile,Questions,'/usr/share/Bastille/Questions.txt' - bfile,QuestionsModules,'/usr/share/Bastille/Modules.txt' - bfile,TODO,'/var/log/Bastille/TODO' - bfile,TODOFlag,'/var/log/Bastille/TODOFlag.txt' diff --git a/recipes-security/bastille/files/set_required_questions.py b/recipes-security/bastille/files/set_required_questions.py deleted file mode 100755 index f306109..0000000 --- a/recipes-security/bastille/files/set_required_questions.py +++ /dev/null @@ -1,157 +0,0 @@ -#!/usr/bin/env python3 - -#Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> - -import argparse, os, shutil, sys, tempfile, traceback -from os import path - - - -def get_config(lines): - """ - From a sequence of lines retrieve the question file name, question identifier - pairs. - """ - for l in lines: - if not l.startswith("#"): - try: - (coord, value) = l.split("=") - try: - (fname, ident) = coord.split(".") - yield fname, ident - except ValueError as e: - raise ValueError("Badly formatted coordinates %s in line %s." % (coord, l.strip())) - except ValueError as e: - raise ValueError("Skipping badly formatted line %s, %s" % (l.strip(), e)) - - - -def check_contains(line, name): - """ - Check if the value field for REQUIRE_DISTRO contains the given name. - @param name line The REQUIRE_DISTRO line - @param name name The name to look for in the value field of the line. - """ - try: - (label, distros) = line.split(":") - return name in distros.split() - except ValueError as e: - raise ValueError("Error splitting REQUIRE_DISTRO line: %s" % e) - - - -def add_requires(the_ident, distro, lines): - - """ - Yield a sequence of lines the same as lines except that where - the_ident matches a question identifier change the REQUIRE_DISTRO so that - it includes the specified distro. - - @param name the_ident The question identifier to be matched. - @param name distro The distribution to added to the questions REQUIRE_DISTRO - field. - @param lines The sequence to be processed. - """ - for l in lines: - yield l - if l.startswith("LABEL:"): - try: - (label, ident) = l.split(":") - if ident.strip() == the_ident: - break - except ValueError as e: - raise ValueError("Unexpected line %s in questions file." % l.strip()) - for l in lines: - if l.startswith("REQUIRE_DISTRO"): - if not check_contains(l, distro): - yield l.rstrip() + " " + distro + "\n" - else: - yield l - break; - else: - yield l - for l in lines: - yield l - - - -def xform_file(qfile, distro, qlabel): - """ - Transform a Questions file. - @param name qfile The designated questions file. - @param name distro The distribution to add to the required distributions. - @param name qlabel The question label for which the distro is to be added. - """ - questions_in = open(qfile) - questions_out = tempfile.NamedTemporaryFile(mode="w+", delete=False) - for l in add_requires(qlabel, distro, questions_in): - questions_out.write(l) - questions_out.close() - questions_in.close() - shutil.copystat(qfile, questions_out.name) - os.remove(qfile) - shutil.move(questions_out.name, qfile) - - - -def handle_args(parser): - parser.add_argument('config_file', - help = "Configuration file path.") - parser.add_argument('questions_dir', - help = "Directory containing Questions files.") - parser.add_argument('--distro', '-d', - help = "The distribution, the default is Yocto.", - default = "Yocto") - parser.add_argument('--debug', '-b', - help = "Print debug information.", - action = 'store_true') - return parser.parse_args() - - - -def check_args(args): - args.config_file = os.path.abspath(args.config_file) - args.questions_dir = os.path.abspath(args.questions_dir) - - if not os.path.isdir(args.questions_dir): - raise ValueError("Specified Questions directory %s does not exist or is not a directory." % args.questions_dir) - - if not os.path.isfile(args.config_file): - raise ValueError("Specified configuration file %s not found." % args.config_file) - - - -def main(): - opts = handle_args(argparse.ArgumentParser(description="A simple script that sets required questions based on the question/answer pairs in a configuration file.")) - - try: - check_args(opts) - except ValueError as e: - if opts.debug: - traceback.print_exc() - else: - sys.exit("Fatal error:\n%s" % e) - - - try: - config_in = open(opts.config_file) - for qfile, qlabel in get_config(config_in): - questions_file = os.path.join(opts.questions_dir, qfile + ".txt") - xform_file(questions_file, opts.distro, qlabel) - config_in.close() - - except IOError as e: - if opts.debug: - traceback.print_exc() - else: - sys.exit("Fatal error reading or writing file:\n%s" % e) - except ValueError as e: - if opts.debug: - traceback.print_exc() - else: - sys.exit("Fatal error:\n%s" % e) - - - -if __name__ == "__main__": - main() diff --git a/recipes-security/bastille/files/simplify_B_place.patch b/recipes-security/bastille/files/simplify_B_place.patch deleted file mode 100644 index 307fdca..0000000 --- a/recipes-security/bastille/files/simplify_B_place.patch +++ /dev/null @@ -1,40 +0,0 @@ -Upstream Status: Inappropriate [No upstream maintenance] - -Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> - ---- - -Index: Bastille/Bastille/API.pm -=================================================================== ---- Bastille.orig/Bastille/API.pm 2013-08-21 08:59:17.939950001 -0400 -+++ Bastille/Bastille/API.pm 2013-08-21 08:59:30.983950001 -0400 -@@ -1679,24 +1679,22 @@ - - use File::Copy; - -- my $original_source=$source; - $source = &getGlobal('BDIR', "share") . $source; -- my $original_target=$target; - - if ( -e $target and -f $target ) { -- &B_backup_file($original_target); -- &B_log("ACTION","About to copy $original_source to $original_target -- had to backup target\n"); -+ &B_backup_file($target); -+ &B_log("ACTION","About to copy $source to $target -- had to backup target\n"); - $had_to_backup_target=1; - } - $retval=copy($source,$target); - if ($retval) { -- &B_log("ACTION","placed file $original_source as $original_target\n"); -+ &B_log("ACTION","placed file $source as $target\n"); - # - # We want to add a line to the &getGlobal('BFILE', "created-files") so that the - # file we just put at $original_target gets deleted. -- &B_revert_log(&getGlobal('BIN',"rm") . " $original_target\n"); -+ &B_revert_log(&getGlobal('BIN',"rm") . " $target\n"); - } else { -- &B_log("ERROR","Failed to place $original_source as $original_target\n"); -+ &B_log("ERROR","Failed to place $source as $target\n"); - } - - # We add the file to the GLOBAL_SUMS hash if it is not already present diff --git a/recipes-security/bastille/files/upgrade_options_processing.patch b/recipes-security/bastille/files/upgrade_options_processing.patch deleted file mode 100644 index 4093867..0000000 --- a/recipes-security/bastille/files/upgrade_options_processing.patch +++ /dev/null @@ -1,91 +0,0 @@ -Upstream Status: Inappropriate [No upstream maintenance] - -Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> - ---- - -Index: Bastille/Bastille/API.pm -=================================================================== ---- Bastille.orig/Bastille/API.pm 2013-08-21 11:41:09.235950000 -0400 -+++ Bastille/Bastille/API.pm 2013-08-21 11:41:16.183950000 -0400 -@@ -271,9 +271,15 @@ - # setOptions takes six arguments, $GLOBAL_DEBUG, $GLOBAL_LOGONLY, - # $GLOBAL_VERBOSE, $GLOBAL_AUDITONLY, $GLOBAL_AUDIT_NO_BROWSER, and GLOBAL_OS; - ########################################################################### --sub setOptions($$$$$$) { -- ($GLOBAL_DEBUG,$GLOBAL_LOGONLY,$GLOBAL_VERBOSE,$GLOBAL_AUDITONLY, -- $GLOBAL_AUDIT_NO_BROWSER,$GLOBAL_OS) = @_; -+sub setOptions { -+ my %opts = @_; -+ -+ $GLOBAL_DEBUG = $opts{debug}; -+ $GLOBAL_LOGONLY = $opts{logonly}; -+ $GLOBAL_VERBOSE = $opts{verbose}; -+ $GLOBAL_AUDITONLY = $opts{auditonly}; -+ $GLOBAL_AUDIT_NO_BROWSER = $opts{audit_no_browser}; -+ $GLOBAL_OS = $opts{os}; - if ($GLOBAL_AUDIT_NO_BROWSER) { - $GLOBAL_AUDITONLY = 1; - } -Index: Bastille/BastilleBackEnd -=================================================================== ---- Bastille.orig/BastilleBackEnd 2013-08-21 11:41:09.235950000 -0400 -+++ Bastille/BastilleBackEnd 2013-08-21 12:40:54.055950001 -0400 -@@ -50,15 +50,13 @@ - my $nodisclaim = 0; - my $verbose = 0; - my $force = 0; --my $log_only = 0; - my $debug = 0; - my $alternate_config=undef; - - if( Getopt::Long::GetOptions( "n" => \$nodisclaim, - "v" => \$verbose, - "force" => \$force, --# "log" => \$log_only, # broken -- "f:s" => \$alternate_config, -+ "f=s" => \$alternate_config, - "debug" => \$debug) ) { - $error = 0; # no parse error - -@@ -66,7 +64,9 @@ - $error = 1; # parse error - } - --&setOptions($debug,$log_only,$verbose); -+&setOptions( -+ debug => $debug, -+ verbose => $verbose); - &ConfigureForDistro; - - if ( $error ) { # GetOptions couldn't parse all of the args -Index: Bastille/InteractiveBastille -=================================================================== ---- Bastille.orig/InteractiveBastille 2013-08-21 11:41:09.235950000 -0400 -+++ Bastille/InteractiveBastille 2013-08-21 12:40:30.531950001 -0400 -@@ -234,8 +234,8 @@ - "a" => \$audit, - "force" => \$force, - "log" => \$log_only, -- "os:s" => \$os_version, -- "f:s" => \$alternate_config, -+ "os=s" => \$os_version, -+ "f=s" => \$alternate_config, - "debug" => \$debug) ) { - $error = 0; # no parse error - } else { -@@ -293,7 +293,13 @@ - $UseRequiresRules = 'N'; - } - --&setOptions($debug,$log_only,$verbose,$audit,$auditnobrowser,$os_version); -+&setOptions( -+ debug => $debug, -+ logonly => $log_only, -+ verbose => $verbose, -+ auditonly => $audit, -+ audit_no_browser => $auditnobrowser, -+ os => $os_version); - &ConfigureForDistro; - - # ensuring mutually exclusive options are exclusive |