Squashed 'import-layers/meta-security/' content from commit 4d139b9

Subtree from git://git.yoctoproject.org/meta-security

Change-Id: I14bb13faa3f2b2dc1f5d81b339dd48ffedf8562f
git-subtree-dir: import-layers/meta-security
git-subtree-split: 4d139b95c4f152d132592f515c5151f4dd6269c1
Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
diff --git a/import-layers/meta-security/recipes-security/bastille/bastille_3.2.1.bb b/import-layers/meta-security/recipes-security/bastille/bastille_3.2.1.bb
new file mode 100644
index 0000000..eee1a38
--- /dev/null
+++ b/import-layers/meta-security/recipes-security/bastille/bastille_3.2.1.bb
@@ -0,0 +1,157 @@
+#The functionality of Bastille that is actually available is restricted. Please
+#consult the README file for the meta-security layer for additional information.
+SUMMARY = "Linux hardening tool"
+DESCRIPTION = "Bastille Linux is a Hardening and Reporting/Auditing Program which enhances the security of a Linux box, by configuring daemons, system settings and firewalling."
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://${S}/COPYING;md5=c93c0550bd3173f4504b2cbd8991e50b"
+# Bash is needed for set +o privileged (check busybox), might also need ncurses
+DEPENDS = "virtual/kernel"
+RDEPENDS_${PN} = "perl bash tcl perl-module-getopt-long perl-module-text-wrap lib-perl perl-module-file-path perl-module-mime-base64 perl-module-file-find perl-module-errno perl-module-file-glob perl-module-tie-hash-namedcapture perl-module-file-copy perl-module-english perl-module-exporter perl-module-cwd libcurses-perl coreutils"
+FILES_${PN} += "/run/lock/subsys/bastille"
+
+inherit allarch module-base
+
+SRC_URI = "http://sourceforge.net/projects/bastille-linux/files/bastille-linux/3.2.1/Bastille-3.2.1.tar.bz2 \
+           file://AccountPermission.pm \
+           file://FileContent.pm \
+           file://HPSpecific.pm \
+           file://Miscellaneous.pm \
+           file://ServiceAdmin.pm \
+           file://config \
+           file://fix_version_parse.patch \
+           file://fixed_defined_warnings.patch \
+           file://call_output_config.patch \
+           file://fix_missing_use_directives.patch \
+           file://fix_number_of_modules.patch \
+           file://remove_questions_text_file_references.patch \
+           file://simplify_B_place.patch \
+           file://find_existing_config.patch \
+           file://upgrade_options_processing.patch \
+           file://accept_os_flag_in_backend.patch \
+           file://allow_os_with_assess.patch \
+           file://edit_usage_message.patch \
+           file://organize_distro_discovery.patch \
+           file://do_not_apply_config.patch \
+           "
+
+SRC_URI[md5sum] = "df803f7e38085aa5da79f85d0539f91b"
+SRC_URI[sha256sum] = "0ea25191b1dc1c8f91e1b6f8cb5436a3aa1e57418809ef902293448efed5021a"
+
+S = "${WORKDIR}/Bastille"
+
+do_install () {
+	install -d ${D}${sbindir}
+	install -d ${D}${libdir}/perl/site_perl/Curses
+	ln -sf perl ${D}/${libdir}/perl5
+
+	install -d ${D}${libdir}/Bastille
+	install -d ${D}${libdir}/Bastille/API
+	install -d ${D}${datadir}/Bastille
+	install -d ${D}${datadir}/Bastille/OSMap
+	install -d ${D}${datadir}/Bastille/OSMap/Modules
+	install -d ${D}${datadir}/Bastille/Questions
+	install -d ${D}${datadir}/Bastille/FKL/configs/
+	install -d ${D}${localstatedir}/lock/subsys/bastille
+	install -d ${D}${localstatedir}/log/Bastille
+	install -d ${D}${sysconfdir}/Bastille
+	install -m 0755 AutomatedBastille  ${D}${sbindir}
+	install -m 0755 BastilleBackEnd    ${D}${sbindir}
+	install -m 0755 InteractiveBastille    ${D}${sbindir}
+	install -m 0644 Modules.txt    ${D}${datadir}/Bastille
+	# New Weights file(s).
+	install -m 0644 Weights.txt    ${D}${datadir}/Bastille
+	# Castle graphic
+	install -m 0644 bastille.jpg    ${D}${datadir}/Bastille/
+	# Javascript file
+	install -m 0644 wz_tooltip.js    ${D}${datadir}/Bastille/
+	install -m 0644 Credits    ${D}${datadir}/Bastille
+	install -m 0644 FKL/configs/fkl_config_redhat.cfg    ${D}${datadir}/Bastille/FKL/configs/
+	install -m 0755 RevertBastille    ${D}${sbindir}
+	install -m 0755 bin/bastille    ${D}${sbindir}
+	install -m 0644 bastille-firewall    ${D}${datadir}/Bastille
+	install -m 0644 bastille-firewall-reset    ${D}${datadir}/Bastille
+	install -m 0644 bastille-firewall-schedule    ${D}${datadir}/Bastille
+	install -m 0644 bastille-tmpdir-defense.sh    ${D}${datadir}/Bastille
+	install -m 0644 bastille-tmpdir.csh    ${D}${datadir}/Bastille
+	install -m 0644 bastille-tmpdir.sh    ${D}${datadir}/Bastille
+	install -m 0644 bastille-firewall.cfg    ${D}${datadir}/Bastille
+	install -m 0644 bastille-ipchains    ${D}${datadir}/Bastille
+	install -m 0644 bastille-netfilter    ${D}${datadir}/Bastille
+	install -m 0644 bastille-firewall-early.sh    ${D}${datadir}/Bastille
+	install -m 0644 bastille-firewall-pre-audit.sh    ${D}${datadir}/Bastille
+	install -m 0644 complete.xbm    ${D}${datadir}/Bastille
+	install -m 0644 incomplete.xbm    ${D}${datadir}/Bastille
+	install -m 0644 disabled.xpm    ${D}${datadir}/Bastille
+	install -m 0644 ifup-local    ${D}${datadir}/Bastille
+	install -m 0644 hosts.allow    ${D}${datadir}/Bastille
+
+	install -m 0644 Bastille/AccountSecurity.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/Apache.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/API.pm    ${D}${libdir}/Bastille
+	install -m 0644 ${WORKDIR}/AccountPermission.pm    ${D}${libdir}/Bastille/API
+	install -m 0644 ${WORKDIR}/FileContent.pm    ${D}${libdir}/Bastille/API
+	install -m 0644 ${WORKDIR}/HPSpecific.pm    ${D}${libdir}/Bastille/API
+	install -m 0644 ${WORKDIR}/ServiceAdmin.pm    ${D}${libdir}/Bastille/API
+	install -m 0644 ${WORKDIR}/Miscellaneous.pm    ${D}${libdir}/Bastille/API
+	install -m 0644 Bastille/BootSecurity.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/ConfigureMiscPAM.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/DisableUserTools.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/DNS.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/FilePermissions.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/FTP.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/Firewall.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/OSX_API.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/LogAPI.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/HP_UX.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/IOLoader.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/Patches.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/Logging.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/MiscellaneousDaemons.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/PatchDownload.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/Printing.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/PSAD.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/RemoteAccess.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/SecureInetd.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/Sendmail.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/TestDriver.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/TMPDIR.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/test_AccountSecurity.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/test_Apache.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/test_DNS.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/test_FTP.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/test_HP_UX.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/test_MiscellaneousDaemons.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/test_Patches.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/test_SecureInetd.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/test_Sendmail.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/test_BootSecurity.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/test_DisableUserTools.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/test_FilePermissions.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/test_Logging.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/test_Printing.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille/IPFilter.pm    ${D}${libdir}/Bastille
+	install -m 0644 Bastille_Curses.pm    ${D}${libdir}/perl5/site_perl
+	install -m 0644 Bastille_Tk.pm    ${D}${libdir}/perl5/site_perl
+	install -m 0644 Curses/Widgets.pm    ${D}${libdir}/perl5/site_perl/Curses
+
+	install -m 0644 OSMap/LINUX.bastille    ${D}${datadir}/Bastille/OSMap
+	install -m 0644 OSMap/LINUX.system    ${D}${datadir}/Bastille/OSMap
+	install -m 0644 OSMap/LINUX.service    ${D}${datadir}/Bastille/OSMap
+	install -m 0644 OSMap/HP-UX.bastille    ${D}${datadir}/Bastille/OSMap
+	install -m 0644 OSMap/HP-UX.system    ${D}${datadir}/Bastille/OSMap
+	install -m 0644 OSMap/HP-UX.service    ${D}${datadir}/Bastille/OSMap
+	install -m 0644 OSMap/OSX.bastille    ${D}${datadir}/Bastille/OSMap
+	install -m 0644 OSMap/OSX.system    ${D}${datadir}/Bastille/OSMap
+
+	install -m 0777 ${WORKDIR}/config ${D}${sysconfdir}/Bastille/config
+
+	for file in `cat Modules.txt` ; do
+		install -m 0644 Questions/$file.txt ${D}${datadir}/Bastille/Questions
+	done
+
+	${THISDIR}/files/set_required_questions.py ${D}${sysconfdir}/Bastille/config ${D}${datadir}/Bastille/Questions
+
+	ln -s RevertBastille ${D}${sbindir}/UndoBastille
+}
+
+FILES_${PN} += "${datadir}/Bastille ${libdir}/Bastille ${libdir}/perl* ${sysconfdir}/*"
diff --git a/import-layers/meta-security/recipes-security/bastille/files/API.pm b/import-layers/meta-security/recipes-security/bastille/files/API.pm
new file mode 100644
index 0000000..5060f52
--- /dev/null
+++ b/import-layers/meta-security/recipes-security/bastille/files/API.pm
@@ -0,0 +1,2528 @@
+# 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/import-layers/meta-security/recipes-security/bastille/files/AccountPermission.pm b/import-layers/meta-security/recipes-security/bastille/files/AccountPermission.pm
new file mode 100644
index 0000000..cfbaab1
--- /dev/null
+++ b/import-layers/meta-security/recipes-security/bastille/files/AccountPermission.pm
@@ -0,0 +1,1060 @@
+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/import-layers/meta-security/recipes-security/bastille/files/FileContent.pm b/import-layers/meta-security/recipes-security/bastille/files/FileContent.pm
new file mode 100644
index 0000000..0a5d609
--- /dev/null
+++ b/import-layers/meta-security/recipes-security/bastille/files/FileContent.pm
@@ -0,0 +1,1153 @@
+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/import-layers/meta-security/recipes-security/bastille/files/HPSpecific.pm b/import-layers/meta-security/recipes-security/bastille/files/HPSpecific.pm
new file mode 100644
index 0000000..7e7d709
--- /dev/null
+++ b/import-layers/meta-security/recipes-security/bastille/files/HPSpecific.pm
@@ -0,0 +1,1983 @@
+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/import-layers/meta-security/recipes-security/bastille/files/Miscellaneous.pm b/import-layers/meta-security/recipes-security/bastille/files/Miscellaneous.pm
new file mode 100644
index 0000000..b3bdf10
--- /dev/null
+++ b/import-layers/meta-security/recipes-security/bastille/files/Miscellaneous.pm
@@ -0,0 +1,166 @@
+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/import-layers/meta-security/recipes-security/bastille/files/ServiceAdmin.pm b/import-layers/meta-security/recipes-security/bastille/files/ServiceAdmin.pm
new file mode 100644
index 0000000..879223a
--- /dev/null
+++ b/import-layers/meta-security/recipes-security/bastille/files/ServiceAdmin.pm
@@ -0,0 +1,690 @@
+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/import-layers/meta-security/recipes-security/bastille/files/accept_os_flag_in_backend.patch b/import-layers/meta-security/recipes-security/bastille/files/accept_os_flag_in_backend.patch
new file mode 100644
index 0000000..4a438e4
--- /dev/null
+++ b/import-layers/meta-security/recipes-security/bastille/files/accept_os_flag_in_backend.patch
@@ -0,0 +1,34 @@
+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/import-layers/meta-security/recipes-security/bastille/files/allow_os_with_assess.patch b/import-layers/meta-security/recipes-security/bastille/files/allow_os_with_assess.patch
new file mode 100644
index 0000000..e112f90
--- /dev/null
+++ b/import-layers/meta-security/recipes-security/bastille/files/allow_os_with_assess.patch
@@ -0,0 +1,43 @@
+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/import-layers/meta-security/recipes-security/bastille/files/call_output_config.patch b/import-layers/meta-security/recipes-security/bastille/files/call_output_config.patch
new file mode 100644
index 0000000..1e898b1
--- /dev/null
+++ b/import-layers/meta-security/recipes-security/bastille/files/call_output_config.patch
@@ -0,0 +1,19 @@
+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/import-layers/meta-security/recipes-security/bastille/files/config b/import-layers/meta-security/recipes-security/bastille/files/config
new file mode 100755
index 0000000..9e5e206
--- /dev/null
+++ b/import-layers/meta-security/recipes-security/bastille/files/config
@@ -0,0 +1,106 @@
+# 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/import-layers/meta-security/recipes-security/bastille/files/do_not_apply_config.patch b/import-layers/meta-security/recipes-security/bastille/files/do_not_apply_config.patch
new file mode 100644
index 0000000..574aa98
--- /dev/null
+++ b/import-layers/meta-security/recipes-security/bastille/files/do_not_apply_config.patch
@@ -0,0 +1,40 @@
+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/import-layers/meta-security/recipes-security/bastille/files/edit_usage_message.patch b/import-layers/meta-security/recipes-security/bastille/files/edit_usage_message.patch
new file mode 100644
index 0000000..72cdc2f
--- /dev/null
+++ b/import-layers/meta-security/recipes-security/bastille/files/edit_usage_message.patch
@@ -0,0 +1,32 @@
+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/import-layers/meta-security/recipes-security/bastille/files/find_existing_config.patch b/import-layers/meta-security/recipes-security/bastille/files/find_existing_config.patch
new file mode 100644
index 0000000..c075875
--- /dev/null
+++ b/import-layers/meta-security/recipes-security/bastille/files/find_existing_config.patch
@@ -0,0 +1,64 @@
+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/import-layers/meta-security/recipes-security/bastille/files/fix_missing_use_directives.patch b/import-layers/meta-security/recipes-security/bastille/files/fix_missing_use_directives.patch
new file mode 100644
index 0000000..05f145a
--- /dev/null
+++ b/import-layers/meta-security/recipes-security/bastille/files/fix_missing_use_directives.patch
@@ -0,0 +1,54 @@
+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/import-layers/meta-security/recipes-security/bastille/files/fix_number_of_modules.patch b/import-layers/meta-security/recipes-security/bastille/files/fix_number_of_modules.patch
new file mode 100644
index 0000000..743e549
--- /dev/null
+++ b/import-layers/meta-security/recipes-security/bastille/files/fix_number_of_modules.patch
@@ -0,0 +1,38 @@
+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/import-layers/meta-security/recipes-security/bastille/files/fix_version_parse.patch b/import-layers/meta-security/recipes-security/bastille/files/fix_version_parse.patch
new file mode 100644
index 0000000..5923c04
--- /dev/null
+++ b/import-layers/meta-security/recipes-security/bastille/files/fix_version_parse.patch
@@ -0,0 +1,27 @@
+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/import-layers/meta-security/recipes-security/bastille/files/fixed_defined_warnings.patch b/import-layers/meta-security/recipes-security/bastille/files/fixed_defined_warnings.patch
new file mode 100644
index 0000000..e7996e3
--- /dev/null
+++ b/import-layers/meta-security/recipes-security/bastille/files/fixed_defined_warnings.patch
@@ -0,0 +1,65 @@
+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/import-layers/meta-security/recipes-security/bastille/files/organize_distro_discovery.patch b/import-layers/meta-security/recipes-security/bastille/files/organize_distro_discovery.patch
new file mode 100644
index 0000000..d64d1e2
--- /dev/null
+++ b/import-layers/meta-security/recipes-security/bastille/files/organize_distro_discovery.patch
@@ -0,0 +1,476 @@
+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/import-layers/meta-security/recipes-security/bastille/files/remove_questions_text_file_references.patch b/import-layers/meta-security/recipes-security/bastille/files/remove_questions_text_file_references.patch
new file mode 100644
index 0000000..bd094ee
--- /dev/null
+++ b/import-layers/meta-security/recipes-security/bastille/files/remove_questions_text_file_references.patch
@@ -0,0 +1,30 @@
+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/import-layers/meta-security/recipes-security/bastille/files/set_required_questions.py b/import-layers/meta-security/recipes-security/bastille/files/set_required_questions.py
new file mode 100755
index 0000000..4a28358
--- /dev/null
+++ b/import-layers/meta-security/recipes-security/bastille/files/set_required_questions.py
@@ -0,0 +1,157 @@
+#!/usr/bin/env python
+
+#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(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/import-layers/meta-security/recipes-security/bastille/files/simplify_B_place.patch b/import-layers/meta-security/recipes-security/bastille/files/simplify_B_place.patch
new file mode 100644
index 0000000..307fdca
--- /dev/null
+++ b/import-layers/meta-security/recipes-security/bastille/files/simplify_B_place.patch
@@ -0,0 +1,40 @@
+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/import-layers/meta-security/recipes-security/bastille/files/upgrade_options_processing.patch b/import-layers/meta-security/recipes-security/bastille/files/upgrade_options_processing.patch
new file mode 100644
index 0000000..4093867
--- /dev/null
+++ b/import-layers/meta-security/recipes-security/bastille/files/upgrade_options_processing.patch
@@ -0,0 +1,91 @@
+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